diff options
-rw-r--r-- | include/clang/AST/Decl.h | 152 | ||||
-rw-r--r-- | include/clang/AST/Redeclarable.h | 153 | ||||
-rw-r--r-- | lib/AST/Decl.cpp | 46 |
3 files changed, 163 insertions, 188 deletions
diff --git a/include/clang/AST/Decl.h b/include/clang/AST/Decl.h index e95f9bb11b..a6feec9179 100644 --- a/include/clang/AST/Decl.h +++ b/include/clang/AST/Decl.h @@ -16,6 +16,7 @@ #include "clang/AST/APValue.h" #include "clang/AST/DeclBase.h" +#include "clang/AST/Redeclarable.h" #include "clang/AST/DeclarationName.h" #include "clang/AST/ExternalASTSource.h" @@ -224,7 +225,7 @@ struct EvaluatedStmt { /// VarDecl - An instance of this class is created to represent a variable /// declaration or definition. -class VarDecl : public ValueDecl { +class VarDecl : public ValueDecl, public Redeclarable<VarDecl> { public: enum StorageClass { None, Auto, Register, Extern, Static, PrivateExtern @@ -247,13 +248,6 @@ private: /// condition, e.g., if (int x = foo()) { ... }. bool DeclaredInCondition : 1; - /// \brief The previous declaration of this variable. - /// - /// If the int part is 0, this is a link to the previous declaration. - /// If the int part is 1, this is the first declaration and - /// PreviousDeclaration points to the latest declaration. - llvm::PointerIntPair<VarDecl *, 1> PreviousDeclaration; - // Move to DeclGroup when it is implemented. SourceLocation TypeSpecStartLoc; friend class StmtIteratorBase; @@ -262,8 +256,7 @@ protected: QualType T, StorageClass SC, SourceLocation TSSL = SourceLocation()) : ValueDecl(DK, DC, L, Id, T), Init(), ThreadSpecified(false), HasCXXDirectInit(false), - DeclaredInCondition(false), PreviousDeclaration(this, 1), - TypeSpecStartLoc(TSSL) { + DeclaredInCondition(false), TypeSpecStartLoc(TSSL) { SClass = SC; } public: @@ -409,69 +402,8 @@ public: DeclaredInCondition = InCondition; } - /// getPreviousDeclaration - Return the previous declaration of this - /// variable or NULL if this is the first declaration. - VarDecl *getPreviousDeclaration() { - if (PreviousDeclaration.getInt() == 0) - return PreviousDeclaration.getPointer(); - return 0; - } - const VarDecl *getPreviousDeclaration() const { - return const_cast<VarDecl *>(this)->getPreviousDeclaration(); - } - - void setPreviousDeclaration(VarDecl *PrevDecl); - virtual VarDecl *getCanonicalDecl(); - /// \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 { @@ -681,7 +613,8 @@ public: /// contains all of the information known about the function. Other, /// previous declarations of the function are available via the /// getPreviousDeclaration() chain. -class FunctionDecl : public ValueDecl, public DeclContext { +class FunctionDecl : public ValueDecl, public DeclContext, + public Redeclarable<FunctionDecl> { public: enum StorageClass { None, Extern, Static, PrivateExtern @@ -694,20 +627,6 @@ private: ParmVarDecl **ParamInfo; LazyDeclStmtPtr Body; - - /// PreviousDeclaration - If the int part is 0, this is a link to the previous - /// declaration of this same function. If the int part is 1, this is the first - /// declaration and PreviousDeclaration points to the latest declaration. For - /// example, in the following code, the PreviousDeclaration can be - /// traversed several times to see all three declarations of the - /// function "f", the last of which is also a definition. - /// - /// #1 int f(int x, int y = 1); // <pointer to #3, 1> - /// #2 int f(int x = 0, int y); // <pointer to #1, 0> - /// #3 int f(int x, int y) { return x + y; } // <pointer to #2, 0> - /// - /// If there is only one declaration, it is <pointer to self, 1> - llvm::PointerIntPair<FunctionDecl *, 1> PreviousDeclaration; // FIXME: This can be packed into the bitfields in Decl. // NOTE: VC++ treats enums as signed, avoid using the StorageClass enum @@ -755,7 +674,7 @@ protected: SourceLocation TSSL = SourceLocation()) : ValueDecl(DK, DC, L, N, T), DeclContext(DK), - ParamInfo(0), Body(), PreviousDeclaration(this, 1), + ParamInfo(0), Body(), SClass(S), IsInline(isInline), C99InlineDefinition(false), IsVirtualAsWritten(false), IsPure(false), HasInheritedPrototype(false), HasWrittenPrototype(true), IsDeleted(false), TypeSpecStartLoc(TSSL), @@ -865,69 +784,10 @@ public: /// \brief Determines whether this is a global function. bool isGlobal() const; - /// getPreviousDeclaration - Return the previous declaration of this - /// function or NULL if this is the first declaration. - FunctionDecl *getPreviousDeclaration() { - if (PreviousDeclaration.getInt() == 0) - return PreviousDeclaration.getPointer(); - return 0; - } - const FunctionDecl *getPreviousDeclaration() const { - return const_cast<FunctionDecl *>(this)->getPreviousDeclaration(); - } - void setPreviousDeclaration(FunctionDecl * PrevDecl); virtual FunctionDecl *getCanonicalDecl(); - /// \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; diff --git a/include/clang/AST/Redeclarable.h b/include/clang/AST/Redeclarable.h new file mode 100644 index 0000000000..ea36353bf2 --- /dev/null +++ b/include/clang/AST/Redeclarable.h @@ -0,0 +1,153 @@ +//===-- Redeclarable.h - Base for Decls that can be redeclared -*- C++ -*-====// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file defines the Redeclarable interface. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_CLANG_AST_REDECLARABLE_H +#define LLVM_CLANG_AST_REDECLARABLE_H + +#include "llvm/ADT/PointerIntPair.h" + +namespace clang { + +/// \brief Provides common interface for the Decls that can be redeclared. +template<typename decl_type> +class Redeclarable { + +protected: + struct DeclLink : public llvm::PointerIntPair<decl_type *, 1, bool> { + DeclLink(decl_type *D, bool isLatest) + : llvm::PointerIntPair<decl_type *, 1, bool>(D, isLatest) { } + + typedef llvm::PointerIntPair<decl_type *, 1, bool> base_type; + + bool NextIsPrevious() const { return base_type::getInt() == false; } + bool NextIsLatest() const { return base_type::getInt() == true; } + decl_type *getNext() const { return base_type::getPointer(); } + }; + + struct PreviousDeclLink : public DeclLink { + PreviousDeclLink(decl_type *D) : DeclLink(D, false) { } + }; + + struct LatestDeclLink : public DeclLink { + LatestDeclLink(decl_type *D) : DeclLink(D, true) { } + }; + + /// \brief Points to the next redeclaration in the chain. + /// + /// If NextIsPrevious() is true, this is a link to the previous declaration + /// of this same Decl. If NextIsLatest() is true, this is the first + /// declaration and Link points to the latest declaration. For example: + /// + /// #1 int f(int x, int y = 1); // <pointer to #3, true> + /// #2 int f(int x = 0, int y); // <pointer to #1, false> + /// #3 int f(int x, int y) { return x + y; } // <pointer to #2, false> + /// + /// If there is only one declaration, it is <pointer to self, true> + DeclLink RedeclLink; + +public: + Redeclarable() : RedeclLink(LatestDeclLink(static_cast<decl_type*>(this))) { } + + /// \brief Return the previous declaration of this declaration or NULL if this + /// is the first declaration. + decl_type *getPreviousDeclaration() { + if (RedeclLink.NextIsPrevious()) + return RedeclLink.getNext(); + return 0; + } + const decl_type *getPreviousDeclaration() const { + return const_cast<decl_type *>( + static_cast<const decl_type*>(this))->getPreviousDeclaration(); + } + + /// \brief Return the first declaration of this declaration or itself if this + /// is the only declaration. + decl_type *getFirstDeclaration() { + decl_type *D = static_cast<decl_type*>(this); + while (D->getPreviousDeclaration()) + D = D->getPreviousDeclaration(); + return D; + } + + /// \brief Set the previous declaration. If PrevDecl is NULL, set this as the + /// first and only declaration. + void setPreviousDeclaration(decl_type *PrevDecl) { + decl_type *First; + + if (PrevDecl) { + // Point to previous. + RedeclLink = PreviousDeclLink(PrevDecl); + First = PrevDecl->getFirstDeclaration(); + assert(First->RedeclLink.NextIsLatest() && "Expected first"); + } else { + // Make this first. + First = static_cast<decl_type*>(this); + } + + // First one will point to this one as latest. + First->RedeclLink = LatestDeclLink(static_cast<decl_type*>(this)); + } + + /// \brief Iterates through all the redeclarations of the same decl. + class redecl_iterator { + /// Current - The current declaration. + decl_type *Current; + decl_type *Starter; + + public: + typedef decl_type* value_type; + typedef decl_type* reference; + typedef decl_type* pointer; + typedef std::forward_iterator_tag iterator_category; + typedef std::ptrdiff_t difference_type; + + redecl_iterator() : Current(0) { } + explicit redecl_iterator(decl_type *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. + decl_type *Next = Current->RedeclLink.getNext(); + 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 decl. + /// It will iterate at least once (when this decl is the only one). + redecl_iterator redecls_begin() const { + return redecl_iterator(const_cast<decl_type*>( + static_cast<const decl_type*>(this))); + } + redecl_iterator redecls_end() const { return redecl_iterator(); } +}; + +} + +#endif diff --git a/lib/AST/Decl.cpp b/lib/AST/Decl.cpp index 23782d6223..e59d632f90 100644 --- a/lib/AST/Decl.cpp +++ b/lib/AST/Decl.cpp @@ -362,29 +362,8 @@ const Expr *VarDecl::getDefinition(const VarDecl *&Def) const { return 0; } -void VarDecl::setPreviousDeclaration(VarDecl *PrevDecl) { - if (PrevDecl) { - // Point to previous. - PreviousDeclaration.setPointer(PrevDecl); - PreviousDeclaration.setInt(0); - - // First one will point to this one as latest. - // getCanonicalDecl returns the first one. - VarDecl *First = PrevDecl->getCanonicalDecl(); - assert(First->PreviousDeclaration.getInt() == 1 && "Expected first"); - First->PreviousDeclaration.setPointer(this); - } else { - // This is first. - PreviousDeclaration.setPointer(this); - PreviousDeclaration.setInt(1); - } -} - VarDecl *VarDecl::getCanonicalDecl() { - VarDecl *Var = this; - while (Var->getPreviousDeclaration()) - Var = Var->getPreviousDeclaration(); - return Var; + return getFirstDeclaration(); } //===----------------------------------------------------------------------===// @@ -586,22 +565,8 @@ bool FunctionDecl::isExternGNUInline(ASTContext &Context) const { void FunctionDecl::setPreviousDeclaration(FunctionDecl *PrevDecl) { - if (PrevDecl) { - // Point to previous. - PreviousDeclaration.setPointer(PrevDecl); - PreviousDeclaration.setInt(0); - - // First one will point to this one as latest. - // getCanonicalDecl returns the first one. - FunctionDecl *First = PrevDecl->getCanonicalDecl(); - assert(First->PreviousDeclaration.getInt() == 1 && "Expected first"); - First->PreviousDeclaration.setPointer(this); - } else { - // This is first. - PreviousDeclaration.setPointer(this); - PreviousDeclaration.setInt(1); - } - + Redeclarable<FunctionDecl>::setPreviousDeclaration(PrevDecl); + if (FunctionTemplateDecl *FunTmpl = getDescribedFunctionTemplate()) { FunctionTemplateDecl *PrevFunTmpl = PrevDecl? PrevDecl->getDescribedFunctionTemplate() : 0; @@ -611,10 +576,7 @@ FunctionDecl::setPreviousDeclaration(FunctionDecl *PrevDecl) { } FunctionDecl *FunctionDecl::getCanonicalDecl() { - FunctionDecl *FD = this; - while (FD->getPreviousDeclaration()) - FD = FD->getPreviousDeclaration(); - return FD; + return getFirstDeclaration(); } /// getOverloadedOperator - Which C++ overloaded operator this |