[clang] [Sema] Fix an out-of-bounds crash when diagnosing bad conversion for a function with a parameter pack. (PR #92721)

Haojian Wu via cfe-commits cfe-commits at lists.llvm.org
Mon May 27 02:44:42 PDT 2024


https://github.com/hokein updated https://github.com/llvm/llvm-project/pull/92721

>From e2dc2cecee5891b88ff4c2e473220cc9fd36df34 Mon Sep 17 00:00:00 2001
From: Haojian Wu <hokein.wu at gmail.com>
Date: Sun, 19 May 2024 22:47:14 +0200
Subject: [PATCH 1/2] [Sema] Fix an out-of-bounds crash when diagnosing bad
 conversion for a function with a parameter pack.

---
 clang/docs/ReleaseNotes.rst                   |  2 ++
 clang/lib/Sema/SemaOverload.cpp               | 10 ++++++++--
 clang/test/Misc/diag-overload-cand-ranges.cpp |  8 ++++++++
 3 files changed, 18 insertions(+), 2 deletions(-)

diff --git a/clang/docs/ReleaseNotes.rst b/clang/docs/ReleaseNotes.rst
index 825e91876ffce..9fd8661949113 100644
--- a/clang/docs/ReleaseNotes.rst
+++ b/clang/docs/ReleaseNotes.rst
@@ -629,6 +629,8 @@ Bug Fixes in This Version
 - ``__is_array`` and ``__is_bounded_array`` no longer return ``true`` for
   zero-sized arrays. Fixes (#GH54705).
 
+- Fix an out-of-bounds crash when diagnosing bad conversion for a function with a parameter pack. 
+
 Bug Fixes to Compiler Builtins
 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
diff --git a/clang/lib/Sema/SemaOverload.cpp b/clang/lib/Sema/SemaOverload.cpp
index 0c89fca8d38eb..a9603e63336ac 100644
--- a/clang/lib/Sema/SemaOverload.cpp
+++ b/clang/lib/Sema/SemaOverload.cpp
@@ -11301,8 +11301,14 @@ static void DiagnoseBadConversion(Sema &S, OverloadCandidate *Cand,
   Expr *FromExpr = Conv.Bad.FromExpr;
   QualType FromTy = Conv.Bad.getFromType();
   QualType ToTy = Conv.Bad.getToType();
-  SourceRange ToParamRange =
-      !isObjectArgument ? Fn->getParamDecl(I)->getSourceRange() : SourceRange();
+  SourceRange ToParamRange;
+  if (!isObjectArgument) {
+    if (I < Fn->getNumParams())
+      ToParamRange = Fn->getParamDecl(I)->getSourceRange();
+    else
+      // parameter pack case.
+      ToParamRange = Fn->parameters().back()->getSourceRange();
+  }
 
   if (FromTy == S.Context.OverloadTy) {
     assert(FromExpr && "overload set argument came from implicit argument?");
diff --git a/clang/test/Misc/diag-overload-cand-ranges.cpp b/clang/test/Misc/diag-overload-cand-ranges.cpp
index 080ca484d4b74..06d638d9b719c 100644
--- a/clang/test/Misc/diag-overload-cand-ranges.cpp
+++ b/clang/test/Misc/diag-overload-cand-ranges.cpp
@@ -70,3 +70,11 @@ template <short T> class Type1 {};
 template <short T> void Function1(int zz, Type1<T> &x, int ww) {}
 
 void Function() { Function1(33, Type1<-42>(), 66); }
+
+// CHECK:      error: no matching function for call to 'b'
+// CHECK:      :{[[@LINE+1]]:41-[[@LINE+1]]:45}: note: {{.*}} no known conversion from 'int' to 'ForwardClass' for 3rd argument
+template <class T, class...U> void b(T, U...);
+class ForwardClass;
+void NoCrash() {
+  b<int, int, ForwardClass>(1, 1, 0);
+}

>From 4358b43e283cb13dbe4d32fcce3c68b6da15b12a Mon Sep 17 00:00:00 2001
From: Haojian Wu <hokein.wu at gmail.com>
Date: Mon, 27 May 2024 09:58:04 +0200
Subject: [PATCH 2/2] review comments

Diagnose on the first parameter pack.
---
 clang/lib/Sema/SemaOverload.cpp               | 12 +++++++++---
 clang/test/Misc/diag-overload-cand-ranges.cpp |  6 +++++-
 2 files changed, 14 insertions(+), 4 deletions(-)

diff --git a/clang/lib/Sema/SemaOverload.cpp b/clang/lib/Sema/SemaOverload.cpp
index a9603e63336ac..f9a5032e10c2d 100644
--- a/clang/lib/Sema/SemaOverload.cpp
+++ b/clang/lib/Sema/SemaOverload.cpp
@@ -11305,9 +11305,15 @@ static void DiagnoseBadConversion(Sema &S, OverloadCandidate *Cand,
   if (!isObjectArgument) {
     if (I < Fn->getNumParams())
       ToParamRange = Fn->getParamDecl(I)->getSourceRange();
-    else
-      // parameter pack case.
-      ToParamRange = Fn->parameters().back()->getSourceRange();
+    else {
+      // For the parameter pack case, diagnose on the first pack.
+      for (const auto* ParamDecl : Fn->parameters()) {
+        if (ParamDecl->isParameterPack()) {
+          ToParamRange = ParamDecl->getSourceRange();
+          break;
+        }
+      }
+    }
   }
 
   if (FromTy == S.Context.OverloadTy) {
diff --git a/clang/test/Misc/diag-overload-cand-ranges.cpp b/clang/test/Misc/diag-overload-cand-ranges.cpp
index 06d638d9b719c..a70ba0d1b1f77 100644
--- a/clang/test/Misc/diag-overload-cand-ranges.cpp
+++ b/clang/test/Misc/diag-overload-cand-ranges.cpp
@@ -1,4 +1,4 @@
-// RUN: not %clang_cc1 -fsyntax-only -fdiagnostics-print-source-range-info %s 2>&1 | FileCheck %s --strict-whitespace
+// RUN: not %clang_cc1 -fsyntax-only -fdiagnostics-print-source-range-info -std=c++20 %s 2>&1 | FileCheck %s --strict-whitespace
 // CHECK:      error: no matching function
 template <typename T> struct mcdata {
   typedef int result_type;
@@ -74,7 +74,11 @@ void Function() { Function1(33, Type1<-42>(), 66); }
 // CHECK:      error: no matching function for call to 'b'
 // CHECK:      :{[[@LINE+1]]:41-[[@LINE+1]]:45}: note: {{.*}} no known conversion from 'int' to 'ForwardClass' for 3rd argument
 template <class T, class...U> void b(T, U...);
+// CHECK:      error: no matching function for call to 'abbreviated_func'
+// CHECK:      :{[[@LINE+1]]:23-[[@LINE+1]]:30}: note: {{.*}} no known conversion from 'int' to 'ForwardClass' for 3rd argument
+void abbreviated_func(auto..., auto...); // diagnose on the first parameter
 class ForwardClass;
 void NoCrash() {
   b<int, int, ForwardClass>(1, 1, 0);
+  abbreviated_func<int, int, ForwardClass>(1, 1, 0);
 }



More information about the cfe-commits mailing list