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 <[email protected]> Date: Mon, 29 Sep 2025 18:55:22 +0200 Subject: [PATCH 1/4] [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@-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 <[email protected]> Date: Mon, 29 Sep 2025 19:11:21 +0200 Subject: [PATCH 2/4] 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@-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@-1 {{in instantiation of static data member 'GH160497::S<void>::mem<void>' requested here}} + // expected-note@-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@-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 <[email protected]> Date: Mon, 29 Sep 2025 19:28:12 +0200 Subject: [PATCH 3/4] 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@-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@-1 {{in instantiation of static data member 'GH99873::GH160497::S<void>::mem<void>' requested here}} + // expected-note@-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@-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@-1 {{expression evaluates to '0 != 0'}} -} - template<typename> class conditional { }; >From 1bc3f7489857c53fc5a7d52d5baf3312d726d4bb Mon Sep 17 00:00:00 2001 From: Corentin Jabot <[email protected]> Date: Mon, 29 Sep 2025 19:39:25 +0200 Subject: [PATCH 4/4] 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 3ff40f98334ca..892473d5c5585 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 <typename T> struct bar { + using type = T; + + template <foo> inline static constexpr auto b = true; +}; + +template <typename T> +concept C = requires(T a) { T::template b<foo{}>; }; + +template <typename T> auto fn(T) { + if constexpr (!C<T>) + return foo{}; + else + return T{}; +} + +auto a = decltype(fn(bar<int>{})){}; + +} + +// CHECK: %"struct.GH56652::bar" = type { i8 } +// CHECK: @_ZN7GH566521aE = global %"struct.GH56652::bar" undef _______________________________________________ cfe-commits mailing list [email protected] https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
