Skip to content

Commit daa795d

Browse files
committed
[Clang] [Sema] Fix a crash when a friend function is redefined as deleted
1 parent 1e153b7 commit daa795d

File tree

3 files changed

+36
-11
lines changed

3 files changed

+36
-11
lines changed

clang/docs/ReleaseNotes.rst

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -389,7 +389,7 @@ Bug Fixes in This Version
389389
390390
#if 1 ? 1 : 999999999999999999999
391391
#endif
392-
392+
- Fixed a crash when a ``friend`` function is redefined as deleted. (#GH135506)
393393
Bug Fixes to Compiler Builtins
394394
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
395395

clang/lib/Sema/SemaDecl.cpp

Lines changed: 5 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -16178,16 +16178,11 @@ Decl *Sema::ActOnFinishFunctionBody(Decl *dcl, Stmt *Body,
1617816178
// This is meant to pop the context added in ActOnStartOfFunctionDef().
1617916179
ExitFunctionBodyRAII ExitRAII(*this, isLambdaCallOperator(FD));
1618016180
if (FD) {
16181-
// If this is called by Parser::ParseFunctionDefinition() after marking
16182-
// the declaration as deleted, and if the deleted-function-body contains
16183-
// a message (C++26), then a DefaultedOrDeletedInfo will have already been
16184-
// added to store that message; do not overwrite it in that case.
16185-
//
16186-
// Since this would always set the body to 'nullptr' in that case anyway,
16187-
// which is already done when the function decl is initially created,
16188-
// always skipping this irrespective of whether there is a delete message
16189-
// should not be a problem.
16190-
if (!FD->isDeletedAsWritten())
16181+
// The function body and the DefaultedOrDeletedInfo, if present, use
16182+
// the same storage; don't overwrite the latter if the former is null
16183+
// (the body is initialised to null anyway, so even if the latter isn't
16184+
// present, this would still be a no-op).
16185+
if (Body)
1619116186
FD->setBody(Body);
1619216187
FD->setWillHaveBody(false);
1619316188

clang/test/SemaCXX/cxx2c-delete-with-message.cpp

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -271,3 +271,33 @@ void operators() {
271271
if (to_int_int) {} // expected-error {{attempt to use a deleted function: deleted (TO<int, int>, operator bool)}}
272272
static_cast<bool>(to_int_int); // expected-error {{static_cast from 'TO<int, int>' to 'bool' uses deleted function: deleted (TO<int, int>, operator bool)}}
273273
};
274+
275+
namespace gh135506 {
276+
struct a {
277+
// FIXME: We currently don't diagnose these invalid redeclarations if the
278+
// second declaration is defaulted or deleted. This probably needs to be
279+
// handled in ParseCXXInlineMethodDef() after parsing the defaulted/deleted
280+
// body.
281+
friend consteval int f() { return 3; }
282+
friend consteval int f() = delete("foo");
283+
284+
friend consteval int g() { return 3; }
285+
friend consteval int g() = delete;
286+
287+
friend int h() { return 3; }
288+
friend int h() = delete;
289+
290+
friend consteval int i() = delete; // expected-note {{previous definition is here}}
291+
friend consteval int i() { return 3; } // expected-error {{redefinition of 'i'}}
292+
};
293+
294+
struct b {
295+
friend consteval bool operator==(b, b) { return true; } // expected-note {{previous declaration is here}}
296+
friend consteval bool operator==(b, b) = default; // expected-error {{defaulting this equality comparison operator is not allowed because it was already declared outside the class}}
297+
};
298+
299+
struct c {
300+
friend consteval bool operator==(c, c) = default; // expected-note {{previous definition is here}}
301+
friend consteval bool operator==(c, c) { return true; } // expected-error {{redefinition of 'operator=='}}
302+
};
303+
}

0 commit comments

Comments
 (0)