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 "llvm/Support/Casting.h" 18 #include <cassert> 19 #include <cstdint> 20 21 using namespace clang; 22 23 // FIXME: Add support for dependent-sized array types in C++? 24 // Does it even make sense to build a CFG for an uninstantiated template? FindVA(const Type * t)25static inline const VariableArrayType *FindVA(const Type* t) { 26 while (const ArrayType *vt = dyn_cast<ArrayType>(t)) { 27 if (const VariableArrayType *vat = dyn_cast<VariableArrayType>(vt)) 28 if (vat->getSizeExpr()) 29 return vat; 30 31 t = vt->getElementType().getTypePtr(); 32 } 33 34 return nullptr; 35 } 36 NextVA()37void StmtIteratorBase::NextVA() { 38 assert(getVAPtr()); 39 40 const VariableArrayType *p = getVAPtr(); 41 p = FindVA(p->getElementType().getTypePtr()); 42 setVAPtr(p); 43 44 if (p) 45 return; 46 47 if (inDeclGroup()) { 48 if (VarDecl* VD = dyn_cast<VarDecl>(*DGI)) 49 if (VD->hasInit()) 50 return; 51 52 NextDecl(); 53 } 54 else { 55 assert(inSizeOfTypeVA()); 56 RawVAPtr = 0; 57 } 58 } 59 NextDecl(bool ImmediateAdvance)60void StmtIteratorBase::NextDecl(bool ImmediateAdvance) { 61 assert(getVAPtr() == nullptr); 62 assert(inDeclGroup()); 63 64 if (ImmediateAdvance) 65 ++DGI; 66 67 for ( ; DGI != DGE; ++DGI) 68 if (HandleDecl(*DGI)) 69 return; 70 71 RawVAPtr = 0; 72 } 73 HandleDecl(Decl * D)74bool StmtIteratorBase::HandleDecl(Decl* D) { 75 if (VarDecl* VD = dyn_cast<VarDecl>(D)) { 76 if (const VariableArrayType* VAPtr = FindVA(VD->getType().getTypePtr())) { 77 setVAPtr(VAPtr); 78 return true; 79 } 80 81 if (VD->getInit()) 82 return true; 83 } 84 else if (TypedefNameDecl* TD = dyn_cast<TypedefNameDecl>(D)) { 85 if (const VariableArrayType* VAPtr = 86 FindVA(TD->getUnderlyingType().getTypePtr())) { 87 setVAPtr(VAPtr); 88 return true; 89 } 90 } 91 else if (EnumConstantDecl* ECD = dyn_cast<EnumConstantDecl>(D)) { 92 if (ECD->getInitExpr()) 93 return true; 94 } 95 96 return false; 97 } 98 StmtIteratorBase(Decl ** dgi,Decl ** dge)99StmtIteratorBase::StmtIteratorBase(Decl** dgi, Decl** dge) 100 : DGI(dgi), RawVAPtr(DeclGroupMode), DGE(dge) { 101 NextDecl(false); 102 } 103 StmtIteratorBase(const VariableArrayType * t)104StmtIteratorBase::StmtIteratorBase(const VariableArrayType* t) 105 : DGI(nullptr), RawVAPtr(SizeOfTypeVAMode) { 106 RawVAPtr |= reinterpret_cast<uintptr_t>(t); 107 } 108 GetDeclExpr() const109Stmt*& StmtIteratorBase::GetDeclExpr() const { 110 if (const VariableArrayType* VAPtr = getVAPtr()) { 111 assert(VAPtr->SizeExpr); 112 return const_cast<Stmt*&>(VAPtr->SizeExpr); 113 } 114 115 assert(inDeclGroup()); 116 VarDecl* VD = cast<VarDecl>(*DGI); 117 return *VD->getInitAddress(); 118 } 119