From 5317e66d8997c0406994809901429d5a88c0e0c6 Mon Sep 17 00:00:00 2001 From: Alex Brachet Date: Mon, 25 Sep 2023 17:35:13 -0400 Subject: [PATCH] [clang] All {con,de}structor attributes to use template args Fixes #67154 --- clang/include/clang/Basic/Attr.td | 8 ++++-- clang/lib/CodeGen/CodeGenModule.cpp | 17 +++++++++-- clang/lib/Sema/SemaDeclAttr.cpp | 33 ++++++++++++++-------- clang/test/CodeGenCXX/constructor-attr.cpp | 14 +++++++++ clang/test/CodeGenCXX/destructor-attr.cpp | 20 +++++++++++++ clang/test/Sema/ctor-dtor-attr.cpp | 13 +++++++++ 6 files changed, 89 insertions(+), 16 deletions(-) create mode 100644 clang/test/CodeGenCXX/destructor-attr.cpp create mode 100644 clang/test/Sema/ctor-dtor-attr.cpp diff --git a/clang/include/clang/Basic/Attr.td b/clang/include/clang/Basic/Attr.td index dd4d45171db48..8c4e63bebf110 100644 --- a/clang/include/clang/Basic/Attr.td +++ b/clang/include/clang/Basic/Attr.td @@ -1156,9 +1156,11 @@ def ConstInit : InheritableAttr { def Constructor : InheritableAttr { let Spellings = [GCC<"constructor">]; - let Args = [DefaultIntArgument<"Priority", 65535>]; + let Args = [ExprArgument<"Priority", 1>]; let Subjects = SubjectList<[Function]>; let Documentation = [CtorDtorDocs]; + let TemplateDependent = 1; + let AdditionalMembers = [{ static const int DefaultPriority = 65535; }]; } def CPUSpecific : InheritableAttr { @@ -1422,9 +1424,11 @@ def Deprecated : InheritableAttr { def Destructor : InheritableAttr { let Spellings = [GCC<"destructor">]; - let Args = [DefaultIntArgument<"Priority", 65535>]; + let Args = [ExprArgument<"Priority", 1>]; let Subjects = SubjectList<[Function]>; let Documentation = [CtorDtorDocs]; + let TemplateDependent = 1; + let AdditionalMembers = [{ static const int DefaultPriority = 65535; }]; } def EmptyBases : InheritableAttr, TargetSpecificAttr { diff --git a/clang/lib/CodeGen/CodeGenModule.cpp b/clang/lib/CodeGen/CodeGenModule.cpp index 130cedcd4f2bf..e93c36bbce95e 100644 --- a/clang/lib/CodeGen/CodeGenModule.cpp +++ b/clang/lib/CodeGen/CodeGenModule.cpp @@ -32,6 +32,7 @@ #include "clang/AST/DeclCXX.h" #include "clang/AST/DeclObjC.h" #include "clang/AST/DeclTemplate.h" +#include "clang/AST/Expr.h" #include "clang/AST/Mangle.h" #include "clang/AST/RecursiveASTVisitor.h" #include "clang/AST/StmtVisitor.h" @@ -5661,10 +5662,20 @@ void CodeGenModule::EmitGlobalFunctionDefinition(GlobalDecl GD, setNonAliasAttributes(GD, Fn); SetLLVMFunctionAttributesForDefinition(D, Fn); - if (const ConstructorAttr *CA = D->getAttr()) - AddGlobalCtor(Fn, CA->getPriority()); + auto getPrio = [this](auto *Attr) -> int { + Expr *E = Attr->getPriority(); + if (!E) + return Attr->DefaultPriority; + if (auto CE = E->getIntegerConstantExpr(getContext())) + return CE->getExtValue(); + return Attr->DefaultPriority; + }; + + if (const ConstructorAttr *CA = D->getAttr()) { + AddGlobalCtor(Fn, getPrio(CA)); + } if (const DestructorAttr *DA = D->getAttr()) - AddGlobalDtor(Fn, DA->getPriority(), true); + AddGlobalDtor(Fn, getPrio(DA), true); if (D->hasAttr()) AddGlobalAnnotations(D, Fn); if (getLangOpts().OpenMP && D->hasAttr()) diff --git a/clang/lib/Sema/SemaDeclAttr.cpp b/clang/lib/Sema/SemaDeclAttr.cpp index 090a54eedaa07..d857f5e78ae97 100644 --- a/clang/lib/Sema/SemaDeclAttr.cpp +++ b/clang/lib/Sema/SemaDeclAttr.cpp @@ -2352,26 +2352,37 @@ static void handleUnusedAttr(Sema &S, Decl *D, const ParsedAttr &AL) { D->addAttr(::new (S.Context) UnusedAttr(S.Context, AL)); } +template +static void handleCtorDtorAttr(Sema &S, Decl *D, const ParsedAttr &AL) { + uint32_t priority = Attr::DefaultPriority; + Expr *E = nullptr; + if (AL.getNumArgs()) { + E = AL.getArgAsExpr(0); + if (E->isValueDependent()) { + if (!E->isTypeDependent() && !E->getType()->isIntegerType()) { + S.Diag(getAttrLoc(AL), diag::err_attribute_argument_type) + << &AL << AANT_ArgumentIntegerConstant << E->getSourceRange(); + return; + } + } else if (!checkUInt32Argument(S, AL, AL.getArgAsExpr(0), priority)) { + return; + } + } + + D->addAttr(::new (S.Context) Attr(S.Context, AL, E)); +} + static void handleConstructorAttr(Sema &S, Decl *D, const ParsedAttr &AL) { - uint32_t priority = ConstructorAttr::DefaultPriority; if (S.getLangOpts().HLSL && AL.getNumArgs()) { S.Diag(AL.getLoc(), diag::err_hlsl_init_priority_unsupported); return; } - if (AL.getNumArgs() && - !checkUInt32Argument(S, AL, AL.getArgAsExpr(0), priority)) - return; - D->addAttr(::new (S.Context) ConstructorAttr(S.Context, AL, priority)); + handleCtorDtorAttr(S, D, AL); } static void handleDestructorAttr(Sema &S, Decl *D, const ParsedAttr &AL) { - uint32_t priority = DestructorAttr::DefaultPriority; - if (AL.getNumArgs() && - !checkUInt32Argument(S, AL, AL.getArgAsExpr(0), priority)) - return; - - D->addAttr(::new (S.Context) DestructorAttr(S.Context, AL, priority)); + return handleCtorDtorAttr(S, D, AL); } template diff --git a/clang/test/CodeGenCXX/constructor-attr.cpp b/clang/test/CodeGenCXX/constructor-attr.cpp index ec27ed210ce76..af0e147d3e510 100644 --- a/clang/test/CodeGenCXX/constructor-attr.cpp +++ b/clang/test/CodeGenCXX/constructor-attr.cpp @@ -1,6 +1,9 @@ // RUN: %clang_cc1 -triple %itanium_abi_triple -emit-llvm -o - %s | FileCheck %s // CHECK: @llvm.global_ctors +// CHECK-SAME: i32 101, ptr @_Z18template_dependentILi101EEvv +// CHECK-SAME: i32 108, ptr @_Z18template_dependentILi108EEvv +// CHECK-SAME: i32 111, ptr @_Z19template_dependent2ILi111EEvv // PR6521 void bar(); @@ -10,3 +13,14 @@ struct Foo { bar(); } }; + +template +[[gnu::constructor(P)]] void template_dependent() {} + +template void template_dependent<101>(); +template void template_dependent<100 + 8>(); + +template +__attribute__((constructor(P))) void template_dependent2() {} + +template void template_dependent2<111>(); diff --git a/clang/test/CodeGenCXX/destructor-attr.cpp b/clang/test/CodeGenCXX/destructor-attr.cpp new file mode 100644 index 0000000000000..0f05385187165 --- /dev/null +++ b/clang/test/CodeGenCXX/destructor-attr.cpp @@ -0,0 +1,20 @@ +// RUN: %clang_cc1 -triple %itanium_abi_triple -emit-llvm -o - %s | FileCheck %s + +// CHECK: @llvm.global_dtors +// CHECK-SAME: i32 101, ptr @_Z18template_dependentILi101EEvv +// CHECK-SAME: i32 108, ptr @_Z18template_dependentILi108EEvv + +// PR6521 +void bar(); +struct Foo { + // CHECK-LABEL: define linkonce_odr {{.*}}void @_ZN3Foo3fooEv + static void foo() __attribute__((constructor)) { + bar(); + } +}; + +template +[[gnu::destructor(P)]] void template_dependent() {} + +template void template_dependent<101>(); +template void template_dependent<100 + 8>(); diff --git a/clang/test/Sema/ctor-dtor-attr.cpp b/clang/test/Sema/ctor-dtor-attr.cpp new file mode 100644 index 0000000000000..a6340805b43c2 --- /dev/null +++ b/clang/test/Sema/ctor-dtor-attr.cpp @@ -0,0 +1,13 @@ +// RUN: %clang_cc1 -fsyntax-only -verify -Wno-strict-prototypes %s + +template [[gnu::constructor(I)]] void ok_ctor(); +template __attribute__((constructor(I))) void ok2_ctor(); + +template [[gnu::constructor(I)]] void bad_ctor(); // expected-error {{'constructor' attribute requires an integer constant}} +template __attribute__((constructor(I))) void bad2_ctor(); // expected-error {{'constructor' attribute requires an integer constant}} + +template [[gnu::destructor(I)]] void ok_ctor(); +template __attribute__((destructor(I))) void ok2_dtor(); + +template [[gnu::destructor(I)]] void bad_dtor(); // expected-error {{'destructor' attribute requires an integer constant}} +template __attribute__((destructor(I))) void bad2_dtor(); // expected-error {{'destructor' attribute requires an integer constant}}