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..d28353486c493 100644 --- a/clang/lib/Parse/ParseCXXInlineMethods.cpp +++ b/clang/lib/Parse/ParseCXXInlineMethods.cpp @@ -142,6 +142,14 @@ NamedDecl *Parser::ParseCXXInlineMethodDef( SkipUntil(tok::semi); } + if (FunctionDecl *FD = + dyn_cast_if_present(FnD->getPreviousDecl())) { + if (isa(FD->getLexicalDeclContext()) || + Actions.getDefaultedFunctionKind(FD).asComparison() == + Sema::DefaultedComparisonKind::None) + Actions.CheckForFunctionRedefinition(FnD->getAsFunction(), FD); + } + return FnD; } diff --git a/clang/test/SemaCXX/cxx2c-delete-with-message.cpp b/clang/test/SemaCXX/cxx2c-delete-with-message.cpp index 5609da18c05aa..78524c50e615c 100644 --- a/clang/test/SemaCXX/cxx2c-delete-with-message.cpp +++ b/clang/test/SemaCXX/cxx2c-delete-with-message.cpp @@ -273,31 +273,34 @@ 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 g() { return 3; } - friend consteval int g() = delete; - - friend int h() { return 3; } - friend int h() = delete; - - friend consteval int i() = delete; // expected-note {{previous definition is here}} - friend consteval int i() { return 3; } // expected-error {{redefinition of 'i'}} +struct s1 { + friend consteval int a() { return 3; } // expected-note {{previous definition is here}} + friend consteval int a() = delete("foo"); // expected-error {{redefinition of 'a'}} + + friend consteval int b() { return 3; } // expected-note {{previous definition is here}} + friend consteval int b() = delete; // expected-error {{redefinition of 'b'}} + + friend int c() { return 3; } // expected-note {{previous definition is here}} + friend int c() = delete; // expected-error {{redefinition of 'c'}} + + friend consteval int d() = delete; // expected-note {{previous definition is here}} + friend consteval int d() { return 3; } // expected-error {{redefinition of 'd'}} }; -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}} +struct s2 { + friend consteval bool operator==(s2, s2) { return true; } // expected-note {{previous definition is here}} + friend consteval bool operator==(s2, s2) = default; // expected-error {{redefinition of 'operator=='}} }; -struct c { - friend consteval bool operator==(c, c) = default; // expected-note {{previous definition is here}} - friend consteval bool operator==(c, c) { return true; } // expected-error {{redefinition of 'operator=='}} +struct s3 { + friend consteval bool operator==(s3, s3) = default; // expected-note {{previous definition is here}} + friend consteval bool operator==(s3, s3) { return true; } // expected-error {{redefinition of 'operator=='}} }; + +void e() {} // expected-note {{previous definition is here}} +struct s4 { friend void e() = delete; }; // expected-error {{redefinition of 'e'}} + +struct s5 { friend void f() {} }; // expected-note {{previous definition is here}} +struct s6 { friend void f() = delete; }; // expected-error {{redefinition of 'f'}} + }