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