]> granicus.if.org Git - clang/commitdiff
Add cc1 option '-fmodule-feature' to add custom values for 'requires' decls
authorBen Langmuir <blangmuir@apple.com>
Mon, 2 Feb 2015 21:56:15 +0000 (21:56 +0000)
committerBen Langmuir <blangmuir@apple.com>
Mon, 2 Feb 2015 21:56:15 +0000 (21:56 +0000)
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

include/clang/Basic/LangOptions.h
include/clang/Driver/CC1Options.td
lib/Basic/Module.cpp
lib/Frontend/CompilerInvocation.cpp
test/Modules/Inputs/DependsOnModule.framework/module.map
test/Modules/requires.m

index 5ac96c51985598895f35f454ced5fa40c665fedf..a021be18051ef19aa65d5c7a3cd9e589ca60a6b5 100644 (file)
@@ -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<std::string> ModuleFeatures;
+
   /// \brief Options for parsing comments.
   CommentOptions CommentOpts;
   
index 4406fc83cf360aece0d8d9facda9ad5c8c96d395..9debfffd4d1513f7af699c3e0cc3504bdb408559 100644 (file)
@@ -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=<FILE>">;
+def fmodule_feature : Separate<["-"], "fmodule-feature">,
+  MetaVarName<"<feature>">,
+  HelpText<"Enable <feature> in module map requires declarations">;
 
 let Group = Action_Group in {
 
index 03f9bd3f329cc8d322072c9b160cc8b4d401f637..e7e37ced80909988c84c796a93527e8b7965e2f9 100644 (file)
@@ -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<bool>(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<bool>(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,
index b5685d81f9da1d0321f87f7f2154c5bf3aca907d..3b7fbb0e137f5cbef4b24004653827a250510fa5 100644 (file)
@@ -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);
index 5a1cacaad2a3eadcf7a5090ae1d01571a50a9482..b62308583df43e2218325f4b2632bb6e2d339c73 100644 (file)
@@ -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"
index b8b2c55698c42d1b3fe81e4755224018f0e94d24..ff0ddfeb335989fc2dd46ad919a44c124c07c526 100644 (file)
@@ -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'}}