[cfe-commits] r118674 - in /cfe/trunk: include/clang/AST/DeclCXX.h lib/AST/DeclCXX.cpp lib/Serialization/ASTReaderDecl.cpp lib/Serialization/ASTWriterDecl.cpp test/Index/load-namespaces.cpp tools/libclang/CIndex.cpp

Argyrios Kyrtzidis akyrtzi at gmail.com
Tue Nov 9 21:40:41 PST 2010


Author: akirtzidis
Date: Tue Nov  9 23:40:41 2010
New Revision: 118674

URL: http://llvm.org/viewvc/llvm-project?rev=118674&view=rev
Log:
Replace UsingDecl's SmallPtrSet of UsingShadowDecls with a linked list to avoid leaking memory.
Fixes rdar://8649963.

Modified:
    cfe/trunk/include/clang/AST/DeclCXX.h
    cfe/trunk/lib/AST/DeclCXX.cpp
    cfe/trunk/lib/Serialization/ASTReaderDecl.cpp
    cfe/trunk/lib/Serialization/ASTWriterDecl.cpp
    cfe/trunk/test/Index/load-namespaces.cpp
    cfe/trunk/tools/libclang/CIndex.cpp

Modified: cfe/trunk/include/clang/AST/DeclCXX.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/AST/DeclCXX.h?rev=118674&r1=118673&r2=118674&view=diff
==============================================================================
--- cfe/trunk/include/clang/AST/DeclCXX.h (original)
+++ cfe/trunk/include/clang/AST/DeclCXX.h Tue Nov  9 23:40:41 2010
@@ -1881,13 +1881,16 @@
   /// The referenced declaration.
   NamedDecl *Underlying;
 
-  /// The using declaration which introduced this decl.
-  UsingDecl *Using;
+  /// \brief The using declaration which introduced this decl or the next using
+  /// shadow declaration contained in the aforementioned using declaration.
+  NamedDecl *UsingOrNextShadow;
+  friend class UsingDecl;
 
   UsingShadowDecl(DeclContext *DC, SourceLocation Loc, UsingDecl *Using,
                   NamedDecl *Target)
     : NamedDecl(UsingShadow, DC, Loc, DeclarationName()),
-      Underlying(Target), Using(Using) {
+      Underlying(Target),
+      UsingOrNextShadow(reinterpret_cast<NamedDecl *>(Using)) {
     if (Target) {
       setDeclName(Target->getDeclName());
       IdentifierNamespace = Target->getIdentifierNamespace();
@@ -1915,15 +1918,20 @@
   }
 
   /// \brief Gets the using declaration to which this declaration is tied.
-  UsingDecl *getUsingDecl() const { return Using; }
+  UsingDecl *getUsingDecl() const;
 
-  /// \brief Sets the using declaration that introduces this target
-  /// declaration.
-  void setUsingDecl(UsingDecl* UD) { Using = UD; }
+  /// \brief The next using shadow declaration contained in the shadow decl
+  /// chain of the using declaration which introduced this decl.
+  UsingShadowDecl *getNextUsingShadowDecl() const {
+    return dyn_cast_or_null<UsingShadowDecl>(UsingOrNextShadow);
+  }
 
   static bool classof(const Decl *D) { return classofKind(D->getKind()); }
   static bool classof(const UsingShadowDecl *D) { return true; }
   static bool classofKind(Kind K) { return K == Decl::UsingShadow; }
+
+  friend class ASTDeclReader;
+  friend class ASTDeclWriter;
 };
 
 /// UsingDecl - Represents a C++ using-declaration. For example:
@@ -1943,10 +1951,9 @@
   /// declaration name embedded in the ValueDecl base class.
   DeclarationNameLoc DNLoc;
 
-  /// \brief The collection of shadow declarations associated with
-  /// this using declaration.  This set can change as a class is
-  /// processed.
-  llvm::SmallPtrSet<UsingShadowDecl*, 8> Shadows;
+  /// \brief The first shadow declaration of the shadow decl chain associated
+  /// with this using declaration.
+  UsingShadowDecl *FirstUsingShadow;
 
   // \brief Has 'typename' keyword.
   bool IsTypeName;
@@ -1956,7 +1963,7 @@
             const DeclarationNameInfo &NameInfo, bool IsTypeNameArg)
     : NamedDecl(Using, DC, NameInfo.getLoc(), NameInfo.getName()),
       NestedNameRange(NNR), UsingLocation(UL), TargetNestedName(TargetNNS),
