]> granicus.if.org Git - clang/commitdiff
Fix autolinking when modules are imported in pch files
authorBen Langmuir <blangmuir@apple.com>
Fri, 31 Jan 2014 01:06:56 +0000 (01:06 +0000)
committerBen Langmuir <blangmuir@apple.com>
Fri, 31 Jan 2014 01:06:56 +0000 (01:06 +0000)
Add the ImportDecl to the set of interesting delcarations that are
deserialized eagerly when an AST file is loaded (rather than lazily like
most decls). This is required to get auto linking to work when there is
no explicit import in the main file. Also resolve a FIXME to rename
'ExternalDefinitions', since that is only one of the things that need eager
deserialization. The new name is 'EagerlyDeserializedDecls'. The corresponding
AST bitcode is also renamed.

git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@200505 91177308-0d34-0410-b5e6-96231b3b80d8

include/clang/Serialization/ASTBitCodes.h
include/clang/Serialization/ASTReader.h
include/clang/Serialization/ASTWriter.h
lib/Serialization/ASTReader.cpp
lib/Serialization/ASTReaderDecl.cpp
lib/Serialization/ASTWriter.cpp
lib/Serialization/ASTWriterDecl.cpp
test/Modules/Inputs/autolink-sub3.h [new file with mode: 0644]
test/Modules/Inputs/autolink-sub3.pch [new file with mode: 0644]
test/Modules/Inputs/module.map
test/Modules/autolink.m

