Reapply "Fix regression in behavior of clang -x c++-header -fmodule-name=XXX"
authorBenjamin Kramer <benny.kra@googlemail.com>
Mon, 5 Nov 2018 12:46:02 +0000 (12:46 +0000)
committerBenjamin Kramer <benny.kra@googlemail.com>
Mon, 5 Nov 2018 12:46:02 +0000 (12:46 +0000)
This reverts commit r345963. We have a path forward now.

Original commit message:
The driver accidentally stopped passing the input filenames on to -cc1
in this mode due to confusion over what action was being requested.

This change also fixes a couple of crashes I encountered when passing
multiple files to such a -cc1 invocation.

llvm-svn: 346130

clang/lib/Driver/ToolChains/Clang.cpp
clang/lib/Frontend/CompilerInstance.cpp
clang/lib/Lex/ModuleMap.cpp
clang/test/Driver/header-module.cpp
clang/test/Modules/strict-decluse-headers.cpp [new file with mode: 0644]

index 83830b51ed517bbde0eee73183bd4addd501c033..c35f7a94053cfaae7eeeade07d6dd9a0ad0eb36e 100644 (file)
@@ -3250,18 +3250,15 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA,
   bool IsCuda = JA.isOffloading(Action::OFK_Cuda);
   bool IsHIP = JA.isOffloading(Action::OFK_HIP);
   bool IsOpenMPDevice = JA.isDeviceOffloading(Action::OFK_OpenMP);
-  bool IsModulePrecompile =
-      isa<PrecompileJobAction>(JA) && JA.getType() == types::TY_ModuleFile;
   bool IsHeaderModulePrecompile = isa<HeaderModulePrecompileJobAction>(JA);
 
   // A header module compilation doesn't have a main input file, so invent a
   // fake one as a placeholder.
-  // FIXME: Pick the language based on the header file language.
   const char *ModuleName = [&]{
     auto *ModuleNameArg = Args.getLastArg(options::OPT_fmodule_name_EQ);
     return ModuleNameArg ? ModuleNameArg->getValue() : "";
   }();
-  InputInfo HeaderModuleInput(types::TY_CXXModule, ModuleName, ModuleName);
+  InputInfo HeaderModuleInput(Inputs[0].getType(), ModuleName, ModuleName);
 
   const InputInfo &Input =
       IsHeaderModulePrecompile ? HeaderModuleInput : Inputs[0];
