]> granicus.if.org Git - clang/commitdiff
Introduce FunctionDecl::getLatestDeclaration() and VarDecl::getLatestDeclaration().
authorArgyrios Kyrtzidis <akyrtzi@gmail.com>
Tue, 14 Jul 2009 03:20:08 +0000 (03:20 +0000)
committerArgyrios Kyrtzidis <akyrtzi@gmail.com>
Tue, 14 Jul 2009 03:20:08 +0000 (03:20 +0000)
For multiple redeclarations they return the last one.

Also, add some non const versions of methods.

git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@75603 91177308-0d34-0410-b5e6-96231b3b80d8

include/clang/AST/Decl.h
lib/AST/Decl.cpp

index e83833f7d941f20735fb38c2002830997c26f652..7f121ba083d28e09b26473b13b3f83f2df711d75 100644 (file)
@@ -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<VarDecl *, 1> 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<VarDecl *>(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<VarDecl *>(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); // <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
@@ -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<FunctionDecl *>(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<FunctionDecl *>(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);
 
index 5ef0c090936455bad98472c08adbd8e997f118d2..ae1df920125dc66ff2a2851d3e918b63e3fe2f66 100644 (file)
@@ -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();