[clang] [Clang][Sema] Reject undeduced static data members without initializers (#173349) (PR #174281)
via cfe-commits
cfe-commits at lists.llvm.org
Sat Jan 3 07:52:01 PST 2026
llvmbot wrote:
<!--LLVM PR SUMMARY COMMENT-->
@llvm/pr-subscribers-clang
Author: Hamza Hassanain (HamzaHassanain)
<details>
<summary>Changes</summary>
### **The Problem**
Clang crashes when encountering a `static` data member declared with an alias template but lacking template arguments (e.g., `static E u;`).
Because of C++ CTAD rules, Clang's parser assigns this a placeholder `AutoType`. If this member is later referenced, the backend (`CodeGen`) attempts to emit the variable. Since the type remains undeduced and no initializer exists, the compiler hits an `llvm_unreachable` in `CodeGenTypes.cpp`.
### **The Fix**
The fix is implemented in `Sema::ActOnUninitializedDecl`. We now explicitly check if a `static` data member still possesses an undeduced placeholder type after all deduction attempts have failed.
* **Logic:** If the type contains an undeduced type, and the variable is a static member without an initializer, we emit `err_auto_var_requires_init`.
### **Changes**
* **SemaDecl.cpp**: Added validation logic to `ActOnUninitializedDecl` to catch undeduced static members.
* **alias-template-static-member.cpp**: Added a regression test to ensure this scenario results in a diagnostic rather than a crash.
### **Notes** on formatting
When I `clang-format` the `SemaDecl.cpp` after applying my changes, I found the whole file got changed, so I undid the formatting.
---
Full diff: https://github.com/llvm/llvm-project/pull/174281.diff
2 Files Affected:
- (modified) clang/lib/Sema/SemaDecl.cpp (+10)
- (added) clang/test/SemaCXX/alias-template-static-member.cpp (+11)
``````````diff
diff --git a/clang/lib/Sema/SemaDecl.cpp b/clang/lib/Sema/SemaDecl.cpp
index 11323803e1910..50a6a4176d1ec 100644
--- a/clang/lib/Sema/SemaDecl.cpp
+++ b/clang/lib/Sema/SemaDecl.cpp
@@ -14337,8 +14337,18 @@ void Sema::ActOnUninitializedDecl(Decl *RealDecl) {
DeduceVariableDeclarationType(Var, false, nullptr))
return;
+ Type = Var->getType();
this->CheckAttributesOnDeducedType(RealDecl);
+ if (auto *Deduced = Type->getContainedDeducedType()) {
+ if (Var->isStaticDataMember() && Deduced->getDeducedType().isNull()) {
+ Diag(Var->getLocation(), diag::err_auto_var_requires_init)
+ << Var->getDeclName() << Type;
+ Var->setInvalidDecl();
+ return;
+ }
+ }
+
// C++11 [class.static.data]p3: A static data member can be declared with
// the constexpr specifier; if so, its declaration shall specify
// a brace-or-equal-initializer.
diff --git a/clang/test/SemaCXX/alias-template-static-member.cpp b/clang/test/SemaCXX/alias-template-static-member.cpp
new file mode 100644
index 0000000000000..0089aea33cc80
--- /dev/null
+++ b/clang/test/SemaCXX/alias-template-static-member.cpp
@@ -0,0 +1,11 @@
+// RUN: %clang_cc1 -fsyntax-only -verify -std=c++17 %s
+
+template <class T>
+struct A {
+ template <class U>
+ using E = U;
+
+ static E u; // expected-error {{declaration of variable 'u' with deduced type 'E' requires an initializer}}
+};
+
+decltype(A<int>::u) a;
\ No newline at end of file
``````````
</details>
https://github.com/llvm/llvm-project/pull/174281
More information about the cfe-commits
mailing list