diff --git a/lib/AST/Decl.cpp b/lib/AST/Decl.cpp index 85ed3ba7db0b9cd2d587df08fa0dee2b8feadd98..d6778ecf397fed5f117b8463a32c60fed924302d 100644 --- a/lib/AST/Decl.cpp +++ b/lib/AST/Decl.cpp @@ -610,11 +610,8 @@ void NamedDecl::ClearLinkageCache() { } Linkage NamedDecl::getLinkage() const { - if (HasCachedLinkage) { - assert(Linkage(CachedLinkage) == - getLVForDecl(this, true).linkage()); + if (HasCachedLinkage) return Linkage(CachedLinkage); - } CachedLinkage = getLVForDecl(this, true).linkage(); HasCachedLinkage = 1; diff --git a/lib/Serialization/ASTReaderDecl.cpp b/lib/Serialization/ASTReaderDecl.cpp index c2ace3078298f3c43074ebc3269748611313335f..64b33b066b0790e866eebeaa7b689cc21825177c 100644 --- a/lib/Serialization/ASTReaderDecl.cpp +++ b/lib/Serialization/ASTReaderDecl.cpp @@ -526,6 +526,8 @@ void ASTDeclReader::VisitFunctionDecl(FunctionDecl *FD) { FD->HasImplicitReturnZero = Record[Idx++]; FD->IsConstexpr = Record[Idx++]; FD->HasSkippedBody = Record[Idx++]; + FD->HasCachedLinkage = true; + FD->CachedLinkage = Record[Idx++]; FD->EndRangeLoc = ReadSourceLocation(Record, Idx); switch ((FunctionDecl::TemplatedKind)Record[Idx++]) { @@ -908,6 +910,8 @@ void ASTDeclReader::VisitVarDecl(VarDecl *VD) { VD->VarDeclBits.CXXForRangeDecl = Record[Idx++]; VD->VarDeclBits.ARCPseudoStrong = Record[Idx++]; VD->VarDeclBits.IsConstexpr = Record[Idx++]; + VD->HasCachedLinkage = true; + VD->CachedLinkage = Record[Idx++]; // Only true variables (not parameters or implicit parameters) can be merged. if (VD->getKind() == Decl::Var) diff --git a/lib/Serialization/ASTWriterDecl.cpp b/lib/Serialization/ASTWriterDecl.cpp index c2e1513586fa6c8c20f02baf5695f7a9f54f93d4..3795e21bdf674f4d5501b356ab71bea0063bd9dd 100644 --- a/lib/Serialization/ASTWriterDecl.cpp +++ b/lib/Serialization/ASTWriterDecl.cpp @@ -330,6 +330,7 @@ void ASTDeclWriter::VisitFunctionDecl(FunctionDecl *D) { Record.push_back(D->hasImplicitReturnZero()); Record.push_back(D->isConstexpr()); Record.push_back(D->HasSkippedBody); + Record.push_back(D->getLinkage()); Writer.AddSourceLocation(D->getLocEnd(), Record); Record.push_back(D->getTemplatedKind()); @@ -682,6 +683,7 @@ void ASTDeclWriter::VisitVarDecl(VarDecl *D) { Record.push_back(D->isCXXForRangeDecl()); Record.push_back(D->isARCPseudoStrong()); Record.push_back(D->isConstexpr()); + Record.push_back(D->getLinkage()); if (D->getInit()) { Record.push_back(!D->isInitKnownICE() ? 1 : (D->isInitICE() ? 3 : 2)); @@ -1505,6 +1507,7 @@ void ASTWriter::WriteDeclsBlockAbbrevs() { Abv->Add(BitCodeAbbrevOp(0)); // isCXXForRangeDecl Abv->Add(BitCodeAbbrevOp(0)); // isARCPseudoStrong Abv->Add(BitCodeAbbrevOp(0)); // isConstexpr + Abv->Add(BitCodeAbbrevOp(0)); // Linkage Abv->Add(BitCodeAbbrevOp(0)); // HasInit Abv->Add(BitCodeAbbrevOp(0)); // HasMemberSpecializationInfo // ParmVarDecl @@ -1584,6 +1587,7 @@ void ASTWriter::WriteDeclsBlockAbbrevs() { Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 1)); // isCXXForRangeDecl Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 1)); // isARCPseudoStrong Abv->Add(BitCodeAbbrevOp(0)); // isConstexpr + Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 2)); // Linkage Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 1)); // HasInit Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 1)); // HasMemberSpecInfo // Type Source Info diff --git a/test/Modules/Inputs/cxx-linkage-cache.h b/test/Modules/Inputs/cxx-linkage-cache.h new file mode 100644 index 0000000000000000000000000000000000000000..df829279761ae7d7c01c1c108841dfbd223673fa --- /dev/null +++ b/test/Modules/Inputs/cxx-linkage-cache.h @@ -0,0 +1,11 @@ +// Reduced from a crash encountered with a modularized libc++, where +// we would try to compute the linkage of a declaration before we +// finish loading the relevant pieces of it. +inline namespace D { + template<class> + struct U { + friend bool f(const U &); + }; + + template class U<int>; +} diff --git a/test/Modules/Inputs/module.map b/test/Modules/Inputs/module.map index f219036e21d6caacf7f857bcb0e0951a6a01ce78..53f2fd65d34ced73de8b22123cfeda467285117e 100644 --- a/test/Modules/Inputs/module.map +++ b/test/Modules/Inputs/module.map @@ -179,3 +179,7 @@ module cxx_many_overloads { module cxx_inline_namespace { header "cxx-inline-namespace.h" } + +module cxx_linkage_cache { + header "cxx-linkage-cache.h" +} diff --git a/test/Modules/cxx-linkage-cache.cpp b/test/Modules/cxx-linkage-cache.cpp new file mode 100644 index 0000000000000000000000000000000000000000..296cc8034f5ada9a476580a41e192120c27e46f8 --- /dev/null +++ b/test/Modules/cxx-linkage-cache.cpp @@ -0,0 +1,8 @@ +// RUN: rm -rf %t +// RUN: %clang_cc1 -x objective-c++ -fmodules -fmodules-cache-path=%t -I %S/Inputs %s -verify -std=c++11 + +@import cxx_linkage_cache; + +T x; // expected-error {{unknown type name 'T'}} +D::U<int> u; +bool b = f(u);