https://github.com/ericastor updated https://github.com/llvm/llvm-project/pull/115924
>From da2e66a6a2636bf1a1ab2e25afdbd29095b6db3f Mon Sep 17 00:00:00 2001 From: Eric Astor <epas...@google.com> Date: Tue, 12 Nov 2024 17:37:42 +0000 Subject: [PATCH 1/8] [clang] Instantiate attributes on other decl types Start propagating attributes on (e.g.) labels inside of templated functions to their instances. --- clang/lib/Sema/SemaTemplateInstantiateDecl.cpp | 16 +++++++++++++--- clang/test/SemaCXX/attr-mode-tmpl.cpp | 4 ++-- 2 files changed, 15 insertions(+), 5 deletions(-) diff --git a/clang/lib/Sema/SemaTemplateInstantiateDecl.cpp b/clang/lib/Sema/SemaTemplateInstantiateDecl.cpp index 5a001843e2ba46..bfc5913dbafd0f 100644 --- a/clang/lib/Sema/SemaTemplateInstantiateDecl.cpp +++ b/clang/lib/Sema/SemaTemplateInstantiateDecl.cpp @@ -990,6 +990,7 @@ Decl * TemplateDeclInstantiator::VisitLabelDecl(LabelDecl *D) { LabelDecl *Inst = LabelDecl::Create(SemaRef.Context, Owner, D->getLocation(), D->getIdentifier()); + SemaRef.InstantiateAttrs(TemplateArgs, D, Inst, LateAttrs, StartingScope); Owner->addDecl(Inst); return Inst; } @@ -1009,6 +1010,7 @@ TemplateDeclInstantiator::VisitNamespaceAliasDecl(NamespaceAliasDecl *D) { D->getQualifierLoc(), D->getTargetNameLoc(), D->getNamespace()); + SemaRef.InstantiateAttrs(TemplateArgs, D, Inst, LateAttrs, StartingScope); Owner->addDecl(Inst); return Inst; } @@ -1095,15 +1097,21 @@ Decl *TemplateDeclInstantiator::InstantiateTypedefNameDecl(TypedefNameDecl *D, Decl *TemplateDeclInstantiator::VisitTypedefDecl(TypedefDecl *D) { Decl *Typedef = InstantiateTypedefNameDecl(D, /*IsTypeAlias=*/false); - if (Typedef) + if (Typedef) { + SemaRef.InstantiateAttrs(TemplateArgs, D, Typedef, LateAttrs, + StartingScope); Owner->addDecl(Typedef); + } return Typedef; } Decl *TemplateDeclInstantiator::VisitTypeAliasDecl(TypeAliasDecl *D) { Decl *Typedef = InstantiateTypedefNameDecl(D, /*IsTypeAlias=*/true); - if (Typedef) + if (Typedef) { + SemaRef.InstantiateAttrs(TemplateArgs, D, Typedef, LateAttrs, + StartingScope); Owner->addDecl(Typedef); + } return Typedef; } @@ -1160,8 +1168,10 @@ Decl *TemplateDeclInstantiator::InstantiateTypeAliasTemplateDecl( Decl * TemplateDeclInstantiator::VisitTypeAliasTemplateDecl(TypeAliasTemplateDecl *D) { Decl *Inst = InstantiateTypeAliasTemplateDecl(D); - if (Inst) + if (Inst) { + SemaRef.InstantiateAttrs(TemplateArgs, D, Inst, LateAttrs, StartingScope); Owner->addDecl(Inst); + } return Inst; } diff --git a/clang/test/SemaCXX/attr-mode-tmpl.cpp b/clang/test/SemaCXX/attr-mode-tmpl.cpp index f665b1ba491237..58266f947051c5 100644 --- a/clang/test/SemaCXX/attr-mode-tmpl.cpp +++ b/clang/test/SemaCXX/attr-mode-tmpl.cpp @@ -9,7 +9,7 @@ void CheckEnumerations() { // Check that non-vector 'mode' attribute is OK with enumeration types. typedef T __attribute__((mode(QI))) T1; typedef T T2 __attribute__((mode(HI))); - typedef T __attribute__((mode(V8SI))) T3; // expected-error{{mode 'V8SI' is not supported for enumeration types}} + typedef T __attribute__((mode(V8SI))) T3; // expected-error2{{mode 'V8SI' is not supported for enumeration types}} // expected-warning@-1{{specifying vector types with the 'mode' attribute is deprecated}} typedef enum __attribute__((mode(HI))) { A4, B4 } T4; @@ -62,7 +62,7 @@ struct TemplatedStruct { // Check typedefs. typedef T __attribute__((mode(DI))) T1; - typedef T __attribute__((mode(V8DI))) T2; // expected-error{{mode 'V8DI' is not supported for enumeration types}} + typedef T __attribute__((mode(V8DI))) T2; // expected-error2{{mode 'V8DI' is not supported for enumeration types}} // expected-warning@-1{{deprecated}} // Check parameters. >From eb4b3a2d1e25b9fc63048e5f2d71d62a3cbd2bde Mon Sep 17 00:00:00 2001 From: Eric Astor <epas...@google.com> Date: Thu, 14 Nov 2024 19:24:45 +0000 Subject: [PATCH 2/8] Include attributes on LabelStmts (forwarding from decls) in AST dumps We apply this to add a test of the new label attribute instantiation support. --- clang/examples/Attribute/Attribute.cpp | 6 +++--- clang/include/clang/AST/ASTNodeTraverser.h | 5 +++++ clang/test/Frontend/plugin-attribute.cpp | 8 ++++++++ 3 files changed, 16 insertions(+), 3 deletions(-) diff --git a/clang/examples/Attribute/Attribute.cpp b/clang/examples/Attribute/Attribute.cpp index 3b90724ad22205..59446a15a6925d 100644 --- a/clang/examples/Attribute/Attribute.cpp +++ b/clang/examples/Attribute/Attribute.cpp @@ -41,9 +41,9 @@ struct ExampleAttrInfo : public ParsedAttrInfo { bool diagAppertainsToDecl(Sema &S, const ParsedAttr &Attr, const Decl *D) const override { // This attribute appertains to functions only. - if (!isa<FunctionDecl>(D)) { + if (!isa<FunctionDecl>(D) && !isa<LabelDecl>(D)) { S.Diag(Attr.getLoc(), diag::warn_attribute_wrong_decl_type_str) - << Attr << Attr.isRegularKeywordAttribute() << "functions"; + << Attr << Attr.isRegularKeywordAttribute() << "functions or labels"; return false; } return true; @@ -52,7 +52,7 @@ struct ExampleAttrInfo : public ParsedAttrInfo { AttrHandling handleDeclAttribute(Sema &S, Decl *D, const ParsedAttr &Attr) const override { // Check if the decl is at file scope. - if (!D->getDeclContext()->isFileContext()) { + if (!D->getDeclContext()->isFileContext() && !isa<LabelDecl>(D)) { unsigned ID = S.getDiagnostics().getCustomDiagID( DiagnosticsEngine::Error, "'example' attribute only allowed at file scope"); diff --git a/clang/include/clang/AST/ASTNodeTraverser.h b/clang/include/clang/AST/ASTNodeTraverser.h index a443a88bab1f2d..876dcb647b27b4 100644 --- a/clang/include/clang/AST/ASTNodeTraverser.h +++ b/clang/include/clang/AST/ASTNodeTraverser.h @@ -800,6 +800,11 @@ class ASTNodeTraverser Visit(A); } + void VisitLabelStmt(const LabelStmt *Node) { + for (const auto *A : Node->getDecl()->getAttrs()) + Visit(A); + } + void VisitCXXCatchStmt(const CXXCatchStmt *Node) { Visit(Node->getExceptionDecl()); } diff --git a/clang/test/Frontend/plugin-attribute.cpp b/clang/test/Frontend/plugin-attribute.cpp index 094ce9f5cbb85f..943ae3f95178d5 100644 --- a/clang/test/Frontend/plugin-attribute.cpp +++ b/clang/test/Frontend/plugin-attribute.cpp @@ -18,6 +18,9 @@ void fn2() __attribute__((example("somestring", 1, 2.0))) { } template <int N> void template_fn() __attribute__((example("template", N))) { __attribute__((example("def", N + 1))) for (int i = 0; i < 9; ++i) {} + __attribute__((example("ghi", N + 2))) +label1: + for (int i = 0; i < 9; ++i) {} } void fn3() { template_fn<5>(); } // CHECK: -AttributedStmt 0x{{[0-9a-z]+}} {{<line:[0-9]+:[0-9]+(, col:[0-9]+)?>}} @@ -44,6 +47,11 @@ void fn3() { template_fn<5>(); } // CHECK: -IntegerLiteral 0x{{[0-9a-z]+}} {{<line:[0-9]+:[0-9]+(, col:[0-9]+)?>}} 'int' 5 // CHECK: -IntegerLiteral 0x{{[0-9a-z]+}} {{<col:[0-9]+(, col:[0-9]+)?>}} 'int' 1 // CHECK: -AnnotateAttr 0x{{[0-9a-z]+}} {{<line:[0-9]+:[0-9]+(, col:[0-9]+)?>}} "example" +// CHECK: -StringLiteral 0x{{[0-9a-z]+}} {{<col:[0-9]+(, col:[0-9]+)?>}} 'const char[{{[0-9]+}}]' lvalue "ghi" +// CHECK: -BinaryOperator 0x{{[0-9a-z]+}} {{<col:[0-9]+(, col:[0-9]+)?>}} 'int' '+' +// CHECK: -IntegerLiteral 0x{{[0-9a-z]+}} {{<line:[0-9]+:[0-9]+(, col:[0-9]+)?>}} 'int' 5 +// CHECK: -IntegerLiteral 0x{{[0-9a-z]+}} {{<col:[0-9]+(, col:[0-9]+)?>}} 'int' 2 +// CHECK: -AnnotateAttr 0x{{[0-9a-z]+}} {{<line:[0-9]+:[0-9]+(, col:[0-9]+)?>}} "example" // CHECK: -StringLiteral 0x{{[0-9a-z]+}} {{<col:[0-9]+(, col:[0-9]+)?>}} 'const char[{{[0-9]+}}]' lvalue "template" // CHECK: -IntegerLiteral 0x{{[0-9a-z]+}} {{<col:[0-9]+(, col:[0-9]+)?>}} 'int' 5 >From 6ba54c4760f943402d3ae47282ebd1502e59afb9 Mon Sep 17 00:00:00 2001 From: Eric Astor <epas...@google.com> Date: Thu, 14 Nov 2024 19:37:39 +0000 Subject: [PATCH 3/8] Scope this change back to just applying to LabelDecls --- clang/lib/Sema/SemaTemplateInstantiateDecl.cpp | 15 +++------------ 1 file changed, 3 insertions(+), 12 deletions(-) diff --git a/clang/lib/Sema/SemaTemplateInstantiateDecl.cpp b/clang/lib/Sema/SemaTemplateInstantiateDecl.cpp index bfc5913dbafd0f..4529eb99377e78 100644 --- a/clang/lib/Sema/SemaTemplateInstantiateDecl.cpp +++ b/clang/lib/Sema/SemaTemplateInstantiateDecl.cpp @@ -1010,7 +1010,6 @@ TemplateDeclInstantiator::VisitNamespaceAliasDecl(NamespaceAliasDecl *D) { D->getQualifierLoc(), D->getTargetNameLoc(), D->getNamespace()); - SemaRef.InstantiateAttrs(TemplateArgs, D, Inst, LateAttrs, StartingScope); Owner->addDecl(Inst); return Inst; } @@ -1097,21 +1096,15 @@ Decl *TemplateDeclInstantiator::InstantiateTypedefNameDecl(TypedefNameDecl *D, Decl *TemplateDeclInstantiator::VisitTypedefDecl(TypedefDecl *D) { Decl *Typedef = InstantiateTypedefNameDecl(D, /*IsTypeAlias=*/false); - if (Typedef) { - SemaRef.InstantiateAttrs(TemplateArgs, D, Typedef, LateAttrs, - StartingScope); + if (Typedef) Owner->addDecl(Typedef); - } return Typedef; } Decl *TemplateDeclInstantiator::VisitTypeAliasDecl(TypeAliasDecl *D) { Decl *Typedef = InstantiateTypedefNameDecl(D, /*IsTypeAlias=*/true); - if (Typedef) { - SemaRef.InstantiateAttrs(TemplateArgs, D, Typedef, LateAttrs, - StartingScope); + if (Typedef) Owner->addDecl(Typedef); - } return Typedef; } @@ -1168,10 +1161,8 @@ Decl *TemplateDeclInstantiator::InstantiateTypeAliasTemplateDecl( Decl * TemplateDeclInstantiator::VisitTypeAliasTemplateDecl(TypeAliasTemplateDecl *D) { Decl *Inst = InstantiateTypeAliasTemplateDecl(D); - if (Inst) { - SemaRef.InstantiateAttrs(TemplateArgs, D, Inst, LateAttrs, StartingScope); + if (Inst) Owner->addDecl(Inst); - } return Inst; } >From 627a4d2a575f8377e22fbc1e19760d38cc278f1d Mon Sep 17 00:00:00 2001 From: Eric Astor <epas...@google.com> Date: Thu, 14 Nov 2024 22:10:37 +0000 Subject: [PATCH 4/8] Add test using standard attribute --- clang/test/SemaCXX/attr-annotate.cpp | 62 ++++++++++++++++++++++++++- clang/test/SemaCXX/attr-mode-tmpl.cpp | 4 +- 2 files changed, 63 insertions(+), 3 deletions(-) diff --git a/clang/test/SemaCXX/attr-annotate.cpp b/clang/test/SemaCXX/attr-annotate.cpp index 846ef4119f1d7c..9975200426a9ba 100644 --- a/clang/test/SemaCXX/attr-annotate.cpp +++ b/clang/test/SemaCXX/attr-annotate.cpp @@ -1,4 +1,64 @@ -// RUN: %clang_cc1 -std=gnu++20 -fsyntax-only -verify %s +// RUN: split-file %s %t +// RUN: %clang_cc1 -std=gnu++20 -fsyntax-only -ast-dump -verify %t/good_annotate.cpp | FileCheck %s +// RUN: %clang_cc1 -std=gnu++20 -fsyntax-only -verify %t/bad_annotate.cpp +//--- good_annotate.cpp +// expected-no-diagnostics + +void f() { + [[clang::annotate("decl", 1)]] int i = 0; + [[clang::annotate("stmt", 2)]] i += 1; +[[clang::annotate("label", 3)]] label1: + i += 2; +} + +// CHECK: -FunctionDecl 0x{{[0-9a-z]+}} {{.*:[0-9]+:[0-9]+, line:[0-9]+:[0-9]+> line:[0-9]+:[0-9]+}} f 'void ()' +// CHECK: -VarDecl 0x{{[0-9a-z]+}} {{<col:[0-9]+(, col:[0-9]+)?> col:[0-9]+}} used i 'int' +// CHECK: -AnnotateAttr 0x{{[0-9a-z]+}} {{<col:[0-9]+(, col:[0-9]+)?>}} "decl" +// CHECK: -IntegerLiteral 0x{{[0-9a-z]+}} {{<col:[0-9]+(, col:[0-9]+)?>}} 'int' 1 +// CHECK: -AttributedStmt 0x{{[0-9a-z]+}} {{<line:[0-9]+:[0-9]+(, col:[0-9]+)?>}} +// CHECK: -AnnotateAttr 0x{{[0-9a-z]+}} {{<col:[0-9]+(, col:[0-9]+)?>}} "stmt" +// CHECK: -IntegerLiteral 0x{{[0-9a-z]+}} {{<col:[0-9]+(, col:[0-9]+)?>}} 'int' 2 +// CHECK: -LabelStmt 0x{{[0-9a-z]+}} {{<line:[0-9]+:[0-9]+(, line:[0-9]+:[0-9]+)?>}} 'label1' +// CHECK: -AnnotateAttr 0x{{[0-9a-z]+}} {{<line:[0-9]+:[0-9]+(, col:[0-9]+)?>}} "label" +// CHECK: -IntegerLiteral 0x{{[0-9a-z]+}} {{<col:[0-9]+(, col:[0-9]+)?>}} 'int' 3 +// CHECK: -CompoundAssignOperator 0x{{[0-9a-z]+}} {{<line:[0-9]+:[0-9]+(, col:[0-9]+)?>}} + +template <typename T> void g() { + [[clang::annotate("tmpl_decl", 4)]] T j = 0; + [[clang::annotate("tmpl_stmt", 5)]] j += 1; +[[clang::annotate("tmpl_label", 6)]] label2: + j += 2; +} + +// CHECK: -FunctionTemplateDecl 0x{{[0-9a-z]+}} {{.*:[0-9]+:[0-9]+, line:[0-9]+:[0-9]+> line:[0-9]+:[0-9]+}} g +// CHECK: -VarDecl 0x{{[0-9a-z]+}} {{<col:[0-9]+(, col:[0-9]+)?> col:[0-9]+}} referenced j 'T' +// CHECK: -AnnotateAttr 0x{{[0-9a-z]+}} {{<col:[0-9]+(, col:[0-9]+)?>}} "tmpl_decl" +// CHECK: -IntegerLiteral 0x{{[0-9a-z]+}} {{<col:[0-9]+(, col:[0-9]+)?>}} 'int' 4 +// CHECK: -AttributedStmt 0x{{[0-9a-z]+}} {{<line:[0-9]+:[0-9]+(, col:[0-9]+)?>}} +// CHECK: -AnnotateAttr 0x{{[0-9a-z]+}} {{<col:[0-9]+(, col:[0-9]+)?>}} "tmpl_stmt" +// CHECK: -IntegerLiteral 0x{{[0-9a-z]+}} {{<col:[0-9]+(, col:[0-9]+)?>}} 'int' 5 +// CHECK: -LabelStmt 0x{{[0-9a-z]+}} {{<line:[0-9]+:[0-9]+(, line:[0-9]+:[0-9]+)?>}} 'label2' +// CHECK: -AnnotateAttr 0x{{[0-9a-z]+}} {{<line:[0-9]+:[0-9]+(, col:[0-9]+)?>}} "tmpl_label" +// CHECK: -IntegerLiteral 0x{{[0-9a-z]+}} {{<col:[0-9]+(, col:[0-9]+)?>}} 'int' 6 +// CHECK: -CompoundAssignOperator 0x{{[0-9a-z]+}} {{<line:[0-9]+:[0-9]+(, col:[0-9]+)?>}} + +void h() { + g<int>(); +} + +// CHECK: -FunctionDecl 0x{{[0-9a-z]+}} {{.*:[0-9]+:[0-9]+, line:[0-9]+:[0-9]+> line:[0-9]+:[0-9]+}} used g 'void ()' implicit_instantiation +// CHECK: -VarDecl 0x{{[0-9a-z]+}} {{<col:[0-9]+(, col:[0-9]+)?> col:[0-9]+}} used j 'int' +// CHECK: -AnnotateAttr 0x{{[0-9a-z]+}} {{<col:[0-9]+(, col:[0-9]+)?>}} "tmpl_decl" +// CHECK: -IntegerLiteral 0x{{[0-9a-z]+}} {{<col:[0-9]+(, col:[0-9]+)?>}} 'int' 4 +// CHECK: -AttributedStmt 0x{{[0-9a-z]+}} {{<line:[0-9]+:[0-9]+(, col:[0-9]+)?>}} +// CHECK: -AnnotateAttr 0x{{[0-9a-z]+}} {{<col:[0-9]+(, col:[0-9]+)?>}} Implicit "tmpl_stmt" +// CHECK: -IntegerLiteral 0x{{[0-9a-z]+}} {{<col:[0-9]+(, col:[0-9]+)?>}} 'int' 5 +// CHECK: -LabelStmt 0x{{[0-9a-z]+}} {{<line:[0-9]+:[0-9]+(, line:[0-9]+:[0-9]+)?>}} 'label2' +// CHECK: -AnnotateAttr 0x{{[0-9a-z]+}} {{<line:[0-9]+:[0-9]+(, col:[0-9]+)?>}} "tmpl_label" +// CHECK: -IntegerLiteral 0x{{[0-9a-z]+}} {{<col:[0-9]+(, col:[0-9]+)?>}} 'int' 6 +// CHECK: -CompoundAssignOperator 0x{{[0-9a-z]+}} {{<line:[0-9]+:[0-9]+(, col:[0-9]+)?>}} + +//--- bad_annotate.cpp template<bool If, typename Type> struct enable_if { diff --git a/clang/test/SemaCXX/attr-mode-tmpl.cpp b/clang/test/SemaCXX/attr-mode-tmpl.cpp index 58266f947051c5..f665b1ba491237 100644 --- a/clang/test/SemaCXX/attr-mode-tmpl.cpp +++ b/clang/test/SemaCXX/attr-mode-tmpl.cpp @@ -9,7 +9,7 @@ void CheckEnumerations() { // Check that non-vector 'mode' attribute is OK with enumeration types. typedef T __attribute__((mode(QI))) T1; typedef T T2 __attribute__((mode(HI))); - typedef T __attribute__((mode(V8SI))) T3; // expected-error2{{mode 'V8SI' is not supported for enumeration types}} + typedef T __attribute__((mode(V8SI))) T3; // expected-error{{mode 'V8SI' is not supported for enumeration types}} // expected-warning@-1{{specifying vector types with the 'mode' attribute is deprecated}} typedef enum __attribute__((mode(HI))) { A4, B4 } T4; @@ -62,7 +62,7 @@ struct TemplatedStruct { // Check typedefs. typedef T __attribute__((mode(DI))) T1; - typedef T __attribute__((mode(V8DI))) T2; // expected-error2{{mode 'V8DI' is not supported for enumeration types}} + typedef T __attribute__((mode(V8DI))) T2; // expected-error{{mode 'V8DI' is not supported for enumeration types}} // expected-warning@-1{{deprecated}} // Check parameters. >From e0d76989721609b516d93d8f69672d9a1e552257 Mon Sep 17 00:00:00 2001 From: Eric Astor <epas...@google.com> Date: Thu, 14 Nov 2024 22:13:11 +0000 Subject: [PATCH 5/8] Remove unnecessary use of plugins for testing --- clang/examples/Attribute/Attribute.cpp | 6 +++--- clang/test/Frontend/plugin-attribute.cpp | 8 -------- 2 files changed, 3 insertions(+), 11 deletions(-) diff --git a/clang/examples/Attribute/Attribute.cpp b/clang/examples/Attribute/Attribute.cpp index 59446a15a6925d..3b90724ad22205 100644 --- a/clang/examples/Attribute/Attribute.cpp +++ b/clang/examples/Attribute/Attribute.cpp @@ -41,9 +41,9 @@ struct ExampleAttrInfo : public ParsedAttrInfo { bool diagAppertainsToDecl(Sema &S, const ParsedAttr &Attr, const Decl *D) const override { // This attribute appertains to functions only. - if (!isa<FunctionDecl>(D) && !isa<LabelDecl>(D)) { + if (!isa<FunctionDecl>(D)) { S.Diag(Attr.getLoc(), diag::warn_attribute_wrong_decl_type_str) - << Attr << Attr.isRegularKeywordAttribute() << "functions or labels"; + << Attr << Attr.isRegularKeywordAttribute() << "functions"; return false; } return true; @@ -52,7 +52,7 @@ struct ExampleAttrInfo : public ParsedAttrInfo { AttrHandling handleDeclAttribute(Sema &S, Decl *D, const ParsedAttr &Attr) const override { // Check if the decl is at file scope. - if (!D->getDeclContext()->isFileContext() && !isa<LabelDecl>(D)) { + if (!D->getDeclContext()->isFileContext()) { unsigned ID = S.getDiagnostics().getCustomDiagID( DiagnosticsEngine::Error, "'example' attribute only allowed at file scope"); diff --git a/clang/test/Frontend/plugin-attribute.cpp b/clang/test/Frontend/plugin-attribute.cpp index 943ae3f95178d5..094ce9f5cbb85f 100644 --- a/clang/test/Frontend/plugin-attribute.cpp +++ b/clang/test/Frontend/plugin-attribute.cpp @@ -18,9 +18,6 @@ void fn2() __attribute__((example("somestring", 1, 2.0))) { } template <int N> void template_fn() __attribute__((example("template", N))) { __attribute__((example("def", N + 1))) for (int i = 0; i < 9; ++i) {} - __attribute__((example("ghi", N + 2))) -label1: - for (int i = 0; i < 9; ++i) {} } void fn3() { template_fn<5>(); } // CHECK: -AttributedStmt 0x{{[0-9a-z]+}} {{<line:[0-9]+:[0-9]+(, col:[0-9]+)?>}} @@ -47,11 +44,6 @@ void fn3() { template_fn<5>(); } // CHECK: -IntegerLiteral 0x{{[0-9a-z]+}} {{<line:[0-9]+:[0-9]+(, col:[0-9]+)?>}} 'int' 5 // CHECK: -IntegerLiteral 0x{{[0-9a-z]+}} {{<col:[0-9]+(, col:[0-9]+)?>}} 'int' 1 // CHECK: -AnnotateAttr 0x{{[0-9a-z]+}} {{<line:[0-9]+:[0-9]+(, col:[0-9]+)?>}} "example" -// CHECK: -StringLiteral 0x{{[0-9a-z]+}} {{<col:[0-9]+(, col:[0-9]+)?>}} 'const char[{{[0-9]+}}]' lvalue "ghi" -// CHECK: -BinaryOperator 0x{{[0-9a-z]+}} {{<col:[0-9]+(, col:[0-9]+)?>}} 'int' '+' -// CHECK: -IntegerLiteral 0x{{[0-9a-z]+}} {{<line:[0-9]+:[0-9]+(, col:[0-9]+)?>}} 'int' 5 -// CHECK: -IntegerLiteral 0x{{[0-9a-z]+}} {{<col:[0-9]+(, col:[0-9]+)?>}} 'int' 2 -// CHECK: -AnnotateAttr 0x{{[0-9a-z]+}} {{<line:[0-9]+:[0-9]+(, col:[0-9]+)?>}} "example" // CHECK: -StringLiteral 0x{{[0-9a-z]+}} {{<col:[0-9]+(, col:[0-9]+)?>}} 'const char[{{[0-9]+}}]' lvalue "template" // CHECK: -IntegerLiteral 0x{{[0-9a-z]+}} {{<col:[0-9]+(, col:[0-9]+)?>}} 'int' 5 >From fb705ad9008d29c3f3efa9199342e38512410ee5 Mon Sep 17 00:00:00 2001 From: Eric Astor <epas...@google.com> Date: Thu, 14 Nov 2024 23:12:27 +0000 Subject: [PATCH 6/8] Fix the no-attributes case --- clang/include/clang/AST/ASTNodeTraverser.h | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/clang/include/clang/AST/ASTNodeTraverser.h b/clang/include/clang/AST/ASTNodeTraverser.h index 876dcb647b27b4..3d63d581a9be60 100644 --- a/clang/include/clang/AST/ASTNodeTraverser.h +++ b/clang/include/clang/AST/ASTNodeTraverser.h @@ -801,8 +801,10 @@ class ASTNodeTraverser } void VisitLabelStmt(const LabelStmt *Node) { - for (const auto *A : Node->getDecl()->getAttrs()) - Visit(A); + if (Node->getDecl()->hasAttrs()) { + for (const auto *A : Node->getDecl()->getAttrs()) + Visit(A); + } } void VisitCXXCatchStmt(const CXXCatchStmt *Node) { >From 96224998e2b5fac90183413df497e8e8308489e2 Mon Sep 17 00:00:00 2001 From: Eric Astor <epas...@google.com> Date: Fri, 15 Nov 2024 14:52:10 +0000 Subject: [PATCH 7/8] Clean up & simplify tests --- clang/test/SemaCXX/attr-annotate.cpp | 62 +--------------------------- 1 file changed, 1 insertion(+), 61 deletions(-) diff --git a/clang/test/SemaCXX/attr-annotate.cpp b/clang/test/SemaCXX/attr-annotate.cpp index 9975200426a9ba..846ef4119f1d7c 100644 --- a/clang/test/SemaCXX/attr-annotate.cpp +++ b/clang/test/SemaCXX/attr-annotate.cpp @@ -1,64 +1,4 @@ -// RUN: split-file %s %t -// RUN: %clang_cc1 -std=gnu++20 -fsyntax-only -ast-dump -verify %t/good_annotate.cpp | FileCheck %s -// RUN: %clang_cc1 -std=gnu++20 -fsyntax-only -verify %t/bad_annotate.cpp -//--- good_annotate.cpp -// expected-no-diagnostics - -void f() { - [[clang::annotate("decl", 1)]] int i = 0; - [[clang::annotate("stmt", 2)]] i += 1; -[[clang::annotate("label", 3)]] label1: - i += 2; -} - -// CHECK: -FunctionDecl 0x{{[0-9a-z]+}} {{.*:[0-9]+:[0-9]+, line:[0-9]+:[0-9]+> line:[0-9]+:[0-9]+}} f 'void ()' -// CHECK: -VarDecl 0x{{[0-9a-z]+}} {{<col:[0-9]+(, col:[0-9]+)?> col:[0-9]+}} used i 'int' -// CHECK: -AnnotateAttr 0x{{[0-9a-z]+}} {{<col:[0-9]+(, col:[0-9]+)?>}} "decl" -// CHECK: -IntegerLiteral 0x{{[0-9a-z]+}} {{<col:[0-9]+(, col:[0-9]+)?>}} 'int' 1 -// CHECK: -AttributedStmt 0x{{[0-9a-z]+}} {{<line:[0-9]+:[0-9]+(, col:[0-9]+)?>}} -// CHECK: -AnnotateAttr 0x{{[0-9a-z]+}} {{<col:[0-9]+(, col:[0-9]+)?>}} "stmt" -// CHECK: -IntegerLiteral 0x{{[0-9a-z]+}} {{<col:[0-9]+(, col:[0-9]+)?>}} 'int' 2 -// CHECK: -LabelStmt 0x{{[0-9a-z]+}} {{<line:[0-9]+:[0-9]+(, line:[0-9]+:[0-9]+)?>}} 'label1' -// CHECK: -AnnotateAttr 0x{{[0-9a-z]+}} {{<line:[0-9]+:[0-9]+(, col:[0-9]+)?>}} "label" -// CHECK: -IntegerLiteral 0x{{[0-9a-z]+}} {{<col:[0-9]+(, col:[0-9]+)?>}} 'int' 3 -// CHECK: -CompoundAssignOperator 0x{{[0-9a-z]+}} {{<line:[0-9]+:[0-9]+(, col:[0-9]+)?>}} - -template <typename T> void g() { - [[clang::annotate("tmpl_decl", 4)]] T j = 0; - [[clang::annotate("tmpl_stmt", 5)]] j += 1; -[[clang::annotate("tmpl_label", 6)]] label2: - j += 2; -} - -// CHECK: -FunctionTemplateDecl 0x{{[0-9a-z]+}} {{.*:[0-9]+:[0-9]+, line:[0-9]+:[0-9]+> line:[0-9]+:[0-9]+}} g -// CHECK: -VarDecl 0x{{[0-9a-z]+}} {{<col:[0-9]+(, col:[0-9]+)?> col:[0-9]+}} referenced j 'T' -// CHECK: -AnnotateAttr 0x{{[0-9a-z]+}} {{<col:[0-9]+(, col:[0-9]+)?>}} "tmpl_decl" -// CHECK: -IntegerLiteral 0x{{[0-9a-z]+}} {{<col:[0-9]+(, col:[0-9]+)?>}} 'int' 4 -// CHECK: -AttributedStmt 0x{{[0-9a-z]+}} {{<line:[0-9]+:[0-9]+(, col:[0-9]+)?>}} -// CHECK: -AnnotateAttr 0x{{[0-9a-z]+}} {{<col:[0-9]+(, col:[0-9]+)?>}} "tmpl_stmt" -// CHECK: -IntegerLiteral 0x{{[0-9a-z]+}} {{<col:[0-9]+(, col:[0-9]+)?>}} 'int' 5 -// CHECK: -LabelStmt 0x{{[0-9a-z]+}} {{<line:[0-9]+:[0-9]+(, line:[0-9]+:[0-9]+)?>}} 'label2' -// CHECK: -AnnotateAttr 0x{{[0-9a-z]+}} {{<line:[0-9]+:[0-9]+(, col:[0-9]+)?>}} "tmpl_label" -// CHECK: -IntegerLiteral 0x{{[0-9a-z]+}} {{<col:[0-9]+(, col:[0-9]+)?>}} 'int' 6 -// CHECK: -CompoundAssignOperator 0x{{[0-9a-z]+}} {{<line:[0-9]+:[0-9]+(, col:[0-9]+)?>}} - -void h() { - g<int>(); -} - -// CHECK: -FunctionDecl 0x{{[0-9a-z]+}} {{.*:[0-9]+:[0-9]+, line:[0-9]+:[0-9]+> line:[0-9]+:[0-9]+}} used g 'void ()' implicit_instantiation -// CHECK: -VarDecl 0x{{[0-9a-z]+}} {{<col:[0-9]+(, col:[0-9]+)?> col:[0-9]+}} used j 'int' -// CHECK: -AnnotateAttr 0x{{[0-9a-z]+}} {{<col:[0-9]+(, col:[0-9]+)?>}} "tmpl_decl" -// CHECK: -IntegerLiteral 0x{{[0-9a-z]+}} {{<col:[0-9]+(, col:[0-9]+)?>}} 'int' 4 -// CHECK: -AttributedStmt 0x{{[0-9a-z]+}} {{<line:[0-9]+:[0-9]+(, col:[0-9]+)?>}} -// CHECK: -AnnotateAttr 0x{{[0-9a-z]+}} {{<col:[0-9]+(, col:[0-9]+)?>}} Implicit "tmpl_stmt" -// CHECK: -IntegerLiteral 0x{{[0-9a-z]+}} {{<col:[0-9]+(, col:[0-9]+)?>}} 'int' 5 -// CHECK: -LabelStmt 0x{{[0-9a-z]+}} {{<line:[0-9]+:[0-9]+(, line:[0-9]+:[0-9]+)?>}} 'label2' -// CHECK: -AnnotateAttr 0x{{[0-9a-z]+}} {{<line:[0-9]+:[0-9]+(, col:[0-9]+)?>}} "tmpl_label" -// CHECK: -IntegerLiteral 0x{{[0-9a-z]+}} {{<col:[0-9]+(, col:[0-9]+)?>}} 'int' 6 -// CHECK: -CompoundAssignOperator 0x{{[0-9a-z]+}} {{<line:[0-9]+:[0-9]+(, col:[0-9]+)?>}} - -//--- bad_annotate.cpp +// RUN: %clang_cc1 -std=gnu++20 -fsyntax-only -verify %s template<bool If, typename Type> struct enable_if { >From fe5f3616f282d54fb21b25368908271d237971ff Mon Sep 17 00:00:00 2001 From: Eric Astor <epas...@google.com> Date: Fri, 15 Nov 2024 15:13:16 +0000 Subject: [PATCH 8/8] Add actual test (missed in previous commit) --- clang/test/SemaCXX/attr-annotate-ast.cpp | 55 ++++++++++++++++++++++++ 1 file changed, 55 insertions(+) create mode 100644 clang/test/SemaCXX/attr-annotate-ast.cpp diff --git a/clang/test/SemaCXX/attr-annotate-ast.cpp b/clang/test/SemaCXX/attr-annotate-ast.cpp new file mode 100644 index 00000000000000..ad8e2c26e666fd --- /dev/null +++ b/clang/test/SemaCXX/attr-annotate-ast.cpp @@ -0,0 +1,55 @@ +// RUN: %clang_cc1 -std=gnu++20 -fsyntax-only -ast-dump %s | FileCheck %s + +void f() { + [[clang::annotate("decl", 1)]] int i = 0; + [[clang::annotate("stmt", 2)]] i += 1; +[[clang::annotate("label", 3)]] label1: + i += 2; +} + +// CHECK: -FunctionDecl {{.*}} f 'void ()' +// CHECK: -VarDecl {{.*}} used i 'int' +// CHECK: -AnnotateAttr {{.*}} "decl" +// CHECK: -IntegerLiteral {{.*}} 'int' 1 +// CHECK: -AttributedStmt +// CHECK: -AnnotateAttr {{.*}} "stmt" +// CHECK: -IntegerLiteral {{.*}} 'int' 2 +// CHECK: -LabelStmt {{.*}} 'label1' +// CHECK: -AnnotateAttr {{.*}} "label" +// CHECK: -IntegerLiteral {{.*}} 'int' 3 +// CHECK: -CompoundAssignOperator + +template <typename T> void g() { + [[clang::annotate("tmpl_decl", 4)]] T j = 0; + [[clang::annotate("tmpl_stmt", 5)]] j += 1; +[[clang::annotate("tmpl_label", 6)]] label2: + j += 2; +} + +// CHECK: -FunctionTemplateDecl {{.*}} g +// CHECK: -VarDecl {{.*}} referenced j 'T' +// CHECK: -AnnotateAttr {{.*}} "tmpl_decl" +// CHECK: -IntegerLiteral {{.*}} 'int' 4 +// CHECK: -AttributedStmt +// CHECK: -AnnotateAttr {{.*}} "tmpl_stmt" +// CHECK: -IntegerLiteral {{.*}} 'int' 5 +// CHECK: -LabelStmt {{.*}} 'label2' +// CHECK: -AnnotateAttr {{.*}} "tmpl_label" +// CHECK: -IntegerLiteral {{.*}} 'int' 6 +// CHECK: -CompoundAssignOperator + +void h() { + g<int>(); +} + +// CHECK: -FunctionDecl {{.*}} used g 'void ()' implicit_instantiation +// CHECK: -VarDecl {{.*}} used j 'int' +// CHECK: -AnnotateAttr {{.*}} "tmpl_decl" +// CHECK: -IntegerLiteral {{.*}} 'int' 4 +// CHECK: -AttributedStmt +// CHECK: -AnnotateAttr {{.*}} Implicit "tmpl_stmt" +// CHECK: -IntegerLiteral {{.*}} 'int' 5 +// CHECK: -LabelStmt {{.*}} 'label2' +// CHECK: -AnnotateAttr {{.*}} "tmpl_label" +// CHECK: -IntegerLiteral {{.*}} 'int' 6 +// CHECK: -CompoundAssignOperator _______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits