From: Ben Langmuir Date: Mon, 2 Feb 2015 21:56:15 +0000 (+0000) Subject: Add cc1 option '-fmodule-feature' to add custom values for 'requires' decls X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=00d7f4c3443ab62b0ee56c0461845994df8faaaf;p=clang Add cc1 option '-fmodule-feature' to add custom values for 'requires' decls This allows clang-based tools to specify custom features that can be tested by the 'requires' declaration in a module map file. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@227868 91177308-0d34-0410-b5e6-96231b3b80d8 --- diff --git a/include/clang/Basic/LangOptions.h b/include/clang/Basic/LangOptions.h index 5ac96c5198..a021be1805 100644 --- a/include/clang/Basic/LangOptions.h +++ b/include/clang/Basic/LangOptions.h @@ -92,6 +92,10 @@ public: /// treat this as the CurrentModule. std::string ImplementationOfModule; + /// \brief The names of any features to enable in module 'requires' decls + /// in addition to the hard-coded list in Module.cpp and the target features. + std::vector ModuleFeatures; + /// \brief Options for parsing comments. CommentOptions CommentOpts; diff --git a/include/clang/Driver/CC1Options.td b/include/clang/Driver/CC1Options.td index 4406fc83cf..9debfffd4d 100644 --- a/include/clang/Driver/CC1Options.td +++ b/include/clang/Driver/CC1Options.td @@ -342,6 +342,9 @@ def fmodule_implementation_of : Separate<["-"], "fmodule-implementation-of">, def fmodule_map_file_home_is_cwd : Flag<["-"], "fmodule-map-file-home-is-cwd">, HelpText<"Use the current working directory as the home directory of " "module maps specified by -fmodule-map-file=">; +def fmodule_feature : Separate<["-"], "fmodule-feature">, + MetaVarName<"">, + HelpText<"Enable in module map requires declarations">; let Group = Action_Group in { diff --git a/lib/Basic/Module.cpp b/lib/Basic/Module.cpp index 03f9bd3f32..e7e37ced80 100644 --- a/lib/Basic/Module.cpp +++ b/lib/Basic/Module.cpp @@ -58,16 +58,21 @@ Module::~Module() { /// language options has the given feature. static bool hasFeature(StringRef Feature, const LangOptions &LangOpts, const TargetInfo &Target) { - return llvm::StringSwitch(Feature) - .Case("altivec", LangOpts.AltiVec) - .Case("blocks", LangOpts.Blocks) - .Case("cplusplus", LangOpts.CPlusPlus) - .Case("cplusplus11", LangOpts.CPlusPlus11) - .Case("objc", LangOpts.ObjC1) - .Case("objc_arc", LangOpts.ObjCAutoRefCount) - .Case("opencl", LangOpts.OpenCL) - .Case("tls", Target.isTLSSupported()) - .Default(Target.hasFeature(Feature)); + bool HasFeature = llvm::StringSwitch(Feature) + .Case("altivec", LangOpts.AltiVec) + .Case("blocks", LangOpts.Blocks) + .Case("cplusplus", LangOpts.CPlusPlus) + .Case("cplusplus11", LangOpts.CPlusPlus11) + .Case("objc", LangOpts.ObjC1) + .Case("objc_arc", LangOpts.ObjCAutoRefCount) + .Case("opencl", LangOpts.OpenCL) + .Case("tls", Target.isTLSSupported()) + .Default(Target.hasFeature(Feature)); + if (!HasFeature) + HasFeature = std::find(LangOpts.ModuleFeatures.begin(), + LangOpts.ModuleFeatures.end(), + Feature) != LangOpts.ModuleFeatures.end(); + return HasFeature; } bool Module::isAvailable(const LangOptions &LangOpts, const TargetInfo &Target, diff --git a/lib/Frontend/CompilerInvocation.cpp b/lib/Frontend/CompilerInvocation.cpp index b5685d81f9..3b7fbb0e13 100644 --- a/lib/Frontend/CompilerInvocation.cpp +++ b/lib/Frontend/CompilerInvocation.cpp @@ -1568,6 +1568,7 @@ static void ParseLangArgs(LangOptions &Opts, ArgList &Args, InputKind IK, Opts.CurrentModule = Args.getLastArgValue(OPT_fmodule_name); Opts.ImplementationOfModule = Args.getLastArgValue(OPT_fmodule_implementation_of); + Opts.ModuleFeatures = Args.getAllArgValues(OPT_fmodule_feature); Opts.NativeHalfType = Opts.NativeHalfType; Opts.HalfArgsAndReturns = Args.hasArg(OPT_fallow_half_arguments_and_returns); Opts.GNUAsm = !Args.hasArg(OPT_fno_gnu_inline_asm); diff --git a/test/Modules/Inputs/DependsOnModule.framework/module.map b/test/Modules/Inputs/DependsOnModule.framework/module.map index 5a1cacaad2..b62308583d 100644 --- a/test/Modules/Inputs/DependsOnModule.framework/module.map +++ b/test/Modules/Inputs/DependsOnModule.framework/module.map @@ -16,6 +16,12 @@ framework module DependsOnModule { requires !objc header "not_objc.h" } + explicit module CustomReq1 { + requires custom_req1 + } + explicit module CustomReq2 { + requires custom_req2 + } explicit framework module SubFramework { umbrella header "SubFramework.h" diff --git a/test/Modules/requires.m b/test/Modules/requires.m index b8b2c55698..ff0ddfeb33 100644 --- a/test/Modules/requires.m +++ b/test/Modules/requires.m @@ -1,6 +1,8 @@ // RUN: rm -rf %t -// RUN: %clang_cc1 -Wauto-import -fmodules-cache-path=%t -fmodules -F %S/Inputs %s -verify +// RUN: %clang_cc1 -Wauto-import -fmodules-cache-path=%t -fmodules -F %S/Inputs %s -verify -fmodule-feature custom_req1 @import DependsOnModule.CXX; // expected-error{{module 'DependsOnModule.CXX' requires feature 'cplusplus'}} @import DependsOnModule.NotCXX; @import DependsOnModule.NotObjC; // expected-error{{module 'DependsOnModule.NotObjC' is incompatible with feature 'objc'}} +@import DependsOnModule.CustomReq1; // OK +@import DependsOnModule.CustomReq2; // expected-error{{module 'DependsOnModule.CustomReq2' requires feature 'custom_req2'}}