1 | //===-- UncheckedOptionalAccessModel.h --------------------------*- C++ -*-===// |
2 | // |
3 | // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. |
4 | // See https://llvm.org/LICENSE.txt for license information. |
5 | // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception |
6 | // |
7 | //===----------------------------------------------------------------------===// |
8 | // |
9 | // This file defines a dataflow analysis that detects unsafe uses of optional |
10 | // values. |
11 | // |
12 | //===----------------------------------------------------------------------===// |
13 | |
14 | #ifndef CLANG_ANALYSIS_FLOWSENSITIVE_MODELS_UNCHECKEDOPTIONALACCESSMODEL_H |
15 | #define CLANG_ANALYSIS_FLOWSENSITIVE_MODELS_UNCHECKEDOPTIONALACCESSMODEL_H |
16 | |
17 | #include "clang/AST/ASTContext.h" |
18 | #include "clang/Analysis/CFG.h" |
19 | #include "clang/Analysis/FlowSensitive/CFGMatchSwitch.h" |
20 | #include "clang/Analysis/FlowSensitive/DataflowAnalysis.h" |
21 | #include "clang/Analysis/FlowSensitive/DataflowEnvironment.h" |
22 | #include "clang/Analysis/FlowSensitive/NoopLattice.h" |
23 | #include "clang/Basic/SourceLocation.h" |
24 | #include "llvm/ADT/SmallVector.h" |
25 | |
26 | namespace clang { |
27 | namespace dataflow { |
28 | |
29 | // FIXME: Explore using an allowlist-approach, where constructs supported by the |
30 | // analysis are always enabled and additional constructs are enabled through the |
31 | // `Options`. |
32 | struct UncheckedOptionalAccessModelOptions { |
33 | /// In generating diagnostics, ignore optionals reachable through overloaded |
34 | /// `operator*` or `operator->` (other than those of the optional type |
35 | /// itself). The analysis does not equate the results of such calls, so it |
36 | /// can't identify when their results are used safely (across calls), |
37 | /// resulting in false positives in all such cases. Note: this option does not |
38 | /// cover access through `operator[]`. |
39 | bool IgnoreSmartPointerDereference = false; |
40 | }; |
41 | |
42 | /// Dataflow analysis that models whether optionals hold values or not. |
43 | /// |
44 | /// Models the `std::optional`, `absl::optional`, and `base::Optional` types. |
45 | class UncheckedOptionalAccessModel |
46 | : public DataflowAnalysis<UncheckedOptionalAccessModel, NoopLattice> { |
47 | public: |
48 | UncheckedOptionalAccessModel(ASTContext &Ctx, dataflow::Environment &Env); |
49 | |
50 | /// Returns a matcher for the optional classes covered by this model. |
51 | static ast_matchers::DeclarationMatcher optionalClassDecl(); |
52 | |
53 | static NoopLattice initialElement() { return {}; } |
54 | |
55 | void transfer(const CFGElement &Elt, NoopLattice &L, Environment &Env); |
56 | |
57 | private: |
58 | CFGMatchSwitch<TransferState<NoopLattice>> TransferMatchSwitch; |
59 | }; |
60 | |
61 | class UncheckedOptionalAccessDiagnoser { |
62 | public: |
63 | UncheckedOptionalAccessDiagnoser( |
64 | UncheckedOptionalAccessModelOptions Options = {}); |
65 | |
66 | llvm::SmallVector<SourceLocation> |
67 | operator()(const CFGElement &Elt, ASTContext &Ctx, |
68 | const TransferStateForDiagnostics<NoopLattice> &State) { |
69 | return DiagnoseMatchSwitch(Elt, Ctx, State.Env); |
70 | } |
71 | |
72 | private: |
73 | CFGMatchSwitch<const Environment, llvm::SmallVector<SourceLocation>> |
74 | DiagnoseMatchSwitch; |
75 | }; |
76 | |
77 | } // namespace dataflow |
78 | } // namespace clang |
79 | |
80 | #endif // CLANG_ANALYSIS_FLOWSENSITIVE_MODELS_UNCHECKEDOPTIONALACCESSMODEL_H |
81 | |