-
Notifications
You must be signed in to change notification settings - Fork 15.2k
[Clang] diagnose deleted/default redeclaration of defined friend functions #136717
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Conversation
|
@llvm/pr-subscribers-clang Author: Oleksandr T. (a-tarasyuk) ChangesFixes #135680 This PR addresses the issue where Clang failed to diagnose the redeclaration of defined friend functions as deleted/defaulted struct S {
friend int f() { return 0; }
friend int f() = delete;
};Full diff: https://github.com/llvm/llvm-project/pull/136717.diff 3 Files Affected:
diff --git a/clang/docs/ReleaseNotes.rst b/clang/docs/ReleaseNotes.rst
index 5ccd346a93b4f..4362c23ce4058 100644
--- a/clang/docs/ReleaseNotes.rst
+++ b/clang/docs/ReleaseNotes.rst
@@ -462,6 +462,8 @@ Bug Fixes in This Version
- Fixed a crash when ``#embed`` appears as a part of a failed constant
evaluation. The crashes were happening during diagnostics emission due to
unimplemented statement printer. (#GH132641)
+- Clang now correctly diagnoses the deleted/defaulted redeclaration of defined
+ friend functions. (#GH135680)
Bug Fixes to Compiler Builtins
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
diff --git a/clang/lib/Parse/ParseCXXInlineMethods.cpp b/clang/lib/Parse/ParseCXXInlineMethods.cpp
index b1064eb02b907..ab19c4d6dd706 100644
--- a/clang/lib/Parse/ParseCXXInlineMethods.cpp
+++ b/clang/lib/Parse/ParseCXXInlineMethods.cpp
@@ -142,6 +142,13 @@ NamedDecl *Parser::ParseCXXInlineMethodDef(
SkipUntil(tok::semi);
}
+ Decl *PrevDecl = FnD->getPreviousDecl();
+ if (PrevDecl && isa<FunctionDecl>(PrevDecl) &&
+ PrevDecl->getLexicalDeclContext() == FnD->getLexicalDeclContext()) {
+ Actions.CheckForFunctionRedefinition(FnD->getAsFunction(),
+ cast<FunctionDecl>(PrevDecl));
+ }
+
return FnD;
}
diff --git a/clang/test/SemaCXX/cxx2c-delete-with-message.cpp b/clang/test/SemaCXX/cxx2c-delete-with-message.cpp
index 5609da18c05aa..e4a68bdcf2a4d 100644
--- a/clang/test/SemaCXX/cxx2c-delete-with-message.cpp
+++ b/clang/test/SemaCXX/cxx2c-delete-with-message.cpp
@@ -274,26 +274,22 @@ void operators() {
namespace gh135506 {
struct a {
- // FIXME: We currently don't diagnose these invalid redeclarations if the
- // second declaration is defaulted or deleted. This probably needs to be
- // handled in ParseCXXInlineMethodDef() after parsing the defaulted/deleted
- // body.
- friend consteval int f() { return 3; }
- friend consteval int f() = delete("foo");
+ friend consteval int f() { return 3; } // expected-note {{previous definition is here}}
+ friend consteval int f() = delete("foo"); // expected-error {{redefinition of 'f'}}
- friend consteval int g() { return 3; }
- friend consteval int g() = delete;
+ friend consteval int g() { return 3; } // expected-note {{previous definition is here}}
+ friend consteval int g() = delete; // expected-error {{redefinition of 'g'}}
- friend int h() { return 3; }
- friend int h() = delete;
+ friend int h() { return 3; } // expected-note {{previous definition is here}}
+ friend int h() = delete; // expected-error {{redefinition of 'h'}}
- friend consteval int i() = delete; // expected-note {{previous definition is here}}
+ friend consteval int i() = delete; // expected-note {{previous definition is here}}
friend consteval int i() { return 3; } // expected-error {{redefinition of 'i'}}
};
struct b {
- friend consteval bool operator==(b, b) { return true; } // expected-note {{previous declaration is here}}
- 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}}
+ friend consteval bool operator==(b, b) { return true; } // expected-note {{previous definition is here}}
+ friend consteval bool operator==(b, b) = default; // expected-error {{redefinition of 'operator=='}}
};
struct c {
|
Sirraide
left a comment
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Some more test cases:
int a();
struct A { friend int a() = delete; };
struct B { friend int b(); };
struct C { friend int b() = delete; };|
Actually, I meant this of course: void a() {}
struct A { friend void a() = delete; };
struct B { friend void b() {} };
struct C { friend void b() = delete; }; |
zwuis
left a comment
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
LGTM
|
@Sirraide, thanks for the feedback. I've added requested tests |
No description provided.