Fznamznon updated this revision to Diff 546445.
Fznamznon added a comment.

Rebase, add more test cases, fix assertion on variadic functions inside of
`haveSameParameterTypes`


Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D156244/new/

https://reviews.llvm.org/D156244

Files:
  clang/docs/ReleaseNotes.rst
  clang/lib/Sema/SemaOverload.cpp
  clang/test/SemaCXX/overloaded-operator-decl.cpp

Index: clang/test/SemaCXX/overloaded-operator-decl.cpp
===================================================================
--- clang/test/SemaCXX/overloaded-operator-decl.cpp
+++ clang/test/SemaCXX/overloaded-operator-decl.cpp
@@ -1,4 +1,5 @@
 // RUN: %clang_cc1 -fsyntax-only -verify %s 
+// RUN: %clang_cc1 -std=c++20 -fsyntax-only -verify %s
 struct X { 
   X();
   X(int); 
@@ -58,3 +59,67 @@
     A()(i);
   }
 }
+
+namespace GH42535 {
+class E {
+  E& operator=(const E& rhs, ...); // expected-error{{overloaded 'operator=' cannot be variadic}}
+  E& operator+=(const E& rhs, ...); // expected-error{{overloaded 'operator+=' cannot be variadic}}
+
+};
+void operator+(E, ...) {} // expected-error{{overloaded 'operator+' cannot be variadic}}
+void operator-(E, ...) {} // expected-error{{overloaded 'operator-' cannot be variadic}}
+void operator*(E, ...) {} // expected-error{{overloaded 'operator*' cannot be variadic}}
+void operator/(E, ...) {} // expected-error{{overloaded 'operator/' must be a binary operator}}
+void operator/(E, E, ...) {} // expected-error{{overloaded 'operator/' cannot be variadic}}
+void operator%(E, ...) {} // expected-error{{overloaded 'operator%' must be a binary operator}}
+void operator%(E, E, ...) {} // expected-error{{overloaded 'operator%' cannot be variadic}}
+E& operator++(E&, ...); // expected-error{{overloaded 'operator++' cannot be variadic}}
+E& operator--(E&, ...); // expected-error{{overloaded 'operator--' cannot be variadic}}
+bool operator<(const E& lhs, ...); // expected-error{{overloaded 'operator<' must be a binary operator}}
+bool operator<(const E& lhs, const E& rhs, ...); // expected-error{{cannot be variadic}}
+bool operator>(const E& lhs, ...); // expected-error{{overloaded 'operator>' must be a binary operator}}
+bool operator>(const E& lhs, const E& rhs, ...); // expected-error{{cannot be variadic}}
+bool operator>=(const E& lhs, ...); // expected-error{{overloaded 'operator>=' must be a binary operator}}
+bool operator>=(const E& lhs, const E& rhs, ...); // expected-error{{cannot be variadic}}
+bool operator<=(const E& lhs, ...); // expected-error{{overloaded 'operator<=' must be a binary operator}}
+bool operator<=(const E& lhs, const E& rhs, ...); // expected-error{{cannot be variadic}}
+bool operator==(const E& lhs, ...); // expected-error{{overloaded 'operator==' must be a binary operator}}
+bool operator==(const E& lhs, const E& rhs, ...); // expected-error{{cannot be variadic}}
+bool operator!=(const E& lhs, ...); // expected-error{{overloaded 'operator!=' must be a binary operator}}
+bool operator!=(const E& lhs, const E& rhs, ...); // expected-error{{cannot be variadic}}
+bool operator&&(const E& lhs, ...); // expected-error{{overloaded 'operator&&' must be a binary operator}}
+bool operator&&(const E& lhs, const E& rhs, ...); // expected-error{{cannot be variadic}}
+bool operator||(const E& lhs, ...); // expected-error{{overloaded 'operator||' must be a binary operator}}
+bool operator||(const E& lhs, const E& rhs, ...); // expected-error{{cannot be variadic}}
+bool operator>>(const E& lhs, ...); // expected-error{{overloaded 'operator>>' must be a binary operator}}
+bool operator>>(const E& lhs, const E& rhs, ...); // expected-error{{cannot be variadic}}
+bool operator&(const E& lhs, ...); // expected-error{{cannot be variadic}}
+#if __cplusplus >= 202002L
+auto operator<=>(const E& lhs, ...);  // expected-error{{overloaded 'operator<=>' must be a binary operator}}
+#endif
+void d() {
+  E() + E();
+  E() - E();
+  E() * E();
+  E() / E();
+  E() % E();
+  ++E(); // expected-error{{cannot increment value of type 'E'}}
+  --E(); // expected-error{{cannot decrement value of type 'E'}}
+  E() < E();
+  E() > E();
+  E() <= E();
+  E() >= E();
+  E() == E();
+  E() != E();
+#if __cplusplus >= 202002L
+  E() <=> E();
+#endif
+  E e;
+  E e1 = e;
+  e += e1;
+  E() && E();
+  E() || E();
+  E() & E();
+  E() >> E();
+}
+}
Index: clang/lib/Sema/SemaOverload.cpp
===================================================================
--- clang/lib/Sema/SemaOverload.cpp
+++ clang/lib/Sema/SemaOverload.cpp
@@ -9850,7 +9850,7 @@
 }
 
 static bool haveSameParameterTypes(ASTContext &Context, const FunctionDecl *F1,
-                                   const FunctionDecl *F2, unsigned NumParams) {
+                                   const FunctionDecl *F2) {
   if (declaresSameEntity(F1, F2))
     return true;
 
@@ -9863,8 +9863,14 @@
     return F->getParamDecl(I++)->getType();
   };
 
