From: Ted Kremenek Date: Fri, 14 Dec 2007 22:52:23 +0000 (+0000) Subject: Added support to StmtIterator to traverse the size expression of a VLA type X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=699e9fbeae34cdd651b8e6308649c8939f090cbd;p=clang Added support to StmtIterator to traverse the size expression of a VLA type declared in a sizeof. For example: sizeof(int[foo()]); the expression "foo()" is an expression that is executed during the evaluation of sizeof. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@45043 91177308-0d34-0410-b5e6-96231b3b80d8 --- diff --git a/AST/Expr.cpp b/AST/Expr.cpp index 11aef7f7d0..22767053db 100644 --- a/AST/Expr.cpp +++ b/AST/Expr.cpp @@ -1036,10 +1036,15 @@ Stmt::child_iterator UnaryOperator::child_end() { // SizeOfAlignOfTypeExpr Stmt::child_iterator SizeOfAlignOfTypeExpr::child_begin() { - return child_iterator(); + // If the type is a VLA type (and not a typedef), the size expression of the + // VLA needs to be treated as an executable expression. + if (VariableArrayType* T = dyn_cast(Ty.getTypePtr())) + return child_iterator(T); + else + return child_iterator(); } Stmt::child_iterator SizeOfAlignOfTypeExpr::child_end() { - return child_iterator(); + return child_iterator(); } // ArraySubscriptExpr diff --git a/AST/StmtIterator.cpp b/AST/StmtIterator.cpp index ae6de11e11..94a539770f 100644 --- a/AST/StmtIterator.cpp +++ b/AST/StmtIterator.cpp @@ -31,19 +31,21 @@ static inline VariableArrayType* FindVA(Type* t) { void StmtIteratorBase::NextVA() { assert (getVAPtr()); - assert (decl); VariableArrayType* p = getVAPtr(); p = FindVA(p->getElementType().getTypePtr()); setVAPtr(p); - if (!p) { + if (!p && decl) { if (VarDecl* VD = dyn_cast(decl)) if (VD->Init) return; NextDecl(); } + else { + RawVAPtr = 0; + } } void StmtIteratorBase::NextDecl(bool ImmediateAdvance) { @@ -94,6 +96,12 @@ StmtIteratorBase::StmtIteratorBase(ScopedDecl* d) NextDecl(false); } +StmtIteratorBase::StmtIteratorBase(VariableArrayType* t) +: decl(NULL), RawVAPtr(VASizeMode) { + RawVAPtr |= reinterpret_cast(t); +} + + Stmt*& StmtIteratorBase::GetDeclExpr() const { if (VariableArrayType* VAPtr = getVAPtr()) { assert (VAPtr->SizeExpr); diff --git a/include/clang/AST/StmtIterator.h b/include/clang/AST/StmtIterator.h index 207e4edc9f..cd097c2903 100644 --- a/include/clang/AST/StmtIterator.h +++ b/include/clang/AST/StmtIterator.h @@ -25,21 +25,21 @@ class VariableArrayType; class StmtIteratorBase { protected: - enum { DeclMode = 0x1 }; + enum { DeclMode = 0x1, VASizeMode = 0x2, Flags = 0x3 }; union { Stmt** stmt; ScopedDecl* decl; }; uintptr_t RawVAPtr; - bool inDeclMode() const { - return RawVAPtr & DeclMode ? true : false; - } + bool inDeclMode() const { return RawVAPtr & DeclMode ? true : false; } + bool inVASizeMode() const { return RawVAPtr & VASizeMode ? true : false; } + bool hasFlags() const { return RawVAPtr & Flags ? true : false; } VariableArrayType* getVAPtr() const { - return reinterpret_cast(RawVAPtr & ~DeclMode); + return reinterpret_cast(RawVAPtr & ~Flags); } void setVAPtr(VariableArrayType* P) { - assert (inDeclMode()); - RawVAPtr = reinterpret_cast(P) | DeclMode; + assert (inDeclMode() || inVASizeMode()); + RawVAPtr = reinterpret_cast(P) | (RawVAPtr & Flags); } void NextDecl(bool ImmediateAdvance = true); @@ -49,6 +49,7 @@ protected: StmtIteratorBase(Stmt** s) : stmt(s), RawVAPtr(0) {} StmtIteratorBase(ScopedDecl* d); + StmtIteratorBase(VariableArrayType* t); StmtIteratorBase() : stmt(NULL), RawVAPtr(0) {} }; @@ -64,14 +65,17 @@ public: StmtIteratorImpl() {} StmtIteratorImpl(Stmt** s) : StmtIteratorBase(s) {} StmtIteratorImpl(ScopedDecl* d) : StmtIteratorBase(d) {} - + StmtIteratorImpl(VariableArrayType* t) : StmtIteratorBase(t) {} DERIVED& operator++() { if (inDeclMode()) { if (getVAPtr()) NextVA(); else NextDecl(); } - else ++stmt; + else if (inVASizeMode()) + NextVA(); + else + ++stmt; return static_cast(*this); } @@ -91,7 +95,7 @@ public: } REFERENCE operator*() const { - return (REFERENCE) (inDeclMode() ? GetDeclExpr() : *stmt); + return (REFERENCE) (hasFlags() ? GetDeclExpr() : *stmt); } REFERENCE operator->() const { return operator*(); } @@ -100,6 +104,7 @@ public: struct StmtIterator : public StmtIteratorImpl { explicit StmtIterator() : StmtIteratorImpl() {} StmtIterator(Stmt** S) : StmtIteratorImpl(S) {} + StmtIterator(VariableArrayType* t):StmtIteratorImpl(t) {} StmtIterator(ScopedDecl* D) : StmtIteratorImpl(D) {} }; @@ -107,7 +112,7 @@ struct ConstStmtIterator : public StmtIteratorImpl { explicit ConstStmtIterator() : StmtIteratorImpl() {} - + ConstStmtIterator(const StmtIterator& RHS) : StmtIteratorImpl(RHS) {} };