aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRichard Smith <richard-llvm@metafoo.co.uk>2013-02-12 05:48:23 +0000
committerRichard Smith <richard-llvm@metafoo.co.uk>2013-02-12 05:48:23 +0000
commitad0e27b18b0cefab049121d4bfd7b12216e7de6e (patch)
tree2dda138e597f0e8a64c07a004f929ec62aa8d7c1
parent43ced74f002fd8dcf0c6c001f017d31769df792d (diff)
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. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@174943 91177308-0d34-0410-b5e6-96231b3b80d8
-rw-r--r--lib/AST/Decl.cpp5
-rw-r--r--lib/Serialization/ASTReaderDecl.cpp4
-rw-r--r--lib/Serialization/ASTWriterDecl.cpp4
-rw-r--r--test/Modules/Inputs/cxx-linkage-cache.h11
-rw-r--r--test/Modules/Inputs/module.map4
-rw-r--r--test/Modules/cxx-linkage-cache.cpp8
6 files changed, 32 insertions, 4 deletions
diff --git a/lib/AST/Decl.cpp b/lib/AST/Decl.cpp
index 85ed3ba7db..d6778ecf39 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 c2ace30782..64b33b066b 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 c2e1513586..3795e21bdf 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 0000000000..df82927976
--- /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 f219036e21..53f2fd65d3 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 0000000000..296cc8034f
--- /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);