Index: include/clang/Basic/LangOptions.def =================================================================== --- include/clang/Basic/LangOptions.def +++ include/clang/Basic/LangOptions.def @@ -90,6 +90,7 @@ 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: include/clang/Basic/TokenKinds.def =================================================================== --- include/clang/Basic/TokenKinds.def +++ include/clang/Basic/TokenKinds.def @@ -469,8 +469,11 @@ 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: include/clang/Driver/Options.td =================================================================== --- include/clang/Driver/Options.td +++ include/clang/Driver/Options.td @@ -516,6 +516,8 @@ def fdiagnostics_show_template_tree : Flag<["-"], "fdiagnostics-show-template-tree">, Group, Flags<[CC1Option]>, HelpText<"Print a template comparison tree for differing templates">; +def fdeclspec : Flag<["-"], "fdeclspec">, Group, + HelpText<"Allow __declspec as a keyword">, Flags<[CC1Option]>; def fdollars_in_identifiers : Flag<["-"], "fdollars-in-identifiers">, Group, HelpText<"Allow '$' in identifiers">, Flags<[CC1Option]>; def fdwarf2_cfi_asm : Flag<["-"], "fdwarf2-cfi-asm">, Group; @@ -808,6 +810,8 @@ def fno_diagnostics_show_option : Flag<["-"], "fno-diagnostics-show-option">, Group; def fno_diagnostics_show_note_include_stack : Flag<["-"], "fno-diagnostics-show-note-include-stack">, Flags<[CC1Option]>, Group; +def fno_declspec : Flag<["-"], "fno-declspec">, Group, + HelpText<"Disallow __declspec as a keyword">, Flags<[CC1Option]>; def fno_dollars_in_identifiers : Flag<["-"], "fno-dollars-in-identifiers">, Group, HelpText<"Disallow '$' in identifiers">, Flags<[CC1Option]>; def fno_elide_constructors : Flag<["-"], "fno-elide-constructors">, Group, Index: include/clang/Parse/Parser.h =================================================================== --- include/clang/Parse/Parser.h +++ include/clang/Parse/Parser.h @@ -2165,8 +2165,7 @@ 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: lib/Basic/IdentifierTable.cpp =================================================================== --- lib/Basic/IdentifierTable.cpp +++ lib/Basic/IdentifierTable.cpp @@ -220,10 +220,7 @@ 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: lib/Driver/Tools.cpp =================================================================== --- lib/Driver/Tools.cpp +++ lib/Driver/Tools.cpp @@ -4655,6 +4655,13 @@ 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: lib/Frontend/CompilerInvocation.cpp =================================================================== --- lib/Frontend/CompilerInvocation.cpp +++ lib/Frontend/CompilerInvocation.cpp @@ -1630,6 +1630,17 @@ 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: lib/Parse/ParseDecl.cpp =================================================================== --- lib/Parse/ParseDecl.cpp +++ lib/Parse/ParseDecl.cpp @@ -532,9 +532,7 @@ /// 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: test/Lexer/keywords_test.c =================================================================== --- test/Lexer/keywords_test.c +++ test/Lexer/keywords_test.c @@ -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 @@ // 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: test/Lexer/keywords_test.cpp =================================================================== --- test/Lexer/keywords_test.cpp +++ test/Lexer/keywords_test.cpp @@ -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) @@ -12,6 +25,12 @@ #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 @@ CONCEPTS_KEYWORD(concept); CONCEPTS_KEYWORD(requires); +// __declspec extension +DECLSPEC_KEYWORD(__declspec); + // Clang extension IS_KEYWORD(__char16_t); IS_TYPE(__char16_t);