[clang] C++26 Annotation (PR #166287)
via cfe-commits
cfe-commits at lists.llvm.org
Mon Nov 3 22:22:53 PST 2025
https://github.com/zebullax updated https://github.com/llvm/llvm-project/pull/166287
>From e2f13c0d8c6e5c6bed1fe445d16eed609e5f03e2 Mon Sep 17 00:00:00 2001
From: acassagnes <acassagnes at bloomberg.net>
Date: Sat, 1 Nov 2025 11:11:25 +0900
Subject: [PATCH 1/7] Add annotation to attribute tablegen
Recognize annotation starting token in attr parsing
Signed-off-by: acassagnes <acassagnes at bloomberg.net>
---
clang/include/clang/Basic/Attr.td | 45 +++++++++++++++++++
.../clang/Basic/DiagnosticParseKinds.td | 5 +++
clang/lib/Parse/ParseDeclCXX.cpp | 11 +++++
clang/utils/TableGen/ClangAttrEmitter.cpp | 8 ++--
4 files changed, 66 insertions(+), 3 deletions(-)
diff --git a/clang/include/clang/Basic/Attr.td b/clang/include/clang/Basic/Attr.td
index 749f531ec9ab1..06b9b1ff3e295 100644
--- a/clang/include/clang/Basic/Attr.td
+++ b/clang/include/clang/Basic/Attr.td
@@ -744,6 +744,9 @@ class Attr {
// Note: Any additional data members will leak and should be constructed
// externally on the ASTContext.
code AdditionalMembers = [{}];
+ // Any additional text that should be included verbatim after instantiating
+ // an attribute on a template.
+ code PostInstantiationStmts =[{}];
// Any documentation that should be associated with the attribute. Since an
// attribute may be documented under multiple categories, more than one
// Documentation entry may be listed.
@@ -930,6 +933,48 @@ def AlwaysInline : DeclOrStmtAttr {
let Documentation = [AlwaysInlineDocs];
}
+def CXX26Annotation : InheritableParamAttr {
+ let Spellings = [];
+ let Args = [ExprArgument<"Arg">];
+ let AdditionalMembers = [{
+private:
+ APValue Value;
+ SourceLocation EqLoc;
+
+public:
+ static CXX26AnnotationAttr *Create(ASTContext &Ctx, \
+ const AttributeCommonInfo &CommonInfo) {
+ return CXX26AnnotationAttr::Create(Ctx, nullptr, CommonInfo);
+ }
+ static CXX26AnnotationAttr *CreateImplicit( \
+ ASTContext &Ctx, \
+ const AttributeCommonInfo &CommonInfo) {
+ return CXX26AnnotationAttr::CreateImplicit(Ctx, nullptr, CommonInfo);
+ }
+
+ APValue getValue() const { return Value; }
+ void setValue(APValue V) { Value = V; }
+
+ SourceLocation getEqLoc() const { return EqLoc; }
+ void setEqLoc(SourceLocation Loc) { EqLoc = Loc; }
+ }];
+
+ let PostInstantiationStmts = [{
+ Expr::EvalResult V;
+ if (!Result->getArg()->isValueDependent() &&
+ !Result->getArg()->EvaluateAsRValue(V, C, true))
+ llvm_unreachable("failed to evaluate annotation expression");
+
+ Result->setValue(V.Val);
+ Result->setEqLoc(A->getEqLoc());
+ }];
+
+ let HasCustomParsing = 1;
+ let TemplateDependent = 1;
+ let MeaningfulToClassTemplateDefinition = 1;
+ let Documentation = [InternalOnly];
+}
+
def Artificial : InheritableAttr {
let Spellings = [GCC<"artificial">];
let Subjects = SubjectList<[InlineFunction]>;
diff --git a/clang/include/clang/Basic/DiagnosticParseKinds.td b/clang/include/clang/Basic/DiagnosticParseKinds.td
index e5e071f43fa75..c7e59ad21b3bb 100644
--- a/clang/include/clang/Basic/DiagnosticParseKinds.td
+++ b/clang/include/clang/Basic/DiagnosticParseKinds.td
@@ -1848,6 +1848,11 @@ def err_placeholder_expected_auto_or_decltype_auto : Error<
"expected 'auto' or 'decltype(auto)' after concept name">;
}
+let CategoryName = "Reflection Issue" in {
+def err_annotation_with_using : Error<
+ "annotations are not permitted following an attribute-using-prefix">;
+}
+
def warn_max_tokens : Warning<
"the number of preprocessor source tokens (%0) exceeds this token limit (%1)">,
InGroup<MaxTokens>, DefaultIgnore;
diff --git a/clang/lib/Parse/ParseDeclCXX.cpp b/clang/lib/Parse/ParseDeclCXX.cpp
index b96968d4592f5..4ca0568b37b12 100644
--- a/clang/lib/Parse/ParseDeclCXX.cpp
+++ b/clang/lib/Parse/ParseDeclCXX.cpp
@@ -17,6 +17,7 @@
#include "clang/Basic/Attributes.h"
#include "clang/Basic/CharInfo.h"
#include "clang/Basic/DiagnosticParse.h"
+#include "clang/Basic/LangOptions.h"
#include "clang/Basic/TargetInfo.h"
#include "clang/Basic/TokenKinds.h"
#include "clang/Lex/LiteralSupport.h"
@@ -4700,6 +4701,16 @@ void Parser::ParseCXX11AttributeSpecifierInternal(ParsedAttributes &Attrs,
SourceLocation ScopeLoc, AttrLoc;
IdentifierInfo *ScopeName = nullptr, *AttrName = nullptr;
+ // '=' token marks the beginning of an annotation
+ if (getLangOpts().CPlusPlus26 && Tok.is(tok::equal)) {
+ if (CommonScopeName) {
+ Diag(Tok.getLocation(), diag::err_annotation_with_using);
+ SkipUntil(tok::r_square, tok::colon, StopBeforeMatch);
+ continue;
+ }
+ continue;
+ }
+
AttrName = TryParseCXX11AttributeIdentifier(
AttrLoc, SemaCodeCompletion::AttributeCompletion::Attribute,
CommonScopeName);
diff --git a/clang/utils/TableGen/ClangAttrEmitter.cpp b/clang/utils/TableGen/ClangAttrEmitter.cpp
index 183952af590e1..7bc4719289441 100644
--- a/clang/utils/TableGen/ClangAttrEmitter.cpp
+++ b/clang/utils/TableGen/ClangAttrEmitter.cpp
@@ -4091,13 +4091,15 @@ EmitClangAttrTemplateInstantiateHelper(ArrayRef<const Record *> Attrs,
for (auto const &ai : Args)
ai->writeTemplateInstantiation(OS);
- OS << " return new (C) " << R.getName() << "Attr(C, *A";
+ OS << " auto* Result = new (C) " << R.getName() << "Attr(C, *A";
for (auto const &ai : Args) {
OS << ", ";
ai->writeTemplateInstantiationArgs(OS);
}
- OS << ");\n"
- << " }\n";
+ OS << ");\n";
+ OS << R.getValueAsString("PostInstantiationStmts");
+ OS << "return Result;\n";
+ OS << " }\n";
}
OS << " } // end switch\n"
<< " llvm_unreachable(\"Unknown attribute!\");\n"
>From 76337f8ae60947346fe4fe2f2569f5affe8f0722 Mon Sep 17 00:00:00 2001
From: acassagnes <acassagnes at bloomberg.net>
Date: Sun, 2 Nov 2025 10:52:44 +0900
Subject: [PATCH 2/7] Build logic around parsing of annotation inside list
Signed-off-by: acassagnes <acassagnes at bloomberg.net>
---
.../clang/Basic/DiagnosticParseKinds.td | 4 ++
clang/include/clang/Parse/Parser.h | 4 ++
clang/lib/Parse/ParseDeclCXX.cpp | 40 ++++++++++++++-----
3 files changed, 37 insertions(+), 11 deletions(-)
diff --git a/clang/include/clang/Basic/DiagnosticParseKinds.td b/clang/include/clang/Basic/DiagnosticParseKinds.td
index c7e59ad21b3bb..e87b605632d19 100644
--- a/clang/include/clang/Basic/DiagnosticParseKinds.td
+++ b/clang/include/clang/Basic/DiagnosticParseKinds.td
@@ -795,6 +795,10 @@ def err_cxx11_attribute_forbids_ellipsis : Error<
def warn_cxx14_compat_using_attribute_ns : Warning<
"default scope specifier for attributes is incompatible with C++ standards "
"before C++17">, InGroup<CXXPre17Compat>, DefaultIgnore;
+def warn_cxx26_compat_annotation : Warning<
+ "annotation is a C++26 extension">, InGroup<CXXPre26Compat>, DefaultIgnore;
+def err_mixed_attributes_and_annotations : Error<
+ "attribute specifier cannot contain both attributes and annotations">;
def ext_using_attribute_ns : ExtWarn<
"default scope specifier for attributes is a C++17 extension">,
InGroup<CXX17>;
diff --git a/clang/include/clang/Parse/Parser.h b/clang/include/clang/Parse/Parser.h
index dad8efd0f017f..dd1e774316ca0 100644
--- a/clang/include/clang/Parse/Parser.h
+++ b/clang/include/clang/Parse/Parser.h
@@ -3046,6 +3046,10 @@ class Parser : public CodeCompletionHandler {
SourceLocation ScopeLoc,
CachedTokens &OpenMPTokens);
+ /// TODO doc
+ void ParseAnnotationSpecifier(ParsedAttributes &Attrs,
+ SourceLocation *EndLoc);
+
/// Parse the argument to C++23's [[assume()]] attribute. Returns true on
/// error.
bool
diff --git a/clang/lib/Parse/ParseDeclCXX.cpp b/clang/lib/Parse/ParseDeclCXX.cpp
index 4ca0568b37b12..4a82a365bb0b8 100644
--- a/clang/lib/Parse/ParseDeclCXX.cpp
+++ b/clang/lib/Parse/ParseDeclCXX.cpp
@@ -4443,6 +4443,12 @@ static bool IsBuiltInOrStandardCXX11Attribute(IdentifierInfo *AttrName,
}
}
+void Parser::ParseAnnotationSpecifier(ParsedAttributes &Attrs,
+ SourceLocation *EndLoc)
+{
+ // TODO
+}
+
bool Parser::ParseCXXAssumeAttributeArg(
ParsedAttributes &Attrs, IdentifierInfo *AttrName,
SourceLocation AttrNameLoc, IdentifierInfo *ScopeName,
@@ -4682,16 +4688,21 @@ void Parser::ParseCXX11AttributeSpecifierInternal(ParsedAttributes &Attrs,
Diag(Tok.getLocation(), diag::err_expected) << tok::colon;
}
- bool AttrParsed = false;
+ bool hasAttribute = false;
+ bool hasAnnotation = false;
while (!Tok.isOneOf(tok::r_square, tok::semi, tok::eof)) {
- if (AttrParsed) {
- // If we parsed an attribute, a comma is required before parsing any
- // additional attributes.
+ // If we parsed an attribute/annotation, a comma is required before parsing
+ // any additional ones.
+ if (hasAttribute || hasAnnotation) {
if (ExpectAndConsume(tok::comma)) {
SkipUntil(tok::r_square, StopAtSemi | StopBeforeMatch);
continue;
}
- AttrParsed = false;
+ if (hasAttribute && hasAnnotation) {
+ Diag(Tok.getLocation(), diag::err_mixed_attributes_and_annotations);
+ SkipUntil(tok::r_square, tok::colon, StopBeforeMatch);
+ continue;
+ }
}
// Eat all remaining superfluous commas before parsing the next attribute.
@@ -4702,12 +4713,19 @@ void Parser::ParseCXX11AttributeSpecifierInternal(ParsedAttributes &Attrs,
IdentifierInfo *ScopeName = nullptr, *AttrName = nullptr;
// '=' token marks the beginning of an annotation
- if (getLangOpts().CPlusPlus26 && Tok.is(tok::equal)) {
+ if (Tok.is(tok::equal)) {
+ if (!getLangOpts().CPlusPlus26) {
+ Diag(Tok.getLocation(), diag::warn_cxx26_compat_annotation);
+ SkipUntil(tok::r_square, tok::colon, StopBeforeMatch);
+ continue;
+ }
if (CommonScopeName) {
Diag(Tok.getLocation(), diag::err_annotation_with_using);
SkipUntil(tok::r_square, tok::colon, StopBeforeMatch);
continue;
}
+ ParseAnnotationSpecifier(Attrs, EndLoc);
+ hasAnnotation = true;
continue;
}
@@ -4744,11 +4762,11 @@ void Parser::ParseCXX11AttributeSpecifierInternal(ParsedAttributes &Attrs,
}
// Parse attribute arguments
- if (Tok.is(tok::l_paren))
- AttrParsed = ParseCXX11AttributeArgs(AttrName, AttrLoc, Attrs, EndLoc,
- ScopeName, ScopeLoc, OpenMPTokens);
+ hasAttribute = Tok.is(tok::l_paren)
+ && ParseCXX11AttributeArgs(AttrName, AttrLoc, Attrs, EndLoc,
+ ScopeName, ScopeLoc, OpenMPTokens);
- if (!AttrParsed) {
+ if (!hasAttribute) {
Attrs.addNew(AttrName,
SourceRange(ScopeLoc.isValid() && CommonScopeLoc.isInvalid()
? ScopeLoc
@@ -4758,7 +4776,7 @@ void Parser::ParseCXX11AttributeSpecifierInternal(ParsedAttributes &Attrs,
nullptr, 0,
getLangOpts().CPlusPlus ? ParsedAttr::Form::CXX11()
: ParsedAttr::Form::C23());
- AttrParsed = true;
+ hasAttribute = true;
}
if (TryConsumeToken(tok::ellipsis))
>From cc405d31f4a9c0eb3d931b7d92729c98b7170889 Mon Sep 17 00:00:00 2001
From: acassagnes <acassagnes at bloomberg.net>
Date: Tue, 4 Nov 2025 09:19:07 +0900
Subject: [PATCH 3/7] Add sema handler for annotation
Add parsing for annotation
Signed-off-by: acassagnes <acassagnes at bloomberg.net>
---
.../include/clang/Basic/AttributeCommonInfo.h | 8 ++-
clang/lib/Parse/ParseDeclCXX.cpp | 28 +++++++++-
clang/lib/Sema/SemaDeclAttr.cpp | 56 +++++++++++++++++++
3 files changed, 88 insertions(+), 4 deletions(-)
diff --git a/clang/include/clang/Basic/AttributeCommonInfo.h b/clang/include/clang/Basic/AttributeCommonInfo.h
index 77b5eb8a1a7cc..c404d840555fd 100644
--- a/clang/include/clang/Basic/AttributeCommonInfo.h
+++ b/clang/include/clang/Basic/AttributeCommonInfo.h
@@ -61,7 +61,10 @@ class AttributeCommonInfo {
/// The attibute has no source code manifestation and is only created
/// implicitly.
- AS_Implicit
+ AS_Implicit,
+
+ /// The attribute is a C++26 annotation.
+ AS_Annotation,
};
enum Kind {
@@ -133,6 +136,7 @@ class AttributeCommonInfo {
static Form ContextSensitiveKeyword() { return AS_ContextSensitiveKeyword; }
static Form HLSLAnnotation() { return AS_HLSLAnnotation; }
static Form Implicit() { return AS_Implicit; }
+ static Form Annotation() { return AS_Annotation; }
private:
constexpr Form(Syntax SyntaxUsed)
@@ -156,7 +160,7 @@ class AttributeCommonInfo {
SpellingIndex(FormUsed.getSpellingIndex()),
IsAlignas(FormUsed.isAlignas()),
IsRegularKeywordAttribute(FormUsed.isRegularKeywordAttribute()) {
- assert(SyntaxUsed >= AS_GNU && SyntaxUsed <= AS_Implicit &&
+ assert(SyntaxUsed >= AS_GNU && SyntaxUsed <= AS_Annotation &&
"Invalid syntax!");
}
diff --git a/clang/lib/Parse/ParseDeclCXX.cpp b/clang/lib/Parse/ParseDeclCXX.cpp
index 4a82a365bb0b8..df33948790fd3 100644
--- a/clang/lib/Parse/ParseDeclCXX.cpp
+++ b/clang/lib/Parse/ParseDeclCXX.cpp
@@ -4446,7 +4446,23 @@ static bool IsBuiltInOrStandardCXX11Attribute(IdentifierInfo *AttrName,
void Parser::ParseAnnotationSpecifier(ParsedAttributes &Attrs,
SourceLocation *EndLoc)
{
- // TODO
+ assert(Tok.is(tok::equal) && "not an annotation");
+ SourceLocation EqLoc = ConsumeToken();
+
+ ExprResult AnnotExpr = ParseConstantExpression();
+ if (AnnotExpr.isInvalid() || AnnotExpr.get()->containsErrors())
+ return;
+
+ IdentifierTable &IT = Actions.PP.getIdentifierTable();
+ IdentifierInfo &Placeholder = IT.get("__annotation_placeholder");
+
+ ArgsVector ArgExprs;
+ ArgExprs.push_back(AnnotExpr.get());
+ Attrs.addNew(&Placeholder, EqLoc, {}, ArgExprs.data(), 1,
+ ParsedAttr::Form::Annotation());
+
+ if (EndLoc)
+ *EndLoc = AnnotExpr.get()->getEndLoc();
}
bool Parser::ParseCXXAssumeAttributeArg(
@@ -4712,7 +4728,10 @@ void Parser::ParseCXX11AttributeSpecifierInternal(ParsedAttributes &Attrs,
SourceLocation ScopeLoc, AttrLoc;
IdentifierInfo *ScopeName = nullptr, *AttrName = nullptr;
- // '=' token marks the beginning of an annotation
+ // A '=' token marks the beginning of an annotation
+ // - We must not be in C++ < 26
+ // - We must not have seen 'using X::'
+ // - We must not mix with an attribute
if (Tok.is(tok::equal)) {
if (!getLangOpts().CPlusPlus26) {
Diag(Tok.getLocation(), diag::warn_cxx26_compat_annotation);
@@ -4724,6 +4743,11 @@ void Parser::ParseCXX11AttributeSpecifierInternal(ParsedAttributes &Attrs,
SkipUntil(tok::r_square, tok::colon, StopBeforeMatch);
continue;
}
+ if (hasAttribute) {
+ Diag(Tok.getLocation(), diag::err_mixed_attributes_and_annotations);
+ SkipUntil(tok::r_square, tok::colon, StopBeforeMatch);
+ continue;
+ }
ParseAnnotationSpecifier(Attrs, EndLoc);
hasAnnotation = true;
continue;
diff --git a/clang/lib/Sema/SemaDeclAttr.cpp b/clang/lib/Sema/SemaDeclAttr.cpp
index a9e7b44ac9d73..725a84fd85c3c 100644
--- a/clang/lib/Sema/SemaDeclAttr.cpp
+++ b/clang/lib/Sema/SemaDeclAttr.cpp
@@ -6409,6 +6409,59 @@ static void handleRequiresCapabilityAttr(Sema &S, Decl *D,
D->addAttr(RCA);
}
+static void handleCxx26AnnotationAttr(Sema &S, Decl *D, const ParsedAttr &AL) {
+ Expr *CE = AL.getArgAsExpr(0);
+ if (CE->isLValue()) {
+ if (CE->getType()->isRecordType()) {
+ InitializedEntity Entity =
+ InitializedEntity::InitializeTemporary(
+ CE->getType().getUnqualifiedType());
+ InitializationKind Kind =
+ InitializationKind::CreateCopy(CE->getExprLoc(), SourceLocation());
+ InitializationSequence Seq(S, Entity, Kind, CE);
+
+ ExprResult CopyResult = Seq.Perform(S, Entity, Kind, CE);
+ if (CopyResult.isInvalid())
+ return;
+
+ CE = CopyResult.get();
+ } else {
+ ExprResult RVExprResult = S.DefaultLvalueConversion(AL.getArgAsExpr(0));
+ assert(!RVExprResult.isInvalid() && RVExprResult.get());
+
+ CE = RVExprResult.get();
+ }
+ }
+
+ Expr::EvalResult Result;
+
+ SmallVector<PartialDiagnosticAt, 4> Notes;
+ Result.Diag = &Notes;
+
+ if (!CE->isValueDependent()) {
+ ConstantExprKind CEKind = (CE->getType()->isClassType() ?
+ ConstantExprKind::ClassTemplateArgument :
+ ConstantExprKind::NonClassTemplateArgument);
+
+ if (!CE->EvaluateAsConstantExpr(Result, S.Context, CEKind)) {
+ S.Diag(CE->getBeginLoc(), diag::err_attribute_argument_type)
+ << "C++26 annotation" << 4 << CE->getSourceRange();
+ for (auto P : Notes)
+ S.Diag(P.first, P.second);
+
+ return;
+ } else if (!CE->getType()->isStructuralType()) {
+ S.Diag(CE->getBeginLoc(), diag::err_attribute_argument_type)
+ << "C++26 annotation" << 5 << CE->getSourceRange();
+ return;
+ }
+ }
+ auto *Annot = CXX26AnnotationAttr::Create(S.Context, CE, AL);
+ Annot->setValue(Result.Val);
+ Annot->setEqLoc(AL.getLoc());
+ D->addAttr(Annot);
+}
+
static void handleDeprecatedAttr(Sema &S, Decl *D, const ParsedAttr &AL) {
if (const auto *NSD = dyn_cast<NamespaceDecl>(D)) {
if (NSD->isAnonymousNamespace()) {
@@ -7179,6 +7232,9 @@ ProcessDeclAttribute(Sema &S, Scope *scope, Decl *D, const ParsedAttr &AL,
case ParsedAttr::AT_Constructor:
handleConstructorAttr(S, D, AL);
break;
+ case ParsedAttr::AT_CXX26Annotation:
+ handleCxx26AnnotationAttr(S, D, AL);
+ break;
case ParsedAttr::AT_Deprecated:
handleDeprecatedAttr(S, D, AL);
break;
>From 0a8e12564aae79285802f6d6598038c1f74de41c Mon Sep 17 00:00:00 2001
From: acassagnes <acassagnes at bloomberg.net>
Date: Tue, 4 Nov 2025 09:43:08 +0900
Subject: [PATCH 4/7] Fix the copy around of common info for attribute
Signed-off-by: acassagnes <acassagnes at bloomberg.net>
---
clang/lib/Sema/ParsedAttr.cpp | 7 +++++++
1 file changed, 7 insertions(+)
diff --git a/clang/lib/Sema/ParsedAttr.cpp b/clang/lib/Sema/ParsedAttr.cpp
index 2b5ad33ad7b29..888a5d42a0ec6 100644
--- a/clang/lib/Sema/ParsedAttr.cpp
+++ b/clang/lib/Sema/ParsedAttr.cpp
@@ -107,6 +107,13 @@ const ParsedAttrInfo &ParsedAttrInfo::get(const AttributeCommonInfo &A) {
if ((size_t)A.getParsedKind() < std::size(AttrInfoMap))
return *AttrInfoMap[A.getParsedKind()];
+ // If this is an annotation then return an appropriate ParsedAttrInfo.
+ static const ParsedAttrInfo AnnotationAttrInfo(
+ AttributeCommonInfo::AT_CXX26Annotation, 1, 0, 1, 1, 0, 0, 1, 1, 0, 0, {},
+ nullptr);
+ if (A.getSyntax() == AttributeCommonInfo::AS_Annotation)
+ return AnnotationAttrInfo;
+
// If this is an ignored attribute then return an appropriate ParsedAttrInfo.
static const ParsedAttrInfo IgnoredParsedAttrInfo(
AttributeCommonInfo::IgnoredAttribute);
>From c579bd993143b0c281fd1e7b4e7e3cb028eb0f4a Mon Sep 17 00:00:00 2001
From: acassagnes <acassagnes at bloomberg.net>
Date: Tue, 4 Nov 2025 11:21:59 +0900
Subject: [PATCH 5/7] Fill the doc for ParseAnnotationSpecifier
Signed-off-by: acassagnes <acassagnes at bloomberg.net>
---
clang/include/clang/Parse/Parser.h | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/clang/include/clang/Parse/Parser.h b/clang/include/clang/Parse/Parser.h
index dd1e774316ca0..52b909ffcae91 100644
--- a/clang/include/clang/Parse/Parser.h
+++ b/clang/include/clang/Parse/Parser.h
@@ -3046,7 +3046,7 @@ class Parser : public CodeCompletionHandler {
SourceLocation ScopeLoc,
CachedTokens &OpenMPTokens);
- /// TODO doc
+ /// Parse an annotation as specified from C++26
void ParseAnnotationSpecifier(ParsedAttributes &Attrs,
SourceLocation *EndLoc);
>From 7673caba149e586a84f0c8e371680a38ccc7cce8 Mon Sep 17 00:00:00 2001
From: acassagnes <acassagnes at bloomberg.net>
Date: Tue, 4 Nov 2025 11:45:06 +0900
Subject: [PATCH 6/7] Apply formatter
Signed-off-by: acassagnes <acassagnes at bloomberg.net>
---
clang/lib/Parse/ParseDeclCXX.cpp | 9 ++++-----
clang/lib/Sema/SemaDeclAttr.cpp | 12 ++++++------
2 files changed, 10 insertions(+), 11 deletions(-)
diff --git a/clang/lib/Parse/ParseDeclCXX.cpp b/clang/lib/Parse/ParseDeclCXX.cpp
index df33948790fd3..04eea962a0208 100644
--- a/clang/lib/Parse/ParseDeclCXX.cpp
+++ b/clang/lib/Parse/ParseDeclCXX.cpp
@@ -4444,8 +4444,7 @@ static bool IsBuiltInOrStandardCXX11Attribute(IdentifierInfo *AttrName,
}
void Parser::ParseAnnotationSpecifier(ParsedAttributes &Attrs,
- SourceLocation *EndLoc)
-{
+ SourceLocation *EndLoc) {
assert(Tok.is(tok::equal) && "not an annotation");
SourceLocation EqLoc = ConsumeToken();
@@ -4786,9 +4785,9 @@ void Parser::ParseCXX11AttributeSpecifierInternal(ParsedAttributes &Attrs,
}
// Parse attribute arguments
- hasAttribute = Tok.is(tok::l_paren)
- && ParseCXX11AttributeArgs(AttrName, AttrLoc, Attrs, EndLoc,
- ScopeName, ScopeLoc, OpenMPTokens);
+ hasAttribute = Tok.is(tok::l_paren) &&
+ ParseCXX11AttributeArgs(AttrName, AttrLoc, Attrs, EndLoc,
+ ScopeName, ScopeLoc, OpenMPTokens);
if (!hasAttribute) {
Attrs.addNew(AttrName,
diff --git a/clang/lib/Sema/SemaDeclAttr.cpp b/clang/lib/Sema/SemaDeclAttr.cpp
index 725a84fd85c3c..f72328facddfc 100644
--- a/clang/lib/Sema/SemaDeclAttr.cpp
+++ b/clang/lib/Sema/SemaDeclAttr.cpp
@@ -6413,9 +6413,8 @@ static void handleCxx26AnnotationAttr(Sema &S, Decl *D, const ParsedAttr &AL) {
Expr *CE = AL.getArgAsExpr(0);
if (CE->isLValue()) {
if (CE->getType()->isRecordType()) {
- InitializedEntity Entity =
- InitializedEntity::InitializeTemporary(
- CE->getType().getUnqualifiedType());
+ InitializedEntity Entity = InitializedEntity::InitializeTemporary(
+ CE->getType().getUnqualifiedType());
InitializationKind Kind =
InitializationKind::CreateCopy(CE->getExprLoc(), SourceLocation());
InitializationSequence Seq(S, Entity, Kind, CE);
@@ -6439,9 +6438,10 @@ static void handleCxx26AnnotationAttr(Sema &S, Decl *D, const ParsedAttr &AL) {
Result.Diag = &Notes;
if (!CE->isValueDependent()) {
- ConstantExprKind CEKind = (CE->getType()->isClassType() ?
- ConstantExprKind::ClassTemplateArgument :
- ConstantExprKind::NonClassTemplateArgument);
+ ConstantExprKind CEKind =
+ (CE->getType()->isClassType()
+ ? ConstantExprKind::ClassTemplateArgument
+ : ConstantExprKind::NonClassTemplateArgument);
if (!CE->EvaluateAsConstantExpr(Result, S.Context, CEKind)) {
S.Diag(CE->getBeginLoc(), diag::err_attribute_argument_type)
>From c28d0666990ffdc06286fa2515714fcb81e6cca8 Mon Sep 17 00:00:00 2001
From: acassagnes <acassagnes at bloomberg.net>
Date: Tue, 4 Nov 2025 14:39:00 +0900
Subject: [PATCH 7/7] Address review
Signed-off-by: acassagnes <acassagnes at bloomberg.net>
Undo dumb edit
Signed-off-by: acassagnes <acassagnes at bloomberg.net>
---
clang/lib/Parse/ParseDeclCXX.cpp | 18 +++++++++---------
clang/lib/Sema/SemaDeclAttr.cpp | 3 ++-
2 files changed, 11 insertions(+), 10 deletions(-)
diff --git a/clang/lib/Parse/ParseDeclCXX.cpp b/clang/lib/Parse/ParseDeclCXX.cpp
index 04eea962a0208..920b7b9429c4c 100644
--- a/clang/lib/Parse/ParseDeclCXX.cpp
+++ b/clang/lib/Parse/ParseDeclCXX.cpp
@@ -4703,17 +4703,17 @@ void Parser::ParseCXX11AttributeSpecifierInternal(ParsedAttributes &Attrs,
Diag(Tok.getLocation(), diag::err_expected) << tok::colon;
}
- bool hasAttribute = false;
- bool hasAnnotation = false;
+ bool HasAttribute = false;
+ bool HasAnnotation = false;
while (!Tok.isOneOf(tok::r_square, tok::semi, tok::eof)) {
// If we parsed an attribute/annotation, a comma is required before parsing
// any additional ones.
- if (hasAttribute || hasAnnotation) {
+ if (HasAttribute || HasAnnotation) {
if (ExpectAndConsume(tok::comma)) {
SkipUntil(tok::r_square, StopAtSemi | StopBeforeMatch);
continue;
}
- if (hasAttribute && hasAnnotation) {
+ if (HasAttribute && HasAnnotation) {
Diag(Tok.getLocation(), diag::err_mixed_attributes_and_annotations);
SkipUntil(tok::r_square, tok::colon, StopBeforeMatch);
continue;
@@ -4742,13 +4742,13 @@ void Parser::ParseCXX11AttributeSpecifierInternal(ParsedAttributes &Attrs,
SkipUntil(tok::r_square, tok::colon, StopBeforeMatch);
continue;
}
- if (hasAttribute) {
+ if (HasAttribute) {
Diag(Tok.getLocation(), diag::err_mixed_attributes_and_annotations);
SkipUntil(tok::r_square, tok::colon, StopBeforeMatch);
continue;
}
ParseAnnotationSpecifier(Attrs, EndLoc);
- hasAnnotation = true;
+ HasAnnotation = true;
continue;
}
@@ -4785,11 +4785,11 @@ void Parser::ParseCXX11AttributeSpecifierInternal(ParsedAttributes &Attrs,
}
// Parse attribute arguments
- hasAttribute = Tok.is(tok::l_paren) &&
+ HasAttribute = Tok.is(tok::l_paren) &&
ParseCXX11AttributeArgs(AttrName, AttrLoc, Attrs, EndLoc,
ScopeName, ScopeLoc, OpenMPTokens);
- if (!hasAttribute) {
+ if (!HasAttribute) {
Attrs.addNew(AttrName,
SourceRange(ScopeLoc.isValid() && CommonScopeLoc.isInvalid()
? ScopeLoc
@@ -4799,7 +4799,7 @@ void Parser::ParseCXX11AttributeSpecifierInternal(ParsedAttributes &Attrs,
nullptr, 0,
getLangOpts().CPlusPlus ? ParsedAttr::Form::CXX11()
: ParsedAttr::Form::C23());
- hasAttribute = true;
+ HasAttribute = true;
}
if (TryConsumeToken(tok::ellipsis))
diff --git a/clang/lib/Sema/SemaDeclAttr.cpp b/clang/lib/Sema/SemaDeclAttr.cpp
index f72328facddfc..2e293b15b97d0 100644
--- a/clang/lib/Sema/SemaDeclAttr.cpp
+++ b/clang/lib/Sema/SemaDeclAttr.cpp
@@ -6450,7 +6450,8 @@ static void handleCxx26AnnotationAttr(Sema &S, Decl *D, const ParsedAttr &AL) {
S.Diag(P.first, P.second);
return;
- } else if (!CE->getType()->isStructuralType()) {
+ }
+ if (!CE->getType()->isStructuralType()) {
S.Diag(CE->getBeginLoc(), diag::err_attribute_argument_type)
<< "C++26 annotation" << 5 << CE->getSourceRange();
return;
More information about the cfe-commits
mailing list