From 8858159fb543624c61459f3afa219404bf3cf6fa Mon Sep 17 00:00:00 2001 From: Richard Smith Date: Tue, 12 Feb 2013 05:48:23 +0000 Subject: [PATCH] Fix a bug reduced from a crash when trying to use modules with libc++. We check the linkage of functions and variables while merging declarations from modules, and we don't necessarily have enough of the rest of the AST loaded at that point to allow us to compute linkage, so serialize it instead. llvm-svn: 174943 --- clang/lib/AST/Decl.cpp | 5 +---- clang/lib/Serialization/ASTReaderDecl.cpp | 4 ++++ clang/lib/Serialization/ASTWriterDecl.cpp | 4 ++++ clang/test/Modules/Inputs/cxx-linkage-cache.h | 11 +++++++++++ clang/test/Modules/Inputs/module.map | 4 ++++ clang/test/Modules/cxx-linkage-cache.cpp | 8 ++++++++ 6 files changed, 32 insertions(+), 4 deletions(-) create mode 100644 clang/test/Modules/Inputs/cxx-linkage-cache.h create mode 100644 clang/test/Modules/cxx-linkage-cache.cpp diff --git a/clang/lib/AST/Decl.cpp b/clang/lib/AST/Decl.cpp index 85ed3ba7db0b..d6778ecf397f 100644 --- a/clang/lib/AST/Decl.cpp +++ b/clang/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/clang/lib/Serialization/ASTReaderDecl.cpp b/clang/lib/Serialization/ASTReaderDecl.cpp index c2ace3078298..64b33b066b07 100644 --- a/clang/lib/Serialization/ASTReaderDecl.cpp +++ b/clang/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/clang/lib/Serialization/ASTWriterDecl.cpp b/clang/lib/Serialization/ASTWriterDecl.cpp index c2e1513586fa..3795e21bdf67 100644 --- a/clang/lib/Serialization/ASTWriterDecl.cpp +++ b/clang/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/clang/test/Modules/Inputs/cxx-linkage-cache.h b/clang/test/Modules/Inputs/cxx-linkage-cache.h new file mode 100644 index 000000000000..df829279761a --- /dev/null +++ b/clang/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 + struct U { + friend bool f(const U &); + }; + + template class U; +} diff --git a/clang/test/Modules/Inputs/module.map b/clang/test/Modules/Inputs/module.map index f219036e21d6..53f2fd65d34c 100644 --- a/clang/test/Modules/Inputs/module.map +++ b/clang/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/clang/test/Modules/cxx-linkage-cache.cpp b/clang/test/Modules/cxx-linkage-cache.cpp new file mode 100644 index 000000000000..296cc8034f5a --- /dev/null +++ b/clang/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 u; +bool b = f(u);