summaryrefslogtreecommitdiffstats
path: root/clang
diff options
context:
space:
mode:
authorDouglas Gregor <dgregor@apple.com>2011-08-25 15:28:26 +0000
committerDouglas Gregor <dgregor@apple.com>2011-08-25 15:28:26 +0000
commitaa7cbfd259086f1600b26ce30e667f428e397d77 (patch)
treed943f6e897bc609ed1f97e418a58180b4fcb2294 /clang
parentc10edd6dd0bfe98dfb1007630a960fa376bc5514 (diff)
downloadbcm5719-llvm-aa7cbfd259086f1600b26ce30e667f428e397d77.tar.gz
bcm5719-llvm-aa7cbfd259086f1600b26ce30e667f428e397d77.zip
Remove a bogus assertion from the AST reader, which assumed that
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. llvm-svn: 138557
Diffstat (limited to 'clang')
-rw-r--r--clang/lib/Serialization/ASTReaderDecl.cpp18
-rw-r--r--clang/test/PCH/chain-friend-instantiation.cpp61
2 files changed, 67 insertions, 12 deletions
diff --git a/clang/lib/Serialization/ASTReaderDecl.cpp b/clang/lib/Serialization/ASTReaderDecl.cpp
index ab46e0a0962..6e7cbbf9b0c 100644
--- a/clang/lib/Serialization/ASTReaderDecl.cpp
+++ b/clang/lib/Serialization/ASTReaderDecl.cpp
@@ -123,8 +123,8 @@ namespace clang {
ClassTemplateSpecializationDecl *D);
void VisitClassTemplatePartialSpecializationDecl(
ClassTemplatePartialSpecializationDecl *D);
- void VisitClassScopeFunctionSpecializationDecl(
- ClassScopeFunctionSpecializationDecl *D);
+ 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(
- ClassScopeFunctionSpecializationDecl *D) {
+void ASTDeclReader::VisitClassScopeFunctionSpecializationDecl(
+ ClassScopeFunctionSpecializationDecl *D) {
VisitDecl(D);
D->Specialization = ReadDeclAs<CXXMethodDecl>(Record, Idx);
}
diff --git a/clang/test/PCH/chain-friend-instantiation.cpp b/clang/test/PCH/chain-friend-instantiation.cpp
new file mode 100644
index 00000000000..294d9791123
--- /dev/null
+++ b/clang/test/PCH/chain-friend-instantiation.cpp
@@ -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
OpenPOWER on IntegriCloud