From 0736c5ca3b6d98d0b2d9df76e6e6c98c8ea45938 Mon Sep 17 00:00:00 2001 From: Argyrios Kyrtzidis Date: Tue, 14 Jul 2009 03:20:08 +0000 Subject: [PATCH] Introduce FunctionDecl::getLatestDeclaration() and VarDecl::getLatestDeclaration(). For multiple redeclarations they return the last one. Also, add some non const versions of methods. llvm-svn: 75603 --- clang/include/clang/AST/Decl.h | 75 ++++++++++++++++++++++++++-------- clang/lib/AST/Decl.cpp | 46 +++++++++++++++++---- 2 files changed, 96 insertions(+), 25 deletions(-) diff --git a/clang/include/clang/AST/Decl.h b/clang/include/clang/AST/Decl.h index e83833f7d941..7f121ba083d2 100644 --- a/clang/include/clang/AST/Decl.h +++ b/clang/include/clang/AST/Decl.h @@ -248,7 +248,11 @@ private: bool DeclaredInCondition : 1; /// \brief The previous declaration of this variable. - VarDecl *PreviousDeclaration; + /// + /// 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 PreviousDeclaration; // Move to DeclGroup when it is implemented. SourceLocation TypeSpecStartLoc; @@ -258,7 +262,7 @@ protected: QualType T, StorageClass SC, SourceLocation TSSL = SourceLocation()) : ValueDecl(DK, DC, L, Id, T), Init(), ThreadSpecified(false), HasCXXDirectInit(false), - DeclaredInCondition(false), PreviousDeclaration(0), + DeclaredInCondition(false), PreviousDeclaration(this, 1), TypeSpecStartLoc(TSSL) { SClass = SC; } @@ -406,16 +410,32 @@ public: } /// getPreviousDeclaration - Return the previous declaration of this - /// variable. - const VarDecl *getPreviousDeclaration() const { return PreviousDeclaration; } - - void setPreviousDeclaration(VarDecl *PrevDecl) { - PreviousDeclaration = PrevDecl; + /// 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(this)->getPreviousDeclaration(); + } + + void setPreviousDeclaration(VarDecl *PrevDecl); /// \brief For multiple redeclarations returns the first one, otherwise /// returns itself. - const VarDecl *getFirstDeclaration() const; + VarDecl *getFirstDeclaration(); + const VarDecl *getFirstDeclaration() const { + return const_cast(this)->getFirstDeclaration(); + } + + /// \brief For multiple redeclarations returns the latest, otherwise + /// returns itself. + const VarDecl *getLatestDeclaration() const { + const VarDecl *First = getFirstDeclaration(); + assert(First->PreviousDeclaration.getInt() == 1 && "Expected first"); + return First->PreviousDeclaration.getPointer(); + } virtual Decl *getPrimaryDecl() const; @@ -642,16 +662,19 @@ private: LazyDeclStmtPtr Body; - /// PreviousDeclaration - A link to the previous declaration of this - /// same function, NULL if this is the first declaration. For + /// 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. /// - /// int f(int x, int y = 1); - /// int f(int x = 0, int y); - /// int f(int x, int y) { return x + y; } - FunctionDecl *PreviousDeclaration; + /// #1 int f(int x, int y = 1); // + /// #2 int f(int x = 0, int y); // + /// #3 int f(int x, int y) { return x + y; } // + /// + /// If there is only one declaration, it is + llvm::PointerIntPair PreviousDeclaration; // FIXME: This can be packed into the bitfields in Decl. // NOTE: VC++ treats enums as signed, avoid using the StorageClass enum @@ -699,7 +722,7 @@ protected: SourceLocation TSSL = SourceLocation()) : ValueDecl(DK, DC, L, N, T), DeclContext(DK), - ParamInfo(0), Body(), PreviousDeclaration(0), + ParamInfo(0), Body(), PreviousDeclaration(this, 1), SClass(S), IsInline(isInline), C99InlineDefinition(false), IsVirtualAsWritten(false), IsPure(false), HasInheritedPrototype(false), HasWrittenPrototype(true), IsDeleted(false), TypeSpecStartLoc(TSSL), @@ -810,14 +833,30 @@ public: bool isGlobal() const; /// getPreviousDeclaration - Return the previous declaration of this - /// function. + /// 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 PreviousDeclaration; + return const_cast(this)->getPreviousDeclaration(); } /// \brief For multiple redeclarations returns the first one, otherwise /// returns itself. - const FunctionDecl *getFirstDeclaration() const; + FunctionDecl *getFirstDeclaration(); + const FunctionDecl *getFirstDeclaration() const { + return const_cast(this)->getFirstDeclaration(); + } + + /// \brief For multiple redeclarations returns the latest, otherwise + /// returns itself. + const FunctionDecl *getLatestDeclaration() const { + const FunctionDecl *First = getFirstDeclaration(); + assert(First->PreviousDeclaration.getInt() == 1 && "Expected first"); + return First->PreviousDeclaration.getPointer(); + } void setPreviousDeclaration(FunctionDecl * PrevDecl); diff --git a/clang/lib/AST/Decl.cpp b/clang/lib/AST/Decl.cpp index 5ef0c0909364..ae1df920125d 100644 --- a/clang/lib/AST/Decl.cpp +++ b/clang/lib/AST/Decl.cpp @@ -358,8 +358,25 @@ const Expr *VarDecl::getDefinition(const VarDecl *&Def) const { return Def? Def->getInit() : 0; } -const VarDecl *VarDecl::getFirstDeclaration() const { - const VarDecl *First = this; +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. + VarDecl *First = PrevDecl->getFirstDeclaration(); + assert(First->PreviousDeclaration.getInt() == 1 && "Expected first"); + First->PreviousDeclaration.setPointer(this); + } else { + // This is first. + PreviousDeclaration.setPointer(this); + PreviousDeclaration.setInt(1); + } +} + +VarDecl *VarDecl::getFirstDeclaration() { + VarDecl *First = this; while (First->getPreviousDeclaration()) First = First->getPreviousDeclaration(); @@ -388,7 +405,8 @@ void FunctionDecl::Destroy(ASTContext& C) { Stmt *FunctionDecl::getBody(const FunctionDecl *&Definition) const { - for (const FunctionDecl *FD = this; FD != 0; FD = FD->PreviousDeclaration) { + for (const FunctionDecl *FD = this; + FD != 0; FD = FD->getPreviousDeclaration()) { if (FD->Body) { Definition = FD; return FD->Body.get(getASTContext().getExternalSource()); @@ -399,7 +417,8 @@ Stmt *FunctionDecl::getBody(const FunctionDecl *&Definition) const { } Stmt *FunctionDecl::getBodyIfAvailable() const { - for (const FunctionDecl *FD = this; FD != 0; FD = FD->PreviousDeclaration) { + for (const FunctionDecl *FD = this; + FD != 0; FD = FD->getPreviousDeclaration()) { if (FD->Body && !FD->Body.isOffset()) { return FD->Body.get(0); } @@ -571,7 +590,20 @@ bool FunctionDecl::isExternGNUInline(ASTContext &Context) const { void FunctionDecl::setPreviousDeclaration(FunctionDecl *PrevDecl) { - PreviousDeclaration = PrevDecl; + if (PrevDecl) { + // Point to previous. + PreviousDeclaration.setPointer(PrevDecl); + PreviousDeclaration.setInt(0); + + // First one will point to this one as latest. + FunctionDecl *First = PrevDecl->getFirstDeclaration(); + assert(First->PreviousDeclaration.getInt() == 1 && "Expected first"); + First->PreviousDeclaration.setPointer(this); + } else { + // This is first. + PreviousDeclaration.setPointer(this); + PreviousDeclaration.setInt(1); + } if (FunctionTemplateDecl *FunTmpl = getDescribedFunctionTemplate()) { FunctionTemplateDecl *PrevFunTmpl @@ -581,8 +613,8 @@ FunctionDecl::setPreviousDeclaration(FunctionDecl *PrevDecl) { } } -const FunctionDecl *FunctionDecl::getFirstDeclaration() const { - const FunctionDecl *First = this; +FunctionDecl *FunctionDecl::getFirstDeclaration() { + FunctionDecl *First = this; while (First->getPreviousDeclaration()) First = First->getPreviousDeclaration();