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 (inDeclGroup()) {
44    if (VarDecl* VD = dyn_cast<VarDecl>(*DGI))
45      if (VD->Init)
46        return;
47
48    NextDecl();
49  }
50  else {
51    assert(inSizeOfTypeVA());
52    RawVAPtr = 0;
53  }
54}
55
56void StmtIteratorBase::NextDecl(bool ImmediateAdvance) {
57  assert (getVAPtr() == NULL);
58  assert(inDeclGroup());
59
60  if (ImmediateAdvance)
61    ++DGI;
62
63  for ( ; DGI != DGE; ++DGI)
64    if (HandleDecl(*DGI))
65      return;
66
67  RawVAPtr = 0;
68}
69
70bool StmtIteratorBase::HandleDecl(Decl* D) {
71  if (VarDecl* VD = dyn_cast<VarDecl>(D)) {
72    if (const VariableArrayType* VAPtr = FindVA(VD->getType().getTypePtr())) {
73      setVAPtr(VAPtr);
74      return true;
75    }
76
77    if (VD->getInit())
78      return true;
79  }
80  else if (TypedefNameDecl* TD = dyn_cast<TypedefNameDecl>(D)) {
81    if (const VariableArrayType* VAPtr =
82        FindVA(TD->getUnderlyingType().getTypePtr())) {
83      setVAPtr(VAPtr);
84      return true;
85    }
86  }
87  else if (EnumConstantDecl* ECD = dyn_cast<EnumConstantDecl>(D)) {
88    if (ECD->getInitExpr())
89      return true;
90  }
91
92  return false;
93}
94
95StmtIteratorBase::StmtIteratorBase(Decl** dgi, Decl** dge)
96  : stmt(0), DGI(dgi), RawVAPtr(DeclGroupMode), DGE(dge) {
97  NextDecl(false);
98}
99
100StmtIteratorBase::StmtIteratorBase(const VariableArrayType* t)
101  : stmt(0), DGI(0), RawVAPtr(SizeOfTypeVAMode) {
102  RawVAPtr |= reinterpret_cast<uintptr_t>(t);
103}
104
105Stmt*& StmtIteratorBase::GetDeclExpr() const {
106  if (const VariableArrayType* VAPtr = getVAPtr()) {
107    assert (VAPtr->SizeExpr);
108    return const_cast<Stmt*&>(VAPtr->SizeExpr);
109  }
110
111  assert (inDeclGroup());
112  VarDecl* VD = cast<VarDecl>(*DGI);
113  return *VD->getInitAddress();
114}
115