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 21using 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? 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 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 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 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 99StmtIteratorBase::StmtIteratorBase(Decl** dgi, Decl** dge) 100 : DGI(dgi), RawVAPtr(DeclGroupMode), DGE(dge) { 101 NextDecl(false); 102} 103 104StmtIteratorBase::StmtIteratorBase(const VariableArrayType* t) 105 : DGI(nullptr), RawVAPtr(SizeOfTypeVAMode) { 106 RawVAPtr |= reinterpret_cast<uintptr_t>(t); 107} 108 109Stmt*& 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