No mixing annotations and attributes.

This commit is contained in:
Dan Katz
2025-06-19 10:01:04 +03:00
parent a2548ff890
commit bebe293731
4 changed files with 30 additions and 17 deletions

View File

@@ -1802,6 +1802,8 @@ def err_expansion_statements_disabled : Error<
"'template for' statements are not enabled; use '-fexpansion-statements'">;
def err_annotation_with_using : Error<
"annotations are not permitted following an attribute-using-prefix">;
def err_mixed_attributes_and_annotations : Error<
"attribute specifier cannot contain both attributes and annotations">;
def warn_meant_parenthesize_reflection : Warning<
"'%0' binds to reflection operand">, InGroup<ReflexingParse>;
def err_splice_template_argument : Error<

View File

@@ -4792,6 +4792,9 @@ void Parser::ParseCXX11AttributeSpecifierInternal(ParsedAttributes &Attrs,
checkCompoundToken(OpenLoc, tok::l_square, CompoundToken::AttrBegin);
ConsumeBracket();
bool AllowAnnotations = getLangOpts().AnnotationAttributes &&
Tok.is(tok::equal);
SourceLocation CommonScopeLoc;
IdentifierInfo *CommonScopeName = nullptr;
if (Tok.is(tok::kw_using)) {
@@ -4830,7 +4833,8 @@ void Parser::ParseCXX11AttributeSpecifierInternal(ParsedAttributes &Attrs,
SourceLocation ScopeLoc, AttrLoc;
IdentifierInfo *ScopeName = nullptr, *AttrName = nullptr;
if (Tok.is(tok::equal) && getLangOpts().AnnotationAttributes) {
if (AllowAnnotations) {
if (Tok.is(tok::equal)) {
// This is a C++2c annotation.
if (CommonScopeName) {
Diag(Tok.getLocation(), diag::err_annotation_with_using);
@@ -4839,6 +4843,13 @@ void Parser::ParseCXX11AttributeSpecifierInternal(ParsedAttributes &Attrs,
ParseAnnotationSpecifier(Attrs, EndLoc);
}
continue;
} else {
Diag(Tok.getLocation(), diag::err_mixed_attributes_and_annotations);
SkipUntil(tok::r_square, tok::colon, tok::r_splice, StopBeforeMatch);
}
} else if (Tok.is(tok::equal)) {
Diag(Tok.getLocation(), diag::err_mixed_attributes_and_annotations);
SkipUntil(tok::r_square, tok::colon, tok::r_splice, StopBeforeMatch);
}
AttrName = TryParseCXX11AttributeIdentifier(

View File

@@ -20,14 +20,14 @@ namespace basic_parsing {
consteval int fn() { return 1; }
[[maybe_unused, =42, =basic_parsing::fn(), maybe_unused]]
[[=42, =basic_parsing::fn()]]
void annFn();
struct [[maybe_unused, =42, =basic_parsing::fn(), maybe_unused]] S;
struct [[=42, =basic_parsing::fn()]] S;
template <typename>
struct [[maybe_unused, =42, =basic_parsing::fn(), maybe_unused]] TCls;
struct [[=42, =basic_parsing::fn()]] TCls;
namespace [[maybe_unused, =42, =basic_parsing::fn(), maybe_unused]] NS {};
namespace [[=42, =basic_parsing::fn()]] NS {};
} // namespace basic_parsing

View File

@@ -43,11 +43,11 @@ static_assert(annotations_of(^^NS).size() == 0);
// =============
namespace non_dependent {
[[maybe_unused, =1, =1, =2, =1.0f]] void fn();
struct [[maybe_unused, =3, =3, =4, =2.0f]] S;
template <typename> struct [[maybe_unused, =5, =5, =6, =3.0f]] TCls {};
template <typename> [[maybe_unused, =5, =5, =6, =3.0f]] void TFn();
namespace [[maybe_unused, =7, =7, =8, =4.0f]] NS {}
[[=1, =1, =2, =1.0f]] void fn();
struct [[=3, =3, =4, =2.0f]] S;
template <typename> struct [[=5, =5, =6, =3.0f]] TCls {};
template <typename> [[=5, =5, =6, =3.0f]] void TFn();
namespace [[=7, =7, =8, =4.0f]] NS {}
static_assert((annotations_of(^^fn) |
std::views::transform(std::meta::constant_of) |
@@ -153,7 +153,7 @@ template <std::meta::info R>
struct TCls {};
template <std::meta::info R> requires (is_function(R))
struct [[=int(annotations_of(R).size()), maybe_unused]] TCls<R> {};
struct [[=int(annotations_of(R).size())]] TCls<R> {};
static_assert(annotations_of(^^TCls<^^::>).size() == 0);
static_assert(annotation_of_type<int>(^^TCls<^^fn>) == 3);