]> granicus.if.org Git - clang/commitdiff
[c++20] Enable driver and frontend support for building and using
authorRichard Smith <richard-llvm@metafoo.co.uk>
Sun, 14 Apr 2019 11:11:37 +0000 (11:11 +0000)
committerRichard Smith <richard-llvm@metafoo.co.uk>
Sun, 14 Apr 2019 11:11:37 +0000 (11:11 +0000)
modules when -std=c++2a is specified.

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

include/clang/Basic/DiagnosticFrontendKinds.td
lib/Driver/ToolChains/Clang.cpp
lib/Frontend/FrontendActions.cpp
lib/Parse/Parser.cpp
test/CXX/module/module.unit/p8.cpp [new file with mode: 0644]
test/Driver/modules.cpp [new file with mode: 0644]

index b44a2d1d48036b71f927019e4b32c89cc930bee0..65f5b412d915345f20fef1cf895df366a35c3fc2 100644 (file)
@@ -173,10 +173,11 @@ def note_incompatible_analyzer_plugin_api : Note<
 
 def err_module_build_requires_fmodules : Error<
   "module compilation requires '-fmodules'">;
-def err_module_interface_requires_modules_ts : Error<
-  "module interface compilation requires '-fmodules-ts'">;
+def err_module_interface_requires_cpp_modules : Error<
+  "module interface compilation requires '-std=c++2a' or '-fmodules-ts'">;
 def err_header_module_requires_modules : Error<
-  "header module compilation requires '-fmodules' or '-fmodules-ts'">;
+  "header module compilation requires '-fmodules', '-std=c++2a', or "
+  "'-fmodules-ts'">;
 def warn_module_config_mismatch : Warning<
   "module file %0 cannot be loaded due to a configuration mismatch with the current "
   "compilation">, InGroup<DiagGroup<"module-file-config-mismatch">>, DefaultError;
index 18856650a949e75fc8077f51be249a3507b37193..0d76aaaacf58ab786a3321c9b21a070eccaa127f 100644 (file)
@@ -2721,7 +2721,7 @@ static void RenderModulesOptions(Compilation &C, const Driver &D,
     }
   }
 
