llvmbot wrote:
<!--LLVM PR SUMMARY COMMENT--> @llvm/pr-subscribers-clang Author: None (Sirraide) <details> <summary>Changes</summary> [[dcl.fct]p6](https://eel.is/c++draft/dcl.fct#<!-- -->6) states: > [...] An explicit-object-parameter-declaration shall appear only as the first parameter-declaration of a parameter-declaration-list of either: > - a member-declarator that declares a member function [class.mem], or > - a lambda-declarator [expr.prim.lambda]. The intent of this pr is to disallow explicit object parameters in all other contexts early on when we handle the function declarator. This fixes #<!-- -->85992. --- Full diff: https://github.com/llvm/llvm-project/pull/89078.diff 4 Files Affected: - (modified) clang/include/clang/Basic/DiagnosticSemaKinds.td (+2) - (modified) clang/lib/Sema/SemaDeclCXX.cpp (+2-4) - (modified) clang/lib/Sema/SemaType.cpp (+30) - (modified) clang/test/SemaCXX/cxx2b-deducing-this.cpp (+20-2) ``````````diff diff --git a/clang/include/clang/Basic/DiagnosticSemaKinds.td b/clang/include/clang/Basic/DiagnosticSemaKinds.td index 5ec0218aedfe86..680638d2e59c6a 100644 --- a/clang/include/clang/Basic/DiagnosticSemaKinds.td +++ b/clang/include/clang/Basic/DiagnosticSemaKinds.td @@ -7494,6 +7494,8 @@ def err_explicit_object_parameter_mutable: Error< def err_invalid_explicit_object_type_in_lambda: Error< "invalid explicit object parameter type %0 in lambda with capture; " "the type must be the same as, or derived from, the lambda">; +def err_explicit_object_parameter_invalid: Error< + "an explicit object parameter is not allowed here">; def err_ref_qualifier_overload : Error< "cannot overload a member function %select{without a ref-qualifier|with " diff --git a/clang/lib/Sema/SemaDeclCXX.cpp b/clang/lib/Sema/SemaDeclCXX.cpp index 7669171fea56ff..ea634df48e5deb 100644 --- a/clang/lib/Sema/SemaDeclCXX.cpp +++ b/clang/lib/Sema/SemaDeclCXX.cpp @@ -11469,10 +11469,8 @@ void Sema::CheckExplicitObjectMemberFunction(Declarator &D, return; if (!DC || !DC->isRecord()) { - Diag(ExplicitObjectParam->getLocation(), - diag::err_explicit_object_parameter_nonmember) - << D.getSourceRange() << /*non-member=*/2 << IsLambda; - D.setInvalidType(); + assert(D.isInvalidType() && "Explicit object parameter in non-member " + "should have been diagnosed already"); return; } diff --git a/clang/lib/Sema/SemaType.cpp b/clang/lib/Sema/SemaType.cpp index 404c4e8e31b558..95257b801c8a6c 100644 --- a/clang/lib/Sema/SemaType.cpp +++ b/clang/lib/Sema/SemaType.cpp @@ -5287,6 +5287,36 @@ static TypeSourceInfo *GetFullTypeForDeclarator(TypeProcessingState &state, // Check for auto functions and trailing return type and adjust the // return type accordingly. if (!D.isInvalidType()) { + // [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 either: + // + // - a member-declarator that declares a member function [class.mem], 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; + if (First && First->isExplicitObjectParameter() && + C != DeclaratorContext::LambdaExpr && + + // Either not a member or nested declarator in a member. + (C != DeclaratorContext::Member || + D.getInnermostNonParenChunk() != &DeclType) && + + // Allow out-of-line definitions if we have a scope spec. + D.getCXXScopeSpec().isEmpty()) { + S.Diag(First->getBeginLoc(), + diag::err_explicit_object_parameter_invalid) + << First->getSourceRange(); + 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 5f29a955e053c3..ddb770a92db0f9 100644 --- a/clang/test/SemaCXX/cxx2b-deducing-this.cpp +++ b/clang/test/SemaCXX/cxx2b-deducing-this.cpp @@ -5,7 +5,7 @@ void f(this); // expected-error{{variable has incomplete type 'void'}} \ // expected-error{{invalid use of 'this' outside of a non-static member function}} -void g(this auto); // expected-error{{an explicit object parameter cannot appear in a non-member function}} +void g(this auto); // expected-error{{an explicit object parameter is not allowed here}} auto l1 = [] (this auto) static {}; // expected-error{{an explicit object parameter cannot appear in a static lambda}} auto l2 = [] (this auto) mutable {}; // expected-error{{a lambda with an explicit object parameter cannot be mutable}} @@ -685,7 +685,7 @@ struct S { static void j(this S s); // expected-error {{an explicit object parameter cannot appear in a static function}} }; -void nonmember(this S s); // expected-error {{an explicit object parameter cannot appear in a non-member function}} +void nonmember(this S s); // expected-error {{an explicit object parameter is not allowed here}} int test() { S s; @@ -838,3 +838,21 @@ int h() { }(); } } + +namespace GH85992 { +struct S { + int (S::*x)(this int); // expected-error {{an explicit object parameter is not allowed here}} + int (*y)(this int); // expected-error {{an explicit object parameter is not allowed here}} + int (***z)(this int); // expected-error {{an explicit object parameter is not allowed here}} + + int f(this S); + int ((g))(this S); + int h(int x, int (*)(this S)); // expected-error {{an explicit object parameter is not allowed here}} +}; + +using T = int (*)(this int); // expected-error {{an explicit object parameter is not allowed here}} +using U = int (S::*)(this int); // expected-error {{an explicit object parameter is not allowed here}} +int h(this int); // expected-error {{an explicit object parameter is not allowed here}} + +int S::f(this S) { return 1; } +} `````````` </details> https://github.com/llvm/llvm-project/pull/89078 _______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits