[cfe-commits] r75604 - in /cfe/trunk: include/clang/AST/Decl.h lib/AST/Decl.cpp
Argiris Kirtzidis
akyrtzi at gmail.com
Mon Jul 13 20:20:22 PDT 2009
Author: akirtzidis
Date: Mon Jul 13 22:20:21 2009
New Revision: 75604
URL: http://llvm.org/viewvc/llvm-project?rev=75604&view=rev
Log:
Introduce redecl_iterator, used for iterating over the redeclarations of a FunctionDecl or VarDecl.
It iterates over all the redeclarations, regardless of the starting point. For example:
1) int f();
2) int f();
3) int f();
if you have the (2) FunctionDecl and call redecls_begin/redecls_end to iterate, you'll get this sequence:
(2)
(1)
(3)
The motivation to introduce this was that, previously, if (3) was a function definition,
and you called getBody() at (2), it would not return it, since getBody() iterated over the previous declarations only,
so it would only check (2) and (1).
Modified:
cfe/trunk/include/clang/AST/Decl.h
cfe/trunk/lib/AST/Decl.cpp
Modified: cfe/trunk/include/clang/AST/Decl.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/AST/Decl.h?rev=75604&r1=75603&r2=75604&view=diff
==============================================================================
--- cfe/trunk/include/clang/AST/Decl.h (original)
+++ cfe/trunk/include/clang/AST/Decl.h Mon Jul 13 22:20:21 2009
@@ -439,6 +439,54 @@
virtual Decl *getPrimaryDecl() const;
+ /// \brief Iterates through all the redeclarations of the same var decl.
+ class redecl_iterator {
+ /// Current - The current declaration.
+ VarDecl *Current;
+ VarDecl *Starter;
+
+ public:
+ typedef VarDecl* value_type;
+ typedef VarDecl* reference;
+ typedef VarDecl* pointer;
+ typedef std::forward_iterator_tag iterator_category;
+ typedef std::ptrdiff_t difference_type;
+
+ redecl_iterator() : Current(0) { }
+ explicit redecl_iterator(VarDecl *C) : Current(C), Starter(C) { }
+
+ reference operator*() const { return Current; }
+ pointer operator->() const { return Current; }
+
+ redecl_iterator& operator++() {
+ assert(Current && "Advancing while iterator has reached end");
+ // Get either previous decl or latest decl.
+ VarDecl *Next = Current->PreviousDeclaration.getPointer();
+ Current = (Next != Starter ? Next : 0);
+ return *this;
+ }
+
+ redecl_iterator operator++(int) {
+ redecl_iterator tmp(*this);
+ ++(*this);
+ return tmp;
+ }
+
+ friend bool operator==(redecl_iterator x, redecl_iterator y) {
+ return x.Current == y.Current;
+ }
+ friend bool operator!=(redecl_iterator x, redecl_iterator y) {
+ return x.Current != y.Current;
+ }
+ };
+
+ /// \brief Returns iterator for all the redeclarations of the same variable.
+ /// It will iterate at least once (when this decl is the only one).
+ redecl_iterator redecls_begin() const {
+ return redecl_iterator(const_cast<VarDecl*>(this));
+ }
+ redecl_iterator redecls_end() const { return redecl_iterator(); }
+
/// hasLocalStorage - Returns true if a variable with function scope
/// is a non-static local variable.
bool hasLocalStorage() const {
@@ -862,6 +910,54 @@
virtual Decl *getPrimaryDecl() const;
+ /// \brief Iterates through all the redeclarations of the same function decl.
+ class redecl_iterator {
+ /// Current - The current declaration.
+ FunctionDecl *Current;
+ FunctionDecl *Starter;
+
+ public:
+ typedef FunctionDecl* value_type;
+ typedef FunctionDecl* reference;
+ typedef FunctionDecl* pointer;
+ typedef std::forward_iterator_tag iterator_category;
+ typedef std::ptrdiff_t difference_type;
+
+ redecl_iterator() : Current(0) { }
+ explicit redecl_iterator(FunctionDecl *C) : Current(C), Starter(C) { }
+
+ reference operator*() const { return Current; }
+ pointer operator->() const { return Current; }
+
+ redecl_iterator& operator++() {
+ assert(Current && "Advancing while iterator has reached end");
+ // Get either previous decl or latest decl.
+ FunctionDecl *Next = Current->PreviousDeclaration.getPointer();
+ Current = (Next != Starter ? Next : 0);
+ return *this;
+ }
+
+ redecl_iterator operator++(int) {
+ redecl_iterator tmp(*this);
+ ++(*this);
+ return tmp;
+ }
+
+ friend bool operator==(redecl_iterator x, redecl_iterator y) {
+ return x.Current == y.Current;
+ }
+ friend bool operator!=(redecl_iterator x, redecl_iterator y) {
+ return x.Current != y.Current;
+ }
+ };
+
+ /// \brief Returns iterator for all the redeclarations of the same function
+ /// decl. It will iterate at least once (when this decl is the only one).
+ redecl_iterator redecls_begin() const {
+ return redecl_iterator(const_cast<FunctionDecl*>(this));
+ }
+ redecl_iterator redecls_end() const { return redecl_iterator(); }
+
unsigned getBuiltinID(ASTContext &Context) const;
unsigned getNumParmVarDeclsFromType() const;
Modified: cfe/trunk/lib/AST/Decl.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/AST/Decl.cpp?rev=75604&r1=75603&r2=75604&view=diff
==============================================================================
--- cfe/trunk/lib/AST/Decl.cpp (original)
+++ cfe/trunk/lib/AST/Decl.cpp Mon Jul 13 22:20:21 2009
@@ -351,11 +351,15 @@
}
const Expr *VarDecl::getDefinition(const VarDecl *&Def) const {
- Def = this;
- while (Def && !Def->getInit())
- Def = Def->getPreviousDeclaration();
-
- return Def? Def->getInit() : 0;
+ redecl_iterator I = redecls_begin(), E = redecls_end();
+ while (I != E && !I->getInit())
+ ++I;
+
+ if (I != E) {
+ Def = *I;
+ return I->getInit();
+ }
+ return 0;
}
void VarDecl::setPreviousDeclaration(VarDecl *PrevDecl) {
@@ -405,11 +409,10 @@
Stmt *FunctionDecl::getBody(const FunctionDecl *&Definition) const {
- for (const FunctionDecl *FD = this;
- FD != 0; FD = FD->getPreviousDeclaration()) {
- if (FD->Body) {
- Definition = FD;
- return FD->Body.get(getASTContext().getExternalSource());
+ for (redecl_iterator I = redecls_begin(), E = redecls_end(); I != E; ++I) {
+ if (I->Body) {
+ Definition = *I;
+ return I->Body.get(getASTContext().getExternalSource());
}
}
@@ -417,10 +420,9 @@
}
Stmt *FunctionDecl::getBodyIfAvailable() const {
- for (const FunctionDecl *FD = this;
- FD != 0; FD = FD->getPreviousDeclaration()) {
- if (FD->Body && !FD->Body.isOffset()) {
- return FD->Body.get(0);
+ for (redecl_iterator I = redecls_begin(), E = redecls_end(); I != E; ++I) {
+ if (I->Body && !I->Body.isOffset()) {
+ return I->Body.get(0);
}
}
@@ -568,11 +570,9 @@
if (!isInline() || !hasAttr<GNUInlineAttr>())
return false;
- for (const FunctionDecl *FD = getPreviousDeclaration(); FD;
- FD = FD->getPreviousDeclaration()) {
- if (FD->isInline() && !FD->hasAttr<GNUInlineAttr>())
+ for (redecl_iterator I = redecls_begin(), E = redecls_end(); I != E; ++I)
+ if (I->isInline() && !I->hasAttr<GNUInlineAttr>())
return false;
- }
return true;
}
@@ -581,8 +581,8 @@
if (!hasActiveGNUInlineAttribute(Context))
return false;
- for (const FunctionDecl *FD = this; FD; FD = FD->getPreviousDeclaration())
- if (FD->getStorageClass() == Extern && FD->hasAttr<GNUInlineAttr>())
+ for (redecl_iterator I = redecls_begin(), E = redecls_end(); I != E; ++I)
+ if (I->getStorageClass() == Extern && I->hasAttr<GNUInlineAttr>())
return true;
return false;
More information about the cfe-commits
mailing list