-      DNLoc(NameInfo.getInfo()), IsTypeName(IsTypeNameArg) {
+      DNLoc(NameInfo.getInfo()), FirstUsingShadow(0),IsTypeName(IsTypeNameArg) {
   }
 
 public:
@@ -1994,29 +2001,58 @@
   /// \brief Sets whether the using declaration has 'typename'.
   void setTypeName(bool TN) { IsTypeName = TN; }
 
-  typedef llvm::SmallPtrSet<UsingShadowDecl*,8>::const_iterator shadow_iterator;
-  shadow_iterator shadow_begin() const { return Shadows.begin(); }
-  shadow_iterator shadow_end() const { return Shadows.end(); }
-
-  void addShadowDecl(UsingShadowDecl *S) {
-    assert(S->getUsingDecl() == this);
-    if (!Shadows.insert(S)) {
-      assert(false && "declaration already in set");
+  /// \brief Iterates through the using shadow declarations assosiated with
+  /// this using declaration.
+  class shadow_iterator {
+    /// \brief The current using shadow declaration.
+    UsingShadowDecl *Current;
+
+  public:
+    typedef UsingShadowDecl*          value_type;
+    typedef UsingShadowDecl*          reference;
+    typedef UsingShadowDecl*          pointer;
+    typedef std::forward_iterator_tag iterator_category;
+    typedef std::ptrdiff_t            difference_type;
+
+    shadow_iterator() : Current(0) { }
+    explicit shadow_iterator(UsingShadowDecl *C) : Current(C) { }
+
+    reference operator*() const { return Current; }
+    pointer operator->() const { return Current; }
+
+    shadow_iterator& operator++() {
+      Current = Current->getNextUsingShadowDecl();
+      return *this;
     }
-  }
-  void removeShadowDecl(UsingShadowDecl *S) {
-    assert(S->getUsingDecl() == this);
-    if (!Shadows.erase(S)) {
-      assert(false && "declaration not in set");
+
+    shadow_iterator operator++(int) {
+      shadow_iterator tmp(*this);
+      ++(*this);
+      return tmp;
     }
+
+    friend bool operator==(shadow_iterator x, shadow_iterator y) {
+      return x.Current == y.Current;
+    }
+    friend bool operator!=(shadow_iterator x, shadow_iterator y) {
+      return x.Current != y.Current;
+    }
+  };
+
+  shadow_iterator shadow_begin() const {
+    return shadow_iterator(FirstUsingShadow);
   }
+  shadow_iterator shadow_end() const { return shadow_iterator(); }
 
   /// \brief Return the number of shadowed declarations associated with this
   /// using declaration.
-  unsigned getNumShadowDecls() const {
-    return Shadows.size();
+  unsigned shadow_size() const {
+    return std::distance(shadow_begin(), shadow_end());
   }
 
+  void addShadowDecl(UsingShadowDecl *S);
+  void removeShadowDecl(UsingShadowDecl *S);
+
   static UsingDecl *Create(ASTContext &C, DeclContext *DC,
                            SourceRange NNR, SourceLocation UsingL,
                            NestedNameSpecifier* TargetNNS,

Modified: cfe/trunk/lib/AST/DeclCXX.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/AST/DeclCXX.cpp?rev=118674&r1=118673&r2=118674&view=diff
==============================================================================
--- cfe/trunk/lib/AST/DeclCXX.cpp (original)
+++ cfe/trunk/lib/AST/DeclCXX.cpp Tue Nov  9 23:40:41 2010
@@ -1276,6 +1276,44 @@
                                     Qualifier, IdentLoc, Namespace);
 }
 
+UsingDecl *UsingShadowDecl::getUsingDecl() const {
+  const UsingShadowDecl *Shadow = this;
+  while (const UsingShadowDecl *NextShadow =
+         dyn_cast<UsingShadowDecl>(Shadow->UsingOrNextShadow))
+    Shadow = NextShadow;
+  return cast<UsingDecl>(Shadow->UsingOrNextShadow);
+}
+
+void UsingDecl::addShadowDecl(UsingShadowDecl *S) {
+  assert(std::find(shadow_begin(), shadow_end(), S) == shadow_end() &&
+         "declaration already in set");
+  assert(S->getUsingDecl() == this);
+
+  if (FirstUsingShadow)
+    S->UsingOrNextShadow = FirstUsingShadow;
+  FirstUsingShadow = S;
+}
+
+void UsingDecl::removeShadowDecl(UsingShadowDecl *S) {
+  assert(std::find(shadow_begin(), shadow_end(), S) != shadow_end() &&
+         "declaration not in set");
+  assert(S->getUsingDecl() == this);
+
+  // Remove S from the shadow decl chain. This is O(n) but hopefully rare.
+
+  if (FirstUsingShadow == S) {
+    FirstUsingShadow = dyn_cast<UsingShadowDecl>(S->UsingOrNextShadow);
+    S->UsingOrNextShadow = this;
+    return;
+  }
+
+  UsingShadowDecl *Prev = FirstUsingShadow;
+  while (Prev->UsingOrNextShadow != S)
+    Prev = cast<UsingShadowDecl>(Prev->UsingOrNextShadow);
+  Prev->UsingOrNextShadow = S->UsingOrNextShadow;
+  S->UsingOrNextShadow = this;
+}
+
 UsingDecl *UsingDecl::Create(ASTContext &C, DeclContext *DC,
                              SourceRange NNR, SourceLocation UL,
                              NestedNameSpecifier* TargetNNS,

Modified: cfe/trunk/lib/Serialization/ASTReaderDecl.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Serialization/ASTReaderDecl.cpp?rev=118674&r1=118673&r2=118674&view=diff
==============================================================================
--- cfe/trunk/lib/Serialization/ASTReaderDecl.cpp (original)
+++ cfe/trunk/lib/Serialization/ASTReaderDecl.cpp Tue Nov  9 23:40:41 2010
@@ -717,16 +717,7 @@
   D->setNestedNameRange(ReadSourceRange(Record, Idx));
   D->setTargetNestedNameDecl(Reader.ReadNestedNameSpecifier(Record, Idx));
   ReadDeclarationNameLoc(D->DNLoc, D->getDeclName(), Record, Idx);
-
-  // FIXME: It would probably be more efficient to read these into a vector
-  // and then re-cosntruct the shadow decl set over that vector since it
-  // would avoid existence checks.
-  unsigned NumShadows = Record[Idx++];
-  for(unsigned I = 0; I != NumShadows; ++I) {
-    // Avoid invariant checking of UsingDecl::addShadowDecl, the decl may still
-    // be initializing.
-    D->Shadows.insert(cast<UsingShadowDecl>(Reader.GetDecl(Record[Idx++])));
-  }
+  D->FirstUsingShadow = cast_or_null<UsingShadowDecl>(Reader.GetDecl(Record[Idx++]));
   D->setTypeName(Record[Idx++]);
   NamedDecl *Pattern = cast_or_null<NamedDecl>(Reader.GetDecl(Record[Idx++]));
   if (Pattern)
@@ -736,7 +727,7 @@
 void ASTDeclReader::VisitUsingShadowDecl(UsingShadowDecl *D) {
   VisitNamedDecl(D);
   D->setTargetDecl(cast<NamedDecl>(Reader.GetDecl(Record[Idx++])));
-  D->setUsingDecl(cast<UsingDecl>(Reader.GetDecl(Record[Idx++])));
+  D->UsingOrNextShadow = cast_or_null<NamedDecl>(Reader.GetDecl(Record[Idx++]));
   UsingShadowDecl *Pattern
       = cast_or_null<UsingShadowDecl>(Reader.GetDecl(Record[Idx++]));
   if (Pattern)

Modified: cfe/trunk/lib/Serialization/ASTWriterDecl.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Serialization/ASTWriterDecl.cpp?rev=118674&r1=118673&r2=118674&view=diff
==============================================================================
--- cfe/trunk/lib/Serialization/ASTWriterDecl.cpp (original)
+++ cfe/trunk/lib/Serialization/ASTWriterDecl.cpp Tue Nov  9 23:40:41 2010
@@ -673,10 +673,7 @@
   Writer.AddSourceLocation(D->getUsingLocation(), Record);
   Writer.AddNestedNameSpecifier(D->getTargetNestedNameDecl(), Record);
   Writer.AddDeclarationNameLoc(D->DNLoc, D->getDeclName(), Record);
-  Record.push_back(D->getNumShadowDecls());
-  for (UsingDecl::shadow_iterator P = D->shadow_begin(),
-       PEnd = D->shadow_end(); P != PEnd; ++P)
-    Writer.AddDeclRef(*P, Record);
+  Writer.AddDeclRef(D->FirstUsingShadow, Record);
   Record.push_back(D->isTypeName());
   Writer.AddDeclRef(Context.getInstantiatedFromUsingDecl(D), Record);
   Code = serialization::DECL_USING;
@@ -685,7 +682,7 @@
 void ASTDeclWriter::VisitUsingShadowDecl(UsingShadowDecl *D) {
   VisitNamedDecl(D);
   Writer.AddDeclRef(D->getTargetDecl(), Record);
-  Writer.AddDeclRef(D->getUsingDecl(), Record);
+  Writer.AddDeclRef(D->UsingOrNextShadow, Record);
   Writer.AddDeclRef(Context.getInstantiatedFromUsingShadowDecl(D), Record);
   Code = serialization::DECL_USING_SHADOW;
 }

Modified: cfe/trunk/test/Index/load-namespaces.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Index/load-namespaces.cpp?rev=118674&r1=118673&r2=118674&view=diff
==============================================================================
--- cfe/trunk/test/Index/load-namespaces.cpp (original)
+++ cfe/trunk/test/Index/load-namespaces.cpp Tue Nov  9 23:40:41 2010
@@ -41,7 +41,7 @@
 // CHECK: load-namespaces.cpp:18:11: Namespace=std:18:11 (Definition) Extent=[18:11 - 20:2]
 // CHECK: load-namespaces.cpp:19:7: FunctionDecl=g:19:7 Extent=[19:7 - 19:13]
 // CHECK: load-namespaces.cpp:19:12: ParmDecl=:19:12 (Definition) Extent=[19:9 - 19:13]
-// CHECK: load-namespaces.cpp:22:12: UsingDeclaration=g[10:8, 19:7] Extent=[22:1 - 22:13]
+// CHECK: load-namespaces.cpp:22:12: UsingDeclaration=g[19:7, 10:8] Extent=[22:1 - 22:13]
 // CHECK: load-namespaces.cpp:22:7: NamespaceRef=std:18:11 Extent=[22:7 - 22:10]
 // CHECK: load-namespaces.cpp:24:11: FunctionDecl=g:24:11 (Definition) Extent=[24:11 - 25:2]
 // CHECK: load-namespaces.cpp:24:6: NamespaceRef=std:18:11 Extent=[24:6 - 24:9]

Modified: cfe/trunk/tools/libclang/CIndex.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/tools/libclang/CIndex.cpp?rev=118674&r1=118673&r2=118674&view=diff
==============================================================================
--- cfe/trunk/tools/libclang/CIndex.cpp (original)
+++ cfe/trunk/tools/libclang/CIndex.cpp Tue Nov  9 23:40:41 2010
@@ -3645,7 +3645,7 @@
   
   Decl *D = Storage.get<Decl*>();
   if (UsingDecl *Using = dyn_cast<UsingDecl>(D))
-    return Using->getNumShadowDecls();
+    return Using->shadow_size();
   if (ObjCClassDecl *Classes = dyn_cast<ObjCClassDecl>(D))
     return Classes->size();
   if (ObjCForwardProtocolDecl *Protocols =dyn_cast<ObjCForwardProtocolDecl>(D))





More information about the cfe-commits mailing list