]> granicus.if.org Git - clang/commitdiff
Add -f[no-]declspec to control recognition of __declspec as a keyword
authorSaleem Abdulrasool <compnerd@compnerd.org>
Sun, 4 Oct 2015 17:51:05 +0000 (17:51 +0000)
committerSaleem Abdulrasool <compnerd@compnerd.org>
Sun, 4 Oct 2015 17:51:05 +0000 (17:51 +0000)
In versions of clang prior to r238238, __declspec was recognized as a keyword in
all modes.  It was then changed to only be enabled when Microsoft or Borland
extensions were enabled (and for CUDA, as a temporary measure).  There is a
desire to support __declspec in Playstation code, and possibly other
environments.  This commit adds a command-line switch to allow explicit
enabling/disabling of the recognition of __declspec as a keyword.  Recognition
is enabled by default in Microsoft, Borland, CUDA, and PS4 environments, and
disabled in all other environments.

Patch by Warren Ristow!

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

include/clang/Basic/LangOptions.def
include/clang/Basic/TokenKinds.def
include/clang/Driver/Options.td
include/clang/Parse/Parser.h
lib/Basic/IdentifierTable.cpp
lib/Driver/Tools.cpp
lib/Format/Format.cpp
lib/Frontend/CompilerInvocation.cpp
lib/Parse/ParseDecl.cpp
test/Lexer/keywords_test.c
test/Lexer/keywords_test.cpp

index 2bc0f83ea55d7934b0bc002f6c85fdfe5ce468df..3c380f30019c7033b3cda168a94bc43b62bc76c3 100644 (file)
@@ -90,6 +90,7 @@ LANGOPT(LineComment       , 1, 0, "'//' comments")
 LANGOPT(Bool              , 1, 0, "bool, true, and false keywords")
 LANGOPT(Half              , 1, 0, "half keyword")
 LANGOPT(WChar             , 1, CPlusPlus, "wchar_t keyword")
+LANGOPT(DeclSpecKeyword   , 1, 0, "__declspec keyword")
 BENIGN_LANGOPT(DollarIdents   , 1, 1, "'$' in identifiers")
 BENIGN_LANGOPT(AsmPreprocessor, 1, 0, "preprocessor in asm mode")
 BENIGN_LANGOPT(GNUMode        , 1, 1, "GNU extensions")
index 0c616a85aff5b18ac49ec5de248ead997db0c744..963e036b6d30c74a9482ad40053f695d05b30f69 100644 (file)
@@ -469,8 +469,11 @@ KEYWORD(__array_extent              , KEYCXX)
 KEYWORD(__private_extern__          , KEYALL)
 KEYWORD(__module_private__          , KEYALL)
 
+// Extension that will be enabled for Microsoft, Borland and PS4, but can be
+// disabled via '-fno-declspec'.
+KEYWORD(__declspec                  , 0)
+
 // Microsoft Extension.
-KEYWORD(__declspec                  , KEYMS|KEYBORLAND)
 KEYWORD(__cdecl                     , KEYALL)
 KEYWORD(__stdcall                   , KEYALL)
 KEYWORD(__fastcall                  , KEYALL)
index e4b461fe9a4225cd05be9d200abc07ee1b98623a..ff01f19f4ba42602c7a3e2d61d4245be366470c2 100644 (file)
@@ -516,6 +516,8 @@ def fdiagnostics_show_category_EQ : Joined<["-"], "fdiagnostics-show-category=">
 def fdiagnostics_show_template_tree : Flag<["-"], "fdiagnostics-show-template-tree">,
     Group<f_Group>, Flags<[CC1Option]>,
     HelpText<"Print a template comparison tree for differing templates">;
