From 4c0152234c53fe7b97fcca65a61d4c29b611fb19 Mon Sep 17 00:00:00 2001 From: Corentin Jabot Date: Mon, 29 Sep 2025 18:55:22 +0200 Subject: [PATCH 1/7] [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 e8deae50e4cb0..df277a13e9f23 100644 --- a/clang/docs/ReleaseNotes.rst +++ b/clang/docs/ReleaseNotes.rst @@ -433,6 +433,7 @@ Bug Fixes to C++ Support object type. (#GH151531) - Suppress ``-Wdouble-promotion`` when explicitly asked for with C++ list initialization (#GH33409). - Fix the result of `__builtin_is_implicit_lifetime` for types with a user-provided constructor. (#GH160610) +- 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(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) { // 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 struct S { + template + 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::mem); + // expected-note@-1 {{in instantiation of static data member 'GH160497::S::mem' requested here}} + +namespace N1 { + +template +struct S { + template + inline static auto mem = 42; +}; + +using T = decltype(S::mem); + +T y = 42; + +} +} From 83d1532dcf163fbfbc665244c152e117f85271c1 Mon Sep 17 00:00:00 2001 From: Corentin Jabot Date: Mon, 29 Sep 2025 19:11:21 +0200 Subject: [PATCH 2/7] 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().f() == 0, ""); -// The result should not be dependent. -static_assert(A().f() != 0, ""); // expected-error {{static assertion failed due to requirement 'GH99873::A().f() != 0'}} - // expected-note@-1 {{expression evaluates to '0 != 0'}} -} - -template -class conditional { -}; - -// FIXME: The diagnostics here are produced twice. -void foo(conditional) { // 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 struct S { template - 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 struct S { }; using T = decltype(S::mem); - // expected-note@-1 {{in instantiation of static data member 'GH160497::S::mem' requested here}} + // expected-note@-1 {{in instantiation of static data member 'GH99873::GH160497::S::mem' requested here}} namespace N1 { @@ -200,3 +186,19 @@ T y = 42; } } +#endif + +// This shouldn't crash. +static_assert(A().f() == 0, ""); +// The result should not be dependent. +static_assert(A().f() != 0, ""); // expected-error {{static assertion failed due to requirement 'GH99873::A().f() != 0'}} + // expected-note@-1 {{expression evaluates to '0 != 0'}} +} + +template +class conditional { +}; + +// FIXME: The diagnostics here are produced twice. +void foo(conditional) { // 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 dcd985345b8a4938fd91bffd7fcfaca2b01be89b Mon Sep 17 00:00:00 2001 From: Corentin Jabot Date: Mon, 29 Sep 2025 19:28:12 +0200 Subject: [PATCH 3/7] 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().f() == 0, ""); +// The result should not be dependent. +static_assert(A().f() != 0, ""); // expected-error {{static assertion failed due to requirement 'GH99873::A().f() != 0'}} + // expected-note@-1 {{expression evaluates to '0 != 0'}} +} + + #if __cplusplus >= 201703L namespace GH160497 { template struct S { template - 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 struct S { }; using T = decltype(S::mem); - // expected-note@-1 {{in instantiation of static data member 'GH99873::GH160497::S::mem' requested here}} + // expected-note@-1 {{in instantiation of static data member 'GH160497::S::mem' requested here}} + + +template struct S2 { + template + inline static auto* mem = + [] { static_assert(false); // expected-error {{static assertion failed}} \ + // expected-note {{while substituting into a lambda expression here}} + return static_cast(nullptr); + }(); +}; + + +using T2 = decltype(S2::mem); +//expected-note@-1 {{in instantiation of static data member 'GH160497::S2::mem' requested here}} namespace N1 { @@ -188,13 +212,6 @@ T y = 42; } #endif -// This shouldn't crash. -static_assert(A().f() == 0, ""); -// The result should not be dependent. -static_assert(A().f() != 0, ""); // expected-error {{static assertion failed due to requirement 'GH99873::A().f() != 0'}} - // expected-note@-1 {{expression evaluates to '0 != 0'}} -} - template class conditional { }; From 8e56a5004269bd7d54a03d6451d2e35726e37d8e Mon Sep 17 00:00:00 2001 From: Corentin Jabot Date: Mon, 29 Sep 2025 19:39:25 +0200 Subject: [PATCH 4/7] add test for GH56652 --- clang/docs/ReleaseNotes.rst | 2 +- clang/test/CodeGenCXX/gh56652.cpp | 28 ++++++++++++++++++++++++++++ 2 files changed, 29 insertions(+), 1 deletion(-) create mode 100644 clang/test/CodeGenCXX/gh56652.cpp diff --git a/clang/docs/ReleaseNotes.rst b/clang/docs/ReleaseNotes.rst index df277a13e9f23..5ce4adee66b21 100644 --- a/clang/docs/ReleaseNotes.rst +++ b/clang/docs/ReleaseNotes.rst @@ -379,7 +379,7 @@ Bug Fixes in This Version - Fixed an assertion when an improper use of the ``malloc`` attribute targeting a function without arguments caused us to try to access a non-existent argument. (#GH159080) -- Fixed a failed assertion with empty filename arguments in ``__has_embed``. (#GH159898) +- Fixed a failed assertion with empty filename arguments in ``__has_embed``. (#GH159898) (#GH56652) Bug Fixes to Compiler Builtins ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ diff --git a/clang/test/CodeGenCXX/gh56652.cpp b/clang/test/CodeGenCXX/gh56652.cpp new file mode 100644 index 0000000000000..0ccadd1493eed --- /dev/null +++ b/clang/test/CodeGenCXX/gh56652.cpp @@ -0,0 +1,28 @@ +// RUN: %clang_cc1 -std=c++20 -triple x86_64-elf-gnu %s -emit-llvm -o - | FileCheck %s + +namespace GH56652{ + +struct foo {}; + +template struct bar { + using type = T; + + template inline static constexpr auto b = true; +}; + +template +concept C = requires(T a) { T::template b; }; + +template auto fn(T) { + if constexpr (!C) + return foo{}; + else + return T{}; +} + +auto a = decltype(fn(bar{})){}; + +} + +// CHECK: %"struct.GH56652::bar" = type { i8 } +// CHECK: @_ZN7GH566521aE = global %"struct.GH56652::bar" undef From 401f93959aa1c96874499256e9be33a197f8a19a Mon Sep 17 00:00:00 2001 From: Corentin Jabot Date: Mon, 29 Sep 2025 19:46:27 +0200 Subject: [PATCH 5/7] add test for GH1163191 --- clang/docs/ReleaseNotes.rst | 4 ++-- clang/test/CodeGenCXX/gh56652.cpp | 13 +++++++++++++ 2 files changed, 15 insertions(+), 2 deletions(-) diff --git a/clang/docs/ReleaseNotes.rst b/clang/docs/ReleaseNotes.rst index 5ce4adee66b21..0d8c781318128 100644 --- a/clang/docs/ReleaseNotes.rst +++ b/clang/docs/ReleaseNotes.rst @@ -379,7 +379,7 @@ Bug Fixes in This Version - Fixed an assertion when an improper use of the ``malloc`` attribute targeting a function without arguments caused us to try to access a non-existent argument. (#GH159080) -- Fixed a failed assertion with empty filename arguments in ``__has_embed``. (#GH159898) (#GH56652) +- Fixed a failed assertion with empty filename arguments in ``__has_embed``. (#GH159898) Bug Fixes to Compiler Builtins ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -433,7 +433,7 @@ Bug Fixes to C++ Support object type. (#GH151531) - Suppress ``-Wdouble-promotion`` when explicitly asked for with C++ list initialization (#GH33409). - Fix the result of `__builtin_is_implicit_lifetime` for types with a user-provided constructor. (#GH160610) -- Correctly deduced return types in ``decltype`` expressions. (#GH160497) +- Correctly deduced return types in ``decltype`` expressions. (#GH160497) (#GH56652) (#GH116319) Bug Fixes to AST Handling ^^^^^^^^^^^^^^^^^^^^^^^^^ diff --git a/clang/test/CodeGenCXX/gh56652.cpp b/clang/test/CodeGenCXX/gh56652.cpp index 0ccadd1493eed..06a496e320bfc 100644 --- a/clang/test/CodeGenCXX/gh56652.cpp +++ b/clang/test/CodeGenCXX/gh56652.cpp @@ -22,7 +22,20 @@ template auto fn(T) { auto a = decltype(fn(bar{})){}; +} + +namespace GH116319 { + +template struct a { +template static constexpr auto b = 2; +template static void c() noexcept(noexcept(b)) {} +}; + +void test() { a<>::c(); } + + } // CHECK: %"struct.GH56652::bar" = type { i8 } +// CHECK: $_ZN8GH1163191aILi0EE1cIiEEvv = comdat any // CHECK: @_ZN7GH566521aE = global %"struct.GH56652::bar" undef From ffdbc5ef0815f54eb643c17c050930e4eef30c60 Mon Sep 17 00:00:00 2001 From: Corentin Jabot Date: Mon, 29 Sep 2025 19:53:34 +0200 Subject: [PATCH 6/7] more tests --- clang/docs/ReleaseNotes.rst | 2 +- clang/test/SemaCXX/decltype.cpp | 29 ++++++++++++++++++++++++++++- 2 files changed, 29 insertions(+), 2 deletions(-) diff --git a/clang/docs/ReleaseNotes.rst b/clang/docs/ReleaseNotes.rst index 0d8c781318128..6521fc3e9a9da 100644 --- a/clang/docs/ReleaseNotes.rst +++ b/clang/docs/ReleaseNotes.rst @@ -433,7 +433,7 @@ Bug Fixes to C++ Support object type. (#GH151531) - Suppress ``-Wdouble-promotion`` when explicitly asked for with C++ list initialization (#GH33409). - Fix the result of `__builtin_is_implicit_lifetime` for types with a user-provided constructor. (#GH160610) -- Correctly deduced return types in ``decltype`` expressions. (#GH160497) (#GH56652) (#GH116319) +- Correctly deduce return types in ``decltype`` expressions. (#GH160497) (#GH56652) (#GH116319) (#GH161196) Bug Fixes to AST Handling ^^^^^^^^^^^^^^^^^^^^^^^^^ diff --git a/clang/test/SemaCXX/decltype.cpp b/clang/test/SemaCXX/decltype.cpp index 893090484fd54..d74e8cf1aead3 100644 --- a/clang/test/SemaCXX/decltype.cpp +++ b/clang/test/SemaCXX/decltype.cpp @@ -192,10 +192,20 @@ template struct S2 { }(); }; - using T2 = decltype(S2::mem); //expected-note@-1 {{in instantiation of static data member 'GH160497::S2::mem' requested here}} +template struct S3 { + template + inline static int mem = // Check we don't instantiate when the type is not deduced. + [] { static_assert(false); + return 42; + }(); +}; + +using T = decltype(S3::mem); +} + namespace N1 { template @@ -210,6 +220,23 @@ T y = 42; } } +namespace GH161196 { + +template struct A { + static constexpr int digits = 0; +}; + +template struct B { + template ::digits> + static constexpr auto XBitMask = 0; +}; + +struct C { + using ReferenceHost = B; + template static decltype(ReferenceHost::XBitMask<0>) XBitMask; +}; + +void test() { (void)C::XBitMask<0>; } #endif template From 73316aaa917136131aac2e8b6ce17b41dcc825d4 Mon Sep 17 00:00:00 2001 From: Corentin Jabot Date: Mon, 29 Sep 2025 20:13:31 +0200 Subject: [PATCH 7/7] more tests --- clang/test/SemaCXX/decltype.cpp | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/clang/test/SemaCXX/decltype.cpp b/clang/test/SemaCXX/decltype.cpp index d74e8cf1aead3..45a4c4cf1ac86 100644 --- a/clang/test/SemaCXX/decltype.cpp +++ b/clang/test/SemaCXX/decltype.cpp @@ -219,7 +219,7 @@ using T = decltype(S::mem); T y = 42; } -} + namespace GH161196 { template struct A { @@ -237,6 +237,8 @@ struct C { }; void test() { (void)C::XBitMask<0>; } + +} #endif template