Googler | 113194c | 2023-07-12 11:03:47 -0700 | [diff] [blame] | 1 | // 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 | |
Googler | e1ddd19 | 2024-06-26 06:56:48 -0700 | [diff] [blame] | 8 | #include <memory> |
Googler | 6acdc64 | 2023-10-19 08:03:40 -0700 | [diff] [blame] | 9 | #include <string> |
| 10 | #include <string_view> |
Googler | 113194c | 2023-07-12 11:03:47 -0700 | [diff] [blame] | 11 | |
| 12 | #include "nullability/inference/inference.proto.h" |
Googler | f1f793d | 2023-10-19 07:51:34 -0700 | [diff] [blame] | 13 | #include "nullability/inference/slot_fingerprint.h" |
Martin Brænne | cceb531 | 2024-05-21 20:22:53 -0700 | [diff] [blame] | 14 | #include "nullability/pointer_nullability_analysis.h" |
Googler | 6850232 | 2024-06-10 11:24:38 -0700 | [diff] [blame] | 15 | #include "nullability/pragma.h" |
Googler | e1ddd19 | 2024-06-26 06:56:48 -0700 | [diff] [blame] | 16 | #include "clang/AST/ASTContext.h" |
Googler | 113194c | 2023-07-12 11:03:47 -0700 | [diff] [blame] | 17 | #include "clang/AST/DeclBase.h" |
Googler | e1ddd19 | 2024-06-26 06:56:48 -0700 | [diff] [blame] | 18 | #include "clang/AST/DeclCXX.h" |
Martin Brænne | cceb531 | 2024-05-21 20:22:53 -0700 | [diff] [blame] | 19 | #include "clang/Analysis/FlowSensitive/Solver.h" |
Sam McCall | cfd2dd1 | 2023-07-18 19:35:21 -0700 | [diff] [blame] | 20 | #include "clang/Basic/SourceLocation.h" |
Googler | 6acdc64 | 2023-10-19 08:03:40 -0700 | [diff] [blame] | 21 | #include "llvm/ADT/DenseMap.h" |
Googler | f1f793d | 2023-10-19 07:51:34 -0700 | [diff] [blame] | 22 | #include "llvm/ADT/DenseSet.h" |
Sam McCall | ebcc123 | 2023-07-14 11:36:44 -0700 | [diff] [blame] | 23 | #include "llvm/ADT/FunctionExtras.h" |
| 24 | #include "llvm/ADT/STLFunctionalExtras.h" |
Googler | 113194c | 2023-07-12 11:03:47 -0700 | [diff] [blame] | 25 | #include "llvm/Support/Error.h" |
| 26 | |
| 27 | namespace clang::tidy::nullability { |
| 28 | |
Googler | 6acdc64 | 2023-10-19 08:03:40 -0700 | [diff] [blame] | 29 | using USRCache = llvm::DenseMap<const Decl *, std::string>; |
| 30 | |
| 31 | std::string_view getOrGenerateUSR(USRCache &Cache, const Decl &); |
| 32 | |
Googler | 2a416ab | 2024-04-30 08:26:07 -0700 | [diff] [blame] | 33 | /// Callback used to report collected nullability evidence. |
Sam McCall | cfd2dd1 | 2023-07-18 19:35:21 -0700 | [diff] [blame] | 34 | using EvidenceEmitter = void(const Decl &Target, Slot, Evidence::Kind, |
| 35 | SourceLocation); |
Googler | 2a416ab | 2024-04-30 08:26:07 -0700 | [diff] [blame] | 36 | /// 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 McCall | ebcc123 | 2023-07-14 11:36:44 -0700 | [diff] [blame] | 38 | llvm::unique_function<EvidenceEmitter> evidenceEmitter( |
Googler | e1ddd19 | 2024-06-26 06:56:48 -0700 | [diff] [blame] | 39 | llvm::unique_function<void(const Evidence &) const>, USRCache &USRCache, |
| 40 | ASTContext &Ctx); |
Sam McCall | ebcc123 | 2023-07-14 11:36:44 -0700 | [diff] [blame] | 41 | |
Googler | 7191949 | 2023-10-23 15:44:06 -0700 | [diff] [blame] | 42 | struct PreviousInferences { |
| 43 | const llvm::DenseSet<SlotFingerprint> &Nullable = {}; |
| 44 | const llvm::DenseSet<SlotFingerprint> &Nonnull = {}; |
| 45 | }; |
| 46 | |
Martin Brænne | cceb531 | 2024-05-21 20:22:53 -0700 | [diff] [blame] | 47 | /// Creates a solver with default parameters that is suitable for passing to |
| 48 | /// `collectEvidenceFromDefinition()`. |
| 49 | std::unique_ptr<dataflow::Solver> makeDefaultSolverForInference(); |
| 50 | |
Googler | 2a416ab | 2024-04-30 08:26:07 -0700 | [diff] [blame] | 51 | /// 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). |
| 60 | llvm::Error collectEvidenceFromDefinition( |
Googler | 6acdc64 | 2023-10-19 08:03:40 -0700 | [diff] [blame] | 61 | const Decl &, llvm::function_ref<EvidenceEmitter>, USRCache &USRCache, |
Googler | 6850232 | 2024-06-10 11:24:38 -0700 | [diff] [blame] | 62 | const NullabilityPragmas &Pragmas, |
Googler | bd965c1 | 2024-01-24 07:12:41 -0800 | [diff] [blame] | 63 | PreviousInferences PreviousInferences = {}, |
Martin Brænne | cceb531 | 2024-05-21 20:22:53 -0700 | [diff] [blame] | 64 | const SolverFactory &MakeSolver = makeDefaultSolverForInference); |
Googler | 113194c | 2023-07-12 11:03:47 -0700 | [diff] [blame] | 65 | |
Googler | 2a416ab | 2024-04-30 08:26:07 -0700 | [diff] [blame] | 66 | /// 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 McCall | ebcc123 | 2023-07-14 11:36:44 -0700 | [diff] [blame] | 73 | void collectEvidenceFromTargetDeclaration(const clang::Decl &, |
Googler | 6850232 | 2024-06-10 11:24:38 -0700 | [diff] [blame] | 74 | llvm::function_ref<EvidenceEmitter>, |
| 75 | const NullabilityPragmas &Pragmas); |
Sam McCall | bd1a6e5 | 2023-07-14 01:04:11 -0700 | [diff] [blame] | 76 | |
Googler | 2a416ab | 2024-04-30 08:26:07 -0700 | [diff] [blame] | 77 | /// Describes locations within an AST that provide evidence for use in |
| 78 | /// inference. |
Sam McCall | 296d070 | 2023-07-14 13:32:57 -0700 | [diff] [blame] | 79 | struct EvidenceSites { |
Googler | 2a416ab | 2024-04-30 08:26:07 -0700 | [diff] [blame] | 80 | /// Declarations of inferable symbols. |
Googler | 96c49ea | 2024-06-10 10:47:32 -0700 | [diff] [blame] | 81 | llvm::DenseSet<const Decl *> Declarations; |
Googler | 2a416ab | 2024-04-30 08:26:07 -0700 | [diff] [blame] | 82 | /// 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(). |
Googler | 96c49ea | 2024-06-10 10:47:32 -0700 | [diff] [blame] | 86 | llvm::DenseSet<const Decl *> Definitions; |
Sam McCall | 296d070 | 2023-07-14 13:32:57 -0700 | [diff] [blame] | 87 | |
Googler | 2a416ab | 2024-04-30 08:26:07 -0700 | [diff] [blame] | 88 | /// Find the evidence sites within the provided AST. |
Sam McCall | 296d070 | 2023-07-14 13:32:57 -0700 | [diff] [blame] | 89 | static EvidenceSites discover(ASTContext &); |
| 90 | }; |
| 91 | |
Googler | 2a416ab | 2024-04-30 08:26:07 -0700 | [diff] [blame] | 92 | /// Returns the slot number for the I'th parameter (0-based). |
Sam McCall | 83bc55c | 2023-07-17 09:47:17 -0700 | [diff] [blame] | 93 | inline Slot paramSlot(unsigned I) { return static_cast<Slot>(SLOT_PARAM + I); } |
| 94 | |
Googler | 113194c | 2023-07-12 11:03:47 -0700 | [diff] [blame] | 95 | } // namespace clang::tidy::nullability |
| 96 | |
| 97 | #endif // CRUBIT_NULLABILITY_INFERENCE_COLLECT_EVIDENCE_H_ |