[clang] [Clang] Instantiate variables referenced in `decltype` with an undeduced type. (PR #161231)
Corentin Jabot via cfe-commits
cfe-commits at lists.llvm.org
Mon Sep 29 10:28:30 PDT 2025
https://github.com/cor3ntin updated https://github.com/llvm/llvm-project/pull/161231
>From 6c4bd440fb13335cf07ac69ed67890640e5e8323 Mon Sep 17 00:00:00 2001
From: Corentin Jabot <corentinjabot at gmail.com>
Date: Mon, 29 Sep 2025 18:55:22 +0200
Subject: [PATCH 1/3] [Clang] Instantiate variables referenced in `decltype`
with an undeduced type.
Fixes #160497
---
clang/docs/ReleaseNotes.rst | 1 +
clang/lib/Sema/SemaExpr.cpp | 5 +++--
clang/test/SemaCXX/decltype.cpp | 30 ++++++++++++++++++++++++++++++
3 files changed, 34 insertions(+), 2 deletions(-)
diff --git a/clang/docs/ReleaseNotes.rst b/clang/docs/ReleaseNotes.rst
index 270b5d336eba7..3ff40f98334ca 100644
--- a/clang/docs/ReleaseNotes.rst
+++ b/clang/docs/ReleaseNotes.rst
@@ -432,6 +432,7 @@ Bug Fixes to C++ Support
- Fix an assertion failure when taking the address on a non-type template parameter argument of
object type. (#GH151531)
- Suppress ``-Wdouble-promotion`` when explicitly asked for with C++ list initialization (#GH33409).
+- Correctly deduced return types in ``decltype`` expressions. (#GH160497)
Bug Fixes to AST Handling
^^^^^^^^^^^^^^^^^^^^^^^^^
diff --git a/clang/lib/Sema/SemaExpr.cpp b/clang/lib/Sema/SemaExpr.cpp
index 3b267c1b1693d..3302bfce193a2 100644
--- a/clang/lib/Sema/SemaExpr.cpp
+++ b/clang/lib/Sema/SemaExpr.cpp
@@ -20108,8 +20108,9 @@ static void DoMarkVarDeclReferenced(
bool NeededForConstantEvaluation =
isPotentiallyConstantEvaluatedContext(SemaRef) && UsableInConstantExpr;
- bool NeedDefinition =
- OdrUse == OdrUseContext::Used || NeededForConstantEvaluation;
+ bool NeedDefinition = OdrUse == OdrUseContext::Used ||
+ NeededForConstantEvaluation ||
+ Var->getType()->isUndeducedType();
assert(!isa<VarTemplatePartialSpecializationDecl>(Var) &&
"Can't instantiate a partial template specialization.");
diff --git a/clang/test/SemaCXX/decltype.cpp b/clang/test/SemaCXX/decltype.cpp
index 739485b57a3ec..971cf5132d4d5 100644
--- a/clang/test/SemaCXX/decltype.cpp
+++ b/clang/test/SemaCXX/decltype.cpp
@@ -170,3 +170,33 @@ class conditional {
// FIXME: The diagnostics here are produced twice.
void foo(conditional<decltype((1),int>) { // expected-note 2 {{to match this '('}} expected-error {{expected ')'}} expected-note 2{{to match this '<'}}
} // expected-error {{expected function body after function declarator}} expected-error 2 {{expected '>'}} expected-error {{expected ')'}}
+
+
+namespace GH160497 {
+
+template <class> struct S {
+ template <class>
+ inline static auto mem =
+ [] { static_assert(false); // expected-error {{static assertion failed}} \
+ // expected-note {{while substituting into a lambda expression here}}
+ return 42;
+ }();
+};
+
+using T = decltype(S<void>::mem<void>);
+ // expected-note at -1 {{in instantiation of static data member 'GH160497::S<void>::mem<void>' requested here}}
+
+namespace N1 {
+
+template<class>
+struct S {
+ template<class>
+ inline static auto mem = 42;
+};
+
+using T = decltype(S<void>::mem<void>);
+
+T y = 42;
+
+}
+}
>From 1dd09353d52f6ccd5e7b2d0fa59e484f85940a91 Mon Sep 17 00:00:00 2001
From: Corentin Jabot <corentinjabot at gmail.com>
Date: Mon, 29 Sep 2025 19:11:21 +0200
Subject: [PATCH 2/3] fix tests
---
clang/test/SemaCXX/decltype.cpp | 38 +++++++++++++++++----------------
1 file changed, 20 insertions(+), 18 deletions(-)
diff --git a/clang/test/SemaCXX/decltype.cpp b/clang/test/SemaCXX/decltype.cpp
index 971cf5132d4d5..7931c6ac45429 100644
--- a/clang/test/SemaCXX/decltype.cpp
+++ b/clang/test/SemaCXX/decltype.cpp
@@ -1,4 +1,5 @@
// RUN: %clang_cc1 -std=c++11 -fsyntax-only -verify -Wno-c99-designator %s
+// RUN: %clang_cc1 -std=c++17 -fsyntax-only -verify -Wno-c99-designator %s
// PR5290
int const f0();
@@ -156,27 +157,12 @@ struct A {
}
};
-// This shouldn't crash.
-static_assert(A<int>().f<int>() == 0, "");
-// The result should not be dependent.
-static_assert(A<int>().f<int>() != 0, ""); // expected-error {{static assertion failed due to requirement 'GH99873::A<int>().f<int>() != 0'}}
- // expected-note at -1 {{expression evaluates to '0 != 0'}}
-}
-
-template<typename>
-class conditional {
-};
-
-// FIXME: The diagnostics here are produced twice.
-void foo(conditional<decltype((1),int>) { // expected-note 2 {{to match this '('}} expected-error {{expected ')'}} expected-note 2{{to match this '<'}}
-} // expected-error {{expected function body after function declarator}} expected-error 2 {{expected '>'}} expected-error {{expected ')'}}
-
-
+#if __cplusplus >= 201703L
namespace GH160497 {
template <class> struct S {
template <class>
- inline static auto mem =
+ static inline auto mem =
[] { static_assert(false); // expected-error {{static assertion failed}} \
// expected-note {{while substituting into a lambda expression here}}
return 42;
@@ -184,7 +170,7 @@ template <class> struct S {
};
using T = decltype(S<void>::mem<void>);
- // expected-note at -1 {{in instantiation of static data member 'GH160497::S<void>::mem<void>' requested here}}
+ // expected-note at -1 {{in instantiation of static data member 'GH99873::GH160497::S<void>::mem<void>' requested here}}
namespace N1 {
@@ -200,3 +186,19 @@ T y = 42;
}
}
+#endif
+
+// This shouldn't crash.
+static_assert(A<int>().f<int>() == 0, "");
+// The result should not be dependent.
+static_assert(A<int>().f<int>() != 0, ""); // expected-error {{static assertion failed due to requirement 'GH99873::A<int>().f<int>() != 0'}}
+ // expected-note at -1 {{expression evaluates to '0 != 0'}}
+}
+
+template<typename>
+class conditional {
+};
+
+// FIXME: The diagnostics here are produced twice.
+void foo(conditional<decltype((1),int>) { // expected-note 2 {{to match this '('}} expected-error {{expected ')'}} expected-note 2{{to match this '<'}}
+} // expected-error {{expected function body after function declarator}} expected-error 2 {{expected '>'}} expected-error {{expected ')'}}
>From 337c71a21a0da8c4e5bfdf42657cae0759eb0832 Mon Sep 17 00:00:00 2001
From: Corentin Jabot <corentinjabot at gmail.com>
Date: Mon, 29 Sep 2025 19:28:12 +0200
Subject: [PATCH 3/3] add tests
---
clang/test/SemaCXX/decltype.cpp | 35 ++++++++++++++++++++++++---------
1 file changed, 26 insertions(+), 9 deletions(-)
diff --git a/clang/test/SemaCXX/decltype.cpp b/clang/test/SemaCXX/decltype.cpp
index 7931c6ac45429..893090484fd54 100644
--- a/clang/test/SemaCXX/decltype.cpp
+++ b/clang/test/SemaCXX/decltype.cpp
@@ -157,12 +157,22 @@ struct A {
}
};
+
+
+// This shouldn't crash.
+static_assert(A<int>().f<int>() == 0, "");
+// The result should not be dependent.
+static_assert(A<int>().f<int>() != 0, ""); // expected-error {{static assertion failed due to requirement 'GH99873::A<int>().f<int>() != 0'}}
+ // expected-note at -1 {{expression evaluates to '0 != 0'}}
+}
+
+
#if __cplusplus >= 201703L
namespace GH160497 {
template <class> struct S {
template <class>
- static inline auto mem =
+ inline static auto mem =
[] { static_assert(false); // expected-error {{static assertion failed}} \
// expected-note {{while substituting into a lambda expression here}}
return 42;
@@ -170,7 +180,21 @@ template <class> struct S {
};
using T = decltype(S<void>::mem<void>);
- // expected-note at -1 {{in instantiation of static data member 'GH99873::GH160497::S<void>::mem<void>' requested here}}
+ // expected-note at -1 {{in instantiation of static data member 'GH160497::S<void>::mem<void>' requested here}}
+
+
+template <class> struct S2 {
+ template <class>
+ inline static auto* mem =
+ [] { static_assert(false); // expected-error {{static assertion failed}} \
+ // expected-note {{while substituting into a lambda expression here}}
+ return static_cast<int*>(nullptr);
+ }();
+};
+
+
+using T2 = decltype(S2<void>::mem<void>);
+//expected-note at -1 {{in instantiation of static data member 'GH160497::S2<void>::mem<void>' requested here}}
namespace N1 {
@@ -188,13 +212,6 @@ T y = 42;
}
#endif
-// This shouldn't crash.
-static_assert(A<int>().f<int>() == 0, "");
-// The result should not be dependent.
-static_assert(A<int>().f<int>() != 0, ""); // expected-error {{static assertion failed due to requirement 'GH99873::A<int>().f<int>() != 0'}}
- // expected-note at -1 {{expression evaluates to '0 != 0'}}
-}
-
template<typename>
class conditional {
};
More information about the cfe-commits
mailing list