https://github.com/hax0kartik updated https://github.com/llvm/llvm-project/pull/174603
>From 5740fe4640244d60d0f8d7f7498df5989f6e31d5 Mon Sep 17 00:00:00 2001 From: hax0kartik <[email protected]> Date: Tue, 6 Jan 2026 23:38:04 +0530 Subject: [PATCH] [Clang] Disallow explicit object parameters irrespective of whether return type is valid --- clang/docs/ReleaseNotes.rst | 1 + clang/lib/Sema/SemaType.cpp | 113 ++++++++++----------- clang/test/SemaCXX/cxx2b-deducing-this.cpp | 11 ++ 3 files changed, 68 insertions(+), 57 deletions(-) diff --git a/clang/docs/ReleaseNotes.rst b/clang/docs/ReleaseNotes.rst index 411cc348d4caf..b95b4ee65282f 100644 --- a/clang/docs/ReleaseNotes.rst +++ b/clang/docs/ReleaseNotes.rst @@ -594,6 +594,7 @@ Bug Fixes to C++ Support "initializing multiple members of union" coincide (#GH149985). - Fix a crash when using ``explicit(bool)`` in pre-C++11 language modes. (#GH152729) - Fix the parsing of variadic member functions when the ellipis immediately follows a default argument.(#GH153445) +- Fix a crash when using an explicit object parameter in a non-member function with an invalid return type.(#GH173943) - Fixed a bug that caused ``this`` captured by value in a lambda with a dependent explicit object parameter to not be instantiated properly. (#GH154054) - Fixed a bug where our ``member-like constrained friend`` checking caused an incorrect analysis of lambda captures. (#GH156225) diff --git a/clang/lib/Sema/SemaType.cpp b/clang/lib/Sema/SemaType.cpp index 7ef83433326ed..28bb352b16196 100644 --- a/clang/lib/Sema/SemaType.cpp +++ b/clang/lib/Sema/SemaType.cpp @@ -4834,66 +4834,65 @@ static TypeSourceInfo *GetFullTypeForDeclarator(TypeProcessingState &state, IsQualifiedFunction = FTI.hasMethodTypeQualifiers() || FTI.hasRefQualifier(); + auto IsClassType = [&](CXXScopeSpec &SS) { + // If there already was an problem with the scope, don’t issue another + // error about the explicit object parameter. + return SS.isInvalid() || + isa_and_present<CXXRecordDecl>(S.computeDeclContext(SS)); + }; + + // C++23 [dcl.fct]p6: + // + // An explicit-object-parameter-declaration is a parameter-declaration + // with a this specifier. An explicit-object-parameter-declaration shall + // appear only as the first parameter-declaration of a + // parameter-declaration-list of one of: + // + // - a declaration of a member function or member function template + // ([class.mem]), or + // + // - an explicit instantiation ([temp.explicit]) or explicit + // specialization ([temp.expl.spec]) of a templated member function, + // or + // + // - a lambda-declarator [expr.prim.lambda]. + DeclaratorContext C = D.getContext(); + ParmVarDecl *First = + FTI.NumParams ? dyn_cast_if_present<ParmVarDecl>(FTI.Params[0].Param) + : nullptr; + + bool IsFunctionDecl = D.getInnermostNonParenChunk() == &DeclType; + if (First && First->isExplicitObjectParameter() && + C != DeclaratorContext::LambdaExpr && + + // Either not a member or nested declarator in a member. + // + // Note that e.g. 'static' or 'friend' declarations are accepted + // here; we diagnose them later when we build the member function + // because it's easier that way. + (C != DeclaratorContext::Member || !IsFunctionDecl) && + + // Allow out-of-line definitions of member functions. + !IsClassType(D.getCXXScopeSpec())) { + if (IsFunctionDecl) + S.Diag(First->getBeginLoc(), + diag::err_explicit_object_parameter_nonmember) + << /*non-member*/ 2 << /*function*/ 0 << First->getSourceRange(); + else + S.Diag(First->getBeginLoc(), + diag::err_explicit_object_parameter_invalid) + << First->getSourceRange(); + + // Do let non-member function have explicit parameters + // to not break assumptions elsewhere in the code. + First->setExplicitObjectParameterLoc(SourceLocation()); + D.setInvalidType(); + AreDeclaratorChunksValid = false; + } + // Check for auto functions and trailing return type and adjust the // return type accordingly. if (!D.isInvalidType()) { - auto IsClassType = [&](CXXScopeSpec &SS) { - // If there already was an problem with the scope, don’t issue another - // error about the explicit object parameter. - return SS.isInvalid() || - isa_and_present<CXXRecordDecl>(S.computeDeclContext(SS)); - }; - - // C++23 [dcl.fct]p6: - // - // An explicit-object-parameter-declaration is a parameter-declaration - // with a this specifier. An explicit-object-parameter-declaration shall - // appear only as the first parameter-declaration of a - // parameter-declaration-list of one of: - // - // - a declaration of a member function or member function template - // ([class.mem]), or - // - // - an explicit instantiation ([temp.explicit]) or explicit - // specialization ([temp.expl.spec]) of a templated member function, - // or - // - // - a lambda-declarator [expr.prim.lambda]. - DeclaratorContext C = D.getContext(); - ParmVarDecl *First = - FTI.NumParams - ? dyn_cast_if_present<ParmVarDecl>(FTI.Params[0].Param) - : nullptr; - - bool IsFunctionDecl = D.getInnermostNonParenChunk() == &DeclType; - if (First && First->isExplicitObjectParameter() && - C != DeclaratorContext::LambdaExpr && - - // Either not a member or nested declarator in a member. - // - // Note that e.g. 'static' or 'friend' declarations are accepted - // here; we diagnose them later when we build the member function - // because it's easier that way. - (C != DeclaratorContext::Member || !IsFunctionDecl) && - - // Allow out-of-line definitions of member functions. - !IsClassType(D.getCXXScopeSpec())) { - if (IsFunctionDecl) - S.Diag(First->getBeginLoc(), - diag::err_explicit_object_parameter_nonmember) - << /*non-member*/ 2 << /*function*/ 0 - << First->getSourceRange(); - else - S.Diag(First->getBeginLoc(), - diag::err_explicit_object_parameter_invalid) - << First->getSourceRange(); - // Do let non-member function have explicit parameters - // to not break assumptions elsewhere in the code. - First->setExplicitObjectParameterLoc(SourceLocation()); - D.setInvalidType(); - AreDeclaratorChunksValid = false; - } - // trailing-return-type is only required if we're declaring a function, // and not, for instance, a pointer to a function. if (D.getDeclSpec().hasAutoTypeSpec() && diff --git a/clang/test/SemaCXX/cxx2b-deducing-this.cpp b/clang/test/SemaCXX/cxx2b-deducing-this.cpp index 6777dc23c44a6..a9e31c3d06676 100644 --- a/clang/test/SemaCXX/cxx2b-deducing-this.cpp +++ b/clang/test/SemaCXX/cxx2b-deducing-this.cpp @@ -1389,3 +1389,14 @@ void f() { } } + +namespace GH173943 { + +a void Bar(this int) { // expected-note {{candidate function}} + // expected-error@-1 {{unknown type name 'a'}} + // expected-error@-2 {{an explicit object parameter cannot appear in a non-member function}} + Bar(0); + Bar(); // expected-error {{no matching function for call to 'Bar'}} +} + +} _______________________________________________ cfe-commits mailing list [email protected] https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
