1 | //===- StmtIterator.cpp - Iterators for Statements ------------------------===// |
2 | // |
3 | // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. |
4 | // See https://llvm.org/LICENSE.txt for license information. |
5 | // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception |
6 | // |
7 | //===----------------------------------------------------------------------===// |
8 | // |
9 | // This file defines internal methods for StmtIterator. |
10 | // |
11 | //===----------------------------------------------------------------------===// |
12 | |
13 | #include "clang/AST/StmtIterator.h" |
14 | #include "clang/AST/Decl.h" |
15 | #include "clang/AST/Type.h" |
16 | #include "clang/Basic/LLVM.h" |
17 | #include <cassert> |
18 | #include <cstdint> |
19 | |
20 | using namespace clang; |
21 | |
22 | // FIXME: Add support for dependent-sized array types in C++? |
23 | // Does it even make sense to build a CFG for an uninstantiated template? |
24 | static inline const VariableArrayType *FindVA(const Type* t) { |
25 | while (const ArrayType *vt = dyn_cast<ArrayType>(Val: t)) { |
26 | if (const VariableArrayType *vat = dyn_cast<VariableArrayType>(Val: vt)) |
27 | if (vat->getSizeExpr()) |
28 | return vat; |
29 | |
30 | t = vt->getElementType().getTypePtr(); |
31 | } |
32 | |
33 | return nullptr; |
34 | } |
35 | |
36 | void StmtIteratorBase::NextVA() { |
37 | assert(getVAPtr()); |
38 | |
39 | const VariableArrayType *p = getVAPtr(); |
40 | p = FindVA(p->getElementType().getTypePtr()); |
41 | setVAPtr(p); |
42 | |
43 | if (p) |
44 | return; |
45 | |
46 | if (inDeclGroup()) { |
47 | if (VarDecl* VD = dyn_cast<VarDecl>(Val: *DGI)) |
48 | if (VD->hasInit()) |
49 | return; |
50 | |
51 | NextDecl(); |
52 | } |
53 | else { |
54 | assert(inSizeOfTypeVA()); |
55 | RawVAPtr = 0; |
56 | } |
57 | } |
58 | |
59 | void StmtIteratorBase::NextDecl(bool ImmediateAdvance) { |
60 | assert(getVAPtr() == nullptr); |
61 | assert(inDeclGroup()); |
62 | |
63 | if (ImmediateAdvance) |
64 | ++DGI; |
65 | |
66 | for ( ; DGI != DGE; ++DGI) |
67 | if (HandleDecl(D: *DGI)) |
68 | return; |
69 | |
70 | RawVAPtr = 0; |
71 | } |
72 | |
73 | bool StmtIteratorBase::HandleDecl(Decl* D) { |
74 | if (VarDecl* VD = dyn_cast<VarDecl>(Val: D)) { |
75 | if (const VariableArrayType* VAPtr = FindVA(VD->getType().getTypePtr())) { |
76 | setVAPtr(VAPtr); |
77 | return true; |
78 | } |
79 | |
80 | if (VD->getInit()) |
81 | return true; |
82 | } |
83 | else if (TypedefNameDecl* TD = dyn_cast<TypedefNameDecl>(Val: D)) { |
84 | if (const VariableArrayType* VAPtr = |
85 | FindVA(t: TD->getUnderlyingType().getTypePtr())) { |
86 | setVAPtr(VAPtr); |
87 | return true; |
88 | } |
89 | } |
90 | else if (EnumConstantDecl* ECD = dyn_cast<EnumConstantDecl>(Val: D)) { |
91 | if (ECD->getInitExpr()) |
92 | return true; |
93 | } |
94 | |
95 | return false; |
96 | } |
97 | |
98 | StmtIteratorBase::StmtIteratorBase(Decl** dgi, Decl** dge) |
99 | : DGI(dgi), RawVAPtr(DeclGroupMode), DGE(dge) { |
100 | NextDecl(ImmediateAdvance: false); |
101 | } |
102 | |
103 | StmtIteratorBase::StmtIteratorBase(const VariableArrayType* t) |
104 | : DGI(nullptr), RawVAPtr(SizeOfTypeVAMode) { |
105 | RawVAPtr |= reinterpret_cast<uintptr_t>(t); |
106 | } |
107 | |
108 | Stmt*& StmtIteratorBase::GetDeclExpr() const { |
109 | if (const VariableArrayType* VAPtr = getVAPtr()) { |
110 | assert(VAPtr->SizeExpr); |
111 | return const_cast<Stmt*&>(VAPtr->SizeExpr); |
112 | } |
113 | |
114 | assert(inDeclGroup()); |
115 | VarDecl* VD = cast<VarDecl>(Val: *DGI); |
116 | return *VD->getInitAddress(); |
117 | } |
118 | |