]> granicus.if.org Git - clang/commitdiff
PCH: fix a regression that reports a module is defined in both pch and pcm.
authorManman Ren <manman.ren@gmail.com>
Mon, 9 Jan 2017 19:20:18 +0000 (19:20 +0000)
committerManman Ren <manman.ren@gmail.com>
Mon, 9 Jan 2017 19:20:18 +0000 (19:20 +0000)
In r276159, we started to say that a module X is defined in a pch if we specify
-fmodule-name when building the pch. This caused a regression that reports
module X is defined in both pch and pcm if we generate the pch with
-fmodule-name=X and then in a separate clang invocation, we include the pch and
also import X.pcm.

This patch adds an option CompilingPCH similar to CompilingModule. When we use
-fmodule-name=X while building a pch, modular headers in X will be textually
included and the compiler knows that we are not building module X, so we don't
put module X in SUBMODULE_DEFINITION of the pch.

Differential Revision: http://reviews.llvm.org/D28415

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

12 files changed:
include/clang/Basic/LangOptions.def
include/clang/Frontend/FrontendActions.h
lib/Frontend/FrontendActions.cpp
lib/Lex/PPDirectives.cpp
lib/Serialization/ASTWriter.cpp
test/Modules/Inputs/pch-with-module-name/A.h [new file with mode: 0644]
test/Modules/Inputs/pch-with-module-name/C.h [new file with mode: 0644]
test/Modules/Inputs/pch-with-module-name/C.m [new file with mode: 0644]
test/Modules/Inputs/pch-with-module-name/D.h [new file with mode: 0644]
test/Modules/Inputs/pch-with-module-name/module.modulemap [new file with mode: 0644]
test/Modules/Inputs/pch-with-module-name/test.h [new file with mode: 0644]
test/Modules/pch-with-module-name.m [new file with mode: 0644]

index 47db50c52b74a816f0c18e2239925816b64f31ff..d944a9d78ab9bc43efa09c4f141b4c13805c6d22 100644 (file)
@@ -146,6 +146,7 @@ LANGOPT(Modules           , 1, 0, "modules extension to C")
 COMPATIBLE_LANGOPT(ModulesTS  , 1, 0, "C++ Modules TS")
 BENIGN_ENUM_LANGOPT(CompilingModule, CompilingModuleKind, 2, CMK_None,
                     "compiling a module interface")
+BENIGN_LANGOPT(CompilingPCH, 1, 0, "building a pch")
 COMPATIBLE_LANGOPT(ModulesDeclUse    , 1, 0, "require declaration of module uses")
 BENIGN_LANGOPT(ModulesSearchAll  , 1, 1, "searching even non-imported modules to find unresolved references")
 COMPATIBLE_LANGOPT(ModulesStrictDeclUse, 1, 0, "requiring declaration of module uses and all headers to be in modules")
index a073ca5bfd2a5238d280a1c4f75d263ed3bb4876..20fddc4d5a5221c71b8c9ff305940c84e854f33f 100644 (file)
@@ -88,6 +88,8 @@ public:
   static std::unique_ptr<raw_pwrite_stream>
   ComputeASTConsumerArguments(CompilerInstance &CI, StringRef InFile,
                               std::string &Sysroot, std::string &OutputFile);
