clang: lib/AST/ParentMapContext.cpp Source File (original) (raw)

1

2

3

4

5

6

7

8

9

10

11

12

13

19

20using namespace clang;

21

23

25

27

30}

31

33 if (E)

34 return nullptr;

35

36 switch (Traversal) {

38 return E;

41 }

42 llvm_unreachable("Invalid Traversal type!");

43}

44

46 if (const auto *E = N.get<Expr>()) {

48 }

49 return N;

50}

51

52template <typename T, typename... U>

56

57template <typename, typename...> struct MatchParents;

58

60

61 template <typename, typename...> friend struct ::MatchParents;

62

63

64 class ParentVector {

65 public:

66 ParentVector() = default;

68 Items.reserve(N);

69 for (; N > 0; --N)

71 }

73 return Seen.contains(Value);

74 }

76 if (Value.getMemoizationData() || Seen.insert(Value).second)

77 Items.push_back(Value);

78 }

80 private:

82 llvm::SmallDenseSet<DynTypedNode, 2> Seen;

83 };

84

85

86

87

88 using ParentMapPointers =

89 llvm::DenseMap<const void *,

90 llvm::PointerUnion<const Decl *, const Stmt *,

92

93

94

95 using ParentMapOtherNodes =

97 llvm::PointerUnion<const Decl *, const Stmt *,

99

100 ParentMapPointers PointerParents;

101 ParentMapOtherNodes OtherParents;

102 class ASTVisitor;

103

105 getSingleDynTypedNodeFromParentMap(ParentMapPointers::mapped_type U) {

106 if (const auto *D = U.dyn_cast<const Decl *>())

108 if (const auto *S = U.dyn_cast<const Stmt *>())

110 return *cast<DynTypedNode *>(U);

111 }

112

113 template <typename NodeTy, typename MapTy>

115 const MapTy &Map) {

116 auto I = Map.find(Node);

117 if (I == Map.end()) {

119 }

120 if (const auto *V = I->second.template dyn_cast<ParentVector *>()) {

121 return V->view();

122 }

123 return getSingleDynTypedNodeFromParentMap(I->second);

124 }

125

126public:

129 for (const auto &Entry : PointerParents) {

130 if (auto *DTN = dyn_cast<DynTypedNode *>(Entry.second)) {

131 delete DTN;

132 } else if (auto *PV = dyn_cast<ParentVector *>(Entry.second)) {

133 delete PV;

134 }

135 }

136 for (const auto &Entry : OtherParents) {

137 if (auto *DTN = dyn_cast<DynTypedNode *>(Entry.second)) {

138 delete DTN;

139 } else if (auto *PV = dyn_cast<ParentVector *>(Entry.second)) {

140 delete PV;

141 }

142 }

143 }

144

147 auto ParentList =

150

151 const auto *ChildExpr = Node.get<Expr>();

152

153 {

154

155

156

157

158

159 auto RewrittenBinOpParentsList = ParentList;

160 int I = 0;

161 while (ChildExpr && RewrittenBinOpParentsList.size() == 1 &&

162 I++ < 4) {

163 const auto *S = RewrittenBinOpParentsList[0].get<Stmt>();

164 if (!S)

165 break;

166

167 const auto *RWBO = dyn_cast(S);

168 if (!RWBO) {

169 RewrittenBinOpParentsList = getDynNodeFromMap(S, PointerParents);

170 continue;

171 }

172 if (RWBO->getLHS()->IgnoreUnlessSpelledInSource() != ChildExpr &&

173 RWBO->getRHS()->IgnoreUnlessSpelledInSource() != ChildExpr)

174 break;

176 }

177 }

178

179 const auto *ParentExpr = ParentList[0].get<Expr>();

180 if (ParentExpr && ChildExpr)

181 return AscendIgnoreUnlessSpelledInSource(ParentExpr, ChildExpr);

182

183 {

184 auto AncestorNodes =

185 matchParents<DeclStmt, CXXForRangeStmt>(ParentList, this);

186 if (std::get(AncestorNodes) &&

187 std::get<const CXXForRangeStmt *>(AncestorNodes)

188 ->getLoopVarStmt() ==

189 std::get<const DeclStmt *>(AncestorNodes))

190 return std::get(AncestorNodes);

191 }

192 {

193 auto AncestorNodes = matchParents<VarDecl, DeclStmt, CXXForRangeStmt>(

194 ParentList, this);

195 if (std::get(AncestorNodes) &&

196 std::get<const CXXForRangeStmt *>(AncestorNodes)

197 ->getRangeStmt() ==

198 std::get<const DeclStmt *>(AncestorNodes))

199 return std::get(AncestorNodes);

200 }

201 {

202 auto AncestorNodes =

203 matchParents<CXXMethodDecl, CXXRecordDecl, LambdaExpr>(ParentList,

204 this);

205 if (std::get(AncestorNodes))

206 return std::get(AncestorNodes);

207 }

