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/CachedConstAccessorsLattice.h" 21 #include "clang/Analysis/FlowSensitive/DataflowAnalysis.h" 22 #include "clang/Analysis/FlowSensitive/DataflowEnvironment.h" 23 #include "clang/Analysis/FlowSensitive/MatchSwitch.h" 24 #include "clang/Analysis/FlowSensitive/NoopLattice.h" 25 #include "clang/Basic/SourceLocation.h" 26 #include "llvm/ADT/SmallVector.h" 27 28 namespace clang { 29 namespace dataflow { 30 31 // FIXME: Explore using an allowlist-approach, where constructs supported by the 32 // analysis are always enabled and additional constructs are enabled through the 33 // `Options`. 34 struct UncheckedOptionalAccessModelOptions { 35 /// In generating diagnostics, ignore optionals reachable through overloaded 36 /// `operator*` or `operator->` (other than those of the optional type 37 /// itself). The analysis does not equate the results of such calls, so it 38 /// can't identify when their results are used safely (across calls), 39 /// resulting in false positives in all such cases. Note: this option does not 40 /// cover access through `operator[]`. 41 /// 42 /// FIXME: we now cache and equate the result of const accessors 43 /// that look like unique_ptr, have both `->` (returning a pointer type) and 44 /// `*` (returning a reference type). This includes mixing `->` and 45 /// `*` in a sequence of calls as long as the object is not modified. Once we 46 /// are confident in this const accessor caching, we shouldn't need the 47 /// IgnoreSmartPointerDereference option anymore. 48 bool IgnoreSmartPointerDereference = false; 49 }; 50 51 using UncheckedOptionalAccessLattice = CachedConstAccessorsLattice<NoopLattice>; 52 53 /// Dataflow analysis that models whether optionals hold values or not. 54 /// 55 /// Models the `std::optional`, `absl::optional`, and `base::Optional` types. 56 class UncheckedOptionalAccessModel 57 : public DataflowAnalysis<UncheckedOptionalAccessModel, 58 UncheckedOptionalAccessLattice> { 59 public: 60 UncheckedOptionalAccessModel(ASTContext &Ctx, dataflow::Environment &Env); 61 62 /// Returns a matcher for the optional classes covered by this model. 63 static ast_matchers::DeclarationMatcher optionalClassDecl(); 64 initialElement()65 static UncheckedOptionalAccessLattice initialElement() { return {}; } 66 67 void transfer(const CFGElement &Elt, UncheckedOptionalAccessLattice &L, 68 Environment &Env); 69 70 private: 71 CFGMatchSwitch<TransferState<UncheckedOptionalAccessLattice>> 72 TransferMatchSwitch; 73 }; 74 75 /// Diagnostic information for an unchecked optional access. 76 struct UncheckedOptionalAccessDiagnostic { 77 CharSourceRange Range; 78 }; 79 80 class UncheckedOptionalAccessDiagnoser { 81 public: 82 UncheckedOptionalAccessDiagnoser( 83 UncheckedOptionalAccessModelOptions Options = {}); 84 85 llvm::SmallVector<UncheckedOptionalAccessDiagnostic> operator()86 operator()(const CFGElement &Elt, ASTContext &Ctx, 87 const TransferStateForDiagnostics<UncheckedOptionalAccessLattice> 88 &State) { 89 return DiagnoseMatchSwitch(Elt, Ctx, State.Env); 90 } 91 92 private: 93 CFGMatchSwitch<const Environment, 94 llvm::SmallVector<UncheckedOptionalAccessDiagnostic>> 95 DiagnoseMatchSwitch; 96 }; 97 98 } // namespace dataflow 99 } // namespace clang 100 101 #endif // CLANG_ANALYSIS_FLOWSENSITIVE_MODELS_UNCHECKEDOPTIONALACCESSMODEL_H 102