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>(t)) { 26 if (const VariableArrayType *vat = dyn_cast<VariableArrayType>(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>(*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(*DGI)) 68 return; 69 70 RawVAPtr = 0; 71 } 72 73 bool StmtIteratorBase::HandleDecl(Decl* D) { 74 if (VarDecl* VD = dyn_cast<VarDecl>(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>(D)) { 84 if (const VariableArrayType* VAPtr = 85 FindVA(TD->getUnderlyingType().getTypePtr())) { 86 setVAPtr(VAPtr); 87 return true; 88 } 89 } 90 else if (EnumConstantDecl* ECD = dyn_cast<EnumConstantDecl>(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(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>(*DGI); 116 return *VD->getInitAddress(); 117 } 118