diff --git a/clang/docs/LanguageExtensions.rst b/clang/docs/LanguageExtensions.rst --- a/clang/docs/LanguageExtensions.rst +++ b/clang/docs/LanguageExtensions.rst @@ -3336,6 +3336,9 @@ - ``variable(is_global)``: Can be used to apply attributes to global variables only. +- ``variable(is_local)``: Can be used to apply attributes to local variables + only. + - ``variable(is_parameter)``: Can be used to apply attributes to parameters only. diff --git a/clang/include/clang/Basic/Attr.td b/clang/include/clang/Basic/Attr.td --- a/clang/include/clang/Basic/Attr.td +++ b/clang/include/clang/Basic/Attr.td @@ -441,6 +441,7 @@ def SubjectMatcherForVar : AttrSubjectMatcherRule<"variable", [Var], [ AttrSubjectMatcherSubRule<"is_thread_local", [TLSVar]>, AttrSubjectMatcherSubRule<"is_global", [GlobalVar]>, + AttrSubjectMatcherSubRule<"is_local", [LocalVar]>, AttrSubjectMatcherSubRule<"is_parameter", [ParmVar]>, // unless(is_parameter) AttrSubjectMatcherSubRule<"is_parameter", [NonParmVar], 1> @@ -3381,6 +3382,7 @@ def Uninitialized : InheritableAttr { let Spellings = [Clang<"uninitialized", 0>]; let Subjects = SubjectList<[LocalVar]>; + let PragmaAttributeSupport = 1; let Documentation = [UninitializedDocs]; } diff --git a/clang/test/CodeGenCXX/trivial-auto-var-init-attribute.cpp b/clang/test/CodeGenCXX/trivial-auto-var-init-attribute.cpp --- a/clang/test/CodeGenCXX/trivial-auto-var-init-attribute.cpp +++ b/clang/test/CodeGenCXX/trivial-auto-var-init-attribute.cpp @@ -20,4 +20,20 @@ used(i); } +#pragma clang attribute push([[clang::uninitialized]], apply_to = variable(is_local)) +// UNINIT-LABEL: test_pragma_attribute_uninitialized( +// UNINIT: alloca +// UNINIT-NEXT: call void +// ZERO-LABEL: test_pragma_attribute_uninitialized( +// ZERO: alloca +// ZERO-NEXT: call void +// PATTERN-LABEL: test_pragma_attribute_uninitialized( +// PATTERN: alloca +// PATTERN-NEXT: call void +void test_pragma_attribute_uninitialized() { + int i; + used(i); +} +#pragma clang attribute pop + } // extern "C" diff --git a/clang/test/Misc/pragma-attribute-supported-attributes-list.test b/clang/test/Misc/pragma-attribute-supported-attributes-list.test --- a/clang/test/Misc/pragma-attribute-supported-attributes-list.test +++ b/clang/test/Misc/pragma-attribute-supported-attributes-list.test @@ -41,6 +41,7 @@ // CHECK-NEXT: Callback (SubjectMatchRule_function) // CHECK-NEXT: Capability (SubjectMatchRule_record, SubjectMatchRule_type_alias) // CHECK-NEXT: CarriesDependency (SubjectMatchRule_variable_is_parameter, SubjectMatchRule_objc_method, SubjectMatchRule_function) +// CHECK-NEXT: Cleanup (SubjectMatchRule_variable_is_local) // CHECK-NEXT: CmseNSEntry (SubjectMatchRule_function) // CHECK-NEXT: Cold (SubjectMatchRule_function) // CHECK-NEXT: Common (SubjectMatchRule_variable) @@ -151,6 +152,7 @@ // CHECK-NEXT: Target (SubjectMatchRule_function) // CHECK-NEXT: TestTypestate (SubjectMatchRule_function_is_member) // CHECK-NEXT: TrivialABI (SubjectMatchRule_record) +// CHECK-NEXT: Uninitialized (SubjectMatchRule_variable_is_local) // CHECK-NEXT: UseHandle (SubjectMatchRule_variable_is_parameter) // CHECK-NEXT: VecReturn (SubjectMatchRule_record) // CHECK-NEXT: VecTypeHint (SubjectMatchRule_function) diff --git a/clang/test/Parser/pragma-attribute.cpp b/clang/test/Parser/pragma-attribute.cpp --- a/clang/test/Parser/pragma-attribute.cpp +++ b/clang/test/Parser/pragma-attribute.cpp @@ -63,14 +63,14 @@ #pragma clang attribute push(__attribute__((annotate("test"))), apply_to = hasType(functionType)) // OK #pragma clang attribute push(__attribute__((annotate("test"))), apply_to = any( variable( )) // expected-error {{expected ')'}} -#pragma clang attribute push(__attribute__((annotate("test"))), apply_to = any( variable( ) )) // expected-error {{expected an identifier that corresponds to an attribute subject matcher sub-rule; 'variable' matcher supports the following sub-rules: 'is_thread_local', 'is_global', 'is_parameter', 'unless(is_parameter)'}} -#pragma clang attribute push(__attribute__((annotate("test"))), apply_to = any( variable(is ) )) // expected-error {{unknown attribute subject matcher sub-rule 'is'; 'variable' matcher supports the following sub-rules: 'is_thread_local', 'is_global', 'is_parameter', 'unless(is_parameter)'}} +#pragma clang attribute push(__attribute__((annotate("test"))), apply_to = any(variable())) // expected-error {{expected an identifier that corresponds to an attribute subject matcher sub-rule; 'variable' matcher supports the following sub-rules: 'is_thread_local', 'is_global', 'is_local', 'is_parameter', 'unless(is_parameter)'}} +#pragma clang attribute push(__attribute__((annotate("test"))), apply_to = any(variable(is))) // expected-error {{unknown attribute subject matcher sub-rule 'is'; 'variable' matcher supports the following sub-rules: 'is_thread_local', 'is_global', 'is_local', 'is_parameter', 'unless(is_parameter)'}} #pragma clang attribute push(__attribute__((annotate("test"))), apply_to = any( variable(is_parameter, not) )) // expected-error {{expected ')'}} expected-note {{to match this '('}} #pragma clang attribute push(__attribute__((annotate("test"))), apply_to = any( variable is_parameter )) // expected-error {{expected ')'}} expected-note {{to match this '('}} #pragma clang attribute push(__attribute__((annotate("test"))), apply_to = any( variable ( ) // expected-error {{expected ')'}} #pragma clang attribute push(__attribute__((annotate("test"))), apply_to = variable ( // expected-error {{expected ')'}} -#pragma clang attribute push(__attribute__((annotate("test"))), apply_to = any( function, variable (is ()) )) // expected-error {{unknown attribute subject matcher sub-rule 'is'; 'variable' matcher supports the following sub-rules: 'is_thread_local', 'is_global', 'is_parameter', 'unless(is_parameter)'}} -#pragma clang attribute push(__attribute__((annotate("test"))), apply_to = any( function, variable (42) )) // expected-error {{expected an identifier that corresponds to an attribute subject matcher sub-rule; 'variable' matcher supports the following sub-rules: 'is_thread_local', 'is_global', 'is_parameter', 'unless(is_parameter)'}} +#pragma clang attribute push(__attribute__((annotate("test"))), apply_to = any(function, variable(is()))) // expected-error {{unknown attribute subject matcher sub-rule 'is'; 'variable' matcher supports the following sub-rules: 'is_thread_local', 'is_global', 'is_local', 'is_parameter', 'unless(is_parameter)'}} +#pragma clang attribute push(__attribute__((annotate("test"))), apply_to = any(function, variable(42))) // expected-error {{expected an identifier that corresponds to an attribute subject matcher sub-rule; 'variable' matcher supports the following sub-rules: 'is_thread_local', 'is_global', 'is_local', 'is_parameter', 'unless(is_parameter)'}} #pragma clang attribute push(__attribute__((annotate("test"))), apply_to = any( function, namespace("test") )) // expected-error {{expected an identifier that corresponds to an attribute subject matcher sub-rule; 'namespace' matcher does not support sub-rules}} #pragma clang attribute push(__attribute__((annotate("test"))), apply_to = any( function, variable ("test" )) // expected-error {{expected ')'}} @@ -79,15 +79,15 @@ #pragma clang attribute push(__attribute__((annotate("test"))), apply_to = any (function, variable (unless) )) // expected-error {{expected '('}} #pragma clang attribute push(__attribute__((annotate("test"))), apply_to = any (function, variable (unless() )) // expected-error {{expected ')'}} -#pragma clang attribute push(__attribute__((annotate("test"))), apply_to = any ( function, variable (unless(is)) )) // expected-error {{unknown attribute subject matcher sub-rule 'unless(is)'; 'variable' matcher supports the following sub-rules: 'is_thread_local', 'is_global', 'is_parameter', 'unless(is_parameter)'}} +#pragma clang attribute push(__attribute__((annotate("test"))), apply_to = any(function, variable(unless(is)))) // expected-error {{unknown attribute subject matcher sub-rule 'unless(is)'; 'variable' matcher supports the following sub-rules: 'is_thread_local', 'is_global', 'is_local', 'is_parameter', 'unless(is_parameter)'}} #pragma clang attribute push(__attribute__((annotate("test"))), apply_to = any( variable(unless(is_parameter, not)) )) // expected-error {{expected ')'}} expected-note {{to match this '('}} #pragma clang attribute push(__attribute__((annotate("test"))), apply_to = any( variable(unless(is_parameter), not) ) // expected-error {{expected ')'}} #pragma clang attribute push(__attribute__((annotate("test"))), apply_to = any( variable unless is_parameter )) // expected-error {{expected ')'}} expected-note {{to match this '('}} #pragma clang attribute push(__attribute__((annotate("test"))), apply_to = any( variable(unless is_parameter) )) // expected-error {{expected '('}} -#pragma clang attribute push(__attribute__((annotate("test"))), apply_to = any( function, variable (unless(42)) )) // expected-error {{expected an identifier that corresponds to an attribute subject matcher sub-rule; 'variable' matcher supports the following sub-rules: 'is_thread_local', 'is_global', 'is_parameter', 'unless(is_parameter)'}} +#pragma clang attribute push(__attribute__((annotate("test"))), apply_to = any(function, variable(unless(42)))) // expected-error {{expected an identifier that corresponds to an attribute subject matcher sub-rule; 'variable' matcher supports the following sub-rules: 'is_thread_local', 'is_global', 'is_local', 'is_parameter', 'unless(is_parameter)'}} #pragma clang attribute push(__attribute__((annotate("test"))), apply_to = any( function, enum(unless("test")) )) // expected-error {{expected an identifier that corresponds to an attribute subject matcher sub-rule; 'enum' matcher does not support sub-rules}} -#pragma clang attribute push(__attribute__((annotate("test"))), apply_to = any( function, variable (unless(is_global)) )) // expected-error {{unknown attribute subject matcher sub-rule 'unless(is_global)'; 'variable' matcher supports the following sub-rules: 'is_thread_local', 'is_global', 'is_parameter', 'unless(is_parameter)'}} +#pragma clang attribute push(__attribute__((annotate("test"))), apply_to = any(function, variable(unless(is_global)))) // expected-error {{unknown attribute subject matcher sub-rule 'unless(is_global)'; 'variable' matcher supports the following sub-rules: 'is_thread_local', 'is_global', 'is_local', 'is_parameter', 'unless(is_parameter)'}} #pragma clang attribute push(__attribute__((annotate("test"))), apply_to = any( enum(unless(is_parameter)) )) // expected-error {{invalid use of attribute subject matcher sub-rule 'unless(is_parameter)'; 'enum' matcher does not support sub-rules}} #pragma clang attribute push(__attribute__((annotate("test"))), apply_to = any( function, function )) // expected-error {{duplicate attribute subject matcher 'function'}} @@ -182,3 +182,16 @@ // expected-note@-1 {{use the GNU '__attribute__' syntax}} #pragma clang attribute push (annotate("test")) // expected-error {{expected an attribute that is specified using the GNU, C++11 or '__declspec' syntax}} // expected-note@-1 {{use the GNU '__attribute__' syntax}} + +#pragma clang attribute push([[clang::uninitialized]], apply_to = variable(is_local)) +#pragma clang attribute pop +#pragma clang attribute push([[clang::uninitialized]], apply_to = function) // expected-error {{attribute 'uninitialized' can't be applied to 'function'}} +#pragma clang attribute pop +#pragma clang attribute push([[clang::uninitialized]], apply_to = variable) // expected-error {{attribute 'uninitialized' can't be applied to 'variable'}} +#pragma clang attribute pop +#pragma clang attribute push([[clang::uninitialized]], apply_to = variable(is_thread_local)) // expected-error {{attribute 'uninitialized' can't be applied to 'variable(is_thread_local)'}} +#pragma clang attribute pop +#pragma clang attribute push([[clang::uninitialized]], apply_to = variable(is_global)) // expected-error {{attribute 'uninitialized' can't be applied to 'variable(is_global)'}} +#pragma clang attribute pop +#pragma clang attribute push([[clang::uninitialized]], apply_to = any(variable(is_parameter), variable(unless(is_parameter)))) // expected-error {{attribute 'uninitialized' can't be applied to 'variable(is_parameter)', and 'variable(unless(is_parameter))'}} +#pragma clang attribute pop