Index: clang/lib/Sema/SemaOverload.cpp =================================================================== --- clang/lib/Sema/SemaOverload.cpp +++ clang/lib/Sema/SemaOverload.cpp @@ -14161,7 +14161,8 @@ Method->getType()->castAs())) return ExprError(); - return MaybeBindToTemporary(TheCall); + return CheckForImmediateInvocation(MaybeBindToTemporary(TheCall), + FnDecl); } else { // We matched a built-in operator. Convert the arguments, then // break out so that we will build the appropriate built-in @@ -14916,7 +14917,7 @@ Method->getType()->castAs())) return ExprError(); - return MaybeBindToTemporary(TheCall); + return CheckForImmediateInvocation(MaybeBindToTemporary(TheCall), Method); } /// BuildLiteralOperatorCall - Build a UserDefinedLiteral by creating a call to Index: clang/test/SemaCXX/cxx2a-consteval.cpp =================================================================== --- clang/test/SemaCXX/cxx2a-consteval.cpp +++ clang/test/SemaCXX/cxx2a-consteval.cpp @@ -612,3 +612,27 @@ static_assert(is_same::value); } // namespace unevaluated + +namespace PR50779 { +struct derp { + int b = 0; +}; + +constexpr derp d; + +struct test { + consteval int operator[](int i) const { return {}; } + consteval const derp * operator->() const { return &d; } +}; + +constexpr test a; + +// We previously rejected both of these overloaded operators as taking the +// address of a consteval function outside of an immediate context, but we +// accepted direct calls to the overloaded operator. Now we show that we accept +// both forms. +constexpr int s = a.operator[](1); +constexpr int t = a[1]; +constexpr int u = a.operator->()->b; +constexpr int v = a->b; +}