208 {

209 auto AncestorNodes =

210 matchParents<FunctionTemplateDecl, CXXRecordDecl, LambdaExpr>(

211 ParentList, this);

212 if (std::get(AncestorNodes))

213 return std::get(AncestorNodes);

214 }

215 }

216 return ParentList;

217 }

218 return getDynNodeFromMap(Node, OtherParents);

219 }

220

222 const Expr *Child) {

223

224 auto ShouldSkip = [](const Expr *E, const Expr *Child) {

225 if (isa(E))

226 return true;

227

228 if (isa(E))

229 return true;

230

231 if (isa(E))

232 return true;

233

234 if (isa(E))

235 return true;

236

237 if (isa(E))

238 return true;

239

240 if (isa(E))

241 return true;

242

243 auto SR = Child->getSourceRange();

244

245 if (const auto *C = dyn_cast(E)) {

246 if (C->getSourceRange() == SR)

247 return true;

248 }

249

250 if (const auto *C = dyn_cast(E)) {

251 if (C->getSourceRange() == SR || C->isElidable())

252 return true;

253 }

254

255 if (const auto *C = dyn_cast(E)) {

256 if (C->getSourceRange() == SR)

257 return true;

258 }

259

260 if (const auto *C = dyn_cast(E)) {

261 if (C->getSourceRange() == SR)

262 return true;

263 }

264 return false;

265 };

266

267 while (ShouldSkip(E, Child)) {

268 auto It = PointerParents.find(E);

269 if (It == PointerParents.end())

270 break;

271 const auto *S = It->second.dyn_cast<const Stmt *>();

272 if (!S) {

273 if (auto *Vec = It->second.dyn_cast<ParentVector *>())

274 return Vec->view();

275 return getSingleDynTypedNodeFromParentMap(It->second);

276 }

277 const auto *P = dyn_cast(S);

278 if (P)

280 Child = E;

281 E = P;

282 }

284 }

285};

286

291 if (const auto *TypedNode = NodeList[0].get()) {

292 auto NextParentList =

294 if (NextParentList.size() == 1) {

296 if (std::get(TailTuple)) {

297 return std::apply(

298 [TypedNode](bool, DynTypedNodeList NodeList, auto... TupleTail) {

299 return std::make_tuple(true, NodeList, TypedNode, TupleTail...);

300 },

301 TailTuple);

302 }

303 }

304 }

305 return std::tuple_cat(std::make_tuple(false, NodeList),

306 std::tuple<const T *, const U *...>());

307 }

308};

309

311 static std::tuple<bool, DynTypedNodeList, const T *>

314 if (const auto *TypedNode = NodeList[0].get()) {

315 auto NextParentList =

317 if (NextParentList.size() == 1)

318 return std::make_tuple(true, NodeList, TypedNode);

319 }

320 return std::make_tuple(false, NodeList, nullptr);

321 }

322};

323

324template <typename T, typename... U>

329}

330

331

332

335}

338}

339template <>

342}

345}

346

347

348

349

350

351

352

353

356public:

358

359private:

361

363

364 bool shouldVisitTemplateInstantiations() const { return true; }

365

366 bool shouldVisitImplicitCode() const { return true; }

367

368

369

370

371 template <typename MapNodeTy, typename MapTy>

372 void addParent(MapNodeTy MapNode, MapTy *Parents) {

373 if (ParentStack.empty())

374 return;

375

376

377

378

379

380

381

382

383

384

385

386 auto &NodeOrVector = (*Parents)[MapNode];

387 if (NodeOrVector.isNull()) {

388 if (const auto *D = ParentStack.back().get<Decl>())

389 NodeOrVector = D;

390 else if (const auto *S = ParentStack.back().get<Stmt>())

391 NodeOrVector = S;

392 else

393 NodeOrVector = new DynTypedNode(ParentStack.back());

394 } else {

395 if (!isa<ParentVector *>(NodeOrVector)) {

396 auto *Vector = new ParentVector(

397 1, getSingleDynTypedNodeFromParentMap(NodeOrVector));

398 delete NodeOrVector.template dyn_cast<DynTypedNode *>();

399 NodeOrVector = Vector;

400 }

401

402 auto *Vector = cast<ParentVector *>(NodeOrVector);

403

404

405

406

407 bool Found = ParentStack.back().getMemoizationData() &&

408 llvm::is_contained(*Vector, ParentStack.back());

410 Vector->push_back(ParentStack.back());

411 }

412 }

413

414 template static bool isNull(T Node) { return Node; }

416

417 template <typename T, typename MapNodeTy, typename BaseTraverseFn,

419 bool TraverseNode(T Node, MapNodeTy MapNode, BaseTraverseFn BaseTraverse,

420 MapTy *Parents) {

421 if (isNull(Node))

422 return true;

423 addParent(MapNode, Parents);

425 bool Result = BaseTraverse();

426 ParentStack.pop_back();

428 }

