]> granicus.if.org Git - clang/commitdiff
Remove a bogus assertion from the AST reader, which assumed that
authorDouglas Gregor <dgregor@apple.com>
Thu, 25 Aug 2011 15:28:26 +0000 (15:28 +0000)
committerDouglas Gregor <dgregor@apple.com>
Thu, 25 Aug 2011 15:28:26 +0000 (15:28 +0000)
redeclarations of a particular entity would occur in source
order. Friend declarations that occur within class templates (or
member classes thereof) do not follow this, nor would modules. Big
thanks to Erik Verbruggen for reducing this problem from the Very
Large Qt preamble testcase he found.

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

lib/Serialization/ASTReaderDecl.cpp
test/PCH/chain-friend-instantiation.cpp [new file with mode: 0644]

index ab46e0a0962a83aad49ac0bbf04f8a85446ab4e2..6e7cbbf9b0c250554a09d5fcc6a797cf682443a4 100644 (file)
@@ -123,8 +123,8 @@ namespace clang {
                                             ClassTemplateSpecializationDecl *D);
     void VisitClassTemplatePartialSpecializationDecl(
                                      ClassTemplatePartialSpecializationDecl *D);
-    void VisitClassScopeFunctionSpecializationDecl(\r
-                                       ClassScopeFunctionSpecializationDecl *D);\r
+    void VisitClassScopeFunctionSpecializationDecl(
+                                       ClassScopeFunctionSpecializationDecl *D);
     void VisitTemplateTypeParmDecl(TemplateTypeParmDecl *D);
     void VisitValueDecl(ValueDecl *VD);
     void VisitEnumConstantDecl(EnumConstantDecl *ECD);
@@ -1087,14 +1087,8 @@ void ASTDeclReader::VisitRedeclarableTemplateDecl(RedeclarableTemplateDecl *D) {
     ASTReader::FirstLatestDeclIDMap::iterator I
         = Reader.FirstLatestDeclIDs.find(ThisDeclID);
     if (I != Reader.FirstLatestDeclIDs.end()) {
-      Decl *NewLatest = Reader.GetDecl(I->second);
-      assert((LatestDecl->getLocation().isInvalid() ||
-              NewLatest->getLocation().isInvalid()  ||
-              !Reader.SourceMgr.isBeforeInTranslationUnit(
-                                                  NewLatest->getLocation(),
-                                                  LatestDecl->getLocation())) &&
-             "The new latest is supposed to come after the previous latest");
-      LatestDecl = cast<RedeclarableTemplateDecl>(NewLatest);
+      if (Decl *NewLatest = Reader.GetDecl(I->second))
+        LatestDecl = cast<RedeclarableTemplateDecl>(NewLatest);
     }
 
     assert(LatestDecl->getKind() == D->getKind() && "Latest kind mismatch");
@@ -1217,8 +1211,8 @@ void ASTDeclReader::VisitClassTemplatePartialSpecializationDecl(
   }
 }
 
-void ASTDeclReader::VisitClassScopeFunctionSpecializationDecl(\r
-                                    ClassScopeFunctionSpecializationDecl *D) {\r
+void ASTDeclReader::VisitClassScopeFunctionSpecializationDecl(
+                                    ClassScopeFunctionSpecializationDecl *D) {
   VisitDecl(D);
   D->Specialization = ReadDeclAs<CXXMethodDecl>(Record, Idx);
 }
diff --git a/test/PCH/chain-friend-instantiation.cpp b/test/PCH/chain-friend-instantiation.cpp
new file mode 100644 (file)
index 0000000..294d979
--- /dev/null
@@ -0,0 +1,61 @@
+// RUN: %clang_cc1 %s -ast-print -o - -chain-include %s -chain-include %s
+
+#if !defined(PASS1)
+#define PASS1
+
+template <class T> class TClass;
+
+namespace NS {
+    template <class X, class Y> TClass<X> problematic(X * ptr, const TClass<Y> &src);
+
+    template <class T>
+    class TBaseClass
+    {
+    protected:
+        template <class X, class Y> friend TClass<X> problematic(X * ptr, const TClass<Y> &src);
+    };
+}
+
+template <class T>
+class TClass: public NS::TBaseClass<T>
+{
+public:
+    inline TClass() { }
+};
+
+
+namespace NS {
+    template <class X, class T>
+    TClass<X> problematic(X *ptr, const TClass<T> &src);
+}
+
+template <class X, class T>
+TClass<X> unconst(const TClass<T> &src);
+
+#elif !defined(PASS2)
+#define PASS2
+
+namespace std {
+class s {};
+}
+
+
+typedef TClass<std::s> TStr;
+
+struct crash {
+  TStr str;
+
+  crash(const TClass<std::s> p)
+  {
+    unconst<TStr>(p);
+  }
+};
+
+#else
+
+void f() {
+    const TStr p;
+    crash c(p);
+}
+
+#endif