Skip to content

Commit

Permalink
[Clang] Mark declarators invalid in the presence of ill-formed explic…
Browse files Browse the repository at this point in the history
…it parameters. (llvm#70018)

To avoid crashes later in sema.

Fixes llvm#69962
Fixes llvm#69838
  • Loading branch information
cor3ntin committed Oct 24, 2023
1 parent 570c168 commit 20d97ad
Show file tree
Hide file tree
Showing 3 changed files with 50 additions and 7 deletions.
7 changes: 6 additions & 1 deletion clang/lib/Sema/SemaDeclCXX.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -11353,12 +11353,14 @@ void Sema::CheckExplicitObjectMemberFunction(Declarator &D,
Diag(ExplicitObjectParam->getBeginLoc(),
diag::err_explicit_object_parameter_nonmember)
<< D.getSourceRange() << /*static=*/0 << IsLambda;
D.setInvalidType();
}

if (D.getDeclSpec().isVirtualSpecified()) {
Diag(ExplicitObjectParam->getBeginLoc(),
diag::err_explicit_object_parameter_nonmember)
<< D.getSourceRange() << /*virtual=*/1 << IsLambda;
D.setInvalidType();
}

if (IsLambda && FTI.hasMutableQualifier()) {
Expand All @@ -11374,16 +11376,19 @@ void Sema::CheckExplicitObjectMemberFunction(Declarator &D,
Diag(ExplicitObjectParam->getLocation(),
diag::err_explicit_object_parameter_nonmember)
<< D.getSourceRange() << /*non-member=*/2 << IsLambda;
D.setInvalidType();
return;
}

// CWG2674: constructors and destructors cannot have explicit parameters.
if (Name.getNameKind() == DeclarationName::CXXConstructorName ||
Name.getNameKind() == DeclarationName::CXXDestructorName)
Name.getNameKind() == DeclarationName::CXXDestructorName) {
Diag(ExplicitObjectParam->getBeginLoc(),
diag::err_explicit_object_parameter_constructor)
<< (Name.getNameKind() == DeclarationName::CXXDestructorName)
<< D.getSourceRange();
D.setInvalidType();
}
}

namespace {
Expand Down
7 changes: 1 addition & 6 deletions clang/test/CXX/drs/dr25xx.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -85,19 +85,14 @@ using ::dr2521::operator""_div;
#if __cplusplus >= 202302L
namespace dr2553 { // dr2553: 18
struct B {
virtual void f(this B&); // expected-error {{an explicit object parameter cannot appear in a virtual function}} \
// expected-note {{here}}
virtual void f(this B&); // expected-error {{an explicit object parameter cannot appear in a virtual function}}
static void f(this B&); // expected-error {{an explicit object parameter cannot appear in a static function}}
virtual void g(); // expected-note {{here}}
};
struct D : B {
void g(this D&); // expected-error {{an explicit object parameter cannot appear in a virtual function}}
};

struct D2 : B {
void f(this B&); // expected-error {{an explicit object parameter cannot appear in a virtual function}}
};

}
#endif

Expand Down
43 changes: 43 additions & 0 deletions clang/test/SemaCXX/cxx2b-deducing-this.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -542,3 +542,46 @@ void foo(C c) {
}

}


namespace GH69838 {
struct S {
S(this auto &self) {} // expected-error {{an explicit object parameter cannot appear in a constructor}}
virtual void f(this S self) {} // expected-error {{an explicit object parameter cannot appear in a virtual function}}
void g(this auto &self) const {} // expected-error {{explicit object member function cannot have 'const' qualifier}}
void h(this S self = S{}) {} // expected-error {{the explicit object parameter cannot have a default argument}}
void i(int i, this S self = S{}) {} // expected-error {{an explicit object parameter can only appear as the first parameter of the function}}
~S(this S &&self); // expected-error {{an explicit object parameter cannot appear in a destructor}} \
// expected-error {{destructor cannot have any parameters}}

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}}

int test() {
S s;
s.f();
s.g();
s.h();
s.i(0);
s.j({});
nonmember(S{});
}

}

namespace GH69962 {
struct S {
S(const S&);
};

struct Thing {
template<typename Self, typename ... Args>
Thing(this Self&& self, Args&& ... args) { } // expected-error {{an explicit object parameter cannot appear in a constructor}}
};

class Server : public Thing {
S name_;
};
}

0 comments on commit 20d97ad

Please sign in to comment.