+
+  bool BeginSourceFileAction(CompilerInstance &CI, StringRef Filename) override;
 };
 
 class GenerateModuleAction : public ASTFrontendAction {
index eb91940cbbfc8078ad05eecf314ec8edbe62a144..f795a1d0475ac885737aef041dcd317a4d99a878 100644 (file)
@@ -127,6 +127,12 @@ GeneratePCHAction::ComputeASTConsumerArguments(CompilerInstance &CI,
   return OS;
 }
 
+bool GeneratePCHAction::BeginSourceFileAction(CompilerInstance &CI,
+                                              StringRef Filename) {
+  CI.getLangOpts().CompilingPCH = true;
+  return true;
+}
+
 std::unique_ptr<ASTConsumer>
 GenerateModuleAction::CreateASTConsumer(CompilerInstance &CI,
                                         StringRef InFile) {
index 85504de3d15d864eefe996f922f19ded13ef2741..9661e7b13f720b9339ea331f856113cd8645afc0 100644 (file)
@@ -1996,10 +1996,12 @@ void Preprocessor::HandleIncludeDirective(SourceLocation HashLoc,
 
   // Ask HeaderInfo if we should enter this #include file.  If not, #including
   // this file will have no effect.
+  bool SkipHeader = false;
   if (ShouldEnter &&
       !HeaderInfo.ShouldEnterIncludeFile(*this, File, isImport,
                                          SuggestedModule.getModule())) {
     ShouldEnter = false;
+    SkipHeader = true;
     if (Callbacks)
       Callbacks->FileSkipped(*File, FilenameTok, FileCharacter);
   }
@@ -2008,6 +2010,14 @@ void Preprocessor::HandleIncludeDirective(SourceLocation HashLoc,
   if (!ShouldEnter) {
     // If this is a module import, make it visible if needed.
     if (auto *M = SuggestedModule.getModule()) {
+      // When building a pch, -fmodule-name tells the compiler to textually
+      // include headers in the specified module. But it is possible that
+      // ShouldEnter is false because we are skipping the header. In that
+      // case, We are not importing the specified module.
+      if (SkipHeader && getLangOpts().CompilingPCH &&
+          M->getTopLevelModuleName() == getLangOpts().CurrentModule)
+        return;
+
       makeModuleVisible(M, HashLoc);
 
       if (IncludeTok.getIdentifierInfo()->getPPKeywordID() !=
@@ -2032,6 +2042,13 @@ void Preprocessor::HandleIncludeDirective(SourceLocation HashLoc,
 
   // Determine if we're switching to building a new submodule, and which one.
   if (auto *M = SuggestedModule.getModule()) {
+    // When building a pch, -fmodule-name tells the compiler to textually
+    // include headers in the specified module. We are not building the
+    // specified module.
+    if (getLangOpts().CompilingPCH &&
+        M->getTopLevelModuleName() == getLangOpts().CurrentModule)
+      return;
+
     assert(!CurSubmodule && "should not have marked this as a module yet");
     CurSubmodule = M;
 
index 2a5eda436f096e367270bcdc41c7f150aa4cd8db..39e842db2baaee7c9cb3ae0d65d5284b81829d59 100644 (file)
@@ -4654,17 +4654,6 @@ uint64_t ASTWriter::WriteASTCore(Sema &SemaRef, StringRef isysroot,
   // If we're emitting a module, write out the submodule information.  
   if (WritingModule)
     WriteSubmodules(WritingModule);
-  else if (!getLangOpts().CurrentModule.empty()) {
-    // If we're building a PCH in the implementation of a module, we may need
-    // the description of the current module.
-    //
-    // FIXME: We may need other modules that we did not load from an AST file,
-    // such as if a module declares a 'conflicts' on a different module.
-    Module *M = PP.getHeaderSearchInfo().getModuleMap().findModule(
-        getLangOpts().CurrentModule);
-    if (M && !M->IsFromModuleFile)
-      WriteSubmodules(M);
-  }
 
   Stream.EmitRecord(SPECIAL_TYPES, SpecialTypes);
 
diff --git a/test/Modules/Inputs/pch-with-module-name/A.h b/test/Modules/Inputs/pch-with-module-name/A.h
new file mode 100644 (file)
index 0000000..a73b375
--- /dev/null
@@ -0,0 +1 @@
+// in pch
diff --git a/test/Modules/Inputs/pch-with-module-name/C.h b/test/Modules/Inputs/pch-with-module-name/C.h
new file mode 100644 (file)
index 0000000..f681dd8
--- /dev/null
@@ -0,0 +1 @@
+#include "D.h"
diff --git a/test/Modules/Inputs/pch-with-module-name/C.m b/test/Modules/Inputs/pch-with-module-name/C.m
new file mode 100644 (file)
index 0000000..90fe1bc
--- /dev/null
@@ -0,0 +1 @@
+//empty
diff --git a/test/Modules/Inputs/pch-with-module-name/D.h b/test/Modules/Inputs/pch-with-module-name/D.h
new file mode 100644 (file)
index 0000000..90fe1bc
--- /dev/null
@@ -0,0 +1 @@
+//empty
diff --git a/test/Modules/Inputs/pch-with-module-name/module.modulemap b/test/Modules/Inputs/pch-with-module-name/module.modulemap
new file mode 100644 (file)
index 0000000..379b0d4
--- /dev/null
@@ -0,0 +1,9 @@
+module CloudKit {
+  header "C.h"
+  export *
+}
+
+module Contacts {
+  header "D.h"
+  export *
+}
diff --git a/test/Modules/Inputs/pch-with-module-name/test.h b/test/Modules/Inputs/pch-with-module-name/test.h
new file mode 100644 (file)
index 0000000..7a13ba4
--- /dev/null
@@ -0,0 +1 @@
+#include "A.h"
diff --git a/test/Modules/pch-with-module-name.m b/test/Modules/pch-with-module-name.m
new file mode 100644 (file)
index 0000000..c409630
--- /dev/null
@@ -0,0 +1,5 @@
+// RUN: rm -rf %t
+// RUN: %clang_cc1 -fmodules -fimplicit-module-maps -fmodules-cache-path=%t -I %S/Inputs/pch-with-module-name -emit-pch -o %t-A.pch %S/Inputs/pch-with-module-name/test.h -fmodule-name=Contacts -x objective-c-header
+// RUN: %clang_cc1 -fmodules -fimplicit-module-maps -fmodules-cache-path=%t -I %S/Inputs/pch-with-module-name -include-pch %t-A.pch %s -fsyntax-only -fmodule-name=Contacts -verify
+// expected-no-diagnostics 
+#include "C.h"