@@ -3272,10 +3269,9 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA,
   for (const InputInfo &I : Inputs) {
     if (&I == &Input) {
       // This is the primary input.
-    } else if (IsModulePrecompile &&
+    } else if (IsHeaderModulePrecompile &&
                types::getPrecompiledType(I.getType()) == types::TY_PCH) {
-      types::ID Expected =
-          types::lookupHeaderTypeForSourceType(Inputs[0].getType());
+      types::ID Expected = HeaderModuleInput.getType();
       if (I.getType() != Expected) {
         D.Diag(diag::err_drv_module_header_wrong_kind)
             << I.getFilename() << types::getTypeName(I.getType())
index a9c51d49f65fca62991bf78aad35fad9dabf56bc..719474dc765c380d9837cb0dfede0d36f7be55a4 100644 (file)
@@ -372,6 +372,9 @@ static void InitializeFileRemapping(DiagnosticsEngine &Diags,
 void CompilerInstance::createPreprocessor(TranslationUnitKind TUKind) {
   const PreprocessorOptions &PPOpts = getPreprocessorOpts();
 
+  // The module manager holds a reference to the old preprocessor (if any).
+  ModuleManager.reset();
+
   // Create a PTH manager if we are using some form of a token cache.
   PTHManager *PTHMgr = nullptr;
   if (!PPOpts.TokenCache.empty())
index d44bf124ffca633693ce948e4187b54a10e4512d..13d2b728f58c360a89047989e066058b58672f03 100644 (file)
@@ -523,7 +523,7 @@ void ModuleMap::diagnoseHeaderInclusion(Module *RequestingModule,
 
   // At this point, only non-modular includes remain.
 
-  if (LangOpts.ModulesStrictDeclUse) {
+  if (RequestingModule && LangOpts.ModulesStrictDeclUse) {
     Diags.Report(FilenameLoc, diag::err_undeclared_use_of_module)
         << RequestingModule->getTopLevelModule()->Name << Filename;
   } else if (RequestingModule && RequestingModuleIsModuleInterface &&
index 2302c495f108da798951186e1f0bfcc260e6f68c..9a6ba5b108fc573190b76c14d6514c5718d8bb82 100644 (file)
@@ -7,7 +7,18 @@
 // CHECK-PRECOMPILE-SAME: -fno-implicit-modules
 // CHECK-PRECOMPILE-SAME: -fmodule-name=foobar
 // CHECK-PRECOMPILE-SAME: -o {{.*}}.pcm
-// CHECK-PRECOMPILE-SAME: -x c++
+// CHECK-PRECOMPILE-SAME: -x c++-header
 // CHECK-PRECOMPILE-SAME: header1.h
 // CHECK-PRECOMPILE-SAME: header2.h
 // CHECK-PRECOMPILE-SAME: header3.h
+//
+// RUN: %clang -fmodules-ts -fmodule-name=foobar -x c++-header -fsyntax-only %S/Inputs/header1.h %S/Inputs/header2.h %S/Inputs/header3.h -v 2>&1 | FileCheck %s --check-prefix=CHECK-SYNTAX-ONLY
+// CHECK-SYNTAX-ONLY: -cc1 {{.*}} -fsyntax-only
+// CHECK-SYNTAX-ONLY-SAME: -fmodules-ts
+// CHECK-SYNTAX-ONLY-SAME: -fno-implicit-modules
+// CHECK-SYNTAX-ONLY-SAME: -fmodule-name=foobar
+// CHECK-SYNTAX-ONLY-NOT: -o{{ }}
+// CHECK-SYNTAX-ONLY-SAME: -x c++-header
+// CHECK-SYNTAX-ONLY-SAME: header1.h
+// CHECK-SYNTAX-ONLY-SAME: header2.h
+// CHECK-SYNTAX-ONLY-SAME: header3.h
diff --git a/clang/test/Modules/strict-decluse-headers.cpp b/clang/test/Modules/strict-decluse-headers.cpp
new file mode 100644 (file)
index 0000000..deeda2f
--- /dev/null
@@ -0,0 +1,17 @@
+// RUN: rm -rf %t
+// RUN: mkdir %t
+// RUN: touch %t/foo.h
+// RUN: echo '#include "foo.h"' > %t/bar.h
+// RUN: touch %t/baz.h
+// RUN: echo 'module X { header "bar.h" header "baz.h" }' > %t/map
+//
+// RUN: not %clang_cc1 -fsyntax-only -fmodules -fmodule-map-file=%t/map -I%t -fmodules-strict-decluse -fmodule-name=X -x c++ %t/bar.h %t/baz.h 2>&1 | FileCheck %s
+// RUN: not %clang_cc1 -fsyntax-only -fmodules -fmodule-map-file=%t/map -I%t -fmodules-strict-decluse -fmodule-name=X -x c++ %t/baz.h %t/bar.h 2>&1 | FileCheck %s
+//
+// Don't crash on this: (FIXME: we should produce an error that the specified module name is not known)
+// RUN: %clang_cc1 -fsyntax-only -fmodules -I%t -fmodules-strict-decluse -fmodule-name=X -x c++ %t/baz.h %t/bar.h
+//
+// Don't crash on this: (FIXME: we should produce an error that the specified file is not part of the specified module)
+// RUN: %clang_cc1 -fsyntax-only -fmodules -fmodule-map-file=%t/map -I%t -fmodules-strict-decluse -fmodule-name=X -x c++ %t/foo.h
+//
+// CHECK: module X does not depend on a module exporting 'foo.h'