[clang] [clang] [C++20] Defaulted operator== doesn't lookup in using-directive properly #97087 (PR #99542)

via cfe-commits cfe-commits at lists.llvm.org
Tue Jul 23 07:11:08 PDT 2024


https://github.com/ofAlpaca updated https://github.com/llvm/llvm-project/pull/99542

>From 2a381b47002db3c7a119a893c1a70e0b1604151f Mon Sep 17 00:00:00 2001
From: schiang <frank70199 at gmail.com>
Date: Thu, 18 Jul 2024 09:53:35 +0800
Subject: [PATCH 1/5] Pass 'Scope *' for 'SetDeclDefaulted()' and related utlis

---
 clang/include/clang/Sema/Sema.h                | 4 ++--
 clang/lib/Parse/ParseCXXInlineMethods.cpp      | 2 +-
 clang/lib/Parse/Parser.cpp                     | 2 +-
 clang/lib/Sema/SemaDeclCXX.cpp                 | 8 ++++----
 clang/lib/Sema/SemaTemplateInstantiateDecl.cpp | 4 ++--
 5 files changed, 10 insertions(+), 10 deletions(-)

diff --git a/clang/include/clang/Sema/Sema.h b/clang/include/clang/Sema/Sema.h
index 48dff1b76cc57..f887fc261a07e 100644
--- a/clang/include/clang/Sema/Sema.h
+++ b/clang/include/clang/Sema/Sema.h
@@ -5995,9 +5995,9 @@ class Sema final : public SemaBase {
   void ActOnPureSpecifier(Decl *D, SourceLocation PureSpecLoc);
   void SetDeclDeleted(Decl *dcl, SourceLocation DelLoc,
                       StringLiteral *Message = nullptr);
-  void SetDeclDefaulted(Decl *dcl, SourceLocation DefaultLoc);
+  void SetDeclDefaulted(Scope *S, Decl *dcl, SourceLocation DefaultLoc);
 
-  void SetFunctionBodyKind(Decl *D, SourceLocation Loc, FnBodyKind BodyKind,
+  void SetFunctionBodyKind(Scope *S, Decl *D, SourceLocation Loc, FnBodyKind BodyKind,
                            StringLiteral *DeletedMessage = nullptr);
   void ActOnStartTrailingRequiresClause(Scope *S, Declarator &D);
   ExprResult ActOnFinishTrailingRequiresClause(ExprResult ConstraintExpr);
diff --git a/clang/lib/Parse/ParseCXXInlineMethods.cpp b/clang/lib/Parse/ParseCXXInlineMethods.cpp
index 9ccbbf9a7d5d0..75a835f512144 100644
--- a/clang/lib/Parse/ParseCXXInlineMethods.cpp
+++ b/clang/lib/Parse/ParseCXXInlineMethods.cpp
@@ -124,7 +124,7 @@ NamedDecl *Parser::ParseCXXInlineMethodDef(
                       ? diag::warn_cxx98_compat_defaulted_deleted_function
                       : diag::ext_defaulted_deleted_function)
         << 0 /* defaulted */;
-      Actions.SetDeclDefaulted(FnD, KWLoc);
+      Actions.SetDeclDefaulted(nullptr, FnD, KWLoc);
       if (auto *DeclAsFunction = dyn_cast<FunctionDecl>(FnD)) {
         DeclAsFunction->setRangeEnd(KWEndLoc);
       }
diff --git a/clang/lib/Parse/Parser.cpp b/clang/lib/Parse/Parser.cpp
index 5ebe71e496a2e..f1d98bced80b2 100644
--- a/clang/lib/Parse/Parser.cpp
+++ b/clang/lib/Parse/Parser.cpp
@@ -1479,7 +1479,7 @@ Decl *Parser::ParseFunctionDefinition(ParsingDeclarator &D,
   D.getMutableDeclSpec().abort();
 
   if (BodyKind != Sema::FnBodyKind::Other) {
-    Actions.SetFunctionBodyKind(Res, KWLoc, BodyKind, DeletedMessage);
+    Actions.SetFunctionBodyKind(getCurScope(), Res, KWLoc, BodyKind, DeletedMessage);
     Stmt *GeneratedBody = Res ? Res->getBody() : nullptr;
     Actions.ActOnFinishFunctionBody(Res, GeneratedBody, false);
     return Res;
diff --git a/clang/lib/Sema/SemaDeclCXX.cpp b/clang/lib/Sema/SemaDeclCXX.cpp
index f24912cde275a..e57057fac10c6 100644
--- a/clang/lib/Sema/SemaDeclCXX.cpp
+++ b/clang/lib/Sema/SemaDeclCXX.cpp
@@ -17940,7 +17940,7 @@ void Sema::SetDeclDeleted(Decl *Dcl, SourceLocation DelLoc,
   Fn->setDeletedAsWritten(true, Message);
 }
 
-void Sema::SetDeclDefaulted(Decl *Dcl, SourceLocation DefaultLoc) {
+void Sema::SetDeclDefaulted(Scope *S, Decl *Dcl, SourceLocation DefaultLoc) {
   if (!Dcl || Dcl->isInvalidDecl())
     return;
 
@@ -18016,7 +18016,7 @@ void Sema::SetDeclDefaulted(Decl *Dcl, SourceLocation DefaultLoc) {
   }
 
   if (DefKind.isComparison()) {
-    if (CheckExplicitlyDefaultedComparison(nullptr, FD, DefKind.asComparison()))
+    if (CheckExplicitlyDefaultedComparison(S, FD, DefKind.asComparison()))
       FD->setInvalidDecl();
     else
       DefineDefaultedComparison(DefaultLoc, FD, DefKind.asComparison());
@@ -18050,14 +18050,14 @@ void Sema::DiagnoseReturnInConstructorExceptionHandler(CXXTryStmt *TryBlock) {
   }
 }
 
-void Sema::SetFunctionBodyKind(Decl *D, SourceLocation Loc, FnBodyKind BodyKind,
+void Sema::SetFunctionBodyKind(Scope *S, Decl *D, SourceLocation Loc, FnBodyKind BodyKind,
                                StringLiteral *DeletedMessage) {
   switch (BodyKind) {
   case FnBodyKind::Delete:
     SetDeclDeleted(D, Loc, DeletedMessage);
     break;
   case FnBodyKind::Default:
-    SetDeclDefaulted(D, Loc);
+    SetDeclDefaulted(S, D, Loc);
     break;
   case FnBodyKind::Other:
     llvm_unreachable(
diff --git a/clang/lib/Sema/SemaTemplateInstantiateDecl.cpp b/clang/lib/Sema/SemaTemplateInstantiateDecl.cpp
index 01432301633ed..65a755cb69048 100644
--- a/clang/lib/Sema/SemaTemplateInstantiateDecl.cpp
+++ b/clang/lib/Sema/SemaTemplateInstantiateDecl.cpp
@@ -4856,7 +4856,7 @@ bool TemplateDeclInstantiator::SubstDefaultedFunction(FunctionDecl *New,
                    : DFI);
   }
 
-  SemaRef.SetDeclDefaulted(New, Tmpl->getLocation());
+  SemaRef.SetDeclDefaulted(nullptr, New, Tmpl->getLocation());
   return false;
 }
 
@@ -5133,7 +5133,7 @@ void Sema::InstantiateFunctionDefinition(SourceLocation PointOfInstantiation,
 
   if (PatternDecl->isDefaulted()) {
     RebuildTypeSourceInfoForDefaultSpecialMembers();
-    SetDeclDefaulted(Function, PatternDecl->getLocation());
+    SetDeclDefaulted(nullptr, Function, PatternDecl->getLocation());
   } else {
     MultiLevelTemplateArgumentList TemplateArgs = getTemplateInstantiationArgs(
         Function, Function->getLexicalDeclContext(), /*Final=*/false,

>From 5dbfe6988c489344c4afff359d23cd0306b32611 Mon Sep 17 00:00:00 2001
From: schiang <frank70199 at gmail.com>
Date: Fri, 19 Jul 2024 01:00:44 +0800
Subject: [PATCH 2/5] git clang-format changes

---
 clang/include/clang/Sema/Sema.h | 3 ++-
 clang/lib/Parse/Parser.cpp      | 3 ++-
 clang/lib/Sema/SemaDeclCXX.cpp  | 3 ++-
 3 files changed, 6 insertions(+), 3 deletions(-)

diff --git a/clang/include/clang/Sema/Sema.h b/clang/include/clang/Sema/Sema.h
index f887fc261a07e..622b107b80081 100644
--- a/clang/include/clang/Sema/Sema.h
+++ b/clang/include/clang/Sema/Sema.h
@@ -5997,7 +5997,8 @@ class Sema final : public SemaBase {
                       StringLiteral *Message = nullptr);
   void SetDeclDefaulted(Scope *S, Decl *dcl, SourceLocation DefaultLoc);
 
-  void SetFunctionBodyKind(Scope *S, Decl *D, SourceLocation Loc, FnBodyKind BodyKind,
+  void SetFunctionBodyKind(Scope *S, Decl *D, SourceLocation Loc,
+                           FnBodyKind BodyKind,
                            StringLiteral *DeletedMessage = nullptr);
   void ActOnStartTrailingRequiresClause(Scope *S, Declarator &D);
   ExprResult ActOnFinishTrailingRequiresClause(ExprResult ConstraintExpr);
diff --git a/clang/lib/Parse/Parser.cpp b/clang/lib/Parse/Parser.cpp
index f1d98bced80b2..eaf67ed633016 100644
--- a/clang/lib/Parse/Parser.cpp
+++ b/clang/lib/Parse/Parser.cpp
@@ -1479,7 +1479,8 @@ Decl *Parser::ParseFunctionDefinition(ParsingDeclarator &D,
   D.getMutableDeclSpec().abort();
 
   if (BodyKind != Sema::FnBodyKind::Other) {
-    Actions.SetFunctionBodyKind(getCurScope(), Res, KWLoc, BodyKind, DeletedMessage);
+    Actions.SetFunctionBodyKind(getCurScope(), Res, KWLoc, BodyKind,
+                                DeletedMessage);
     Stmt *GeneratedBody = Res ? Res->getBody() : nullptr;
     Actions.ActOnFinishFunctionBody(Res, GeneratedBody, false);
     return Res;
diff --git a/clang/lib/Sema/SemaDeclCXX.cpp b/clang/lib/Sema/SemaDeclCXX.cpp
index e57057fac10c6..0f0fe10b57517 100644
--- a/clang/lib/Sema/SemaDeclCXX.cpp
+++ b/clang/lib/Sema/SemaDeclCXX.cpp
@@ -18050,7 +18050,8 @@ void Sema::DiagnoseReturnInConstructorExceptionHandler(CXXTryStmt *TryBlock) {
   }
 }
 
-void Sema::SetFunctionBodyKind(Scope *S, Decl *D, SourceLocation Loc, FnBodyKind BodyKind,
+void Sema::SetFunctionBodyKind(Scope *S, Decl *D, SourceLocation Loc,
+                               FnBodyKind BodyKind,
                                StringLiteral *DeletedMessage) {
   switch (BodyKind) {
   case FnBodyKind::Delete:

>From b4bbcee9d928d73c7c3327056dbb325ab250f0a4 Mon Sep 17 00:00:00 2001
From: schiang <frank70199 at gmail.com>
Date: Mon, 22 Jul 2024 02:16:34 +0800
Subject: [PATCH 3/5] Add release note and testcase

---
 clang/docs/ReleaseNotes.rst    |  2 ++
 clang/test/SemaCXX/GH97087.cpp | 12 ++++++++++++
 2 files changed, 14 insertions(+)
 create mode 100644 clang/test/SemaCXX/GH97087.cpp

diff --git a/clang/docs/ReleaseNotes.rst b/clang/docs/ReleaseNotes.rst
index 969856a8f978c..36f00cda724fa 100644
--- a/clang/docs/ReleaseNotes.rst
+++ b/clang/docs/ReleaseNotes.rst
@@ -826,6 +826,8 @@ Bug Fixes in This Version
 - ``__is_trivially_equality_comparable`` no longer returns true for types which
   have a constrained defaulted comparison operator (#GH89293).
 
+- Fixed defaulted `operator==` doesn't lookup its scope properly (#GH97087).
+
 Bug Fixes to Compiler Builtins
 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
diff --git a/clang/test/SemaCXX/GH97087.cpp b/clang/test/SemaCXX/GH97087.cpp
new file mode 100644
index 0000000000000..06902db4bf860
--- /dev/null
+++ b/clang/test/SemaCXX/GH97087.cpp
@@ -0,0 +1,12 @@
+// RUN: %clang_cc1 -std=c++20 -fsyntax-only %s
+// expected-no-diagnostics 
+struct X {};
+namespace NS {
+    bool operator==(X, X);
+}
+using namespace NS;
+struct Y {
+    X x;
+    friend bool operator==(Y, Y);
+};
+bool operator==(Y, Y) = default;

>From 39f04fd603a71f598aad951a42f1d0e76344fad3 Mon Sep 17 00:00:00 2001
From: schiang <frank70199 at gmail.com>
Date: Tue, 23 Jul 2024 13:35:08 +0800
Subject: [PATCH 4/5] Update testcases

---
 clang/test/SemaCXX/GH97087.cpp               | 12 ----------
 clang/test/SemaCXX/cxx20-default-compare.cpp | 25 +++++++++++++++++++-
 2 files changed, 24 insertions(+), 13 deletions(-)
 delete mode 100644 clang/test/SemaCXX/GH97087.cpp

diff --git a/clang/test/SemaCXX/GH97087.cpp b/clang/test/SemaCXX/GH97087.cpp
deleted file mode 100644
index 06902db4bf860..0000000000000
--- a/clang/test/SemaCXX/GH97087.cpp
+++ /dev/null
@@ -1,12 +0,0 @@
-// RUN: %clang_cc1 -std=c++20 -fsyntax-only %s
-// expected-no-diagnostics 
-struct X {};
-namespace NS {
-    bool operator==(X, X);
-}
-using namespace NS;
-struct Y {
-    X x;
-    friend bool operator==(Y, Y);
-};
-bool operator==(Y, Y) = default;
diff --git a/clang/test/SemaCXX/cxx20-default-compare.cpp b/clang/test/SemaCXX/cxx20-default-compare.cpp
index 7074ee885ac4a..62d7abb03c71e 100644
--- a/clang/test/SemaCXX/cxx20-default-compare.cpp
+++ b/clang/test/SemaCXX/cxx20-default-compare.cpp
@@ -1,5 +1,4 @@
 // RUN: %clang_cc1 %s -std=c++23 -verify -Wfloat-equal
-
 struct Foo {
   float val;
   bool operator==(const Foo &) const;
@@ -7,6 +6,24 @@ struct Foo {
   friend bool operator==(Foo, Foo );
 };
 
+struct X {};
+namespace NS {
+  bool operator==(X, X);
+}
+using namespace NS;
+
+struct Y {
+  X x;
+  friend bool operator==(Y, Y);
+};
+
+template <typename T>
+struct Z {
+  T x;
+  friend bool operator==(Z, Z);
+};
+template class Z<X>;
+
 // Declare the defaulted comparison function as a member function.
 bool Foo::operator==(const Foo &) const = default; // expected-warning {{comparing floating point with == or != is unsafe}} expected-note {{in defaulted equality comparison operator for 'Foo' first required here}}
 
@@ -15,3 +32,9 @@ bool operator==(const Foo &, const Foo &) = default;  // expected-warning {{comp
 
 // Declare the defaulted comparison function as a non-member function. Arguments are passed by value.
 bool operator==(Foo, Foo) = default;  // expected-warning {{comparing floating point with == or != is unsafe}} expected-note {{in defaulted equality comparison operator for 'Foo' first required here}}
+
+// Declare the defaulted comparsion function as a non-member function. Arguments are passed by value. Arguments look up NS namespace.
+bool operator==(Y, Y) = default; 
+
+// Declare the defaulted comparsion function as a non-member function. Arguments are passed by value. Arguments look up NS namespace and use template struct.
+bool operator==(Z<X>, Z<X>) = default;
\ No newline at end of file

>From 0a5da9c64284ed39a2de23ac68b7439c46d54133 Mon Sep 17 00:00:00 2001
From: schiang <frank70199 at gmail.com>
Date: Tue, 23 Jul 2024 17:34:47 +0800
Subject: [PATCH 5/5] Update nullptr with comment /*Scope=*/ and add new line
 at the end of testcase

---
 clang/lib/Parse/ParseCXXInlineMethods.cpp      | 2 +-
 clang/lib/Sema/SemaTemplateInstantiateDecl.cpp | 4 ++--
 clang/test/SemaCXX/cxx20-default-compare.cpp   | 3 ++-
 3 files changed, 5 insertions(+), 4 deletions(-)

diff --git a/clang/lib/Parse/ParseCXXInlineMethods.cpp b/clang/lib/Parse/ParseCXXInlineMethods.cpp
index 75a835f512144..99646499efaea 100644
--- a/clang/lib/Parse/ParseCXXInlineMethods.cpp
+++ b/clang/lib/Parse/ParseCXXInlineMethods.cpp
@@ -124,7 +124,7 @@ NamedDecl *Parser::ParseCXXInlineMethodDef(
                       ? diag::warn_cxx98_compat_defaulted_deleted_function
                       : diag::ext_defaulted_deleted_function)
         << 0 /* defaulted */;
-      Actions.SetDeclDefaulted(nullptr, FnD, KWLoc);
+      Actions.SetDeclDefaulted(/*Scope=*/nullptr, FnD, KWLoc);
       if (auto *DeclAsFunction = dyn_cast<FunctionDecl>(FnD)) {
         DeclAsFunction->setRangeEnd(KWEndLoc);
       }
diff --git a/clang/lib/Sema/SemaTemplateInstantiateDecl.cpp b/clang/lib/Sema/SemaTemplateInstantiateDecl.cpp
index 65a755cb69048..855fb8867c444 100644
--- a/clang/lib/Sema/SemaTemplateInstantiateDecl.cpp
+++ b/clang/lib/Sema/SemaTemplateInstantiateDecl.cpp
@@ -4856,7 +4856,7 @@ bool TemplateDeclInstantiator::SubstDefaultedFunction(FunctionDecl *New,
                    : DFI);
   }
 
-  SemaRef.SetDeclDefaulted(nullptr, New, Tmpl->getLocation());
+  SemaRef.SetDeclDefaulted(/*Scope=*/nullptr, New, Tmpl->getLocation());
   return false;
 }
 
@@ -5133,7 +5133,7 @@ void Sema::InstantiateFunctionDefinition(SourceLocation PointOfInstantiation,
 
   if (PatternDecl->isDefaulted()) {
     RebuildTypeSourceInfoForDefaultSpecialMembers();
-    SetDeclDefaulted(nullptr, Function, PatternDecl->getLocation());
+    SetDeclDefaulted(/*Scope=*/nullptr, Function, PatternDecl->getLocation());
   } else {
     MultiLevelTemplateArgumentList TemplateArgs = getTemplateInstantiationArgs(
         Function, Function->getLexicalDeclContext(), /*Final=*/false,
diff --git a/clang/test/SemaCXX/cxx20-default-compare.cpp b/clang/test/SemaCXX/cxx20-default-compare.cpp
index 62d7abb03c71e..00f0323d098c4 100644
--- a/clang/test/SemaCXX/cxx20-default-compare.cpp
+++ b/clang/test/SemaCXX/cxx20-default-compare.cpp
@@ -1,4 +1,5 @@
 // RUN: %clang_cc1 %s -std=c++23 -verify -Wfloat-equal
+
 struct Foo {
   float val;
   bool operator==(const Foo &) const;
@@ -37,4 +38,4 @@ bool operator==(Foo, Foo) = default;  // expected-warning {{comparing floating p
 bool operator==(Y, Y) = default; 
 
 // Declare the defaulted comparsion function as a non-member function. Arguments are passed by value. Arguments look up NS namespace and use template struct.
-bool operator==(Z<X>, Z<X>) = default;
\ No newline at end of file
+bool operator==(Z<X>, Z<X>) = default;



More information about the cfe-commits mailing list