|
|
|||
File indexing completed on 2026-05-10 08:36:24
0001 //===-- ASTOps.h -------------------------------*- C++ -*-===// 0002 // 0003 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 0004 // See https://llvm.org/LICENSE.txt for license information. 0005 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 0006 // 0007 //===----------------------------------------------------------------------===// 0008 // 0009 // Operations on AST nodes that are used in flow-sensitive analysis. 0010 // 0011 //===----------------------------------------------------------------------===// 0012 0013 #ifndef LLVM_CLANG_ANALYSIS_FLOWSENSITIVE_ASTOPS_H 0014 #define LLVM_CLANG_ANALYSIS_FLOWSENSITIVE_ASTOPS_H 0015 0016 #include "clang/AST/Decl.h" 0017 #include "clang/AST/DynamicRecursiveASTVisitor.h" 0018 #include "clang/AST/Expr.h" 0019 #include "clang/AST/ExprCXX.h" 0020 #include "clang/AST/Type.h" 0021 #include "clang/Analysis/FlowSensitive/StorageLocation.h" 0022 #include "llvm/ADT/DenseSet.h" 0023 #include "llvm/ADT/SetVector.h" 0024 0025 namespace clang { 0026 namespace dataflow { 0027 0028 /// Skip past nodes that the CFG does not emit. These nodes are invisible to 0029 /// flow-sensitive analysis, and should be ignored as they will effectively not 0030 /// exist. 0031 /// 0032 /// * `ParenExpr` - The CFG takes the operator precedence into account, but 0033 /// otherwise omits the node afterwards. 0034 /// 0035 /// * `ExprWithCleanups` - The CFG will generate the appropriate calls to 0036 /// destructors and then omit the node. 0037 /// 0038 const Expr &ignoreCFGOmittedNodes(const Expr &E); 0039 const Stmt &ignoreCFGOmittedNodes(const Stmt &S); 0040 0041 /// A set of `FieldDecl *`. Use `SmallSetVector` to guarantee deterministic 0042 /// iteration order. 0043 using FieldSet = llvm::SmallSetVector<const FieldDecl *, 4>; 0044 0045 /// Returns the set of all fields in the type. 0046 FieldSet getObjectFields(QualType Type); 0047 0048 /// Returns whether `Fields` and `FieldLocs` contain the same fields. 0049 bool containsSameFields(const FieldSet &Fields, 0050 const RecordStorageLocation::FieldToLoc &FieldLocs); 0051 0052 /// Helper class for initialization of a record with an `InitListExpr`. 0053 /// `InitListExpr::inits()` contains the initializers for both the base classes 0054 /// and the fields of the record; this helper class separates these out into two 0055 /// different lists. In addition, it deals with special cases associated with 0056 /// unions. 0057 class RecordInitListHelper { 0058 public: 0059 // `InitList` must have record type. 0060 RecordInitListHelper(const InitListExpr *InitList); 0061 RecordInitListHelper(const CXXParenListInitExpr *ParenInitList); 0062 0063 // Base classes with their associated initializer expressions. 0064 ArrayRef<std::pair<const CXXBaseSpecifier *, Expr *>> base_inits() const { 0065 return BaseInits; 0066 } 0067 0068 // Fields with their associated initializer expressions. 0069 ArrayRef<std::pair<const FieldDecl *, Expr *>> field_inits() const { 0070 return FieldInits; 0071 } 0072 0073 private: 0074 RecordInitListHelper(QualType Ty, std::vector<const FieldDecl *> Fields, 0075 ArrayRef<Expr *> Inits); 0076 0077 SmallVector<std::pair<const CXXBaseSpecifier *, Expr *>> BaseInits; 0078 SmallVector<std::pair<const FieldDecl *, Expr *>> FieldInits; 0079 0080 // We potentially synthesize an `ImplicitValueInitExpr` for unions. It's a 0081 // member variable because we store a pointer to it in `FieldInits`. 0082 std::optional<ImplicitValueInitExpr> ImplicitValueInitForUnion; 0083 }; 0084 0085 /// Specialization of `RecursiveASTVisitor` that visits those nodes that are 0086 /// relevant to the dataflow analysis; generally, these are the ones that also 0087 /// appear in the CFG. 0088 /// To start the traversal, call `TraverseStmt()` on the statement or body of 0089 /// the function to analyze. Don't call `TraverseDecl()` on the function itself; 0090 /// this won't work as `TraverseDecl()` contains code to avoid traversing nested 0091 /// functions. 0092 class AnalysisASTVisitor : public DynamicRecursiveASTVisitor { 0093 public: 0094 AnalysisASTVisitor() { 0095 ShouldVisitImplicitCode = true; 0096 ShouldVisitLambdaBody = false; 0097 } 0098 0099 bool TraverseDecl(Decl *D) override { 0100 // Don't traverse nested record or function declarations. 0101 // - We won't be analyzing code contained in these anyway 0102 // - We don't model fields that are used only in these nested declaration, 0103 // so trying to propagate a result object to initializers of such fields 0104 // would cause an error. 0105 if (isa_and_nonnull<RecordDecl>(D) || isa_and_nonnull<FunctionDecl>(D)) 0106 return true; 0107 0108 return DynamicRecursiveASTVisitor::TraverseDecl(D); 0109 } 0110 0111 // Don't traverse expressions in unevaluated contexts, as we don't model 0112 // fields that are only used in these. 0113 // Note: The operand of the `noexcept` operator is an unevaluated operand, but 0114 // nevertheless it appears in the Clang CFG, so we don't exclude it here. 0115 bool TraverseDecltypeTypeLoc(DecltypeTypeLoc) override { return true; } 0116 bool TraverseTypeOfExprTypeLoc(TypeOfExprTypeLoc) override { return true; } 0117 bool TraverseCXXTypeidExpr(CXXTypeidExpr *TIE) override { 0118 if (TIE->isPotentiallyEvaluated()) 0119 return DynamicRecursiveASTVisitor::TraverseCXXTypeidExpr(TIE); 0120 return true; 0121 } 0122 bool TraverseUnaryExprOrTypeTraitExpr(UnaryExprOrTypeTraitExpr *) override { 0123 return true; 0124 } 0125 0126 bool TraverseBindingDecl(BindingDecl *BD) override { 0127 // `RecursiveASTVisitor` doesn't traverse holding variables for 0128 // `BindingDecl`s by itself, so we need to tell it to. 0129 if (VarDecl *HoldingVar = BD->getHoldingVar()) 0130 TraverseDecl(HoldingVar); 0131 return DynamicRecursiveASTVisitor::TraverseBindingDecl(BD); 0132 } 0133 }; 0134 0135 /// A collection of several types of declarations, all referenced from the same 0136 /// function. 0137 struct ReferencedDecls { 0138 /// Non-static member variables. 0139 FieldSet Fields; 0140 /// All variables with static storage duration, notably including static 0141 /// member variables and static variables declared within a function. 0142 llvm::DenseSet<const VarDecl *> Globals; 0143 /// Local variables, not including parameters or static variables declared 0144 /// within a function. 0145 llvm::DenseSet<const VarDecl *> Locals; 0146 /// Free functions and member functions which are referenced (but not 0147 /// necessarily called). 0148 llvm::DenseSet<const FunctionDecl *> Functions; 0149 /// When analyzing a lambda's call operator, the set of all parameters (from 0150 /// the surrounding function) that the lambda captures. Captured local 0151 /// variables are already included in `Locals` above. 0152 llvm::DenseSet<const ParmVarDecl *> LambdaCapturedParams; 0153 }; 0154 0155 /// Returns declarations that are declared in or referenced from `FD`. 0156 ReferencedDecls getReferencedDecls(const FunctionDecl &FD); 0157 0158 /// Returns declarations that are declared in or referenced from `S`. 0159 ReferencedDecls getReferencedDecls(const Stmt &S); 0160 0161 } // namespace dataflow 0162 } // namespace clang 0163 0164 #endif // LLVM_CLANG_ANALYSIS_FLOWSENSITIVE_ASTOPS_H
| [ Source navigation ] | [ Diff markup ] | [ Identifier search ] | [ general search ] |
|
This page was automatically generated by the 2.3.7 LXR engine. The LXR team |
|