From: Daniel Jasper Date: Fri, 11 Apr 2014 11:47:45 +0000 (+0000) Subject: Add -fmodules-strict-decluse to check that all headers are in modules X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=0e1ed6bc355fa2e5d967c82c4124b1674e0131d2;p=clang Add -fmodules-strict-decluse to check that all headers are in modules Review: http://reviews.llvm.org/D3335 git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@206027 91177308-0d34-0410-b5e6-96231b3b80d8 --- diff --git a/include/clang/Basic/LangOptions.def b/include/clang/Basic/LangOptions.def index 22662e0db6..3295ca4a27 100644 --- a/include/clang/Basic/LangOptions.def +++ b/include/clang/Basic/LangOptions.def @@ -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__)") diff --git a/include/clang/Driver/Options.td b/include/clang/Driver/Options.td index d71cd5fd70..1c84d74b8c 100644 --- a/include/clang/Driver/Options.td +++ b/include/clang/Driver/Options.td @@ -607,6 +607,9 @@ def fmodules_ignore_macro : Joined<["-"], "fmodules-ignore-macro=">, Group, Group, Flags<[DriverOption,CC1Option]>, HelpText<"Require declaration of modules used within a module">; +def fmodules_strict_decluse : Flag <["-"], "fmodules-strict-decluse">, 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, Flags<[CC1Option]>; def fmudflapth : Flag<["-"], "fmudflapth">, Group; @@ -666,6 +669,8 @@ def fno_module_maps : Flag <["-"], "fno-module-maps">, Group, Flags<[DriverOption]>; def fno_modules_decluse : Flag <["-"], "fno-modules-decluse">, Group, Flags<[DriverOption]>; +def fno_modules_strict_decluse : Flag <["-"], "fno-strict-modules-decluse">, Group, + Flags<[DriverOption]>; def fno_ms_extensions : Flag<["-"], "fno-ms-extensions">, Group; def fno_ms_compatibility : Flag<["-"], "fno-ms-compatibility">, Group; def fno_delayed_template_parsing : Flag<["-"], "fno-delayed-template-parsing">, Group; diff --git a/lib/Driver/Tools.cpp b/lib/Driver/Tools.cpp index 28702836de..9eb6fd44d6 100644 --- a/lib/Driver/Tools.cpp +++ b/lib/Driver/Tools.cpp @@ -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)) { diff --git a/lib/Frontend/CompilerInvocation.cpp b/lib/Frontend/CompilerInvocation.cpp index b9706e8263..b22ea9a07f 100644 --- a/lib/Frontend/CompilerInvocation.cpp +++ b/lib/Frontend/CompilerInvocation.cpp @@ -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); diff --git a/lib/Lex/ModuleMap.cpp b/lib/Lex/ModuleMap.cpp index f0dcc1a149..689ef73b46 100644 --- a/lib/Lex/ModuleMap.cpp +++ b/lib/Lex/ModuleMap.cpp @@ -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 index 0000000000..fa6955aef0 --- /dev/null +++ b/test/Modules/strict-decluse.cpp @@ -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;