clang: lib/Analysis/FlowSensitive/ASTOps.cpp Source File (original) (raw)

1

2

3

4

5

6

7

8

9

10

11

12

25#include "llvm/ADT/DenseSet.h"

26#include "llvm/ADT/STLExtras.h"

27#include

28#include

29#include

30

31#define DEBUG_TYPE "dataflow"

32

34

36 const Expr *Current = &E;

38 while (Current != Last) {

39 Last = Current;

40 if (auto *EWC = dyn_cast(Current)) {

41 Current = EWC->getSubExpr();

42 assert(Current != nullptr);

43 }

44 if (auto *CE = dyn_cast(Current)) {

45 Current = CE->getSubExpr();

46 assert(Current != nullptr);

47 }

48 Current = Current->IgnoreParens();

49 assert(Current != nullptr);

50 }

51 return *Current;

52}

53

55 if (auto *E = dyn_cast(&S))

57 return S;

58}

59

60

61

65 return;

66

68 Fields.insert(Field);

72}

73

74

78 return Fields;

79}

80

83 if (Fields.size() != FieldLocs.size())

84 return false;

85 for ([[maybe_unused]] auto [Field, Loc] : FieldLocs)

86 if (!Fields.contains(cast_or_null(Field)))

87 return false;

88 return true;

89}

90

91

92

93

94

95template

96static std::vector<const FieldDecl *>

98 const RecordDecl *RD = InitList->getType()->getAsRecordDecl();

99 assert(RD != nullptr);

100

101 std::vector<const FieldDecl *> Fields;

102

103 if (InitList->getType()->isUnionType()) {

104 if (const FieldDecl *Field = InitList->getInitializedFieldInUnion())

105 Fields.push_back(Field);

106 return Fields;

107 }

108

109

110

111

112

113 llvm::copy_if(

114 RD->fields(), std::back_inserter(Fields),

115 [](const FieldDecl *Field) { return !Field->isUnnamedBitField(); });

116 return Fields;

117}

118

122 InitList->inits()) {}

123

128 ParenInitList->getInitExprs()) {}

129

131 QualType Ty, std::vector<const FieldDecl *> Fields,

134 assert(RD != nullptr);

135

136

137

138

139

141 if (Ty->isUnionType() && Inits.empty()) {

142 assert(Fields.size() <= 1);

143 if (!Fields.empty()) {

144 ImplicitValueInitForUnion.emplace(Fields.front()->getType());

145 InitsForUnion.push_back(&*ImplicitValueInitForUnion);

146 }

147 Inits = InitsForUnion;

148 }

149

150 size_t InitIdx = 0;

151

152 assert(Fields.size() + RD->getNumBases() == Inits.size());

153 for (const CXXBaseSpecifier &Base : RD->bases()) {

154 assert(InitIdx < Inits.size());

155 Expr *Init = Inits[InitIdx++];

156 BaseInits.emplace_back(&Base, Init);

157 }

158

159 assert(Fields.size() == Inits.size() - InitIdx);

160 for (const FieldDecl *Field : Fields) {

161 assert(InitIdx < Inits.size());

162 Expr *Init = Inits[InitIdx++];

163 FieldInits.emplace_back(Field, Init);

164 }

165}

166

168 llvm::DenseSet<const VarDecl *> &Globals) {

169 if (auto *V = dyn_cast(&D))

170 if (V->hasGlobalStorage())

171 Globals.insert(V);

172}

173

175 llvm::DenseSet<const VarDecl *> &Locals) {

176 if (auto *V = dyn_cast(&D))

177 if (V->hasLocalStorage() && !isa(V))

178 Locals.insert(V);

179}

180

182 llvm::DenseSet<const FunctionDecl *> &Funcs) {

183 if (auto *FD = dyn_cast(&D))

184 Funcs.insert(FD);

185}

186

188

189

190 const auto *MethodDecl = dyn_cast_or_null(C.getCalleeDecl());

191 if (!MethodDecl)

192 return nullptr;

