1//===--- StmtIterator.cpp - Iterators for Statements ------------------------===//
2//
3//                     The LLVM Compiler Infrastructure
4//
5// This file is distributed under the University of Illinois Open Source
6// License. See LICENSE.TXT for details.
7//
8//===----------------------------------------------------------------------===//
9//
10// This file defines internal methods for StmtIterator.
11//
12//===----------------------------------------------------------------------===//
13
14#include "clang/AST/StmtIterator.h"
15#include "clang/AST/Decl.h"
16
17using namespace clang;
18
19// FIXME: Add support for dependent-sized array types in C++?
20// Does it even make sense to build a CFG for an uninstantiated template?
21static inline const VariableArrayType *FindVA(const Type* t) {
22  while (const ArrayType *vt = dyn_cast<ArrayType>(t)) {
23    if (const VariableArrayType *vat = dyn_cast<VariableArrayType>(vt))
24      if (vat->getSizeExpr())
25        return vat;
26
27    t = vt->getElementType().getTypePtr();
28  }
29
30  return NULL;
31}
32
33void StmtIteratorBase::NextVA() {
34  assert (getVAPtr());
35
36  const VariableArrayType *p = getVAPtr();
37  p = FindVA(p->getElementType().getTypePtr());
38  setVAPtr(p);
39
40  if (p)
41    return;
42
43  if (inDecl()) {
44    if (VarDecl* VD = dyn_cast<VarDecl>(decl))
45      if (VD->Init)
46        return;
47
48    NextDecl();
49  }
50  else if (inDeclGroup()) {
51    if (VarDecl* VD = dyn_cast<VarDecl>(*DGI))
52      if (VD->Init)
53        return;
54
55    NextDecl();
56  }
57  else {
58    assert (inSizeOfTypeVA());
59    assert(!decl);
60    RawVAPtr = 0;
61  }
62}
63
64void StmtIteratorBase::NextDecl(bool ImmediateAdvance) {
65  assert (getVAPtr() == NULL);
66
67  if (inDecl()) {
68    assert(decl);
69
70    // FIXME: SIMPLIFY AWAY.
71    if (ImmediateAdvance)
72      decl = 0;
73    else if (HandleDecl(decl))
74      return;
75  }
76  else {
77    assert(inDeclGroup());
78
79    if (ImmediateAdvance)
80      ++DGI;
81
82    for ( ; DGI != DGE; ++DGI)
83      if (HandleDecl(*DGI))
84        return;
85  }
86
87  RawVAPtr = 0;
88}
89
90bool StmtIteratorBase::HandleDecl(Decl* D) {
91
92  if (VarDecl* VD = dyn_cast<VarDecl>(D)) {
93    if (const VariableArrayType* VAPtr = FindVA(VD->getType().getTypePtr())) {
94      setVAPtr(VAPtr);
95      return true;
96    }
97
98    if (VD->getInit())
99      return true;
100  }
101  else if (TypedefNameDecl* TD = dyn_cast<TypedefNameDecl>(D)) {
102    if (const VariableArrayType* VAPtr =
103        FindVA(TD->getUnderlyingType().getTypePtr())) {
104      setVAPtr(VAPtr);
105      return true;
106    }
107  }
108  else if (EnumConstantDecl* ECD = dyn_cast<EnumConstantDecl>(D)) {
109    if (ECD->getInitExpr())
110      return true;
111  }
112
113  return false;
114}
115
116StmtIteratorBase::StmtIteratorBase(Decl *d, Stmt **s)
117  : stmt(s), decl(d), RawVAPtr(d ? DeclMode : 0) {
118  if (decl)
119    NextDecl(false);
120}
121
122StmtIteratorBase::StmtIteratorBase(Decl** dgi, Decl** dge)
123  : stmt(0), DGI(dgi), RawVAPtr(DeclGroupMode), DGE(dge) {
124  NextDecl(false);
125}
126
127StmtIteratorBase::StmtIteratorBase(const VariableArrayType* t)
128  : stmt(0), decl(0), RawVAPtr(SizeOfTypeVAMode) {
129  RawVAPtr |= reinterpret_cast<uintptr_t>(t);
130}
131
132Stmt*& StmtIteratorBase::GetDeclExpr() const {
133
134  if (const VariableArrayType* VAPtr = getVAPtr()) {
135    assert (VAPtr->SizeExpr);
136    return const_cast<Stmt*&>(VAPtr->SizeExpr);
137  }
138
139  assert (inDecl() || inDeclGroup());
140
141  if (inDeclGroup()) {
142    VarDecl* VD = cast<VarDecl>(*DGI);
143    return *VD->getInitAddress();
144  }
145
146  assert (inDecl());
147
148  if (VarDecl* VD = dyn_cast<VarDecl>(decl)) {
149    assert (VD->Init);
150    return *VD->getInitAddress();
151  }
152
153  EnumConstantDecl* ECD = cast<EnumConstantDecl>(decl);
154  return ECD->Init;
155}
156