Skip to content

Commit cca0eac

Browse files
committed
[Clang] diagnose deleted/defaulted redeclaration of defined friend functions
1 parent 901ac60 commit cca0eac

File tree

3 files changed

+18
-13
lines changed

3 files changed

+18
-13
lines changed

clang/docs/ReleaseNotes.rst

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -462,6 +462,8 @@ Bug Fixes in This Version
462462
- Fixed a crash when ``#embed`` appears as a part of a failed constant
463463
evaluation. The crashes were happening during diagnostics emission due to
464464
unimplemented statement printer. (#GH132641)
465+
- Clang now correctly diagnoses the deleted/defaulted redeclaration of defined
466+
friend functions. (#GH135680)
465467

466468
Bug Fixes to Compiler Builtins
467469
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

clang/lib/Parse/ParseCXXInlineMethods.cpp

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -142,6 +142,13 @@ NamedDecl *Parser::ParseCXXInlineMethodDef(
142142
SkipUntil(tok::semi);
143143
}
144144

145+
Decl *PrevDecl = FnD->getPreviousDecl();
146+
if (PrevDecl && isa<FunctionDecl>(PrevDecl) &&
147+
PrevDecl->getLexicalDeclContext() == FnD->getLexicalDeclContext()) {
148+
Actions.CheckForFunctionRedefinition(FnD->getAsFunction(),
149+
cast<FunctionDecl>(PrevDecl));
150+
}
151+
145152
return FnD;
146153
}
147154

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

Lines changed: 9 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -274,26 +274,22 @@ void operators() {
274274

275275
namespace gh135506 {
276276
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");
277+
friend consteval int f() { return 3; } // expected-note {{previous definition is here}}
278+
friend consteval int f() = delete("foo"); // expected-error {{redefinition of 'f'}}
283279

284-
friend consteval int g() { return 3; }
285-
friend consteval int g() = delete;
280+
friend consteval int g() { return 3; } // expected-note {{previous definition is here}}
281+
friend consteval int g() = delete; // expected-error {{redefinition of 'g'}}
286282

287-
friend int h() { return 3; }
288-
friend int h() = delete;
283+
friend int h() { return 3; } // expected-note {{previous definition is here}}
284+
friend int h() = delete; // expected-error {{redefinition of 'h'}}
289285

290-
friend consteval int i() = delete; // expected-note {{previous definition is here}}
286+
friend consteval int i() = delete; // expected-note {{previous definition is here}}
291287
friend consteval int i() { return 3; } // expected-error {{redefinition of 'i'}}
292288
};
293289

294290
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}}
291+
friend consteval bool operator==(b, b) { return true; } // expected-note {{previous definition is here}}
292+
friend consteval bool operator==(b, b) = default; // expected-error {{redefinition of 'operator=='}}
297293
};
298294

299295
struct c {

0 commit comments

Comments
 (0)