From bcdcbd11ba68649eb9c7579d7002f36907d3b9a9 Mon Sep 17 00:00:00 2001 From: Eric Fiselier Date: Fri, 2 Sep 2016 18:43:25 +0000 Subject: [PATCH] Revert r280516 since it contained accidental changes. llvm-svn: 280521 --- clang/include/clang/Basic/Attr.td | 10 - clang/include/clang/Basic/AttrDocs.td | 67 +---- .../clang/Basic/DiagnosticSemaKinds.td | 9 +- clang/include/clang/Sema/AttributeList.h | 1 - clang/lib/Sema/SemaDecl.cpp | 74 ++--- clang/lib/Sema/SemaDeclAttr.cpp | 3 - .../attr-require-constant-initialization.cpp | 282 ------------------ clang/utils/TableGen/ClangAttrEmitter.cpp | 4 +- 8 files changed, 42 insertions(+), 408 deletions(-) delete mode 100644 clang/test/SemaCXX/attr-require-constant-initialization.cpp diff --git a/clang/include/clang/Basic/Attr.td b/clang/include/clang/Basic/Attr.td index 912d15153828..7da1efe5ff40 100644 --- a/clang/include/clang/Basic/Attr.td +++ b/clang/include/clang/Basic/Attr.td @@ -241,7 +241,6 @@ def MicrosoftExt : LangOpt<"MicrosoftExt">; def Borland : LangOpt<"Borland">; def CUDA : LangOpt<"CUDA">; def COnly : LangOpt<"CPlusPlus", 1>; -def CPlusPlus : LangOpt<"CPlusPlus">; def OpenCL : LangOpt<"OpenCL">; def RenderScript : LangOpt<"RenderScript">; @@ -1381,15 +1380,6 @@ def ReqdWorkGroupSize : InheritableAttr { let Documentation = [Undocumented]; } -def RequireConstantInit : InheritableAttr { - let Spellings = [GNU<"require_constant_initialization">, - CXX11<"clang", "require_constant_initialization">]; - let Subjects = SubjectList<[GlobalVar], ErrorDiag, - "ExpectedStaticOrTLSVar">; - let Documentation = [RequireConstantInitDocs]; - let LangOpts = [CPlusPlus]; -} - def WorkGroupSizeHint : InheritableAttr { let Spellings = [GNU<"work_group_size_hint">]; let Args = [UnsignedArgument<"XDim">, diff --git a/clang/include/clang/Basic/AttrDocs.td b/clang/include/clang/Basic/AttrDocs.td index af494df2a592..9b1ddca05a5d 100644 --- a/clang/include/clang/Basic/AttrDocs.td +++ b/clang/include/clang/Basic/AttrDocs.td @@ -829,43 +829,6 @@ When one method overrides another, the overriding method can be more widely avai }]; } - -def RequireConstantInitDocs : Documentation { - let Category = DocCatVariable; - let Content = [{ -This attribute specifies that the variable to which it is attached is intended -to have a `constant initializer `_ -according to the rules of [basic.start.static]. The variable is required to -have static or thread storage duration. If the initialization of the variable -is not a constant initializer, an error will be produced. This attribute may -only be used in C++. - -Note that in C++03 strict constant expression checking is not done. Instead -the attribute reports if Clang can emit the the variable as a constant, even -if it's not technically a 'constant initializer'. This behavior is non-portable. - -Static storage duration variables with constant initializers avoid hard-to-find -bugs caused by the indeterminate order of dynamic initialization. They can also -be safely used during dynamic initialization across translation units. - -This attribute acts as a compile time assertion that the requirements -for constant initialization have been met. Since these requirements change -between dialects and have subtle pitfalls it's important to fail fast instead -of silently falling back on dynamic initialization. - -.. code-block:: c++ - // -std=c++14 - #define SAFE_STATIC __attribute__((require_constant_initialization)) static - struct T { - constexpr T(int) {} - ~T(); // non-trivial - }; - SAFE_STATIC T x = {42}; // Initialization OK. Doesn't check destructor. - SAFE_STATIC T y = 42; // error: variable does not have a constant initializer - // copy initialization is not a constant expression on a non-literal type. - }]; -} - def WarnMaybeUnusedDocs : Documentation { let Category = DocCatVariable; let Heading = "maybe_unused, unused, gnu::unused"; @@ -882,12 +845,12 @@ variable, a function or method, a function parameter, an enumeration, an enumerator, a non-static data member, or a label. .. code-block: c++ - #include - - [[maybe_unused]] void f([[maybe_unused]] bool thing1, - [[maybe_unused]] bool thing2) { - [[maybe_unused]] bool b = thing1 && thing2; - assert(b); + #include + + [[maybe_unused]] void f([[maybe_unused]] bool thing1, + [[maybe_unused]] bool thing2) { + [[maybe_unused]] bool b = thing1 && thing2; + assert(b); } }]; } @@ -904,15 +867,15 @@ potentially-evaluated discarded-value expression that is not explicitly cast to `void`. .. code-block: c++ - struct [[nodiscard]] error_info { /*...*/ }; - error_info enable_missile_safety_mode(); - - void launch_missiles(); - void test_missiles() { - enable_missile_safety_mode(); // diagnoses - launch_missiles(); - } - error_info &foo(); + struct [[nodiscard]] error_info { /*...*/ }; + error_info enable_missile_safety_mode(); + + void launch_missiles(); + void test_missiles() { + enable_missile_safety_mode(); // diagnoses + launch_missiles(); + } + error_info &foo(); void f() { foo(); } // Does not diagnose, error_info is a reference. }]; } diff --git a/clang/include/clang/Basic/DiagnosticSemaKinds.td b/clang/include/clang/Basic/DiagnosticSemaKinds.td index 414a6b45e7de..a70b27bac2cc 100644 --- a/clang/include/clang/Basic/DiagnosticSemaKinds.td +++ b/clang/include/clang/Basic/DiagnosticSemaKinds.td @@ -2572,7 +2572,7 @@ def warn_attribute_wrong_decl_type : Warning< "Objective-C instance methods|init methods of interface or class extension declarations|" "variables, functions and classes|" "functions, variables, classes, and Objective-C interfaces|" - "Objective-C protocols|variables with static or thread storage duration|" + "Objective-C protocols|" "functions and global variables|structs, unions, and typedefs|structs and typedefs|" "interface or protocol declarations|kernel functions|non-K&R-style functions|" "variables, enums, fields and typedefs|functions, methods, enums, and classes|" @@ -6839,12 +6839,7 @@ def note_inequality_comparison_to_or_assign : Note< def err_incomplete_type_used_in_type_trait_expr : Error< "incomplete type %0 used in type trait expression">; - -def err_require_constant_init_failed : Error< - "variable does not have a constant initializer">; -def note_declared_required_constant_init_here : Note< - "required by 'require_constant_initializer' attribute here">; - + def err_dimension_expr_not_constant_integer : Error< "dimension expression does not evaluate to a constant unsigned int">; diff --git a/clang/include/clang/Sema/AttributeList.h b/clang/include/clang/Sema/AttributeList.h index 6e3dcd7b6227..fcddbecc029c 100644 --- a/clang/include/clang/Sema/AttributeList.h +++ b/clang/include/clang/Sema/AttributeList.h @@ -897,7 +897,6 @@ enum AttributeDeclKind { ExpectedFunctionVariableOrClass, ExpectedFunctionVariableClassOrObjCInterface, ExpectedObjectiveCProtocol, - ExpectedStaticOrTLSVar, ExpectedFunctionGlobalVarMethodOrProperty, ExpectedStructOrUnionOrTypedef, ExpectedStructOrTypedef, diff --git a/clang/lib/Sema/SemaDecl.cpp b/clang/lib/Sema/SemaDecl.cpp index e6381fbe49f4..2a514ab1bd26 100644 --- a/clang/lib/Sema/SemaDecl.cpp +++ b/clang/lib/Sema/SemaDecl.cpp @@ -10393,17 +10393,8 @@ void Sema::CheckCompleteVariableDeclaration(VarDecl *var) { Diag(var->getLocation(), diag::warn_missing_variable_declarations) << var; } - // Cache the result of checking for constant initialization. - Optional CacheHasConstInit; - const Expr *CacheCulprit; - auto checkConstInit = [&]() mutable { - if (!CacheHasConstInit) - CacheHasConstInit = var->getInit()->isConstantInitializer( - Context, var->getType()->isReferenceType(), &CacheCulprit); - return *CacheHasConstInit; - }; - if (var->getTLSKind() == VarDecl::TLS_Static) { + const Expr *Culprit; if (var->getType().isDestructedType()) { // GNU C++98 edits for __thread, [basic.start.term]p3: // The type of an object with thread storage duration shall not @@ -10411,17 +10402,17 @@ void Sema::CheckCompleteVariableDeclaration(VarDecl *var) { Diag(var->getLocation(), diag::err_thread_nontrivial_dtor); if (getLangOpts().CPlusPlus11) Diag(var->getLocation(), diag::note_use_thread_local); - } else if (getLangOpts().CPlusPlus && var->hasInit()) { - if (!checkConstInit()) { - // GNU C++98 edits for __thread, [basic.start.init]p4: - // An object of thread storage duration shall not require dynamic - // initialization. - // FIXME: Need strict checking here. - Diag(CacheCulprit->getExprLoc(), diag::err_thread_dynamic_init) - << CacheCulprit->getSourceRange(); - if (getLangOpts().CPlusPlus11) - Diag(var->getLocation(), diag::note_use_thread_local); - } + } else if (getLangOpts().CPlusPlus && var->hasInit() && + !var->getInit()->isConstantInitializer( + Context, var->getType()->isReferenceType(), &Culprit)) { + // GNU C++98 edits for __thread, [basic.start.init]p4: + // An object of thread storage duration shall not require dynamic + // initialization. + // FIXME: Need strict checking here. + Diag(Culprit->getExprLoc(), diag::err_thread_dynamic_init) + << Culprit->getSourceRange(); + if (getLangOpts().CPlusPlus11) + Diag(var->getLocation(), diag::note_use_thread_local); } } @@ -10495,6 +10486,18 @@ void Sema::CheckCompleteVariableDeclaration(VarDecl *var) { if (!var->getDeclContext()->isDependentContext() && Init && !Init->isValueDependent()) { + if (IsGlobal && !var->isConstexpr() && + !getDiagnostics().isIgnored(diag::warn_global_constructor, + var->getLocation())) { + // Warn about globals which don't have a constant initializer. Don't + // warn about globals with a non-trivial destructor because we already + // warned about them. + CXXRecordDecl *RD = baseType->getAsCXXRecordDecl(); + if (!(RD && !RD->hasTrivialDestructor()) && + !Init->isConstantInitializer(Context, baseType->isReferenceType())) + Diag(var->getLocation(), diag::warn_global_constructor) + << Init->getSourceRange(); + } if (var->isConstexpr()) { SmallVector Notes; @@ -10518,35 +10521,6 @@ void Sema::CheckCompleteVariableDeclaration(VarDecl *var) { // initialized by a constant expression if we check later. var->checkInitIsICE(); } - - // Don't emit further diagnostics about constexpr globals since they - // were just diagnosed. - if (!var->isConstexpr() && GlobalStorage && - var->hasAttr()) { - // FIXME: Need strict checking in C++03 here. - bool DiagErr = getLangOpts().CPlusPlus11 - ? !var->checkInitIsICE() : !checkConstInit(); - if (DiagErr) { - auto attr = var->getAttr(); - Diag(var->getLocation(), diag::err_require_constant_init_failed) - << Init->getSourceRange(); - Diag(attr->getLocation(), diag::note_declared_required_constant_init_here) - << attr->getRange(); - } - } - else if (!var->isConstexpr() && IsGlobal && - !getDiagnostics().isIgnored(diag::warn_global_constructor, - var->getLocation())) { - // Warn about globals which don't have a constant initializer. Don't - // warn about globals with a non-trivial destructor because we already - // warned about them. - CXXRecordDecl *RD = baseType->getAsCXXRecordDecl(); - if (!(RD && !RD->hasTrivialDestructor())) { - if (!checkConstInit()) - Diag(var->getLocation(), diag::warn_global_constructor) - << Init->getSourceRange(); - } - } } // Require the destructor. diff --git a/clang/lib/Sema/SemaDeclAttr.cpp b/clang/lib/Sema/SemaDeclAttr.cpp index 824d68e838eb..0471f65cccd7 100644 --- a/clang/lib/Sema/SemaDeclAttr.cpp +++ b/clang/lib/Sema/SemaDeclAttr.cpp @@ -5630,9 +5630,6 @@ static void ProcessDeclAttribute(Sema &S, Scope *scope, Decl *D, case AttributeList::AT_VecTypeHint: handleVecTypeHint(S, D, Attr); break; - case AttributeList::AT_RequireConstantInit: - handleSimpleAttribute(S, D, Attr); - break; case AttributeList::AT_InitPriority: handleInitPriorityAttr(S, D, Attr); break; diff --git a/clang/test/SemaCXX/attr-require-constant-initialization.cpp b/clang/test/SemaCXX/attr-require-constant-initialization.cpp deleted file mode 100644 index 73f81cb1fc1d..000000000000 --- a/clang/test/SemaCXX/attr-require-constant-initialization.cpp +++ /dev/null @@ -1,282 +0,0 @@ -// RUN: %clang_cc1 -fsyntax-only -verify -DTEST_ONE -std=c++03 %s -// RUN: %clang_cc1 -fsyntax-only -verify -DTEST_ONE -std=c++11 %s -// RUN: %clang_cc1 -fsyntax-only -verify -DTEST_ONE -std=c++14 %s -// RUN: %clang_cc1 -fsyntax-only -verify -DTEST_TWO \ -// RUN: -Wglobal-constructors -std=c++14 %s -// RUN: %clang_cc1 -fsyntax-only -verify -DTEST_THREE -xc %s - -#define ATTR __attribute__((require_constant_initialization)) // expected-note 0+ {{expanded from macro}} - -int ReturnInt(); - -struct PODType { - int value; - int value2; -}; - -#if defined(__cplusplus) - -#if __cplusplus >= 201103L -struct LitType { - constexpr LitType() : value(0) {} - constexpr LitType(int x) : value(x) {} - LitType(void *) : value(-1) {} - int value; -}; -#endif - -struct NonLit { -#if __cplusplus >= 201402L - constexpr NonLit() : value(0) {} - constexpr NonLit(int x) : value(x) {} -#else - NonLit() : value(0) {} - NonLit(int x) : value(x) {} -#endif - NonLit(void *) : value(-1) {} - ~NonLit() {} - int value; -}; - -struct StoresNonLit { -#if __cplusplus >= 201402L - constexpr StoresNonLit() : obj() {} - constexpr StoresNonLit(int x) : obj(x) {} -#else - StoresNonLit() : obj() {} - StoresNonLit(int x) : obj(x) {} -#endif - StoresNonLit(void *p) : obj(p) {} - NonLit obj; -}; - -#endif // __cplusplus - - -#if defined(TEST_ONE) // Test semantics of attribute - -// Test diagnostics when attribute is applied to non-static declarations. -void test_func_local(ATTR int param) { // expected-error {{only applies to variables with static or thread}} - ATTR int x = 42; // expected-error {{only applies to variables with static or thread}} - ATTR extern int y; -} -struct ATTR class_mem { // expected-error {{only applies to variables with static or thread}} - ATTR int x; // expected-error {{only applies to variables with static or thread}} -}; - -// [basic.start.static]p2.1 -// if each full-expression (including implicit conversions) that appears in -// the initializer of a reference with static or thread storage duration is -// a constant expression (5.20) and the reference is bound to a glvalue -// designating an object with static storage duration, to a temporary object -// (see 12.2) or subobject thereof, or to a function; - -// Test binding to a static glvalue -const int glvalue_int = 42; -const int glvalue_int2 = ReturnInt(); -ATTR const int &glvalue_ref ATTR = glvalue_int; -ATTR const int &glvalue_ref2 ATTR = glvalue_int2; -ATTR __thread const int &glvalue_ref_tl = glvalue_int; - -void test_basic_start_static_2_1() { - const int non_global = 42; - ATTR static const int &local_init = non_global; // expected-error {{variable does not have a constant initializer}} - // expected-note@-1 {{required by 'require_constant_initializer' attribute here}} - ATTR static const int &global_init = glvalue_int; - ATTR static const int &temp_init = 42; -} - -ATTR const int &temp_ref = 42; -ATTR const int &temp_ref2 = ReturnInt(); // expected-error {{variable does not have a constant initializer}} -// expected-note@-1 {{required by 'require_constant_initializer' attribute here}} -ATTR const NonLit &nl_temp_ref = 42; // expected-error {{variable does not have a constant initializer}} -// expected-note@-1 {{required by 'require_constant_initializer' attribute here}} - -#if __cplusplus >= 201103L -ATTR const LitType &lit_temp_ref = 42; -ATTR const int &subobj_ref = LitType{}.value; -#endif - -ATTR const int &nl_subobj_ref = NonLit().value; // expected-error {{variable does not have a constant initializer}} -// expected-note@-1 {{required by 'require_constant_initializer' attribute here}} - -struct TT1 { - ATTR static const int &no_init; - ATTR static const int &glvalue_init; - ATTR static const int &temp_init; - ATTR static const int &subobj_init; -#if __cplusplus >= 201103L - ATTR static thread_local const int &tl_glvalue_init; - ATTR static thread_local const int &tl_temp_init; // expected-note {{required by 'require_constant_initializer' attribute here}} -#endif -}; -const int &TT1::glvalue_init = glvalue_int; -const int &TT1::temp_init = 42; -const int &TT1::subobj_init = PODType().value; -#if __cplusplus >= 201103L -thread_local const int &TT1::tl_glvalue_init = glvalue_int; -thread_local const int &TT1::tl_temp_init = 42; // expected-error {{variable does not have a constant initializer}} -#endif - -// [basic.start.static]p2.2 -// if an object with static or thread storage duration is initialized by a -// constructor call, and if the initialization full-expression is a constant -// initializer for the object; - -void test_basic_start_static_2_2() { -#if __cplusplus < 201103L - ATTR static PODType pod; -#else - ATTR static PODType pod; // expected-error {{variable does not have a constant initializer}} -// expected-note@-1 {{required by 'require_constant_initializer' attribute here}} -#endif - ATTR static PODType pot2 = {ReturnInt()}; // expected-error {{variable does not have a constant initializer}} - // expected-note@-1 {{required by 'require_constant_initializer' attribute here}} - -#if __cplusplus >= 201103L - constexpr LitType l; - ATTR static LitType static_lit = l; - ATTR static LitType static_lit2 = (void *)0; // expected-error {{variable does not have a constant initializer}} - // expected-note@-1 {{required by 'require_constant_initializer' attribute here}} - ATTR static LitType static_lit3 = ReturnInt(); // expected-error {{variable does not have a constant initializer}} - // expected-note@-1 {{required by 'require_constant_initializer' attribute here}} - ATTR thread_local LitType tls = 42; -#endif -} - -struct TT2 { - ATTR static PODType pod_noinit; -#if __cplusplus >= 201103L -// expected-note@-2 {{required by 'require_constant_initializer' attribute here}} -#endif - ATTR static PODType pod_copy_init; // expected-note {{required by 'require_constant_initializer' attribute here}} -#if __cplusplus >= 201402L - ATTR static constexpr LitType lit = {}; - ATTR static const NonLit non_lit; - ATTR static const NonLit non_lit_list_init; - ATTR static const NonLit non_lit_copy_init; // expected-note {{required by 'require_constant_initializer' attribute here}} -#endif -}; -PODType TT2::pod_noinit; -#if __cplusplus >= 201103L -// expected-error@-2 {{variable does not have a constant initializer}} -#endif -PODType TT2::pod_copy_init(TT2::pod_noinit); // expected-error {{variable does not have a constant initializer}} -#if __cplusplus >= 201402L -const NonLit TT2::non_lit(42); -const NonLit TT2::non_lit_list_init = {42}; -const NonLit TT2::non_lit_copy_init = 42; // expected-error {{variable does not have a constant initializer}} -#endif - -#if __cplusplus >= 201103L -ATTR LitType lit_ctor; -ATTR LitType lit_ctor2{}; -ATTR LitType lit_ctor3 = {}; -ATTR __thread LitType lit_ctor_tl = {}; - -#if __cplusplus >= 201402L -ATTR NonLit nl_ctor; -ATTR NonLit nl_ctor2{}; -ATTR NonLit nl_ctor3 = {}; -ATTR thread_local NonLit nl_ctor_tl = {}; -ATTR StoresNonLit snl; -#else -ATTR NonLit nl_ctor; // expected-error {{variable does not have a constant initializer}} -// expected-note@-1 {{required by 'require_constant_initializer' attribute here}} -ATTR NonLit nl_ctor2{}; // expected-error {{variable does not have a constant initializer}} -// expected-note@-1 {{required by 'require_constant_initializer' attribute here}} -ATTR NonLit nl_ctor3 = {}; // expected-error {{variable does not have a constant initializer}} -// expected-note@-1 {{required by 'require_constant_initializer' attribute here}} -ATTR thread_local NonLit nl_ctor_tl = {}; // expected-error {{variable does not have a constant initializer}} -// expected-note@-1 {{required by 'require_constant_initializer' attribute here}} -ATTR StoresNonLit snl; // expected-error {{variable does not have a constant initializer}} -// expected-note@-1 {{required by 'require_constant_initializer' attribute here}} -#endif - -// Non-literal types cannot appear in the initializer of a non-literal type. -ATTR int nl_in_init = NonLit{42}.value; // expected-error {{variable does not have a constant initializer}} -// expected-note@-1 {{required by 'require_constant_initializer' attribute here}} -ATTR int lit_in_init = LitType{42}.value; -#endif - -// [basic.start.static]p2.3 -// if an object with static or thread storage duration is not initialized by a -// constructor call and if either the object is value-initialized or every -// full-expression that appears in its initializer is a constant expression. -void test_basic_start_static_2_3() { - ATTR static int static_local = 42; - ATTR static int static_local2; // zero-initialization takes place -#if __cplusplus >= 201103L - ATTR thread_local int tl_local = 42; -#endif -} - -ATTR int no_init; // zero initialization takes place -ATTR int arg_init = 42; -ATTR PODType pod_init = {}; -ATTR PODType pod_missing_init = {42 /* should have second arg */}; -ATTR PODType pod_full_init = {1, 2}; -ATTR PODType pod_non_constexpr_init = {1, ReturnInt()}; // expected-error {{variable does not have a constant initializer}} -// expected-note@-1 {{required by 'require_constant_initializer' attribute here}} - -#if __cplusplus >= 201103L -ATTR int val_init{}; -ATTR int brace_init = {}; -#endif - -ATTR __thread int tl_init = 0; -typedef const char *StrType; - -#if __cplusplus >= 201103L - -// Test that the validity of the selected constructor is checked, not just the -// initializer -struct NotC { - constexpr NotC(void *) {} - NotC(int) {} -}; -template -struct TestCtor { - constexpr TestCtor(int x) : value(x) {} - T value; -}; -ATTR TestCtor t(42); // expected-error {{variable does not have a constant initializer}} -// expected-note@-1 {{required by 'require_constant_initializer' attribute here}} -#endif - -// Test various array types -ATTR const char *foo[] = {"abc", "def"}; -ATTR PODType bar[] = {{}, {123, 456}}; - -#elif defined(TEST_TWO) // Test for duplicate warnings -struct NotC { - constexpr NotC(void *) {} - NotC(int) {} // expected-note 2 {{declared here}} -}; -template -struct TestCtor { - constexpr TestCtor(int x) : value(x) {} // expected-note 2 {{non-constexpr constructor}} - T value; -}; - -ATTR LitType non_const_lit(nullptr); // expected-error {{variable does not have a constant initializer}} -// expected-note@-1 {{required by 'require_constant_initializer' attribute here}} -ATTR NonLit non_const(nullptr); // expected-error {{variable does not have a constant initializer}} -// expected-warning@-1 {{declaration requires a global destructor}} -// expected-note@-2 {{required by 'require_constant_initializer' attribute here}} -LitType const_init_lit(nullptr); // expected-warning {{declaration requires a global constructor}} -NonLit const_init{42}; // expected-warning {{declaration requires a global destructor}} -constexpr TestCtor inval_constexpr(42); // expected-error {{must be initialized by a constant expression}} -// expected-note@-1 {{in call to 'TestCtor(42)'}} -ATTR constexpr TestCtor inval_constexpr2(42); // expected-error {{must be initialized by a constant expression}} -// expected-note@-1 {{in call to 'TestCtor(42)'}} - -#elif defined(TEST_THREE) -#if defined(__cplusplus) -#error This test requires C -#endif -// Test that using the attribute in C results in a diagnostic -ATTR int x = 0; // expected-warning {{attribute ignored}} -#else -#error No test case specified -#endif // defined(TEST_N) diff --git a/clang/utils/TableGen/ClangAttrEmitter.cpp b/clang/utils/TableGen/ClangAttrEmitter.cpp index 071e06dd93bb..50102af33a5a 100644 --- a/clang/utils/TableGen/ClangAttrEmitter.cpp +++ b/clang/utils/TableGen/ClangAttrEmitter.cpp @@ -2790,10 +2790,8 @@ static std::string GenerateLangOptRequirements(const Record &R, std::string FnName = "check", Test; for (auto I = LangOpts.begin(), E = LangOpts.end(); I != E; ++I) { std::string Part = (*I)->getValueAsString("Name"); - if ((*I)->getValueAsBit("Negated")) { - FnName += "Not"; + if ((*I)->getValueAsBit("Negated")) Test += "!"; - } Test += "S.LangOpts." + Part; if (I + 1 != E) Test += " || "; -- 2.34.1