[clang] [Clang] Disallow explicit object parameters in more contexts (PR #89078)
via cfe-commits
cfe-commits at lists.llvm.org
Wed Apr 17 07:27:19 PDT 2024
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
More information about the cfe-commits
mailing list