+  unsigned F1NumParams = F1->getNumParams() + isa<CXXMethodDecl>(F1);
+  unsigned F2NumParams = F2->getNumParams() + isa<CXXMethodDecl>(F2);
+
+  if (F1NumParams != F2NumParams)
+    return false;
+
   unsigned I1 = 0, I2 = 0;
-  for (unsigned I = 0; I != NumParams; ++I) {
+  for (unsigned I = 0; I != F1NumParams; ++I) {
     QualType T1 = NextParam(F1, I1, I == 0);
     QualType T2 = NextParam(F2, I2, I == 0);
     assert(!T1.isNull() && !T2.isNull() && "Unexpected null param types");
@@ -10032,8 +10038,7 @@
     case ImplicitConversionSequence::Worse:
       if (Cand1.Function && Cand2.Function &&
           Cand1.isReversed() != Cand2.isReversed() &&
-          haveSameParameterTypes(S.Context, Cand1.Function, Cand2.Function,
-                                 NumArgs)) {
+          haveSameParameterTypes(S.Context, Cand1.Function, Cand2.Function)) {
         // Work around large-scale breakage caused by considering reversed
         // forms of operator== in C++20:
         //
@@ -13997,6 +14002,10 @@
         std::swap(Args[0], Args[1]);
 
       if (FnDecl) {
+
+        if (FnDecl->isInvalidDecl())
+          return ExprError();
+
         Expr *Base = nullptr;
         // We matched an overloaded operator. Build a call to that
         // operator.
@@ -14029,7 +14038,7 @@
           llvm::SmallVector<FunctionDecl*, 4> AmbiguousWith;
           for (OverloadCandidate &Cand : CandidateSet) {
             if (Cand.Viable && Cand.Function && Cand.isReversed() &&
-                haveSameParameterTypes(Context, Cand.Function, FnDecl, 2)) {
+                haveSameParameterTypes(Context, Cand.Function, FnDecl)) {
               for (unsigned ArgIdx = 0; ArgIdx < 2; ++ArgIdx) {
                 if (CompareImplicitConversionSequences(
                         *this, OpLoc, Cand.Conversions[ArgIdx],
Index: clang/docs/ReleaseNotes.rst
===================================================================
--- clang/docs/ReleaseNotes.rst
+++ clang/docs/ReleaseNotes.rst
@@ -104,6 +104,8 @@
   instantiated in one module and whose definition is instantiated in another
   module may end up with members associated with the wrong declaration of the
   class, which can result in miscompiles in some cases.
+- Fix crash on use of a variadic overloaded operator.
+  (`#42535 <https://github.com/llvm/llvm-project/issues/42535>_`)
 
 Bug Fixes to Compiler Builtins
 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
_______________________________________________
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to