[clang] cecd847 - [Clang][Parser] Accept GNU attributes preceding C++ attributes on templates
Elizabeth Andrews via cfe-commits
cfe-commits at lists.llvm.org
Fri Jun 2 08:11:31 PDT 2023
Author: Elizabeth Andrews
Date: 2023-06-02T08:11:18-07:00
New Revision: cecd8471e4991b4bea5d2b38a3758cafdb1cbe29
URL: https://github.com/llvm/llvm-project/commit/cecd8471e4991b4bea5d2b38a3758cafdb1cbe29
DIFF: https://github.com/llvm/llvm-project/commit/cecd8471e4991b4bea5d2b38a3758cafdb1cbe29.diff
LOG: [Clang][Parser] Accept GNU attributes preceding C++ attributes on templates
Clang was rejecting valid code where GNU style attributes preceded C++ style
attributes in template declarations as follows:
template<int a>
__attribute__((deprecated("oh no!"))) [[deprecated("oh no!")]] void foo();
This PR fixes the bug.
Differential Revision: https://reviews.llvm.org/D151837
Added:
Modified:
clang/docs/ReleaseNotes.rst
clang/lib/Parse/ParseTemplate.cpp
clang/test/Parser/attr-order.cpp
Removed:
################################################################################
diff --git a/clang/docs/ReleaseNotes.rst b/clang/docs/ReleaseNotes.rst
index 02736f2ee67fc..69ab645d49c23 100644
--- a/clang/docs/ReleaseNotes.rst
+++ b/clang/docs/ReleaseNotes.rst
@@ -473,6 +473,10 @@ Bug Fixes to Attribute Support
structs, unions, and scoped enums) were not properly ignored, resulting in
misleading warning messages. Now, such attribute annotations are correctly
ignored. (`#61660 <https://github.com/llvm/llvm-project/issues/61660>`_)
+- GNU attributes preceding C++ style attributes on templates were not properly
+ handled, resulting in compilation error. This has been corrected to match the
+ behavior exhibited by GCC, which permits mixed ordering of GNU and C++
+ attributes.
Bug Fixes to C++ Support
^^^^^^^^^^^^^^^^^^^^^^^^
diff --git a/clang/lib/Parse/ParseTemplate.cpp b/clang/lib/Parse/ParseTemplate.cpp
index 79f4ab683281e..d2e8a81ad521a 100644
--- a/clang/lib/Parse/ParseTemplate.cpp
+++ b/clang/lib/Parse/ParseTemplate.cpp
@@ -210,7 +210,15 @@ Decl *Parser::ParseSingleDeclarationAfterTemplate(
}
ParsedAttributes prefixAttrs(AttrFactory);
- MaybeParseCXX11Attributes(prefixAttrs);
+ ParsedAttributes DeclSpecAttrs(AttrFactory);
+
+ // GNU attributes are applied to the declaration specification while the
+ // standard attributes are applied to the declaration. We parse the two
+ // attribute sets into
diff erent containters so we can apply them during
+ // the regular parsing process.
+ while (MaybeParseCXX11Attributes(prefixAttrs) ||
+ MaybeParseGNUAttributes(DeclSpecAttrs))
+ ;
if (Tok.is(tok::kw_using)) {
auto usingDeclPtr = ParseUsingDirectiveOrDeclaration(Context, TemplateInfo, DeclEnd,
@@ -223,6 +231,9 @@ Decl *Parser::ParseSingleDeclarationAfterTemplate(
// Parse the declaration specifiers, stealing any diagnostics from
// the template parameters.
ParsingDeclSpec DS(*this, &DiagsFromTParams);
+ DS.SetRangeStart(DeclSpecAttrs.Range.getBegin());
+ DS.SetRangeEnd(DeclSpecAttrs.Range.getEnd());
+ DS.takeAttributesFrom(DeclSpecAttrs);
ParseDeclarationSpecifiers(DS, TemplateInfo, AS,
getDeclSpecContextFromDeclaratorContext(Context));
diff --git a/clang/test/Parser/attr-order.cpp b/clang/test/Parser/attr-order.cpp
index 9a8490d819ee3..10bad38cac644 100644
--- a/clang/test/Parser/attr-order.cpp
+++ b/clang/test/Parser/attr-order.cpp
@@ -13,12 +13,21 @@ struct [[]] __attribute__((lockable)) [[]] __declspec(dllexport) H {}; // ok
[[noreturn]] __declspec(dllexport) __attribute__((cdecl)) void b(); // ok
[[]] [[noreturn]] __attribute__((cdecl)) __declspec(dllexport) void c(); // ok
-// [[]] attributes before a declaration must be at the start of the line.
__declspec(dllexport) [[noreturn]] __attribute__((cdecl)) void d(); // expected-error {{an attribute list cannot appear here}}
__declspec(dllexport) __attribute__((cdecl)) [[noreturn]] void e(); // expected-error {{an attribute list cannot appear here}}
__attribute__((cdecl)) __declspec(dllexport) [[noreturn]] void f(); // expected-error {{an attribute list cannot appear here}}
-__attribute__((cdecl)) [[noreturn]] __declspec(dllexport) void g();
+
+__attribute__((cdecl)) [[noreturn]] __declspec(dllexport) void g(); // ok
[[noreturn]] __attribute__((cdecl))
[[]]
__declspec(dllexport) void h();
+
+template <int a>
+__attribute__((cdecl)) [[noreturn]] __declspec(dllexport) void i(); // ok
+
+template <int a>
+[[]] [[noreturn]] __attribute__((cdecl)) __declspec(dllexport) void j(); // ok
+
+template <int a>
+[[noreturn]] __declspec(dllexport) __attribute__((cdecl)) void k(); // ok
More information about the cfe-commits
mailing list