diff --git a/clang/docs/ReleaseNotes.rst b/clang/docs/ReleaseNotes.rst index 88862f7661191..159991e8db981 100644 --- a/clang/docs/ReleaseNotes.rst +++ b/clang/docs/ReleaseNotes.rst @@ -354,6 +354,7 @@ Bug Fixes to C++ Support - Correctly diagnoses if unresolved using declarations shadows template paramters (#GH129411) - Clang was previously coalescing volatile writes to members of volatile base class subobjects. The issue has been addressed by propagating qualifiers during derived-to-base conversions in the AST. (#GH127824) +- Fixed a Clang regression in C++20 mode where unresolved dependent call expressions were created inside non-dependent contexts (#GH122892) - Clang now emits the ``-Wunused-variable`` warning when some structured bindings are unused and the ``[[maybe_unused]]`` attribute is not applied. (#GH125810) diff --git a/clang/lib/Sema/SemaOverload.cpp b/clang/lib/Sema/SemaOverload.cpp index 161c0daa2f510..f185bc3cb358a 100644 --- a/clang/lib/Sema/SemaOverload.cpp +++ b/clang/lib/Sema/SemaOverload.cpp @@ -14329,9 +14329,24 @@ ExprResult Sema::BuildOverloadedCallExpr(Scope *S, Expr *Fn, const FunctionDecl *FDecl = Best->Function; if (FDecl && FDecl->isTemplateInstantiation() && FDecl->getReturnType()->isUndeducedType()) { + + // Creating dependent CallExpr is not okay if the enclosing context itself + // is not dependent. This situation notably arises if a non-dependent + // member function calls the later-defined overloaded static function. + // + // For example, in + // class A { + // void c() { callee(1); } + // static auto callee(auto x) { } + // }; + // + // Here callee(1) is unresolved at the call site, but is not inside a + // dependent context. There will be no further attempt to resolve this + // call if it is made dependent. + if (const auto *TP = FDecl->getTemplateInstantiationPattern(/*ForDefinition=*/false); - TP && TP->willHaveBody()) { + TP && TP->willHaveBody() && CurContext->isDependentContext()) { return CallExpr::Create(Context, Fn, Args, Context.DependentTy, VK_PRValue, RParenLoc, CurFPFeatureOverrides()); } diff --git a/clang/test/SemaCXX/deduced-return-type-cxx14.cpp b/clang/test/SemaCXX/deduced-return-type-cxx14.cpp index c33e07088ba32..aa62c4a57a636 100644 --- a/clang/test/SemaCXX/deduced-return-type-cxx14.cpp +++ b/clang/test/SemaCXX/deduced-return-type-cxx14.cpp @@ -703,6 +703,48 @@ auto f(auto x) { // cxx14-error {{'auto' not allowed in function prototype}} return f(1) + 1; } +namespace GH122892 { + struct NonTemplate { + void caller() { + c1(int{}); // since-cxx20-error {{cannot be used before it is defined}} + c2(int{}); // since-cxx14-error {{cannot be used before it is defined}} + } + + static auto c1(auto x) { // since-cxx20-note {{declared here}} // cxx14-error {{'auto' not allowed in function prototype}} + } + + template + static auto c2(T x) { // since-cxx14-note {{declared here}} + return x; + } + }; + + struct FunctionTemplateSpecialized { + template + void specialized(){} + + template <> + void specialized() { + c1(int{}); // since-cxx20-error {{cannot be used before it is defined}} + c2(int{}); // since-cxx14-error {{cannot be used before it is defined}} + } + + static auto c1(auto x) { // since-cxx20-note {{declared here}} // cxx14-error {{'auto' not allowed in function prototype}} + } + + template + static auto c2(T x) { // since-cxx14-note {{declared here}} + return x; + } + }; + + struct MemberInit { + int x1 = c1(int{}); // since-cxx20-error {{cannot be used before it is defined}} + + static auto c1(auto x) { return x; } // since-cxx20-note {{declared here}} // cxx14-error {{'auto' not allowed in function prototype}} + }; + +} } #if __cplusplus >= 202002L