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