-  HaveModules = HaveClangModules;
+  HaveModules |= HaveClangModules;
   if (Args.hasArg(options::OPT_fmodules_ts)) {
     CmdArgs.push_back("-fmodules-ts");
     HaveModules = true;
@@ -4259,7 +4259,8 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA,
   // If a std is supplied, only add -trigraphs if it follows the
   // option.
   bool ImplyVCPPCXXVer = false;
-  if (Arg *Std = Args.getLastArg(options::OPT_std_EQ, options::OPT_ansi)) {
+  const Arg *Std = Args.getLastArg(options::OPT_std_EQ, options::OPT_ansi);
+  if (Std) {
     if (Std->getOption().matches(options::OPT_ansi))
       if (types::isCXX(InputType))
         CmdArgs.push_back("-std=c++98");
@@ -4696,9 +4697,6 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA,
   Args.AddLastArg(CmdArgs, options::OPT_fdouble_square_bracket_attributes,
                   options::OPT_fno_double_square_bracket_attributes);
 
-  bool HaveModules = false;
-  RenderModulesOptions(C, D, Args, Input, Output, CmdArgs, HaveModules);
-
   // -faccess-control is default.
   if (Args.hasFlag(options::OPT_fno_access_control,
                    options::OPT_faccess_control, false))
@@ -4765,6 +4763,7 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA,
   if (ImplyVCPPCXXVer) {
     StringRef LanguageStandard;
     if (const Arg *StdArg = Args.getLastArg(options::OPT__SLASH_std)) {
+      Std = StdArg;
       LanguageStandard = llvm::StringSwitch<StringRef>(StdArg->getValue())
                              .Case("c++14", "-std=c++14")
                              .Case("c++17", "-std=c++17")
@@ -4830,6 +4829,12 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA,
                                        options::OPT_fno_inline_functions))
     InlineArg->render(Args, CmdArgs);
 
+  // FIXME: Find a better way to determine whether the language has modules
+  // support by default, or just assume that all languages do.
+  bool HaveModules =
+      Std && (Std->containsValue("c++2a") || Std->containsValue("c++latest"));
+  RenderModulesOptions(C, D, Args, Input, Output, CmdArgs, HaveModules);
+
   Args.AddLastArg(CmdArgs, options::OPT_fexperimental_new_pass_manager,
                   options::OPT_fno_experimental_new_pass_manager);
 
index 9cb2ab2d5ee2e3bfea7d3a9c3cf43fb57deb3385..882d985fa0ae86f7e5f4a648685e50ac9204836b 100644 (file)
@@ -221,8 +221,8 @@ GenerateModuleFromModuleMapAction::CreateOutputFile(CompilerInstance &CI,
 
 bool GenerateModuleInterfaceAction::BeginSourceFileAction(
     CompilerInstance &CI) {
-  if (!CI.getLangOpts().ModulesTS) {
-    CI.getDiagnostics().Report(diag::err_module_interface_requires_modules_ts);
+  if (!CI.getLangOpts().ModulesTS && !CI.getLangOpts().CPlusPlusModules) {
+    CI.getDiagnostics().Report(diag::err_module_interface_requires_cpp_modules);
     return false;
   }
 
@@ -239,7 +239,7 @@ GenerateModuleInterfaceAction::CreateOutputFile(CompilerInstance &CI,
 
 bool GenerateHeaderModuleAction::PrepareToExecuteAction(
     CompilerInstance &CI) {
-  if (!CI.getLangOpts().Modules && !CI.getLangOpts().ModulesTS) {
+  if (!CI.getLangOpts().Modules) {
     CI.getDiagnostics().Report(diag::err_header_module_requires_modules);
     return false;
   }
index d1920a9ae7a6ce4c5d3d89dd9976fa7a4e49e3fd..febb0f942e8ed0a6584897d62ce5841765857175 100644 (file)
@@ -837,7 +837,7 @@ Parser::ParseExternalDeclaration(ParsedAttributesWithRange &attrs,
     SingleDecl = ParseModuleImport(SourceLocation());
     break;
   case tok::kw_export:
-    if (getLangOpts().ModulesTS) {
+    if (getLangOpts().CPlusPlusModules || getLangOpts().ModulesTS) {
       SingleDecl = ParseExportDeclaration();
       break;
     }
diff --git a/test/CXX/module/module.unit/p8.cpp b/test/CXX/module/module.unit/p8.cpp
new file mode 100644 (file)
index 0000000..aad6527
--- /dev/null
@@ -0,0 +1,40 @@
+// RUN: echo 'export module foo; export int n;' > %t.cppm
+// RUN: %clang_cc1 -std=c++2a %t.cppm -emit-module-interface -o %t.pcm
+// RUN: %clang_cc1 -std=c++2a -fmodule-file=%t.pcm -verify -DMODE=0 %s
+// RUN: %clang_cc1 -std=c++2a -fmodule-file=%t.pcm -verify -DMODE=1 %s
+// RUN: %clang_cc1 -std=c++2a -fmodule-file=%t.pcm -verify -DMODE=2 %s
+// RUN: %clang_cc1 -std=c++2a -fmodule-file=%t.pcm -verify -DMODE=3 %s
+// RUN: %clang_cc1 -std=c++2a -fmodule-file=%t.pcm -verify -DMODE=4 %s
+// RUN: %clang_cc1 -std=c++2a -fmodule-file=%t.pcm -verify -DMODE=5 %s
+
+#if MODE == 0
+// no module declaration
+
+#elif MODE == 1
+// expected-no-diagnostics
+module foo;
+#define IMPORTED
+
+#elif MODE == 2
+export module foo; // expected-error {{redefinition of module 'foo'}}
+// expected-note-re@* {{module loaded from '{{.*}}.pcm'}}
+#define IMPORTED
+
+#elif MODE == 3
+export module bar;
+
+#elif MODE == 4
+module foo:bar; // expected-error {{not yet supported}}
+#define IMPORTED // FIXME
+
+#elif MODE == 5
+export module foo:bar; // expected-error {{not yet supported}} expected-error {{redefinition}} expected-note@* {{loaded from}}
+#define IMPORTED // FIXME
+
+#endif
+
+int k = n;
+#ifndef IMPORTED
+// expected-error@-2 {{declaration of 'n' must be imported from module 'foo' before it is required}}
+// expected-note@* {{previous}}
+#endif
diff --git a/test/Driver/modules.cpp b/test/Driver/modules.cpp
new file mode 100644 (file)
index 0000000..4f7439c
--- /dev/null
@@ -0,0 +1,74 @@
+// RUN: rm -rf %t
+// RUN: mkdir %t
+
+// Check compiling a module interface to a .pcm file.
+//
+// RUN: %clang -std=c++2a -x c++-module --precompile %s -o %t/module.pcm -v 2>&1 | FileCheck %s --check-prefix=CHECK-PRECOMPILE
+//
+// CHECK-PRECOMPILE: -cc1 {{.*}} -emit-module-interface
+// CHECK-PRECOMPILE-SAME: -o {{.*}}.pcm
+// CHECK-PRECOMPILE-SAME: -x c++
+// CHECK-PRECOMPILE-SAME: modules.cpp
+
+// Check compiling a .pcm file to a .o file.
+//
+// RUN: %clang -std=c++2a %t/module.pcm -c -o %t/module.pcm.o -v 2>&1 | FileCheck %s --check-prefix=CHECK-COMPILE
+//
+// CHECK-COMPILE: -cc1 {{.*}} -emit-obj
+// CHECK-COMPILE-SAME: -o {{.*}}.pcm.o
+// CHECK-COMPILE-SAME: -x pcm
+// CHECK-COMPILE-SAME: {{.*}}.pcm
+
+// Check use of a .pcm file in another compilation.
+//
+// RUN: %clang -std=c++2a -fmodule-file=%t/module.pcm -Dexport= %s -c -o %t/module.o -v 2>&1 | FileCheck %s --check-prefix=CHECK-USE
+//
+// CHECK-USE: -cc1
+// CHECK-USE-SAME: -emit-obj
+// CHECK-USE-SAME: -fmodule-file={{.*}}.pcm
+// CHECK-USE-SAME: -o {{.*}}.o{{"?}} {{.*}}-x c++
+// CHECK-USE-SAME: modules.cpp
+
+// Check combining precompile and compile steps works.
+//
+// RUN: %clang -std=c++2a -x c++-module %s -c -o %t/module2.pcm.o -v 2>&1 | FileCheck %s --check-prefix=CHECK-PRECOMPILE --check-prefix=CHECK-COMPILE
+
+// Check that .cppm is treated as a module implicitly.
+//
+// RUN: cp %s %t/module.cppm
+// RUN: %clang -std=c++2a --precompile %t/module.cppm -o %t/module.pcm -v 2>&1 | FileCheck %s --check-prefix=CHECK-PRECOMPILE
+
+// Check compiling a header unit to a .pcm file.
+//
+// RUN: echo '#define FOO BAR' > %t/foo.h
+// RUN: %clang -std=c++2a --precompile -x c++-header %t/foo.h -fmodule-name=header -o %t/foo.pcm -v 2>&1 | FileCheck %s --check-prefix=CHECK-HEADER-UNIT
+//
+// CHECK-HEADER-UNIT: -cc1
+// CHECK-HEADER-UNIT-SAME: -emit-header-module
+// CHECK-HEADER-UNIT-SAME: -fmodule-name=header
+// CHECK-HEADER-UNIT-SAME: -o {{.*}}foo.pcm
+// CHECK-HEADER-UNIT-SAME: -x c++-header
+// CHECK-HEADER-UNIT-SAME: foo.h
+
+// Check use of header unit.
+//
+// RUN: %clang -std=c++2a -fmodule-file=%t/module.pcm -fmodule-file=%t/foo.pcm -I%t -DIMPORT -Dexport= %s -E -o - -v 2>&1 | FileCheck %s --check-prefix=CHECK-HEADER-UNIT-USE
+//
+// CHECK-HEADER-UNIT-USE: -cc1
+// CHECK-HEADER-UNIT-USE: -E
+// CHECK-HEADER-UNIT-USE: -fmodule-file={{.*}}module.pcm
+// CHECK-HEADER-UNIT-USE: -fmodule-file={{.*}}foo.pcm
+
+// Note, we use -Dexport= to make this a module implementation unit when building the implementation.
+export module foo;
+
+#ifdef IMPORT
+// CHECK-HEADER-UNIT-USE: FOO;
+FOO;
+
+// CHECK-HEADER-UNIT-USE: import header.{{.*}}foo.h{{.*}};
+import "foo.h";
+
+// CHECK-HEADER-UNIT-USE: BAR;
+FOO;
+#endif