24#include "llvm/ADT/DenseSet.h"
25#include "llvm/ADT/STLExtras.h"
30#define DEBUG_TYPE "dataflow"
35 const Expr *Current = &E;
37 while (Current !=
Last) {
39 if (
auto *EWC = dyn_cast<ExprWithCleanups>(Current)) {
40 Current = EWC->getSubExpr();
41 assert(Current !=
nullptr);
43 if (
auto *CE = dyn_cast<ConstantExpr>(Current)) {
44 Current = CE->getSubExpr();
45 assert(Current !=
nullptr);
47 Current = Current->IgnoreParens();
48 assert(Current !=
nullptr);
54 if (
auto *E = dyn_cast<Expr>(&S))
82 if (Fields.size() != FieldLocs.size())
84 for ([[maybe_unused]]
auto [Field, Loc] : FieldLocs)
85 if (!Fields.contains(cast_or_null<FieldDecl>(Field)))
94template <
class InitListT>
95static std::vector<const FieldDecl *>
97 const RecordDecl *RD = InitList->getType()->getAsRecordDecl();
98 assert(RD !=
nullptr);
100 std::vector<const FieldDecl *> Fields;
102 if (InitList->getType()->isUnionType()) {
103 Fields.push_back(InitList->getInitializedFieldInUnion());
112 RD->
fields(), std::back_inserter(Fields),
113 [](
const FieldDecl *Field) { return !Field->isUnnamedBitField(); });
120 InitList->inits()) {}
126 ParenInitList->getInitExprs()) {}
129 QualType Ty, std::vector<const FieldDecl *> Fields,
132 assert(RD !=
nullptr);
140 assert(Fields.size() == 1);
141 ImplicitValueInitForUnion.emplace(Fields.front()->getType());
142 InitsForUnion.push_back(&*ImplicitValueInitForUnion);
143 Inits = InitsForUnion;
148 assert(Fields.size() + RD->getNumBases() == Inits.size());
150 assert(InitIdx < Inits.size());
152 BaseInits.emplace_back(&
Base,
Init);
155 assert(Fields.size() == Inits.size() - InitIdx);
156 for (
const FieldDecl *Field : Fields) {
157 assert(InitIdx < Inits.size());
158 Expr *
Init = Inits[InitIdx++];
159 FieldInits.emplace_back(Field,
Init);
165 if (
auto *
V = dyn_cast<VarDecl>(&D))
166 if (
V->hasGlobalStorage())
172 if (
auto *FD = dyn_cast<FunctionDecl>(&D))
179 const auto *MethodDecl = dyn_cast_or_null<CXXMethodDecl>(
C.getCalleeDecl());
182 auto *Body = dyn_cast_or_null<CompoundStmt>(MethodDecl->getBody());
183 if (!Body || Body->size() != 1)
185 if (
auto *RS = dyn_cast<ReturnStmt>(*Body->body_begin()))
186 if (
auto *Return = RS->getRetValue())
187 return dyn_cast<MemberExpr>(Return->IgnoreParenImpCasts());
194 if (
const auto *Decomp = dyn_cast<DecompositionDecl>(&D))
195 for (
const auto *B : Decomp->bindings())
196 if (
auto *ME = dyn_cast_or_null<MemberExpr>(B->getBinding()))
198 if (
const auto *FD = dyn_cast<FieldDecl>(ME->getMemberDecl()))
199 Referenced.
Fields.insert(FD);
205 for (
auto *Child : S.children())
206 if (Child !=
nullptr)
208 if (
const auto *DefaultArg = dyn_cast<CXXDefaultArgExpr>(&S))
210 if (
const auto *DefaultInit = dyn_cast<CXXDefaultInitExpr>(&S))
213 if (
auto *DS = dyn_cast<DeclStmt>(&S)) {
214 if (DS->isSingleDecl())
217 for (
auto *D : DS->getDeclGroup())
219 }
else if (
auto *E = dyn_cast<DeclRefExpr>(&S)) {
222 }
else if (
const auto *
C = dyn_cast<CXXMemberCallExpr>(&S)) {
226 if (
const auto *FD = dyn_cast<FieldDecl>(E->getMemberDecl()))
227 Referenced.
Fields.insert(FD);
228 }
else if (
auto *E = dyn_cast<MemberExpr>(&S)) {
230 const ValueDecl *VD = E->getMemberDecl();
233 if (
const auto *FD = dyn_cast<FieldDecl>(VD))
234 Referenced.
Fields.insert(FD);
235 }
else if (
auto *InitList = dyn_cast<InitListExpr>(&S)) {
236 if (InitList->getType()->isRecordType())
238 Referenced.
Fields.insert(FD);
239 }
else if (
auto *ParenInitList = dyn_cast<CXXParenListInitExpr>(&S)) {
240 if (ParenInitList->getType()->isRecordType())
242 Referenced.
Fields.insert(FD);
250 if (
const auto *CtorDecl = dyn_cast<CXXConstructorDecl>(&FD)) {
251 for (
const auto *
Init : CtorDecl->inits()) {
252 if (
Init->isMemberInitializer()) {
254 }
else if (
Init->isIndirectMemberInitializer()) {
255 for (
const auto *I :
Init->getIndirectMember()->chain())
256 Result.Fields.insert(cast<FieldDecl>(I));
259 assert(E !=
nullptr);
264 if (
const auto *I = F->getInClassInitializer())
Defines the C++ Decl subclasses, other than those for templates (found in DeclTemplate....
Defines the clang::Expr interface and subclasses for C++ expressions.
Forward-declares and imports various common LLVM datatypes that clang wants to use unqualified.
C Language Family Type Representation.
Represents a base class of a C++ class.
Represents a call to a member function that may be written either with member call syntax (e....
Represents a list-initialization with parenthesis.
Decl - This represents one declaration (or definition), e.g.
This represents one expression.
Represents a member of a struct/union/class.
const RecordDecl * getParent() const
Returns the parent of this field declaration, which is the struct in which this field is defined.
Represents a function declaration or definition.
Stmt * getBody(const FunctionDecl *&Definition) const
Retrieve the body (definition) of the function.
Describes an C or C++ initializer list.
MemberExpr - [C99 6.5.2.3] Structure and Union Members.
A (possibly-)qualified type.
Represents a struct/union/class.
field_range fields() const
Stmt - This represents one statement.
The base class of the type hierarchy.
CXXRecordDecl * getAsCXXRecordDecl() const
Retrieves the CXXRecordDecl that this type refers to, either because the type is a RecordType or beca...
bool isDependentType() const
Whether this type is a dependent type, meaning that its definition somehow depends on a template para...
bool isIncompleteType(NamedDecl **Def=nullptr) const
Types are partitioned into 3 broad categories (C99 6.2.5p1): object types, function types,...
bool isRecordType() const
RecordDecl * getAsRecordDecl() const
Retrieves the RecordDecl this type refers to.
Represent the declaration of a variable (in which case it is an lvalue) a function (in which case it ...
Helper class for initialization of a record with an InitListExpr.
RecordInitListHelper(const InitListExpr *InitList)
llvm::DenseMap< const ValueDecl *, StorageLocation * > FieldToLoc
Dataflow Directional Tag Classes.
static void getFieldsFromClassHierarchy(QualType Type, FieldSet &Fields)
static void insertIfFunction(const Decl &D, llvm::DenseSet< const FunctionDecl * > &Funcs)
static MemberExpr * getMemberForAccessor(const CXXMemberCallExpr &C)
ReferencedDecls getReferencedDecls(const FunctionDecl &FD)
Returns declarations that are declared in or referenced from FD.
static std::vector< const FieldDecl * > getFieldsForInitListExpr(const InitListT *InitList)
Returns the fields of a RecordDecl that are initialized by an InitListExpr or CXXParenListInitExpr,...
const Expr & ignoreCFGOmittedNodes(const Expr &E)
Skip past nodes that the CFG does not emit.
FieldSet getObjectFields(QualType Type)
Returns the set of all fields in the type.
static void insertIfGlobal(const Decl &D, llvm::DenseSet< const VarDecl * > &Globals)
bool containsSameFields(const FieldSet &Fields, const RecordStorageLocation::FieldToLoc &FieldLocs)
Returns whether Fields and FieldLocs contain the same fields.
@ Result
The result type of a method or function.
A collection of several types of declarations, all referenced from the same function.
llvm::DenseSet< const VarDecl * > Globals
All variables with static storage duration, notably including static member variables and static vari...
llvm::DenseSet< const FunctionDecl * > Functions
Free functions and member functions which are referenced (but not necessarily called).
FieldSet Fields
Non-static member variables.