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