+def fdeclspec : Flag<["-"], "fdeclspec">, Group<f_clang_Group>,
+  HelpText<"Allow __declspec as a keyword">, Flags<[CC1Option]>;
 def fdollars_in_identifiers : Flag<["-"], "fdollars-in-identifiers">, Group<f_Group>,
   HelpText<"Allow '$' in identifiers">, Flags<[CC1Option]>;
 def fdwarf2_cfi_asm : Flag<["-"], "fdwarf2-cfi-asm">, Group<clang_ignored_f_Group>;
@@ -808,6 +810,8 @@ def fno_diagnostics_fixit_info : Flag<["-"], "fno-diagnostics-fixit-info">, Grou
 def fno_diagnostics_show_option : Flag<["-"], "fno-diagnostics-show-option">, Group<f_Group>;
 def fno_diagnostics_show_note_include_stack : Flag<["-"], "fno-diagnostics-show-note-include-stack">,
     Flags<[CC1Option]>, Group<f_Group>;
+def fno_declspec : Flag<["-"], "fno-declspec">, Group<f_clang_Group>,
+  HelpText<"Disallow __declspec as a keyword">, Flags<[CC1Option]>;
 def fno_dollars_in_identifiers : Flag<["-"], "fno-dollars-in-identifiers">, Group<f_Group>,
   HelpText<"Disallow '$' in identifiers">, Flags<[CC1Option]>;
 def fno_elide_constructors : Flag<["-"], "fno-elide-constructors">, Group<f_Group>,
index 54bac154894b0be4a70bcf7340d20717353a4ab3..d2afff592511acd7f8718d5a65d257850c6d9efc 100644 (file)
@@ -2165,8 +2165,7 @@ private:
   void MaybeParseMicrosoftDeclSpecs(ParsedAttributes &Attrs,
                                     SourceLocation *End = nullptr) {
     const auto &LO = getLangOpts();
-    if ((LO.MicrosoftExt || LO.Borland || LO.CUDA) &&
-        Tok.is(tok::kw___declspec))
+    if (LO.DeclSpecKeyword && Tok.is(tok::kw___declspec))
       ParseMicrosoftDeclSpecs(Attrs, End);
   }
   void ParseMicrosoftDeclSpecs(ParsedAttributes &Attrs,
index 7705834d91a05a11304f99b07fe4171b9cee7162..199815aa891b5be6854ba9c627f7c5bcf56683b4 100644 (file)
@@ -220,10 +220,7 @@ void IdentifierTable::AddKeywords(const LangOptions &LangOpts) {
     AddKeyword("__unknown_anytype", tok::kw___unknown_anytype, KEYALL,
                LangOpts, *this);
 
-  // FIXME: __declspec isn't really a CUDA extension, however it is required for
-  // supporting cuda_builtin_vars.h, which uses __declspec(property). Once that
-  // has been rewritten in terms of something more generic, remove this code.
-  if (LangOpts.CUDA)
+  if (LangOpts.DeclSpecKeyword)
     AddKeyword("__declspec", tok::kw___declspec, KEYALL, LangOpts, *this);
 }
 
index 7cccf09665ca7ea38d00cbf2e1272dbfdc3016fe..1b42ff70f2b9e52fc4cb0d9b3b76ae8a5f080a0f 100644 (file)
@@ -4610,6 +4610,13 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA,
                    options::OPT_fno_borland_extensions, false))
     CmdArgs.push_back("-fborland-extensions");
 
