From: Reid Kleckner Date: Fri, 15 Feb 2019 19:59:45 +0000 (+0000) Subject: [MSVC] Recognize `static_assert` keyword in C and C++98 X-Git-Tag: llvmorg-10-init~11855 X-Git-Url: http://review.tizen.org/git/?a=commitdiff_plain;h=c1648f2bfdc8cdc72c8304a56b9450a65c182ff9;p=platform%2Fupstream%2Fllvm.git [MSVC] Recognize `static_assert` keyword in C and C++98 Summary: The main effect is that clang now accepts the following conforming C11 code with MSVC headers: #include static_assert(1, "true"); This is a non-conforming extension (the keyword is outside the implementer's namespace), so it is placed under -fms-compatibility instead of -fms-extensions like most MSVC-specific keyword extensions. Normally, in C11, the compiler is supposed to provide the _Static_assert keyword, and assert.h should define static_assert to _Static_assert. However, that is not what MSVC does, and MSVC doesn't even provide _Static_assert. This also has the less important side effect of enabling static_assert in C++98 mode with -fms-compatibility. It's exceptionally difficult to use modern MSVC headers without C++14 even, so this is relatively unimportant. Fixes PR26672 Patch by Andrey Bokhanko! Reviewers: rsmith, thakis Subscribers: cfe-commits, STL_MSFT Differential Revision: https://reviews.llvm.org/D17444 llvm-svn: 354162 --- diff --git a/clang/include/clang/Basic/TokenKinds.def b/clang/include/clang/Basic/TokenKinds.def index a9ae067..01b2f62 100644 --- a/clang/include/clang/Basic/TokenKinds.def +++ b/clang/include/clang/Basic/TokenKinds.def @@ -243,6 +243,7 @@ PUNCTUATOR(caretcaret, "^^") // are enabled. // KEYGNU - This is a keyword if GNU extensions are enabled // KEYMS - This is a keyword if Microsoft extensions are enabled +// KEYMSCOMPAT - This is a keyword if Microsoft compatibility mode is enabled // KEYNOMS18 - This is a keyword that must never be enabled under // MSVC <= v18. // KEYOPENCLC - This is a keyword in OpenCL C @@ -363,7 +364,7 @@ CXX11_KEYWORD(constexpr , 0) CXX11_KEYWORD(decltype , 0) CXX11_KEYWORD(noexcept , 0) CXX11_KEYWORD(nullptr , 0) -CXX11_KEYWORD(static_assert , 0) +CXX11_KEYWORD(static_assert , KEYMSCOMPAT) CXX11_KEYWORD(thread_local , 0) // C++2a / concepts TS keywords diff --git a/clang/lib/Basic/IdentifierTable.cpp b/clang/lib/Basic/IdentifierTable.cpp index 3a87f91..7dfcc9c 100644 --- a/clang/lib/Basic/IdentifierTable.cpp +++ b/clang/lib/Basic/IdentifierTable.cpp @@ -99,6 +99,7 @@ namespace { KEYMODULES = 0x100000, KEYCXX2A = 0x200000, KEYOPENCLCXX = 0x400000, + KEYMSCOMPAT = 0x800000, KEYALLCXX = KEYCXX | KEYCXX11 | KEYCXX2A, KEYALL = (0xffffff & ~KEYNOMS18 & ~KEYNOOPENCL) // KEYNOMS18 and KEYNOOPENCL are used to exclude. @@ -125,6 +126,7 @@ static KeywordStatus getKeywordStatus(const LangOptions &LangOpts, if (LangOpts.C99 && (Flags & KEYC99)) return KS_Enabled; if (LangOpts.GNUKeywords && (Flags & KEYGNU)) return KS_Extension; if (LangOpts.MicrosoftExt && (Flags & KEYMS)) return KS_Extension; + if (LangOpts.MSVCCompat && (Flags & KEYMSCOMPAT)) return KS_Enabled; if (LangOpts.Borland && (Flags & KEYBORLAND)) return KS_Extension; if (LangOpts.Bool && (Flags & BOOLSUPPORT)) return KS_Enabled; if (LangOpts.Half && (Flags & HALFSUPPORT)) return KS_Enabled; diff --git a/clang/test/Lexer/keywords_test.c b/clang/test/Lexer/keywords_test.c index 7f840c1..1677814 100644 --- a/clang/test/Lexer/keywords_test.c +++ b/clang/test/Lexer/keywords_test.c @@ -7,7 +7,7 @@ // RUN: %clang_cc1 -std=gnu89 -fno-gnu-keywords -E %s -o - \ // RUN: | FileCheck --check-prefix=CHECK-NONE %s -// RUN: %clang_cc1 -std=c99 -fms-extensions -E %s -o - \ +// RUN: %clang_cc1 -std=c99 -fms-extensions -fms-compatibility -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 @@ -42,3 +42,13 @@ void no_declspec(); #else void has_declspec(); #endif + +// CHECK-NONE: no_static_assert +// CHECK-GNU-KEYWORDS: no_static_assert +// CHECK-MS-KEYWORDS: has_static_assert +// CHECK-MS-KEYWORDS-WITHOUT-DECLSPEC: no_static_assert +#if __is_identifier(static_assert) +void no_static_assert(); +#else +void has_static_assert(); +#endif diff --git a/clang/test/Lexer/keywords_test.cpp b/clang/test/Lexer/keywords_test.cpp index e7edf96..4c6ccca3 100644 --- a/clang/test/Lexer/keywords_test.cpp +++ b/clang/test/Lexer/keywords_test.cpp @@ -11,9 +11,9 @@ // 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 i686-windows-msvc -DMS -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 i686-windows-msvc -DMS -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) @@ -51,7 +51,12 @@ CXX11_KEYWORD(char32_t); CXX11_TYPE(char32_t); CXX11_KEYWORD(constexpr); CXX11_KEYWORD(noexcept); +#ifndef MS CXX11_KEYWORD(static_assert); +#else +// MS compiler recognizes static_assert in all modes. So should we. +IS_KEYWORD(static_assert); +#endif CXX11_KEYWORD(thread_local); // Concepts TS keywords