429

430 bool TraverseDecl(Decl *DeclNode) {

431 return TraverseNode(

433 &Map.PointerParents);

434 }

435 bool TraverseTypeLoc(TypeLoc TypeLocNode) {

436 return TraverseNode(

439 &Map.OtherParents);

440 }

442 return TraverseNode(

445 &Map.OtherParents);

446 }

447 bool TraverseAttr(Attr *AttrNode) {

448 return TraverseNode(

450 &Map.PointerParents);

451 }

452 bool TraverseObjCProtocolLoc(ObjCProtocolLoc ProtocolLocNode) {

453 return TraverseNode(

456 &Map.OtherParents);

457 }

458

459

460 bool dataTraverseStmtPre(Stmt *StmtNode) {

461 addParent(StmtNode, &Map.PointerParents);

463 return true;

464 }

465 bool dataTraverseStmtPost(Stmt *StmtNode) {

466 ParentStack.pop_back();

467 return true;

468 }

469

472};

473

476}

477

479 if (!Parents)

480

481

482 Parents = std::make_unique(ASTCtx);

484}

static DynTypedNode createDynTypedNode(const T &Node)

Template specializations to abstract away from pointers and TypeLocs.

static std::tuple< bool, DynTypedNodeList, const T *, const U *... > matchParents(const DynTypedNodeList &NodeList, ParentMapContext::ParentMap *ParentMap)

llvm::DenseMap< Stmt *, Stmt * > MapTy

static bool contains(const std::set< tok::TokenKind > &Terminators, const Token &Tok)

A RecursiveASTVisitor that builds a map from nodes to their parents as defined by the RecursiveASTVis...

ASTVisitor(ParentMap &Map)

DynTypedNodeList getParents(TraversalKind TK, const DynTypedNode &Node)

DynTypedNodeList AscendIgnoreUnlessSpelledInSource(const Expr *E, const Expr *Child)

ParentMap(ASTContext &Ctx)

Holds long-lived AST nodes (such as types and decls) that can be referred to throughout the semantic ...

constexpr bool hasPointerIdentity() const

Check if the given ASTNodeKind identifies a type that offers pointer identity.

Attr - This represents one attribute.

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

Container for either a single DynTypedNode or for an ArrayRef to DynTypedNode.

A dynamically typed AST node container.

ASTNodeKind getNodeKind() const

const T * get() const

Retrieve the stored node as type T.

static DynTypedNode create(const T &Node)

Creates a DynTypedNode from Node.

const void * getMemoizationData() const

Returns a pointer that identifies the stored AST node.

This represents one expression.

Expr * IgnoreUnlessSpelledInSource()

Skip past any invisible AST nodes which might surround this statement, such as ExprWithCleanups or Im...

A C++ nested-name-specifier augmented with source location information.

const Expr * traverseIgnored(const Expr *E) const

void clear()

Clear parent maps.

TraversalKind getTraversalKind() const

DynTypedNodeList getParents(const NodeT &Node)

Returns the parents of the given node (within the traversal scope).

ParentMapContext(ASTContext &Ctx)

A class that does preorder or postorder depth-first traversal on the entire Clang AST and visits each...

bool TraverseObjCProtocolLoc(ObjCProtocolLoc ProtocolLoc)

Recursively visit an Objective-C protocol reference with location information.

bool TraverseAST(ASTContext &AST)

Recursively visits an entire AST, starting from the TranslationUnitDecl.

bool TraverseNestedNameSpecifierLoc(NestedNameSpecifierLoc NNS)

Recursively visit a C++ nested-name-specifier with location information.

bool TraverseDecl(Decl *D)

Recursively visit a declaration, by dispatching to Traverse*Decl() based on the argument's dynamic ty...

bool TraverseTypeLoc(TypeLoc TL)

Recursively visit a type with location, by dispatching to Traverse*TypeLoc() based on the argument ty...

bool TraverseAttr(Attr *At)

Recursively visit an attribute, by dispatching to Traverse*Attr() based on the argument's dynamic typ...

Stmt - This represents one statement.

Base wrapper for a particular "section" of type source info.

The JSON file list parser is used to communicate input to InstallAPI.

@ Vector

'vector' clause, allowed on 'loop', Combined, and 'routine' directives.

TraversalKind

Defines how we descend a level in the AST when we pass through expressions.

@ TK_AsIs

Will traverse all child nodes.

@ TK_IgnoreUnlessSpelledInSource

Ignore AST nodes not written in the source.

@ Result

The result type of a method or function.

const FunctionProtoType * T

static std::tuple< bool, DynTypedNodeList, const T * > match(const DynTypedNodeList &NodeList, ParentMapContext::ParentMap *ParentMap)

static std::tuple< bool, DynTypedNodeList, const T *, const U *... > match(const DynTypedNodeList &NodeList, ParentMapContext::ParentMap *ParentMap)