index 4bfa8b7b1e58b2bf9ff6604115033bc2ac27ae12..eccf7404ced87c49d085f9f28ddc41e864ecc6e9 100644 (file)
@@ -349,15 +349,15 @@ namespace clang {
       /// IDs).
       IDENTIFIER_TABLE = 5,
 
-      /// \brief Record code for the array of external definitions.
+      /// \brief Record code for the array of eagerly deserialized decls.
       ///
-      /// The AST file contains a list of all of the unnamed external
-      /// definitions present within the parsed headers, stored as an
-      /// array of declaration IDs. These external definitions will be
+      /// The AST file contains a list of all of the declarations that should be
+      /// eagerly deserialized present within the parsed headers, stored as an
+      /// array of declaration IDs. These declarations will be
       /// reported to the AST consumer after the AST file has been
       /// read, since their presence can affect the semantics of the
       /// program (e.g., for code generation).
-      EXTERNAL_DEFINITIONS = 6,
+      EAGERLY_DESERIALIZED_DECLS = 6,
 
       /// \brief Record code for the set of non-builtin, special
       /// types.
index 9b92fd8ce3ec17b03b1c0a3c28d137ecb9d3c3a6..3cfd17ca027ae9bf7378e2c363941cc1e0f82fa3 100644 (file)
@@ -610,10 +610,10 @@ private:
   /// \brief The IDs of all declarations that fulfill the criteria of
   /// "interesting" decls.
   ///
-  /// This contains the data loaded from all EXTERNAL_DEFINITIONS blocks in the
-  /// chain. The referenced declarations are deserialized and passed to the
-  /// consumer eagerly.
-  SmallVector<uint64_t, 16> ExternalDefinitions;
+  /// This contains the data loaded from all EAGERLY_DESERIALIZED_DECLS blocks
+  /// in the chain. The referenced declarations are deserialized and passed to
+  /// the consumer eagerly.
+  SmallVector<uint64_t, 16> EagerlyDeserializedDecls;
 
   /// \brief The IDs of all tentative definitions stored in the chain.
   ///
index 66cab4625786ea53f332134096a542af9ee9fc01..cb2d83bbac5b914524701e15474b9301928ba0fd 100644 (file)
@@ -297,16 +297,15 @@ private:
   /// \brief Declarations encountered that might be external
   /// definitions.
   ///
-  /// We keep track of external definitions (as well as tentative
-  /// definitions) as we are emitting declarations to the AST
-  /// file. The AST file contains a separate record for these external
-  /// definitions, which are provided to the AST consumer by the AST
-  /// reader. This is behavior is required to properly cope with,
+  /// We keep track of external definitions and other 'interesting' declarations
+  /// as we are emitting declarations to the AST file. The AST file contains a
+  /// separate record for these declarations, which are provided to the AST
+  /// consumer by the AST reader. This is behavior is required to properly cope with,
   /// e.g., tentative variable definitions that occur within
   /// headers. The declarations themselves are stored as declaration
-  /// IDs, since they will be written out to an EXTERNAL_DEFINITIONS
+  /// IDs, since they will be written out to an EAGERLY_DESERIALIZED_DECLS
   /// record.
-  SmallVector<uint64_t, 16> ExternalDefinitions;
+  SmallVector<uint64_t, 16> EagerlyDeserializedDecls;
 
   /// \brief DeclContexts that have received extensions since their serialized
   /// form.
index 10a182fe9e89bcbe548d41bd729e6ed66cc1ff6b..3a93804eab74c2965bf79c89dffc18688c1c4dfe 100644 (file)
@@ -2256,9 +2256,9 @@ bool ASTReader::ReadASTBlock(ModuleFile &F) {
       break;
     }
 
-    case EXTERNAL_DEFINITIONS:
+    case EAGERLY_DESERIALIZED_DECLS:
       for (unsigned I = 0, N = Record.size(); I != N; ++I)
-        ExternalDefinitions.push_back(getGlobalDeclID(F, Record[I]));
+        EagerlyDeserializedDecls.push_back(getGlobalDeclID(F, Record[I]));
       break;
 
     case SPECIAL_TYPES:
@@ -5985,12 +5985,12 @@ void ASTReader::StartTranslationUnit(ASTConsumer *Consumer) {
   if (!Consumer)
     return;
 
-  for (unsigned I = 0, N = ExternalDefinitions.size(); I != N; ++I) {
+  for (unsigned I = 0, N = EagerlyDeserializedDecls.size(); I != N; ++I) {
     // Force deserialization of this decl, which will cause it to be queued for
     // passing to the consumer.
-    GetDecl(ExternalDefinitions[I]);
+    GetDecl(EagerlyDeserializedDecls[I]);
   }
-  ExternalDefinitions.clear();
+  EagerlyDeserializedDecls.clear();
 
   PassInterestingDeclsToConsumer();
 }
index a9ff8a0b73166168dd0ee8ef94721462c5dea93f..943328b9cdc7fc1340fab6616890a0a0b0f0b85a 100644 (file)
@@ -1984,7 +1984,8 @@ static bool isConsumerInterestedIn(Decl *D, bool HasBody) {
 
   if (isa<FileScopeAsmDecl>(D) || 
       isa<ObjCProtocolDecl>(D) || 
-      isa<ObjCImplDecl>(D))
+      isa<ObjCImplDecl>(D) ||
+      isa<ImportDecl>(D))
     return true;
   if (VarDecl *Var = dyn_cast<VarDecl>(D))
     return Var->isFileVarDecl() &&
index e931a7eeb2ae59781d088dbf3ed4d2a6a234cc5a..18d83cfe6aeee36a5034dbf80c075e303f296a97 100644 (file)
@@ -813,7 +813,7 @@ void ASTWriter::WriteBlockInfoBlock() {
   RECORD(DECL_OFFSET);
   RECORD(IDENTIFIER_OFFSET);
   RECORD(IDENTIFIER_TABLE);
-  RECORD(EXTERNAL_DEFINITIONS);
+  RECORD(EAGERLY_DESERIALIZED_DECLS);
   RECORD(SPECIAL_TYPES);
   RECORD(STATISTICS);
   RECORD(TENTATIVE_DEFINITIONS);
@@ -4192,8 +4192,8 @@ void ASTWriter::WriteASTCore(Sema &SemaRef,
   Stream.EmitRecord(SPECIAL_TYPES, SpecialTypes);
 
   // Write the record containing external, unnamed definitions.
-  if (!ExternalDefinitions.empty())
-    Stream.EmitRecord(EXTERNAL_DEFINITIONS, ExternalDefinitions);
+  if (!EagerlyDeserializedDecls.empty())
+    Stream.EmitRecord(EAGERLY_DESERIALIZED_DECLS, EagerlyDeserializedDecls);
 
   // Write the record containing tentative definitions.
   if (!TentativeDefinitions.empty())
index 89f9b4885faebdb432c1f6186226107efbd04ca0..5d5e4bb428f07350c8ee1aff8555a20fc90c4d44 100644 (file)
@@ -1817,8 +1817,10 @@ static bool isRequiredDecl(const Decl *D, ASTContext &Context) {
   // An ObjCMethodDecl is never considered as "required" because its
   // implementation container always is.
 
-  // File scoped assembly or obj-c implementation must be seen.
-  if (isa<FileScopeAsmDecl>(D) || isa<ObjCImplDecl>(D))
+  // File scoped assembly or obj-c implementation must be seen. ImportDecl is
+  // used by codegen to determine the set of imported modules to search for
+  // inputs for automatic linking.
+  if (isa<FileScopeAsmDecl>(D) || isa<ObjCImplDecl>(D) || isa<ImportDecl>(D))
     return true;
 
   return Context.DeclMustBeEmitted(D);
@@ -1906,10 +1908,8 @@ void ASTWriter::WriteDecl(ASTContext &Context, Decl *D) {
   // Flush C++ base specifiers, if there are any.
   FlushCXXBaseSpecifiers();
   
-  // Note "external" declarations so that we can add them to a record in the
-  // AST file later.
-  //
-  // FIXME: This should be renamed, the predicate is much more complicated.
+  // Note declarations that should be deserialized eagerly so that we can add
+  // them to a record in the AST file later.
   if (isRequiredDecl(D, Context))
-    ExternalDefinitions.push_back(ID);
+    EagerlyDeserializedDecls.push_back(ID);
 }
diff --git a/test/Modules/Inputs/autolink-sub3.h b/test/Modules/Inputs/autolink-sub3.h
new file mode 100644 (file)
index 0000000..132c729
--- /dev/null
@@ -0,0 +1 @@
+int autolink_sub3(void);
diff --git a/test/Modules/Inputs/autolink-sub3.pch b/test/Modules/Inputs/autolink-sub3.pch
new file mode 100644 (file)
index 0000000..f63b2d5
--- /dev/null
@@ -0,0 +1 @@
+@import autolink.sub3;
index cf8a298ccee72d9366337e9ea4ae4ede43803909..c0cdf76cdc3874033b80f8c22f2830e02b83eb06 100644 (file)
@@ -166,6 +166,11 @@ module autolink {
     header "autolink-sub2.h"
     link framework "autolink_framework"
   }
+
+  explicit module sub3 {
+    header "autolink-sub3.h"
+    link "autolink_from_pch"
+  }
 }
 
 module weird_objc {
index 077aac5374a0eefd90d8304a61225535f25062b3..883a2f52e50ee351190d5c74a5dcd1f75b982015 100644 (file)
@@ -1,6 +1,7 @@
 // RUN: rm -rf %t
-// RUN: %clang_cc1 -emit-llvm -o - -fmodules-cache-path=%t -fmodules -F %S/Inputs -I %S/Inputs %s | FileCheck %s
-// RUN: %clang_cc1 -emit-llvm -fno-autolink -o - -fmodules-cache-path=%t -fmodules -F %S/Inputs -I %S/Inputs %s | FileCheck --check-prefix=CHECK-AUTOLINK-DISABLED %s
+// RUN: %clang_cc1 -emit-pch -fmodules-cache-path=%t -fmodules -o %t.pch -I %S/Inputs -x objective-c-header %S/Inputs/autolink-sub3.pch
+// RUN: %clang_cc1 -emit-llvm -o - -fmodules-cache-path=%t -fmodules -F %S/Inputs -I %S/Inputs -include-pch %t.pch %s | FileCheck %s
+// RUN: %clang_cc1 -emit-llvm -fno-autolink -o - -fmodules-cache-path=%t -fmodules -F %S/Inputs -I %S/Inputs -include-pch %t.pch %s | FileCheck --check-prefix=CHECK-AUTOLINK-DISABLED %s
 
 @import autolink.sub2;
 
@@ -29,11 +30,16 @@ int use_no_umbrella() {
   return no_umbrella_A;
 }
 
+int use_autolink_sub3() {
+  return autolink_sub3();
+}
+
 // NOTE: "autolink_sub" is intentionally not linked.
 
 // CHECK: !llvm.module.flags = !{!0, !1, !2, !3, !4}
 // CHECK: !4 = metadata !{i32 6, metadata !"Linker Options", metadata ![[AUTOLINK_OPTIONS:[0-9]+]]}
-// CHECK: ![[AUTOLINK_OPTIONS]] = metadata !{metadata ![[AUTOLINK_FRAMEWORK:[0-9]+]], metadata ![[AUTOLINK:[0-9]+]], metadata ![[DEPENDSONMODULE:[0-9]+]], metadata ![[MODULE:[0-9]+]], metadata ![[NOUMBRELLA:[0-9]+]]}
+// CHECK: ![[AUTOLINK_OPTIONS]] = metadata !{metadata ![[AUTOLINK_PCH:[0-9]+]], metadata ![[AUTOLINK_FRAMEWORK:[0-9]+]], metadata ![[AUTOLINK:[0-9]+]], metadata ![[DEPENDSONMODULE:[0-9]+]], metadata ![[MODULE:[0-9]+]], metadata ![[NOUMBRELLA:[0-9]+]]}
+// CHECK: ![[AUTOLINK_PCH]] = metadata !{metadata !"{{(-l|/DEFAULTLIB:)}}autolink_from_pch{{(\.lib)?}}"}
 // CHECK: ![[AUTOLINK_FRAMEWORK]] = metadata !{metadata !"-framework", metadata !"autolink_framework"}
 // CHECK: ![[AUTOLINK]] = metadata !{metadata !"{{(-l|/DEFAULTLIB:)}}autolink{{(\.lib)?}}"}
 // CHECK: ![[DEPENDSONMODULE]] = metadata !{metadata !"-framework", metadata !"DependsOnModule"}