r345517 - Revert "Revert "Support for groups of attributes in #pragma clang attribute""
Erik Pilkington via cfe-commits
cfe-commits at lists.llvm.org
Mon Oct 29 10:38:42 PDT 2018
Author: epilk
Date: Mon Oct 29 10:38:42 2018
New Revision: 345517
URL: http://llvm.org/viewvc/llvm-project?rev=345517&view=rev
Log:
Revert "Revert "Support for groups of attributes in #pragma clang attribute""
This reverts commit r345487, which reverted r345486. I think the crashes were
caused by an OOM on the builder, trying again to confirm...
Modified:
cfe/trunk/docs/LanguageExtensions.rst
cfe/trunk/docs/ReleaseNotes.rst
cfe/trunk/include/clang/Basic/DiagnosticParseKinds.td
cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td
cfe/trunk/include/clang/Sema/Sema.h
cfe/trunk/lib/Parse/ParsePragma.cpp
cfe/trunk/lib/Sema/SemaAttr.cpp
cfe/trunk/test/Parser/pragma-attribute.cpp
cfe/trunk/test/Sema/pragma-attribute.c
Modified: cfe/trunk/docs/LanguageExtensions.rst
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/docs/LanguageExtensions.rst?rev=345517&r1=345516&r2=345517&view=diff
==============================================================================
--- cfe/trunk/docs/LanguageExtensions.rst (original)
+++ cfe/trunk/docs/LanguageExtensions.rst Mon Oct 29 10:38:42 2018
@@ -2651,17 +2651,19 @@ Specifying an attribute for multiple dec
The ``#pragma clang attribute`` directive can be used to apply an attribute to
multiple declarations. The ``#pragma clang attribute push`` variation of the
-directive pushes a new attribute to the attribute stack. The declarations that
-follow the pragma receive the attributes that are on the attribute stack, until
-the stack is cleared using a ``#pragma clang attribute pop`` directive. Multiple
-push directives can be nested inside each other.
+directive pushes a new "scope" of ``#pragma clang attribute`` that attributes
+can be added to. The ``#pragma clang attribute (...)`` variation adds an
+attribute to that scope, and the ``#pragma clang attribute pop`` variation pops
+the scope. You can also use ``#pragma clang attribute push (...)``, which is a
+shorthand for when you want to add one attribute to a new scope. Multiple push
+directives can be nested inside each other.
The attributes that are used in the ``#pragma clang attribute`` directives
can be written using the GNU-style syntax:
.. code-block:: c++
- #pragma clang attribute push(__attribute__((annotate("custom"))), apply_to = function)
+ #pragma clang attribute push (__attribute__((annotate("custom"))), apply_to = function)
void function(); // The function now has the annotate("custom") attribute
@@ -2671,7 +2673,7 @@ The attributes can also be written using
.. code-block:: c++
- #pragma clang attribute push([[noreturn]], apply_to = function)
+ #pragma clang attribute push ([[noreturn]], apply_to = function)
void function(); // The function now has the [[noreturn]] attribute
@@ -2681,7 +2683,7 @@ The ``__declspec`` style syntax is also
.. code-block:: c++
- #pragma clang attribute push(__declspec(dllexport), apply_to = function)
+ #pragma clang attribute push (__declspec(dllexport), apply_to = function)
void function(); // The function now has the __declspec(dllexport) attribute
Modified: cfe/trunk/docs/ReleaseNotes.rst
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/docs/ReleaseNotes.rst?rev=345517&r1=345516&r2=345517&view=diff
==============================================================================
--- cfe/trunk/docs/ReleaseNotes.rst (original)
+++ cfe/trunk/docs/ReleaseNotes.rst Mon Oct 29 10:38:42 2018
@@ -86,8 +86,8 @@ Modified Compiler Flags
New Pragmas in Clang
--------------------
-Clang now supports the ...
-
+- Clang now supports adding multiple `#pragma clang attribute` attributes into
+ a scope of pushed attributes.
Attribute Changes in Clang
--------------------------
Modified: cfe/trunk/include/clang/Basic/DiagnosticParseKinds.td
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Basic/DiagnosticParseKinds.td?rev=345517&r1=345516&r2=345517&view=diff
==============================================================================
--- cfe/trunk/include/clang/Basic/DiagnosticParseKinds.td (original)
+++ cfe/trunk/include/clang/Basic/DiagnosticParseKinds.td Mon Oct 29 10:38:42 2018
@@ -1032,8 +1032,8 @@ def err_pragma_optimize_invalid_argument
def err_pragma_optimize_extra_argument : Error<
"unexpected extra argument '%0' to '#pragma clang optimize'">;
// - #pragma clang attribute
-def err_pragma_attribute_expected_push_pop : Error<
- "expected 'push' or 'pop' after '#pragma clang attribute'">;
+def err_pragma_attribute_expected_push_pop_paren : Error<
+ "expected 'push', 'pop', or '(' after '#pragma clang attribute'">;
def err_pragma_attribute_invalid_argument : Error<
"unexpected argument '%0' to '#pragma clang attribute'; "
"expected 'push' or 'pop'">;
Modified: cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td?rev=345517&r1=345516&r2=345517&view=diff
==============================================================================
--- cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td (original)
+++ cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td Mon Oct 29 10:38:42 2018
@@ -851,6 +851,9 @@ def err_pragma_attribute_no_pop_eof : Er
"'#pragma clang attribute push' at end of file">;
def note_pragma_attribute_applied_decl_here : Note<
"when applied to this declaration">;
+def err_pragma_attr_attr_no_push : Error<
+ "'#pragma clang attribute' attribute with no matching "
+ "'#pragma clang attribute push'">;
/// Objective-C parser diagnostics
def err_duplicate_class_def : Error<
Modified: cfe/trunk/include/clang/Sema/Sema.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Sema/Sema.h?rev=345517&r1=345516&r2=345517&view=diff
==============================================================================
--- cfe/trunk/include/clang/Sema/Sema.h (original)
+++ cfe/trunk/include/clang/Sema/Sema.h Mon Oct 29 10:38:42 2018
@@ -491,15 +491,22 @@ public:
/// VisContext - Manages the stack for \#pragma GCC visibility.
void *VisContext; // Really a "PragmaVisStack*"
- /// This represents the stack of attributes that were pushed by
- /// \#pragma clang attribute.
+ /// This an attribute introduced by \#pragma clang attribute.
struct PragmaAttributeEntry {
SourceLocation Loc;
ParsedAttr *Attribute;
SmallVector<attr::SubjectMatchRule, 4> MatchRules;
bool IsUsed;
};
- SmallVector<PragmaAttributeEntry, 2> PragmaAttributeStack;
+
+ /// A push'd group of PragmaAttributeEntries.
+ struct PragmaAttributeGroup {
+ /// The location of the push attribute.
+ SourceLocation Loc;
+ SmallVector<PragmaAttributeEntry, 2> Entries;
+ };
+
+ SmallVector<PragmaAttributeGroup, 2> PragmaAttributeStack;
/// The declaration that is currently receiving an attribute from the
/// #pragma attribute stack.
@@ -8470,9 +8477,10 @@ public:
/// the appropriate attribute.
void AddCFAuditedAttribute(Decl *D);
- /// Called on well-formed '\#pragma clang attribute push'.
- void ActOnPragmaAttributePush(ParsedAttr &Attribute, SourceLocation PragmaLoc,
- attr::ParsedSubjectMatchRuleSet Rules);
+ void ActOnPragmaAttributeAttribute(ParsedAttr &Attribute,
+ SourceLocation PragmaLoc,
+ attr::ParsedSubjectMatchRuleSet Rules);
+ void ActOnPragmaAttributeEmptyPush(SourceLocation PragmaLoc);
/// Called on well-formed '\#pragma clang attribute pop'.
void ActOnPragmaAttributePop(SourceLocation PragmaLoc);
Modified: cfe/trunk/lib/Parse/ParsePragma.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Parse/ParsePragma.cpp?rev=345517&r1=345516&r2=345517&view=diff
==============================================================================
--- cfe/trunk/lib/Parse/ParsePragma.cpp (original)
+++ cfe/trunk/lib/Parse/ParsePragma.cpp Mon Oct 29 10:38:42 2018
@@ -1133,7 +1133,7 @@ bool Parser::HandlePragmaLoopHint(LoopHi
namespace {
struct PragmaAttributeInfo {
- enum ActionType { Push, Pop };
+ enum ActionType { Push, Pop, Attribute };
ParsedAttributes &Attributes;
ActionType Action;
ArrayRef<Token> Tokens;
@@ -1394,8 +1394,16 @@ void Parser::HandlePragmaAttribute() {
return;
}
// Parse the actual attribute with its arguments.
- assert(Info->Action == PragmaAttributeInfo::Push &&
+ assert((Info->Action == PragmaAttributeInfo::Push ||
+ Info->Action == PragmaAttributeInfo::Attribute) &&
"Unexpected #pragma attribute command");
+
+ if (Info->Action == PragmaAttributeInfo::Push && Info->Tokens.empty()) {
+ ConsumeAnnotationToken();
+ Actions.ActOnPragmaAttributeEmptyPush(PragmaLoc);
+ return;
+ }
+
PP.EnterTokenStream(Info->Tokens, /*DisableMacroExpansion=*/false);
ConsumeAnnotationToken();
@@ -1542,8 +1550,12 @@ void Parser::HandlePragmaAttribute() {
// Consume the eof terminator token.
ConsumeToken();
- Actions.ActOnPragmaAttributePush(Attribute, PragmaLoc,
- std::move(SubjectMatchRules));
+ // Handle a mixed push/attribute by desurging to a push, then an attribute.
+ if (Info->Action == PragmaAttributeInfo::Push)
+ Actions.ActOnPragmaAttributeEmptyPush(PragmaLoc);
+
+ Actions.ActOnPragmaAttributeAttribute(Attribute, PragmaLoc,
+ std::move(SubjectMatchRules));
}
// #pragma GCC visibility comes in two variants:
@@ -3104,6 +3116,8 @@ void PragmaForceCUDAHostDeviceHandler::H
/// The syntax is:
/// \code
/// #pragma clang attribute push(attribute, subject-set)
+/// #pragma clang attribute push
+/// #pragma clang attribute (attribute, subject-set)
/// #pragma clang attribute pop
/// \endcode
///
@@ -3122,25 +3136,33 @@ void PragmaAttributeHandler::HandlePragm
auto *Info = new (PP.getPreprocessorAllocator())
PragmaAttributeInfo(AttributesForPragmaAttribute);
- // Parse the 'push' or 'pop'.
- if (Tok.isNot(tok::identifier)) {
- PP.Diag(Tok.getLocation(), diag::err_pragma_attribute_expected_push_pop);
+ if (!Tok.isOneOf(tok::identifier, tok::l_paren)) {
+ PP.Diag(Tok.getLocation(),
+ diag::err_pragma_attribute_expected_push_pop_paren);
return;
}
- const auto *II = Tok.getIdentifierInfo();
- if (II->isStr("push"))
- Info->Action = PragmaAttributeInfo::Push;
- else if (II->isStr("pop"))
- Info->Action = PragmaAttributeInfo::Pop;
+
+ // Determine what action this pragma clang attribute represents.
+ if (Tok.is(tok::l_paren))
+ Info->Action = PragmaAttributeInfo::Attribute;
else {
- PP.Diag(Tok.getLocation(), diag::err_pragma_attribute_invalid_argument)
- << PP.getSpelling(Tok);
- return;
+ const IdentifierInfo *II = Tok.getIdentifierInfo();
+ if (II->isStr("push"))
+ Info->Action = PragmaAttributeInfo::Push;
+ else if (II->isStr("pop"))
+ Info->Action = PragmaAttributeInfo::Pop;
+ else {
+ PP.Diag(Tok.getLocation(), diag::err_pragma_attribute_invalid_argument)
+ << PP.getSpelling(Tok);
+ return;
+ }
+
+ PP.Lex(Tok);
}
- PP.Lex(Tok);
// Parse the actual attribute.
- if (Info->Action == PragmaAttributeInfo::Push) {
+ if ((Info->Action == PragmaAttributeInfo::Push && Tok.isNot(tok::eod)) ||
+ Info->Action == PragmaAttributeInfo::Attribute) {
if (Tok.isNot(tok::l_paren)) {
PP.Diag(Tok.getLocation(), diag::err_expected) << tok::l_paren;
return;
Modified: cfe/trunk/lib/Sema/SemaAttr.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaAttr.cpp?rev=345517&r1=345516&r2=345517&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/SemaAttr.cpp (original)
+++ cfe/trunk/lib/Sema/SemaAttr.cpp Mon Oct 29 10:38:42 2018
@@ -520,9 +520,9 @@ attrMatcherRuleListToString(ArrayRef<att
} // end anonymous namespace
-void Sema::ActOnPragmaAttributePush(ParsedAttr &Attribute,
- SourceLocation PragmaLoc,
- attr::ParsedSubjectMatchRuleSet Rules) {
+void Sema::ActOnPragmaAttributeAttribute(
+ ParsedAttr &Attribute, SourceLocation PragmaLoc,
+ attr::ParsedSubjectMatchRuleSet Rules) {
SmallVector<attr::SubjectMatchRule, 4> SubjectMatchRules;
// Gather the subject match rules that are supported by the attribute.
SmallVector<std::pair<attr::SubjectMatchRule, bool>, 4>
@@ -622,48 +622,64 @@ void Sema::ActOnPragmaAttributePush(Pars
Diagnostic << attrMatcherRuleListToString(ExtraRules);
}
- PragmaAttributeStack.push_back(
+ if (PragmaAttributeStack.empty()) {
+ Diag(PragmaLoc, diag::err_pragma_attr_attr_no_push);
+ return;
+ }
+
+ PragmaAttributeStack.back().Entries.push_back(
{PragmaLoc, &Attribute, std::move(SubjectMatchRules), /*IsUsed=*/false});
}
+void Sema::ActOnPragmaAttributeEmptyPush(SourceLocation PragmaLoc) {
+ PragmaAttributeStack.emplace_back();
+ PragmaAttributeStack.back().Loc = PragmaLoc;
+}
+
void Sema::ActOnPragmaAttributePop(SourceLocation PragmaLoc) {
if (PragmaAttributeStack.empty()) {
Diag(PragmaLoc, diag::err_pragma_attribute_stack_mismatch);
return;
}
- const PragmaAttributeEntry &Entry = PragmaAttributeStack.back();
- if (!Entry.IsUsed) {
- assert(Entry.Attribute && "Expected an attribute");
- Diag(Entry.Attribute->getLoc(), diag::warn_pragma_attribute_unused)
- << Entry.Attribute->getName();
- Diag(PragmaLoc, diag::note_pragma_attribute_region_ends_here);
+
+ for (const PragmaAttributeEntry &Entry :
+ PragmaAttributeStack.back().Entries) {
+ if (!Entry.IsUsed) {
+ assert(Entry.Attribute && "Expected an attribute");
+ Diag(Entry.Attribute->getLoc(), diag::warn_pragma_attribute_unused)
+ << Entry.Attribute->getName();
+ Diag(PragmaLoc, diag::note_pragma_attribute_region_ends_here);
+ }
}
+
PragmaAttributeStack.pop_back();
}
void Sema::AddPragmaAttributes(Scope *S, Decl *D) {
if (PragmaAttributeStack.empty())
return;
- for (auto &Entry : PragmaAttributeStack) {
- ParsedAttr *Attribute = Entry.Attribute;
- assert(Attribute && "Expected an attribute");
-
- // Ensure that the attribute can be applied to the given declaration.
- bool Applies = false;
- for (const auto &Rule : Entry.MatchRules) {
- if (Attribute->appliesToDecl(D, Rule)) {
- Applies = true;
- break;
+ for (auto &Group : PragmaAttributeStack) {
+ for (auto &Entry : Group.Entries) {
+ ParsedAttr *Attribute = Entry.Attribute;
+ assert(Attribute && "Expected an attribute");
+
+ // Ensure that the attribute can be applied to the given declaration.
+ bool Applies = false;
+ for (const auto &Rule : Entry.MatchRules) {
+ if (Attribute->appliesToDecl(D, Rule)) {
+ Applies = true;
+ break;
+ }
}
+ if (!Applies)
+ continue;
+ Entry.IsUsed = true;
+ PragmaAttributeCurrentTargetDecl = D;
+ ParsedAttributesView Attrs;
+ Attrs.addAtEnd(Attribute);
+ ProcessDeclAttributeList(S, D, Attrs);
+ PragmaAttributeCurrentTargetDecl = nullptr;
}
- if (!Applies)
- continue;
- Entry.IsUsed = true;
- PragmaAttributeCurrentTargetDecl = D;
- ParsedAttributesView Attrs;
- Attrs.addAtEnd(Attribute);
- ProcessDeclAttributeList(S, D, Attrs);
- PragmaAttributeCurrentTargetDecl = nullptr;
}
}
Modified: cfe/trunk/test/Parser/pragma-attribute.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Parser/pragma-attribute.cpp?rev=345517&r1=345516&r2=345517&view=diff
==============================================================================
--- cfe/trunk/test/Parser/pragma-attribute.cpp (original)
+++ cfe/trunk/test/Parser/pragma-attribute.cpp Mon Oct 29 10:38:42 2018
@@ -100,11 +100,12 @@ void function();
#pragma clang attribute push(__attribute__((annotate("test"))), apply_to = any( variable(unless(is_parameter)), variable(unless(is_parameter)) )) // expected-error {{duplicate attribute subject matcher 'variable(unless(is_parameter))'}}
#pragma clang attribute push(__attribute__((annotate("test"))), apply_to = any( variable(unless(is_parameter)), variable(unless(is_parameter)), enum, variable(unless(is_parameter)) )) // expected-error 2 {{duplicate attribute subject matcher 'variable(unless(is_parameter))'}}
-#pragma clang attribute // expected-error {{expected 'push' or 'pop' after '#pragma clang attribute'}}
-#pragma clang attribute 42 // expected-error {{expected 'push' or 'pop' after '#pragma clang attribute'}}
+#pragma clang attribute // expected-error {{expected 'push', 'pop', or '(' after '#pragma clang attribute'}}
+#pragma clang attribute 42 // expected-error {{expected 'push', 'pop', or '(' after '#pragma clang attribute'}}
#pragma clang attribute pushpop // expected-error {{unexpected argument 'pushpop' to '#pragma clang attribute'; expected 'push' or 'pop'}}
-#pragma clang attribute push // expected-error {{expected '('}}
+#pragma clang attribute push
+#pragma clang attribute pop
#pragma clang attribute push ( // expected-error {{expected an attribute after '('}}
#pragma clang attribute push (__attribute__((annotate)) // expected-error {{expected ')'}}
#pragma clang attribute push () // expected-error {{expected an attribute after '('}}
Modified: cfe/trunk/test/Sema/pragma-attribute.c
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Sema/pragma-attribute.c?rev=345517&r1=345516&r2=345517&view=diff
==============================================================================
--- cfe/trunk/test/Sema/pragma-attribute.c (original)
+++ cfe/trunk/test/Sema/pragma-attribute.c Mon Oct 29 10:38:42 2018
@@ -38,6 +38,29 @@ __attribute__((always_inline)) void optn
#pragma clang attribute pop
+#pragma clang attribute push (__attribute__((annotate())), apply_to = function) // expected-error{{'annotate' attribute takes one argument}}
+#pragma clang attribute (__attribute__((annotate())), apply_to = function) // expected-error{{'annotate' attribute takes one argument}}
+
+void fun(); // expected-note 2 {{when applied to this declaration}}
+
+#pragma clang attribute pop
+#pragma clang attribute pop // expected-error{{'#pragma clang attribute pop' with no matching '#pragma clang attribute push'}}
+
+
+#pragma clang attribute push
+#pragma clang attribute (__attribute__((annotate())), apply_to = function) // expected-error 2 {{'annotate' attribute takes one argument}}
+
+void fun2(); // expected-note {{when applied to this declaration}}
+
+#pragma clang attribute push (__attribute__((annotate())), apply_to = function) // expected-error{{'annotate' attribute takes one argument}}
+void fun3(); // expected-note 2 {{when applied to this declaration}}
+#pragma clang attribute pop
+
+#pragma clang attribute pop
+#pragma clang attribute pop // expected-error{{'#pragma clang attribute pop' with no matching '#pragma clang attribute push'}}
+
+#pragma clang attribute (__attribute__((annotate)), apply_to = function) // expected-error{{'#pragma clang attribute' attribute with no matching '#pragma clang attribute push}}
+
#pragma clang attribute push ([[]], apply_to = function) // A noop
#pragma clang attribute pop // expected-error {{'#pragma clang attribute pop' with no matching '#pragma clang attribute push'}}
More information about the cfe-commits
mailing list