1 //===-- ASTOps.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 // Operations on AST nodes that are used in flow-sensitive analysis. 10 // 11 //===----------------------------------------------------------------------===// 12 13 #ifndef LLVM_CLANG_ANALYSIS_FLOWSENSITIVE_ASTOPS_H 14 #define LLVM_CLANG_ANALYSIS_FLOWSENSITIVE_ASTOPS_H 15 16 #include "clang/AST/Decl.h" 17 #include "clang/AST/DynamicRecursiveASTVisitor.h" 18 #include "clang/AST/Expr.h" 19 #include "clang/AST/ExprCXX.h" 20 #include "clang/AST/Type.h" 21 #include "clang/Analysis/FlowSensitive/StorageLocation.h" 22 #include "llvm/ADT/DenseSet.h" 23 #include "llvm/ADT/SetVector.h" 24 25 namespace clang { 26 namespace dataflow { 27 28 /// Skip past nodes that the CFG does not emit. These nodes are invisible to 29 /// flow-sensitive analysis, and should be ignored as they will effectively not 30 /// exist. 31 /// 32 /// * `ParenExpr` - The CFG takes the operator precedence into account, but 33 /// otherwise omits the node afterwards. 34 /// 35 /// * `ExprWithCleanups` - The CFG will generate the appropriate calls to 36 /// destructors and then omit the node. 37 /// 38 const Expr &ignoreCFGOmittedNodes(const Expr &E); 39 const Stmt &ignoreCFGOmittedNodes(const Stmt &S); 40 41 /// A set of `FieldDecl *`. Use `SmallSetVector` to guarantee deterministic 42 /// iteration order. 43 using FieldSet = llvm::SmallSetVector<const FieldDecl *, 4>; 44 45 /// Returns the set of all fields in the type. 46 FieldSet getObjectFields(QualType Type); 47 48 /// Returns whether `Fields` and `FieldLocs` contain the same fields. 49 bool containsSameFields(const FieldSet &Fields, 50 const RecordStorageLocation::FieldToLoc &FieldLocs); 51 52 /// Helper class for initialization of a record with an `InitListExpr`. 53 /// `InitListExpr::inits()` contains the initializers for both the base classes 54 /// and the fields of the record; this helper class separates these out into two 55 /// different lists. In addition, it deals with special cases associated with 56 /// unions. 57 class RecordInitListHelper { 58 public: 59 // `InitList` must have record type. 60 RecordInitListHelper(const InitListExpr *InitList); 61 RecordInitListHelper(const CXXParenListInitExpr *ParenInitList); 62 63 // Base classes with their associated initializer expressions. 64 ArrayRef<std::pair<const CXXBaseSpecifier *, Expr *>> base_inits() const { 65 return BaseInits; 66 } 67 68 // Fields with their associated initializer expressions. 69 ArrayRef<std::pair<const FieldDecl *, Expr *>> field_inits() const { 70 return FieldInits; 71 } 72 73 private: 74 RecordInitListHelper(QualType Ty, std::vector<const FieldDecl *> Fields, 75 ArrayRef<Expr *> Inits); 76 77 SmallVector<std::pair<const CXXBaseSpecifier *, Expr *>> BaseInits; 78 SmallVector<std::pair<const FieldDecl *, Expr *>> FieldInits; 79 80 // We potentially synthesize an `ImplicitValueInitExpr` for unions. It's a 81 // member variable because we store a pointer to it in `FieldInits`. 82 std::optional<ImplicitValueInitExpr> ImplicitValueInitForUnion; 83 }; 84 85 /// Specialization of `RecursiveASTVisitor` that visits those nodes that are 86 /// relevant to the dataflow analysis; generally, these are the ones that also 87 /// appear in the CFG. 88 /// To start the traversal, call `TraverseStmt()` on the statement or body of 89 /// the function to analyze. Don't call `TraverseDecl()` on the function itself; 90 /// this won't work as `TraverseDecl()` contains code to avoid traversing nested 91 /// functions. 92 class AnalysisASTVisitor : public DynamicRecursiveASTVisitor { 93 public: 94 AnalysisASTVisitor() { 95 ShouldVisitImplicitCode = true; 96 ShouldVisitLambdaBody = false; 97 } 98 99 bool TraverseDecl(Decl *D) override { 100 // Don't traverse nested record or function declarations. 101 // - We won't be analyzing code contained in these anyway 102 // - We don't model fields that are used only in these nested declaration, 103 // so trying to propagate a result object to initializers of such fields 104 // would cause an error. 105 if (isa_and_nonnull<RecordDecl>(D) || isa_and_nonnull<FunctionDecl>(D)) 106 return true; 107 108 return DynamicRecursiveASTVisitor::TraverseDecl(D); 109 } 110 111 // Don't traverse expressions in unevaluated contexts, as we don't model 112 // fields that are only used in these. 113 // Note: The operand of the `noexcept` operator is an unevaluated operand, but 114 // nevertheless it appears in the Clang CFG, so we don't exclude it here. 115 bool TraverseDecltypeTypeLoc(DecltypeTypeLoc) override { return true; } 116 bool TraverseTypeOfExprTypeLoc(TypeOfExprTypeLoc) override { return true; } 117 bool TraverseCXXTypeidExpr(CXXTypeidExpr *TIE) override { 118 if (TIE->isPotentiallyEvaluated()) 119 return DynamicRecursiveASTVisitor::TraverseCXXTypeidExpr(TIE); 120 return true; 121 } 122 bool TraverseUnaryExprOrTypeTraitExpr(UnaryExprOrTypeTraitExpr *) override { 123 return true; 124 } 125 126 bool TraverseBindingDecl(BindingDecl *BD) override { 127 // `RecursiveASTVisitor` doesn't traverse holding variables for 128 // `BindingDecl`s by itself, so we need to tell it to. 129 if (VarDecl *HoldingVar = BD->getHoldingVar()) 130 TraverseDecl(HoldingVar); 131 return DynamicRecursiveASTVisitor::TraverseBindingDecl(BD); 132 } 133 }; 134 135 /// A collection of several types of declarations, all referenced from the same 136 /// function. 137 struct ReferencedDecls { 138 /// Non-static member variables. 139 FieldSet Fields; 140 /// All variables with static storage duration, notably including static 141 /// member variables and static variables declared within a function. 142 llvm::DenseSet<const VarDecl *> Globals; 143 /// Local variables, not including parameters or static variables declared 144 /// within a function. 145 llvm::DenseSet<const VarDecl *> Locals; 146 /// Free functions and member functions which are referenced (but not 147 /// necessarily called). 148 llvm::DenseSet<const FunctionDecl *> Functions; 149 /// When analyzing a lambda's call operator, the set of all parameters (from 150 /// the surrounding function) that the lambda captures. Captured local 151 /// variables are already included in `Locals` above. 152 llvm::DenseSet<const ParmVarDecl *> LambdaCapturedParams; 153 }; 154 155 /// Returns declarations that are declared in or referenced from `FD`. 156 ReferencedDecls getReferencedDecls(const FunctionDecl &FD); 157 158 /// Returns declarations that are declared in or referenced from `S`. 159 ReferencedDecls getReferencedDecls(const Stmt &S); 160 161 } // namespace dataflow 162 } // namespace clang 163 164 #endif // LLVM_CLANG_ANALYSIS_FLOWSENSITIVE_ASTOPS_H 165