-
Notifications
You must be signed in to change notification settings - Fork 13.5k
[clang] All {con,de}structor attributes to use template args #67376
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
base: main
Are you sure you want to change the base?
Conversation
@llvm/pr-subscribers-clang @llvm/pr-subscribers-clang-codegen ChangesFixes #67154 Full diff: https://github.com/llvm/llvm-project/pull/67376.diff 6 Files Affected:
diff --git a/clang/include/clang/Basic/Attr.td b/clang/include/clang/Basic/Attr.td
index dd4d45171db4899..8c4e63bebf110cf 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<TargetMicrosoftCXXABI> {
diff --git a/clang/lib/CodeGen/CodeGenModule.cpp b/clang/lib/CodeGen/CodeGenModule.cpp
index 130cedcd4f2bf68..e93c36bbce95ec6 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<ConstructorAttr>())
- 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<ConstructorAttr>()) {
+ AddGlobalCtor(Fn, getPrio(CA));
+ }
if (const DestructorAttr *DA = D->getAttr<DestructorAttr>())
- AddGlobalDtor(Fn, DA->getPriority(), true);
+ AddGlobalDtor(Fn, getPrio(DA), true);
if (D->hasAttr<AnnotateAttr>())
AddGlobalAnnotations(D, Fn);
if (getLangOpts().OpenMP && D->hasAttr<OMPDeclareTargetDeclAttr>())
diff --git a/clang/lib/Sema/SemaDeclAttr.cpp b/clang/lib/Sema/SemaDeclAttr.cpp
index 090a54eedaa07d0..d857f5e78ae97a3 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 <typename Attr>
+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<ConstructorAttr>(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<DestructorAttr>(S, D, AL);
}
template <typename AttrTy>
diff --git a/clang/test/CodeGenCXX/constructor-attr.cpp b/clang/test/CodeGenCXX/constructor-attr.cpp
index ec27ed210ce760f..af0e147d3e51057 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 <int P>
+[[gnu::constructor(P)]] void template_dependent() {}
+
+template void template_dependent<101>();
+template void template_dependent<100 + 8>();
+
+template <int P>
+__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 000000000000000..0f05385187165cf
--- /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 <int P>
+[[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 000000000000000..a6340805b43c2d3
--- /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 <int I> [[gnu::constructor(I)]] void ok_ctor();
+template <int I> __attribute__((constructor(I))) void ok2_ctor();
+
+template <int *I> [[gnu::constructor(I)]] void bad_ctor(); // expected-error {{'constructor' attribute requires an integer constant}}
+template <int *I> __attribute__((constructor(I))) void bad2_ctor(); // expected-error {{'constructor' attribute requires an integer constant}}
+
+template <int I> [[gnu::destructor(I)]] void ok_ctor();
+template <int I> __attribute__((destructor(I))) void ok2_dtor();
+
+template <int *I> [[gnu::destructor(I)]] void bad_dtor(); // expected-error {{'destructor' attribute requires an integer constant}}
+template <int *I> __attribute__((destructor(I))) void bad2_dtor(); // expected-error {{'destructor' attribute requires an integer constant}}
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
So it looks like this breaks the ast-dump-attr.cpp test, so that needs fixing.
Also, there is quite a bit of changes happening around the SemaDeclAttr.cpp changes by @AaronBallman, so the two need to be merged in some way.
let Subjects = SubjectList<[Function]>; | ||
let Documentation = [CtorDtorDocs]; | ||
let TemplateDependent = 1; | ||
let AdditionalMembers = [{ static const int DefaultPriority = 65535; }]; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@AaronBallman : I see in your other patch (#67360) you're using this as a magic number! Might be useful to get on the same page as this author.
let AdditionalMembers = [{ static const int DefaultPriority = 65535; }]; | |
let AdditionalMembers = [{ static constexpr int DefaultPriority = 65535; }]; |
let Subjects = SubjectList<[Function]>; | ||
let Documentation = [CtorDtorDocs]; | ||
let TemplateDependent = 1; | ||
let AdditionalMembers = [{ static const int DefaultPriority = 65535; }]; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
let AdditionalMembers = [{ static const int DefaultPriority = 65535; }]; | |
let AdditionalMembers = [{ static constexpr int DefaultPriority = 65535; }]; |
Also wonder if these should be unsigned
?
@@ -10,3 +13,14 @@ struct Foo { | |||
bar(); | |||
} | |||
}; | |||
|
|||
template <int P> |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Please write a test where the argument is NTTP dependent on another template argument.
return Attr->DefaultPriority; | ||
if (auto CE = E->getIntegerConstantExpr(getContext())) | ||
return CE->getExtValue(); | ||
return Attr->DefaultPriority; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This condition seems to me should be an assertion, right?
static void handleCtorDtorAttr(Sema &S, Decl *D, const ParsedAttr &AL) { | ||
uint32_t priority = Attr::DefaultPriority; | ||
Expr *E = nullptr; | ||
if (AL.getNumArgs()) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We also should ensure we don't have more than 1 argument.
"Merged" could be: 1-rebased on the other, but ONE Of the two things needs to happen. |
@abrachet Are you still working on that? |
No, feel free to commandeer this patch |
Fixes #67154