+  // -fno-declspec is default, except for PS4.
+  if (Args.hasFlag(options::OPT_fdeclspec, options::OPT_fno_declspec,
+                   getToolChain().getTriple().isPS4()))
+    CmdArgs.push_back("-fdeclspec");
+  else if (Args.hasArg(options::OPT_fno_declspec))
+    CmdArgs.push_back("-fno-declspec"); // Explicitly disabling __declspec.
+
   // -fthreadsafe-static is default, except for MSVC compatibility versions less
   // than 19.
   if (!Args.hasFlag(options::OPT_fthreadsafe_statics,
index d8a15e4cdfbbb1b493166284d3dd974948ce7d4b..fffd80cb682ff29be596cf3b6d36405412da06b5 100644 (file)
@@ -1826,6 +1826,7 @@ LangOptions getFormattingLangOpts(const FormatStyle &Style) {
   LangOpts.ObjC1 = 1;
   LangOpts.ObjC2 = 1;
   LangOpts.MicrosoftExt = 1; // To get kw___try, kw___finally.
+  LangOpts.DeclSpecKeyword = 1; // To get __declspec.
   return LangOpts;
 }
 
index 5f81ce268cf15feef31381528fa1d76726282d85..a1afd80f69917977ea71a709e58fce0778e68929 100644 (file)
@@ -1630,6 +1630,17 @@ static void ParseLangArgs(LangOptions &Opts, ArgList &Args, InputKind IK,
   Opts.HalfArgsAndReturns = Args.hasArg(OPT_fallow_half_arguments_and_returns);
   Opts.GNUAsm = !Args.hasArg(OPT_fno_gnu_inline_asm);
 
+  // __declspec is enabled by default for the PS4 by the driver, and also
+  // enabled for Microsoft Extensions or Borland Extensions, here.
+  //
+  // FIXME: __declspec is also currently enabled for CUDA, but isn't really a
+  // CUDA extension, however it is required for supporting cuda_builtin_vars.h,
+  // which uses __declspec(property). Once that has been rewritten in terms of
+  // something more generic, remove the Opts.CUDA term here.
+  Opts.DeclSpecKeyword =
+      Args.hasFlag(OPT_fdeclspec, OPT_fno_declspec,
+                   (Opts.MicrosoftExt || Opts.Borland || Opts.CUDA));
+
   if (!Opts.CurrentModule.empty() && !Opts.ImplementationOfModule.empty() &&
       Opts.CurrentModule != Opts.ImplementationOfModule) {
     Diags.Report(diag::err_conflicting_module_names)
index f5983c0295eb87d71a635cfb0f11a8507eac8344..ccd0ed104f5825e1a1157b7e45137232b7176011 100644 (file)
@@ -532,9 +532,7 @@ bool Parser::ParseMicrosoftDeclSpecArgs(IdentifierInfo *AttrName,
 ///             extended-decl-modifier extended-decl-modifier-seq
 void Parser::ParseMicrosoftDeclSpecs(ParsedAttributes &Attrs,
                                      SourceLocation *End) {
-  assert((getLangOpts().MicrosoftExt || getLangOpts().Borland ||
-          getLangOpts().CUDA) &&
-         "Incorrect language options for parsing __declspec");
+  assert(getLangOpts().DeclSpecKeyword && "__declspec keyword is not enabled");
   assert(Tok.is(tok::kw___declspec) && "Not a declspec!");
 
   while (Tok.is(tok::kw___declspec)) {
index 4eb1700e9b609b85649636c8083928b1784ca5de..7f840c1154ca6f405c8707c9ffb0b07ff1845a4c 100644 (file)
@@ -9,6 +9,10 @@
 
 // RUN: %clang_cc1 -std=c99 -fms-extensions -E %s -o - \
 // RUN:     | FileCheck --check-prefix=CHECK-MS-KEYWORDS %s
+// RUN: %clang_cc1 -std=c99 -fdeclspec -E %s -o - \
+// RUN:     | FileCheck --check-prefix=CHECK-DECLSPEC-KEYWORD %s
+// RUN: %clang_cc1 -std=c99 -fms-extensions -fno-declspec -E %s -o - \
+// RUN:     | FileCheck --check-prefix=CHECK-MS-KEYWORDS-WITHOUT-DECLSPEC %s
 
 void f() {
 // CHECK-NONE: int asm
@@ -22,8 +26,19 @@ void f() {
 
 // CHECK-NONE: no_ms_wchar
 // CHECK-MS-KEYWORDS: has_ms_wchar
+// CHECK-MS-KEYWORDS-WITHOUT-DECLSPEC: has_ms_wchar
 #if __is_identifier(__wchar_t)
 void no_ms_wchar();
 #else
 void has_ms_wchar();
 #endif
+
+// CHECK-NONE: no_declspec
+// CHECK-MS-KEYWORDS: has_declspec
+// CHECK-MS-KEYWORDS-WITHOUT-DECLSPEC: no_declspec
+// CHECK-DECLSPEC-KEYWORD: has_declspec
+#if __is_identifier(__declspec)
+void no_declspec();
+#else
+void has_declspec();
+#endif
index dd45b40edcabdfb4143888da85ca7e5abf9ce13f..aba8d023c761136c143f19bd2d1c714fa8008442 100644 (file)
@@ -1,6 +1,19 @@
 // RUN: %clang_cc1 -std=c++03 -fsyntax-only %s
 // RUN: %clang_cc1 -std=c++11 -DCXX11 -fsyntax-only %s
 // RUN: %clang_cc1 -std=c++14 -fconcepts-ts -DCXX11 -DCONCEPTS -fsyntax-only %s
+// RUN: %clang_cc1 -std=c++03 -fdeclspec -DDECLSPEC -fsyntax-only %s
+// RUN: %clang_cc1 -std=c++03 -fms-extensions -DDECLSPEC -fsyntax-only %s
+// RUN: %clang_cc1 -std=c++03 -fborland-extensions -DDECLSPEC -fsyntax-only %s
+// RUN: %clang_cc1 -std=c++03 -fms-extensions -fno-declspec -fsyntax-only %s
+// RUN: %clang_cc1 -std=c++03 -fborland-extensions -fno-declspec -fsyntax-only %s
+// RUN: %clang_cc1 -std=c++03 -fno-declspec -fdeclspec -DDECLSPEC -fsyntax-only %s
+// RUN: %clang_cc1 -std=c++03 -fdeclspec -fno-declspec -fsyntax-only %s
+// RUN: %clang_cc1 -std=c++03 -fms-extensions -fno-declspec -fdeclspec -DDECLSPEC -fsyntax-only %s
+// RUN: %clang_cc1 -std=c++03 -fms-extensions -fdeclspec -fno-declspec -fsyntax-only %s
+// RUN: %clang -std=c++03 -target i686-windows-msvc -DDECLSPEC -fsyntax-only %s
+// RUN: %clang -std=c++03 -target x86_64-scei-ps4 -DDECLSPEC -fsyntax-only %s
+// RUN: %clang -std=c++03 -target i686-windows-msvc -fno-declspec -fsyntax-only %s
+// RUN: %clang -std=c++03 -target x86_64-scei-ps4 -fno-declspec -fsyntax-only %s
 
 #define IS_KEYWORD(NAME) _Static_assert(!__is_identifier(NAME), #NAME)
 #define NOT_KEYWORD(NAME) _Static_assert(__is_identifier(NAME), #NAME)
 #define CONCEPTS_KEYWORD(NAME)  NOT_KEYWORD(NAME)
 #endif
 
+#ifdef DECLSPEC
+#define DECLSPEC_KEYWORD(NAME)  IS_KEYWORD(NAME)
+#else
+#define DECLSPEC_KEYWORD(NAME)  NOT_KEYWORD(NAME)
+#endif
+
 #ifdef CXX11
 #define CXX11_KEYWORD(NAME)  IS_KEYWORD(NAME)
 #define CXX11_TYPE(NAME)     IS_TYPE(NAME)
@@ -38,6 +57,9 @@ CXX11_KEYWORD(thread_local);
 CONCEPTS_KEYWORD(concept);
 CONCEPTS_KEYWORD(requires);
 
+// __declspec extension
+DECLSPEC_KEYWORD(__declspec);
+
 // Clang extension
 IS_KEYWORD(__char16_t);
 IS_TYPE(__char16_t);