[clang] 924f773 - [Clang] Don't diagnose missing members when looking at the instantiating class template (#180725)

via cfe-commits cfe-commits at lists.llvm.org
Wed Feb 11 04:42:16 PST 2026


Author: Younan Zhang
Date: 2026-02-11T20:42:11+08:00
New Revision: 924f773f5e261df260116ccb9849dbb58af56b69

URL: https://github.com/llvm/llvm-project/commit/924f773f5e261df260116ccb9849dbb58af56b69
DIFF: https://github.com/llvm/llvm-project/commit/924f773f5e261df260116ccb9849dbb58af56b69.diff

LOG: [Clang] Don't diagnose missing members when looking at the instantiating class template (#180725)

The perfect matching patch revealed another bug where recursive
instantiations could lead to the escape of SFINAE errors, as shown in
the issue.

Fixes https://github.com/llvm/llvm-project/issues/179118

Added: 
    

Modified: 
    clang/lib/Sema/SemaExpr.cpp
    clang/test/SemaCXX/overload-resolution-deferred-templates.cpp

Removed: 
    


################################################################################
diff  --git a/clang/lib/Sema/SemaExpr.cpp b/clang/lib/Sema/SemaExpr.cpp
index 60b5478371288..233f9ff297608 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, "");
+
+}


        


More information about the cfe-commits mailing list