193 auto *Body = dyn_cast_or_null(MethodDecl->getBody());

194 if (!Body || Body->size() != 1)

195 return nullptr;

196 if (auto *RS = dyn_cast(*Body->body_begin()))

197 if (auto *Return = RS->getRetValue())

198 return dyn_cast(Return->IgnoreParenImpCasts());

199 return nullptr;

200}

201

203public:

205 : Referenced(Referenced) {}

206

209 if (Init->isMemberInitializer()) {

210 Referenced.Fields.insert(Init->getMember());

211 } else if (Init->isIndirectMemberInitializer()) {

212 for (const auto *I : Init->getIndirectMember()->chain())

213 Referenced.Fields.insert(cast(I));

214 }

215

216 Expr *InitExpr = Init->getInit();

217

218

220

221

222

223 if (auto *DefaultInit = dyn_cast(InitExpr))

225 }

226 }

227

232 return true;

233 }

234

239 return true;

240 }

241

243

244

246 if (const auto *FD = dyn_cast(E->getMemberDecl()))

247 Referenced.Fields.insert(FD);

248 return true;

249 }

250

252

253 const ValueDecl *VD = E->getMemberDecl();

256 if (const auto *FD = dyn_cast(VD))

257 Referenced.Fields.insert(FD);

258 return true;

259 }

260

264 Referenced.Fields.insert(FD);

265 return true;

266 }

267

271 Referenced.Fields.insert(FD);

272 return true;

273 }

274

275private:

277};

278

283 if (const auto *CtorDecl = dyn_cast(&FD))

285

286

287

288

289

290

291

292

293

294

295

296 if (const auto *Method = dyn_cast(&FD);

298 for (const auto &Capture : Method->getParent()->captures()) {

299 if (Capture.capturesVariable()) {

300 if (const auto *Param =

301 dyn_cast(Capture.getCapturedVar())) {

302 Result.LambdaCapturedParams.insert(Param);

303 }

304 }

305 }

306 }

307

309}

310

316}

317

318}

This file provides some common utility functions for processing Lambda related AST Constructs.

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 C++ constructor within a class.

Represents a C++ base or member initializer.

Represents a call to a member function that may be written either with member call syntax (e....

Represents a list-initialization with parenthesis.

A reference to a declared variable, function, enum, etc.

Decl - This represents one declaration (or definition), e.g.

virtual bool TraverseStmt(Stmt *S)

Recursively visit a statement or expression, by dispatching to Traverse*() based on the argument's dy...

This represents one expression.

Represents a member of a struct/union/class.

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 ...

Specialization of RecursiveASTVisitor that visits those nodes that are relevant to the dataflow analy...

Helper class for initialization of a record with an InitListExpr.

RecordInitListHelper(const InitListExpr *InitList)

llvm::DenseMap< const ValueDecl *, StorageLocation * > FieldToLoc

bool VisitCXXParenListInitExpr(CXXParenListInitExpr *ParenInitList) override

bool VisitInitListExpr(InitListExpr *InitList) override

bool VisitMemberExpr(MemberExpr *E) override

bool VisitDeclRefExpr(DeclRefExpr *E) override

void traverseConstructorInits(const CXXConstructorDecl *Ctor)

bool VisitCXXMemberCallExpr(CXXMemberCallExpr *C) override

ReferencedDeclsVisitor(ReferencedDecls &Referenced)

bool VisitDecl(Decl *D) override

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)

static void insertIfLocal(const Decl &D, llvm::DenseSet< const VarDecl * > &Locals)

bool containsSameFields(const FieldSet &Fields, const RecordStorageLocation::FieldToLoc &FieldLocs)

Returns whether Fields and FieldLocs contain the same fields.

bool isLambdaCallOperator(const CXXMethodDecl *MD)

@ 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 VarDecl * > Locals

Local variables, not including parameters or static variables declared within a function.

llvm::DenseSet< const FunctionDecl * > Functions

Free functions and member functions which are referenced (but not necessarily called).

FieldSet Fields

Non-static member variables.