[PATCH] D64874: Improve handling of function pointer conversions

Mark de Wever via Phabricator via cfe-commits cfe-commits at lists.llvm.org
Wed Jul 17 11:16:39 PDT 2019


Mordante created this revision.
Mordante added a reviewer: rsmith.
Mordante added a project: clang.

Starting with C++17 the `noexcept` is part of the function signature but a `noexcept` function can be converted to a `noexcept(false)` function. The overload resolution code handles it properly but expression builder doesn't. It causes the following code to trigger and assertion failure:

  struct S {
      int f(void) noexcept { return 110; }
  } s;
  
  template <int(S::*a)(void)> int f10(void) { return (s.*a)(); }
  
  int foo(void)
  {
    return f10<&S::f >();
  }

The fix adds an extra implicit cast when needed. I picked the `CK_NoOp` as `CastKind` since it seems to be the best fit. However I wonder whether it would be better to add a new value `CK_FunctionPointerConversion`.

This fixes bug 40024.


Repository:
  rG LLVM Github Monorepo

https://reviews.llvm.org/D64874

Files:
  clang/lib/Sema/SemaTemplate.cpp
  clang/test/CXX/conv/conv.fctptr/template-noexcept-invalid.cpp
  clang/test/CXX/conv/conv.fctptr/template-noexcept-valid.cpp


Index: clang/test/CXX/conv/conv.fctptr/template-noexcept-valid.cpp
===================================================================
--- /dev/null
+++ clang/test/CXX/conv/conv.fctptr/template-noexcept-valid.cpp
@@ -0,0 +1,20 @@
+// RUN: %clang_cc1 -std=c++11 -fsyntax-only %s
+// RUN: %clang_cc1 -std=c++14 -fsyntax-only %s
+// RUN: %clang_cc1 -std=c++17 -fsyntax-only %s
+// RUN: %clang_cc1 -std=c++2a -fsyntax-only %s
+
+// Starting with C++17 the noexcept is part of the function signature but
+// a noexcept function can be converted to a noexcept(false) function.
+// The tests were added for https://bugs.llvm.org/show_bug.cgi?id=40024
+// Tests the still valid function pointer conversions
+
+struct S {
+  int f(void) noexcept { return 110; }
+} s;
+
+template <int (S::*a)(void)>
+int f10(void) { return (s.*a)(); }
+
+int foo(void) {
+  return f10<&S::f>();
+}
Index: clang/test/CXX/conv/conv.fctptr/template-noexcept-invalid.cpp
===================================================================
--- /dev/null
+++ clang/test/CXX/conv/conv.fctptr/template-noexcept-invalid.cpp
@@ -0,0 +1,22 @@
+// RUN: %clang_cc1 -std=c++11 -fsyntax-only %s
+// RUN: %clang_cc1 -std=c++14 -fsyntax-only %s
+// RUN: not %clang_cc1 -std=c++17 -fsyntax-only %s 2>&1 | FileCheck %s
+// RUN: not %clang_cc1 -std=c++2a -fsyntax-only %s 2>&1 | FileCheck %s
+
+// Starting with C++17 the noexcept is part of the function signature but
+// a noexcept function can be converted to a noexcept(false) function.
+// The tests were added for https://bugs.llvm.org/show_bug.cgi?id=40024
+// Tests the no longer valid function pointer conversions
+
+struct S {
+  int f(void) { return 110; }
+} s;
+
+template <int (S::*a)(void) noexcept>
+int f10(void) { return (s.*a)(); }
+
+int foo(void) {
+  return f10<&S::f>();
+}
+
+// CHECK: error: no matching function for call to 'f10'
Index: clang/lib/Sema/SemaTemplate.cpp
===================================================================
--- clang/lib/Sema/SemaTemplate.cpp
+++ clang/lib/Sema/SemaTemplate.cpp
@@ -6991,6 +6991,14 @@
                                     ObjCLifetimeConversion))
         RefExpr = ImpCastExprToType(RefExpr.get(), ParamType.getUnqualifiedType(), CK_NoOp);
 
+      // Starting with C++17 the noexcept is part of the function signature but
+      // a noexcept function can be converted to a noexcept(false) function.
+      QualType resultTy;
+      if (getLangOpts().CPlusPlus17 &&
+          IsFunctionConversion(((Expr *)RefExpr.get())->getType(),
+                               ParamType.getUnqualifiedType(), resultTy))
+        RefExpr = ImpCastExprToType(RefExpr.get(), resultTy, CK_NoOp);
+
       assert(!RefExpr.isInvalid() &&
              Context.hasSameType(((Expr*) RefExpr.get())->getType(),
                                  ParamType.getUnqualifiedType()));


-------------- next part --------------
A non-text attachment was scrubbed...
Name: D64874.210369.patch
Type: text/x-patch
Size: 2839 bytes
Desc: not available
URL: <http://lists.llvm.org/pipermail/cfe-commits/attachments/20190717/64585db9/attachment-0001.bin>


More information about the cfe-commits mailing list