blob: 66f109eb9247eba55fad64f6d61f5032138a0272 [file] [log] [blame]
Googler113194c2023-07-12 11:03:47 -07001// Part of the Crubit project, under the Apache License v2.0 with LLVM
2// Exceptions. See /LICENSE for license information.
3// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
4
5#ifndef CRUBIT_NULLABILITY_INFERENCE_COLLECT_EVIDENCE_H_
6#define CRUBIT_NULLABILITY_INFERENCE_COLLECT_EVIDENCE_H_
7
Googlere1ddd192024-06-26 06:56:48 -07008#include <memory>
Googler6acdc642023-10-19 08:03:40 -07009#include <string>
10#include <string_view>
Googler113194c2023-07-12 11:03:47 -070011
12#include "nullability/inference/inference.proto.h"
Googlerf1f793d2023-10-19 07:51:34 -070013#include "nullability/inference/slot_fingerprint.h"
Martin Brænnecceb5312024-05-21 20:22:53 -070014#include "nullability/pointer_nullability_analysis.h"
Googler68502322024-06-10 11:24:38 -070015#include "nullability/pragma.h"
Googlere1ddd192024-06-26 06:56:48 -070016#include "clang/AST/ASTContext.h"
Googler113194c2023-07-12 11:03:47 -070017#include "clang/AST/DeclBase.h"
Googlere1ddd192024-06-26 06:56:48 -070018#include "clang/AST/DeclCXX.h"
Martin Brænnecceb5312024-05-21 20:22:53 -070019#include "clang/Analysis/FlowSensitive/Solver.h"
Sam McCallcfd2dd12023-07-18 19:35:21 -070020#include "clang/Basic/SourceLocation.h"
Googler6acdc642023-10-19 08:03:40 -070021#include "llvm/ADT/DenseMap.h"
Googlerf1f793d2023-10-19 07:51:34 -070022#include "llvm/ADT/DenseSet.h"
Sam McCallebcc1232023-07-14 11:36:44 -070023#include "llvm/ADT/FunctionExtras.h"
24#include "llvm/ADT/STLFunctionalExtras.h"
Googler113194c2023-07-12 11:03:47 -070025#include "llvm/Support/Error.h"
26
27namespace clang::tidy::nullability {
28
Googler6acdc642023-10-19 08:03:40 -070029using USRCache = llvm::DenseMap<const Decl *, std::string>;
30
31std::string_view getOrGenerateUSR(USRCache &Cache, const Decl &);
32
Googler2a416ab2024-04-30 08:26:07 -070033/// Callback used to report collected nullability evidence.
Sam McCallcfd2dd12023-07-18 19:35:21 -070034using EvidenceEmitter = void(const Decl &Target, Slot, Evidence::Kind,
35 SourceLocation);
Googler2a416ab2024-04-30 08:26:07 -070036/// Creates an EvidenceEmitter that serializes the evidence as Evidence protos.
37/// This emitter caches USR generation, and should be reused for the whole AST.
Sam McCallebcc1232023-07-14 11:36:44 -070038llvm::unique_function<EvidenceEmitter> evidenceEmitter(
Googlere1ddd192024-06-26 06:56:48 -070039 llvm::unique_function<void(const Evidence &) const>, USRCache &USRCache,
40 ASTContext &Ctx);
Sam McCallebcc1232023-07-14 11:36:44 -070041
Googler71919492023-10-23 15:44:06 -070042struct PreviousInferences {
43 const llvm::DenseSet<SlotFingerprint> &Nullable = {};
44 const llvm::DenseSet<SlotFingerprint> &Nonnull = {};
45};
46
Martin Brænnecceb5312024-05-21 20:22:53 -070047/// Creates a solver with default parameters that is suitable for passing to
48/// `collectEvidenceFromDefinition()`.
49std::unique_ptr<dataflow::Solver> makeDefaultSolverForInference();
50
Googler2a416ab2024-04-30 08:26:07 -070051/// Analyze code (such as a function body or variable initializer) to infer
52/// nullability.
53///
54/// Produces Evidence constraining the nullability slots of the symbols that
55/// the code interacts with, such as the function's own parameters.
56/// This is based on the code's behavior and our definition of null-safety.
57///
58/// It is up to the caller to ensure the definition is eligible for inference
59/// (function has a body, is not dependent, etc).
60llvm::Error collectEvidenceFromDefinition(
Googler6acdc642023-10-19 08:03:40 -070061 const Decl &, llvm::function_ref<EvidenceEmitter>, USRCache &USRCache,
Googler68502322024-06-10 11:24:38 -070062 const NullabilityPragmas &Pragmas,
Googlerbd965c12024-01-24 07:12:41 -080063 PreviousInferences PreviousInferences = {},
Martin Brænnecceb5312024-05-21 20:22:53 -070064 const SolverFactory &MakeSolver = makeDefaultSolverForInference);
Googler113194c2023-07-12 11:03:47 -070065
Googler2a416ab2024-04-30 08:26:07 -070066/// Gathers evidence of a symbol's nullability from a declaration of it.
67///
68/// These are trivial "inferences" of what's already written in the code. e.g:
69/// void foo(Nullable<int*>);
70/// The first parameter of foo must be nullable.
71///
72/// It is the caller's responsibility to ensure that the symbol is inferable.
Sam McCallebcc1232023-07-14 11:36:44 -070073void collectEvidenceFromTargetDeclaration(const clang::Decl &,
Googler68502322024-06-10 11:24:38 -070074 llvm::function_ref<EvidenceEmitter>,
75 const NullabilityPragmas &Pragmas);
Sam McCallbd1a6e52023-07-14 01:04:11 -070076
Googler2a416ab2024-04-30 08:26:07 -070077/// Describes locations within an AST that provide evidence for use in
78/// inference.
Sam McCall296d0702023-07-14 13:32:57 -070079struct EvidenceSites {
Googler2a416ab2024-04-30 08:26:07 -070080 /// Declarations of inferable symbols.
Googler96c49ea2024-06-10 10:47:32 -070081 llvm::DenseSet<const Decl *> Declarations;
Googler2a416ab2024-04-30 08:26:07 -070082 /// Definitions (e.g. function body, variable initializer) that can be
83 /// analyzed.
84 /// This will always be concrete code, not a template pattern. These may be
85 /// passed to collectEvidenceFromDefinition().
Googler96c49ea2024-06-10 10:47:32 -070086 llvm::DenseSet<const Decl *> Definitions;
Sam McCall296d0702023-07-14 13:32:57 -070087
Googler2a416ab2024-04-30 08:26:07 -070088 /// Find the evidence sites within the provided AST.
Sam McCall296d0702023-07-14 13:32:57 -070089 static EvidenceSites discover(ASTContext &);
90};
91
Googler2a416ab2024-04-30 08:26:07 -070092/// Returns the slot number for the I'th parameter (0-based).
Sam McCall83bc55c2023-07-17 09:47:17 -070093inline Slot paramSlot(unsigned I) { return static_cast<Slot>(SLOT_PARAM + I); }
94
Googler113194c2023-07-12 11:03:47 -070095} // namespace clang::tidy::nullability
96
97#endif // CRUBIT_NULLABILITY_INFERENCE_COLLECT_EVIDENCE_H_