[clang] af91092 - [clang] Do not crash on use of a variadic overloaded operator

via cfe-commits cfe-commits at lists.llvm.org
Fri Aug 4 01:45:00 PDT 2023


Author: Podchishchaeva, Mariya
Date: 2023-08-04T01:44:10-07:00
New Revision: af91092c449d6d4bcf60b0cd233c48cd8a41e0e1

URL: https://github.com/llvm/llvm-project/commit/af91092c449d6d4bcf60b0cd233c48cd8a41e0e1
DIFF: https://github.com/llvm/llvm-project/commit/af91092c449d6d4bcf60b0cd233c48cd8a41e0e1.diff

LOG: [clang] Do not crash on use of a variadic overloaded operator

Just exit instead.
Fixes https://github.com/llvm/llvm-project/issues/42535

Reviewed By: aaron.ballman

Differential Revision: https://reviews.llvm.org/D156244

Added: 
    

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

Removed: 
    


################################################################################
diff  --git a/clang/docs/ReleaseNotes.rst b/clang/docs/ReleaseNotes.rst
index da3cb85dce8e76..a98ad496d22498 100644
--- a/clang/docs/ReleaseNotes.rst
+++ b/clang/docs/ReleaseNotes.rst
@@ -107,6 +107,8 @@ Bug Fixes in This Version
   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
 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

diff  --git a/clang/lib/Sema/SemaOverload.cpp b/clang/lib/Sema/SemaOverload.cpp
index 40a94e13c72950..ad47b81b9dfadf 100644
--- a/clang/lib/Sema/SemaOverload.cpp
+++ b/clang/lib/Sema/SemaOverload.cpp
@@ -9850,7 +9850,7 @@ getImplicitObjectParamType(ASTContext &Context, const FunctionDecl *F) {
 }
 
 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 @@ static bool haveSameParameterTypes(ASTContext &Context, const FunctionDecl *F1,
     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 @@ bool clang::isBetterOverloadCandidate(
     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 @@ ExprResult Sema::CreateOverloadedBinOp(SourceLocation OpLoc,
         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 @@ ExprResult Sema::CreateOverloadedBinOp(SourceLocation OpLoc,
           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],

diff  --git a/clang/test/SemaCXX/overloaded-operator-decl.cpp b/clang/test/SemaCXX/overloaded-operator-decl.cpp
index 777be6c5a0487f..8a76c9251e419a 100644
--- a/clang/test/SemaCXX/overloaded-operator-decl.cpp
+++ b/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 @@ namespace PR14120 {
     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();
+}
+}


        


More information about the cfe-commits mailing list