[clang] 1e7efca - [clang] fix crash when template with constructor attribute is instantiated without a priority (#169282)
via cfe-commits
cfe-commits at lists.llvm.org
Thu Nov 27 23:26:47 PST 2025
Author: Carson Radtke
Date: 2025-11-28T15:26:43+08:00
New Revision: 1e7efca659cdf37a95e27e35fa002d340ea68b32
URL: https://github.com/llvm/llvm-project/commit/1e7efca659cdf37a95e27e35fa002d340ea68b32
DIFF: https://github.com/llvm/llvm-project/commit/1e7efca659cdf37a95e27e35fa002d340ea68b32.diff
LOG: [clang] fix crash when template with constructor attribute is instantiated without a priority (#169282)
fixes: https://github.com/llvm/llvm-project/issues/169072
The current implementation expects the priority argument to be provided
to `[[gnu::constructor(<priority>)]]`, but the argument is really
optional. This was causing a segfault when instantiating the
function-template because we were trying to fold an `Expr*` that was a
nullptr.
This change skips the evaluation of the priority argument when it is
missing; this will instantiate a function declaration with the default
priority (65535).
Added:
Modified:
clang/docs/ReleaseNotes.rst
clang/lib/Sema/SemaTemplateInstantiateDecl.cpp
clang/test/SemaTemplate/attributes.cpp
Removed:
################################################################################
diff --git a/clang/docs/ReleaseNotes.rst b/clang/docs/ReleaseNotes.rst
index 4cfcd37df1866..da064534c25d9 100644
--- a/clang/docs/ReleaseNotes.rst
+++ b/clang/docs/ReleaseNotes.rst
@@ -518,6 +518,8 @@ Bug Fixes to Attribute Support
- Fix handling of parameter indexes when an attribute is applied to a C++23 explicit object member function.
- Fixed several false positives and false negatives in function effect (`nonblocking`) analysis. (#GH166078) (#GH166101) (#GH166110)
- Fix ``cleanup`` attribute by delaying type checks until after the type is deduced. (#GH129631)
+- Fix a crash when instantiating a function template with ``constructor`` or ``destructor``
+ attributes without a priority argument. (#GH169072)
Bug Fixes to C++ Support
^^^^^^^^^^^^^^^^^^^^^^^^
diff --git a/clang/lib/Sema/SemaTemplateInstantiateDecl.cpp b/clang/lib/Sema/SemaTemplateInstantiateDecl.cpp
index 26693514bb278..e74c41517ecbf 100644
--- a/clang/lib/Sema/SemaTemplateInstantiateDecl.cpp
+++ b/clang/lib/Sema/SemaTemplateInstantiateDecl.cpp
@@ -245,15 +245,17 @@ static void sharedInstantiateConstructorDestructorAttr(
ExprResult Result = S.SubstExpr(A->getPriority(), TemplateArgs);
if (Result.isInvalid())
return;
- tempInstPriority = Result.get();
- if (std::optional<llvm::APSInt> CE =
- tempInstPriority->getIntegerConstantExpr(C)) {
- // Consistent with non-templated priority arguments, which must fit in a
- // 32-bit unsigned integer.
- if (!CE->isIntN(32)) {
- S.Diag(tempInstPriority->getExprLoc(), diag::err_ice_too_large)
- << toString(*CE, 10, false) << /*Size=*/32 << /*Unsigned=*/1;
- return;
+ if (Result.isUsable()) {
+ tempInstPriority = Result.get();
+ if (std::optional<llvm::APSInt> CE =
+ tempInstPriority->getIntegerConstantExpr(C)) {
+ // Consistent with non-templated priority arguments, which must fit in a
+ // 32-bit unsigned integer.
+ if (!CE->isIntN(32)) {
+ S.Diag(tempInstPriority->getExprLoc(), diag::err_ice_too_large)
+ << toString(*CE, 10, false) << /*Size=*/32 << /*Unsigned=*/1;
+ return;
+ }
}
}
}
diff --git a/clang/test/SemaTemplate/attributes.cpp b/clang/test/SemaTemplate/attributes.cpp
index 20fe983af28f7..d0ab0a68dec2a 100644
--- a/clang/test/SemaTemplate/attributes.cpp
+++ b/clang/test/SemaTemplate/attributes.cpp
@@ -640,3 +640,23 @@ namespace preferred_name {
Foo<1, 2, int, float>::nosuch x; // expected-error {{no type named 'nosuch' in 'preferred_name::Bar<int, float>'}}
}
::preferred_name::Foo<1, 2, int, float>::nosuch x; // expected-error {{no type named 'nosuch' in 'preferred_name::Bar<int, float>'}}
+
+// GH169072: templated attribute((constructor)) function crashes clang
+// constructor/destructor attribute without priority argument should not crash.
+namespace gh169072 {
+ template <typename T>
+ [[gnu::constructor]] void foo() {}
+
+ template void foo<int>();
+
+ template <typename T>
+ [[gnu::destructor]] void bar() {}
+
+ template void bar<int>();
+
+ // Also test with explicit priority argument
+ template <typename T>
+ [[gnu::constructor(101)]] void baz() {}
+
+ template void baz<int>();
+}
More information about the cfe-commits
mailing list