Skip to content

[Clang] handle both gnu and cpp11 attributes to ensure correct parsing inside extern block #102864

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 9 commits into from
Aug 15, 2024
Merged
1 change: 1 addition & 0 deletions clang/docs/ReleaseNotes.rst
Original file line number Diff line number Diff line change
Expand Up @@ -257,6 +257,7 @@ Bug Fixes to C++ Support
- Properly reject defaulted relational operators with invalid types for explicit object parameters,
e.g., ``bool operator==(this int, const Foo&)`` (#GH100329), and rvalue reference parameters.
- Properly reject defaulted copy/move assignment operators that have a non-reference explicit object parameter.
- Clang now properly handles the order of attributes in `extern` blocks. (#GH101990).
- Fixed an assertion failure by preventing null explicit object arguments from being deduced. (#GH102025).

Bug Fixes to AST Handling
Expand Down
5 changes: 4 additions & 1 deletion clang/lib/Parse/ParseDeclCXX.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -425,7 +425,10 @@ Decl *Parser::ParseLinkage(ParsingDeclSpec &DS, DeclaratorContext Context) {
[[fallthrough]];
default:
ParsedAttributes DeclAttrs(AttrFactory);
MaybeParseCXX11Attributes(DeclAttrs);
ParsedAttributes DeclSpecAttrs(AttrFactory);
while (MaybeParseCXX11Attributes(DeclAttrs) ||
MaybeParseGNUAttributes(DeclSpecAttrs))
;
ParseExternalDeclaration(DeclAttrs, DeclSpecAttrs);
continue;
}
Expand Down
13 changes: 13 additions & 0 deletions clang/test/Parser/attr-order.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -31,3 +31,16 @@ template <int a>

template <int a>
[[noreturn]] __declspec(dllexport) __attribute__((cdecl)) void k(); // ok

extern "C" {
__attribute__ ((__warn_unused_result__)) [[__maybe_unused__]] int l(int); // ok
[[__maybe_unused__]] __attribute__ ((__warn_unused_result__)) int m(int); // ok
}

extern "C" {
__attribute__ ((__warn_unused_result__)) [[__maybe_unused__]] int n (int); // ok
__attribute__ ((__warn_unused_result__)) [[__maybe_unused__]] static int o (int x) { return x; }; // ok
}

extern "C" __attribute__ ((__warn_unused_result__)) [[__maybe_unused__]] int p(int); // ok
extern "C" [[__maybe_unused__]] __attribute__ ((__warn_unused_result__)) int q(int); // ok
Loading