Back to home page

EIC code displayed by LXR

 
 

    


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