]> granicus.if.org Git - clang/commitdiff
Add -fmodules-strict-decluse to check that all headers are in modules
authorDaniel Jasper <djasper@google.com>
Fri, 11 Apr 2014 11:47:45 +0000 (11:47 +0000)
committerDaniel Jasper <djasper@google.com>
Fri, 11 Apr 2014 11:47:45 +0000 (11:47 +0000)
Review: http://reviews.llvm.org/D3335

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

include/clang/Basic/LangOptions.def
include/clang/Driver/Options.td
lib/Driver/Tools.cpp
lib/Frontend/CompilerInvocation.cpp
lib/Lex/ModuleMap.cpp
test/Modules/strict-decluse.cpp [new file with mode: 0644]

index 22662e0db6c26c7f911e1804d6ea4a998d197453..3295ca4a2786ada79c67c91ff056bbb6e13cb0ef 100644 (file)
@@ -96,6 +96,7 @@ LANGOPT(MathErrno         , 1, 1, "errno support for math functions")
 BENIGN_LANGOPT(HeinousExtensions , 1, 0, "Extensions that we really don't like and may be ripped out at any time")
 LANGOPT(Modules           , 1, 0, "modules extension to C")
 LANGOPT(ModulesDeclUse    , 1, 0, "require declaration of module uses")
+LANGOPT(ModulesStrictDeclUse, 1, 0, "require declaration of module uses and all headers to be in modules")
 LANGOPT(Optimize          , 1, 0, "__OPTIMIZE__ predefined macro")
 LANGOPT(OptimizeSize      , 1, 0, "__OPTIMIZE_SIZE__ predefined macro")
 LANGOPT(Static            , 1, 0, "__STATIC__ predefined macro (as opposed to __DYNAMIC__)")
index d71cd5fd7026cbfcb8df17d12290f83139683902..1c84d74b8cc9cbe208a9d620cccce083192b2ac4 100644 (file)
@@ -607,6 +607,9 @@ def fmodules_ignore_macro : Joined<["-"], "fmodules-ignore-macro=">, Group<f_Gro
 def fmodules_decluse : Flag <["-"], "fmodules-decluse">, Group<f_Group>,
   Flags<[DriverOption,CC1Option]>,
   HelpText<"Require declaration of modules used within a module">;
+def fmodules_strict_decluse : Flag <["-"], "fmodules-strict-decluse">, Group<f_Group>,
+  Flags<[DriverOption,CC1Option]>,
+  HelpText<"Like -fmodules-decluse but requires all headers to be in modules">;
 def fretain_comments_from_system_headers : Flag<["-"], "fretain-comments-from-system-headers">, Group<f_Group>, Flags<[CC1Option]>;
 
 def fmudflapth : Flag<["-"], "fmudflapth">, Group<f_Group>;
@@ -666,6 +669,8 @@ def fno_module_maps : Flag <["-"], "fno-module-maps">, Group<f_Group>,
   Flags<[DriverOption]>;
 def fno_modules_decluse : Flag <["-"], "fno-modules-decluse">, Group<f_Group>,
   Flags<[DriverOption]>;
+def fno_modules_strict_decluse : Flag <["-"], "fno-strict-modules-decluse">, Group<f_Group>,
+  Flags<[DriverOption]>;
 def fno_ms_extensions : Flag<["-"], "fno-ms-extensions">, Group<f_Group>;
 def fno_ms_compatibility : Flag<["-"], "fno-ms-compatibility">, Group<f_Group>;
 def fno_delayed_template_parsing : Flag<["-"], "fno-delayed-template-parsing">, Group<f_Group>;
index 28702836de1ab868338f3f7ef42b9a8de2d1c41f..9eb6fd44d63da2d930bd76090f3f382072b9f7a7 100644 (file)
@@ -3469,6 +3469,14 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA,
     CmdArgs.push_back("-fmodules-decluse");
   }
 
+  // -fmodules-strict-decluse is like -fmodule-decluse, but also checks that
+  // all #included headers are part of modules.
+  if (Args.hasFlag(options::OPT_fmodules_strict_decluse,
+                   options::OPT_fno_modules_strict_decluse,
+                   false)) {
+    CmdArgs.push_back("-fmodules-strict-decluse");
+  }
+
   // -fmodule-name specifies the module that is currently being built (or
   // used for header checking by -fmodule-maps).
   if (Arg *A = Args.getLastArg(options::OPT_fmodule_name)) {
index b9706e8263ba87e94ad314d10e94dcbea2bca8b6..b22ea9a07f618fe39d3a79be7c28c423f4f0045a 100644 (file)
@@ -1343,7 +1343,9 @@ static void ParseLangArgs(LangOptions &Opts, ArgList &Args, InputKind IK,
   Opts.Blocks = Args.hasArg(OPT_fblocks);
   Opts.BlocksRuntimeOptional = Args.hasArg(OPT_fblocks_runtime_optional);
   Opts.Modules = Args.hasArg(OPT_fmodules);
-  Opts.ModulesDeclUse = Args.hasArg(OPT_fmodules_decluse);
+  Opts.ModulesStrictDeclUse = Args.hasArg(OPT_fmodules_strict_decluse);
+  Opts.ModulesDeclUse =
+      Args.hasArg(OPT_fmodules_decluse) || Opts.ModulesStrictDeclUse;
   Opts.CharIsSigned = Opts.OpenCL || !Args.hasArg(OPT_fno_signed_char);
   Opts.WChar = Opts.CPlusPlus && !Args.hasArg(OPT_fno_wchar);
   Opts.ShortWChar = Args.hasFlag(OPT_fshort_wchar, OPT_fno_short_wchar, false);
index f0dcc1a14927349b87ceaaac4826ee98599a0cc4..689ef73b4668c0105c7631a859a75e9bb719400f 100644 (file)
@@ -243,8 +243,12 @@ void ModuleMap::diagnoseHeaderInclusion(Module *RequestingModule,
     resolveUses(RequestingModule, /*Complain=*/false);
 
   HeadersMap::iterator Known = findKnownHeader(File);
-  if (Known == Headers.end())
+  if (Known == Headers.end()) {
+    if (LangOpts.ModulesStrictDeclUse)
+      Diags.Report(FilenameLoc, diag::error_undeclared_use_of_module)
+          << RequestingModule->getFullModuleName() << Filename;
     return;
+  }
 
   Module *Private = NULL;
   Module *NotUsed = NULL;
diff --git a/test/Modules/strict-decluse.cpp b/test/Modules/strict-decluse.cpp
new file mode 100644 (file)
index 0000000..fa6955a
--- /dev/null
@@ -0,0 +1,9 @@
+// RUN: rm -rf %t
+// RUN: %clang_cc1 -fmodule-maps -fmodules-cache-path=%t -fmodules-strict-decluse -fmodule-name=XG -I %S/Inputs/declare-use %s -verify
+
+#include "g.h"
+#include "e.h"
+#include "f.h" // expected-error {{module XG does not depend on a module exporting 'f.h'}}
+#include "i.h" // expected-error {{module XG does not depend on a module exporting 'i.h'}}
+
+const int g2 = g1 + e + f + aux_i;