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/2] [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/2] 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 ')'}} _______________________________________________ cfe-commits mailing list [email protected] https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
