llvmbot wrote:
<!--LLVM PR SUMMARY COMMENT--> @llvm/pr-subscribers-clang Author: Younan Zhang (zyn0217) <details> <summary>Changes</summary> The perfect matching patch revealed another bug where recursive instantiations could lead to the escape of SFINAE errors, as shown in the issue. I intend to backport this to Clang 22, so I will include a release note during the backporting process. Fixes https://github.com/llvm/llvm-project/issues/179118 --- Full diff: https://github.com/llvm/llvm-project/pull/180725.diff 2 Files Affected: - (modified) clang/lib/Sema/SemaExpr.cpp (+1-1) - (modified) clang/test/SemaCXX/overload-resolution-deferred-templates.cpp (+81) ``````````diff diff --git a/clang/lib/Sema/SemaExpr.cpp b/clang/lib/Sema/SemaExpr.cpp index 5795a71b5cae8..f27de8de04f7a 100644 --- a/clang/lib/Sema/SemaExpr.cpp +++ b/clang/lib/Sema/SemaExpr.cpp @@ -2938,7 +2938,7 @@ ExprResult Sema::BuildQualifiedDeclarationNameExpr( // members were likely supposed to be inherited. DeclContext *DC = computeDeclContext(SS); if (const auto *CD = dyn_cast<CXXRecordDecl>(DC)) - if (CD->isInvalidDecl()) + if (CD->isInvalidDecl() || CD->isBeingDefined()) return ExprError(); Diag(NameInfo.getLoc(), diag::err_no_member) << NameInfo.getName() << DC << SS.getRange(); diff --git a/clang/test/SemaCXX/overload-resolution-deferred-templates.cpp b/clang/test/SemaCXX/overload-resolution-deferred-templates.cpp index c3bda3988484d..acd38b37c3b5c 100644 --- a/clang/test/SemaCXX/overload-resolution-deferred-templates.cpp +++ b/clang/test/SemaCXX/overload-resolution-deferred-templates.cpp @@ -310,3 +310,84 @@ void test() { } } + +namespace GH179118 { + +namespace std { + +template <bool __v> struct integral_constant { + static constexpr bool value = __v; +}; + +template <typename _Tp, typename... _Args> +using __is_constructible_impl = + integral_constant<__is_constructible(_Tp, _Args...)>; + +template <typename _Tp, typename... _Args> +struct is_constructible : public std::__is_constructible_impl<_Tp, _Args...> {}; + +template <bool> struct _cond { + template <typename Then, typename> using invoke = Then; +}; +template <> struct _cond<false> { + template <typename, typename Else> using invoke = Else; +}; + +template <bool If, typename Then, typename Else> +using conditional_t = typename _cond<If>::template invoke<Then, Else>; + +template <bool, class _Tp = void> struct enable_if; +template <class _Tp> struct enable_if<true, _Tp> { + typedef _Tp type; +}; +template <bool _Bp, class _Tp = void> +using enable_if_t = typename enable_if<_Bp, _Tp>::type; + +} // namespace std + +namespace base { + +template <typename...> struct disjunction {}; +template <typename B1, typename... Bn> +struct disjunction<B1, Bn...> + : std::conditional_t<B1::value, B1, disjunction<>> {}; +template <typename> class Optional; + +namespace internal { +template <typename T, typename U> +using IsConvertibleFromOptional = + disjunction<std::is_constructible<T, Optional<U> &>>; +template <typename T, typename U> +using IsAssignableFromOptional = IsConvertibleFromOptional<T, U>; +} // namespace internal + +template <typename T> class Optional { +public: + Optional(Optional &&); + + template <typename U, + std::enable_if_t<internal::IsConvertibleFromOptional<T, U>::value> = + false> + Optional(Optional<U>); + + Optional(const Optional &); + void operator=(Optional &&); + + template <typename U> + std::enable_if_t<std::is_constructible<T, U>::value> operator=(U &&); + + template <typename U> + std::enable_if_t<internal::IsAssignableFromOptional<T, U>::Optional> + operator=(Optional<U>); +}; + +} // namespace base + +struct LayoutUnit { + template <typename IntegerType> LayoutUnit(IntegerType); +}; + +static_assert( + std::is_constructible<LayoutUnit, base::Optional<LayoutUnit> &>::value, ""); + +} `````````` </details> https://github.com/llvm/llvm-project/pull/180725 _______________________________________________ cfe-commits mailing list [email protected] https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
