]> granicus.if.org Git - clang/commitdiff
Fix a bug reduced from a crash when trying to use modules with libc++. We check
authorRichard Smith <richard-llvm@metafoo.co.uk>
Tue, 12 Feb 2013 05:48:23 +0000 (05:48 +0000)
committerRichard Smith <richard-llvm@metafoo.co.uk>
Tue, 12 Feb 2013 05:48:23 +0000 (05:48 +0000)
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

lib/AST/Decl.cpp
lib/Serialization/ASTReaderDecl.cpp
lib/Serialization/ASTWriterDecl.cpp
test/Modules/Inputs/cxx-linkage-cache.h [new file with mode: 0644]
test/Modules/Inputs/module.map
test/Modules/cxx-linkage-cache.cpp [new file with mode: 0644]

index 85ed3ba7db0b9cd2d587df08fa0dee2b8feadd98..d6778ecf397fed5f117b8463a32c60fed924302d 100644 (file)
@@ -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;
index c2ace3078298f3c43074ebc3269748611313335f..64b33b066b0790e866eebeaa7b689cc21825177c 100644 (file)
@@ -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)
index c2e1513586fa6c8c20f02baf5695f7a9f54f93d4..3795e21bdf674f4d5501b356ab71bea0063bd9dd 100644 (file)
@@ -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 (file)
index 0000000..df82927
--- /dev/null
@@ -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>;
+}
index f219036e21d6caacf7f857bcb0e0951a6a01ce78..53f2fd65d34ced73de8b22123cfeda467285117e 100644 (file)
@@ -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 (file)
index 0000000..296cc80
--- /dev/null
@@ -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);