]> granicus.if.org Git - clang/commitdiff
Mark the lambda function pointer conversion operator as noexcept.
authorAaron Ballman <aaron@aaronballman.com>
Mon, 21 Jan 2019 16:25:08 +0000 (16:25 +0000)
committerAaron Ballman <aaron@aaronballman.com>
Mon, 21 Jan 2019 16:25:08 +0000 (16:25 +0000)
This implements CWG DR 1722 and fixes PR40309. Patch by Ignat Loskutov.

git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@351750 91177308-0d34-0410-b5e6-96231b3b80d8

lib/Sema/SemaLambda.cpp
test/AST/ast-dump-expr.cpp
test/CXX/drs/dr17xx.cpp
test/CXX/expr/expr.prim/expr.prim.lambda/p9.cpp [new file with mode: 0644]
www/cxx_dr_status.html

index 70fcacb157a127cce49f4cd908374550be6b1de2..4ed9fdc359d28a7b156713c6102a0126e575ae66 100644 (file)
@@ -1227,9 +1227,10 @@ static void addFunctionPointerConversion(Sema &S,
   FunctionProtoType::ExtProtoInfo ConvExtInfo(
       S.Context.getDefaultCallingConvention(
       /*IsVariadic=*/false, /*IsCXXMethod=*/true));
-  // The conversion function is always const.
+  // The conversion function is always const and noexcept.
   ConvExtInfo.TypeQuals = Qualifiers();
   ConvExtInfo.TypeQuals.addConst();
+  ConvExtInfo.ExceptionSpec.Type = EST_BasicNoexcept;
   QualType ConvTy =
       S.Context.getFunctionType(PtrToFunctionTy, None, ConvExtInfo);
 
index 915a14bc563971cd50117008ce22f0cd3b017aa0..0c85e2eea2df7fa7ac3980ff846a253c687731f3 100644 (file)
@@ -290,7 +290,7 @@ void PrimaryExpressions(Ts... a) {
   // CHECK-NEXT: Destructor
   // CHECK-NEXT: CXXMethodDecl 0x{{[^ ]*}} <col:6, col:8> col:3 operator() 'auto () const' inline
   // CHECK-NEXT: CompoundStmt
-  // CHECK-NEXT: CXXConversionDecl 0x{{[^ ]*}} <col:3, col:8> col:3 implicit constexpr operator auto (*)() 'auto (*() const)()' inline
+  // CHECK-NEXT: CXXConversionDecl 0x{{[^ ]*}} <col:3, col:8> col:3 implicit constexpr operator auto (*)() 'auto (*() const noexcept)()' inline
   // CHECK-NEXT: CXXMethodDecl 0x{{[^ ]*}} <col:3, col:8> col:3 implicit __invoke 'auto ()' static inline
   // CHECK-NEXT: CompoundStmt 0x{{[^ ]*}} <col:7, col:8>
 
@@ -307,7 +307,7 @@ void PrimaryExpressions(Ts... a) {
   // CHECK-NEXT: CXXMethodDecl 0x{{[^ ]*}} <col:16, col:18> col:3 operator() 'auto (int, ...) const' inline
   // CHECK-NEXT: ParmVarDecl 0x{{[^ ]*}} <col:6, col:10> col:10 a 'int'
   // CHECK-NEXT: CompoundStmt
-  // CHECK-NEXT: CXXConversionDecl 0x{{[^ ]*}} <col:3, col:18> col:3 implicit constexpr operator auto (*)(int, ...) 'auto (*() const)(int, ...)' inline
+  // CHECK-NEXT: CXXConversionDecl 0x{{[^ ]*}} <col:3, col:18> col:3 implicit constexpr operator auto (*)(int, ...) 'auto (*() const noexcept)(int, ...)' inline
   // CHECK-NEXT: CXXMethodDecl 0x{{[^ ]*}} <col:3, col:18> col:3 implicit __invoke 'auto (int, ...)' static inline
   // CHECK-NEXT: ParmVarDecl 0x{{[^ ]*}} <col:6, col:10> col:10 a 'int'
   // CHECK-NEXT: CompoundStmt 0x{{[^ ]*}} <col:17, col:18>
@@ -455,7 +455,7 @@ void PrimaryExpressions(Ts... a) {
   // CHECK-NEXT: Destructor
   // CHECK-NEXT: CXXMethodDecl 0x{{[^ ]*}} <col:8, col:19> col:3 constexpr operator() 'auto () const' inline
   // CHECK-NEXT: CompoundStmt
-  // CHECK-NEXT: CXXConversionDecl 0x{{[^ ]*}} <col:3, col:19> col:3 implicit constexpr operator auto (*)() 'auto (*() const)()' inline
+  // CHECK-NEXT: CXXConversionDecl 0x{{[^ ]*}} <col:3, col:19> col:3 implicit constexpr operator auto (*)() 'auto (*() const noexcept)()' inline
   // CHECK-NEXT: CXXMethodDecl 0x{{[^ ]*}} <col:3, col:19> col:3 implicit __invoke 'auto ()' static inline
   // CHECK-NEXT: CompoundStmt 0x{{[^ ]*}} <col:18, col:19>
 
@@ -471,7 +471,7 @@ void PrimaryExpressions(Ts... a) {
   // CHECK-NEXT: Destructor
   // CHECK-NEXT: CXXMethodDecl 0x{{[^ ]*}} <col:8, col:17> col:3 operator() 'auto ()' inline
   // CHECK-NEXT: CompoundStmt
-  // CHECK-NEXT: CXXConversionDecl 0x{{[^ ]*}} <col:3, col:17> col:3 implicit constexpr operator auto (*)() 'auto (*() const)()' inline
+  // CHECK-NEXT: CXXConversionDecl 0x{{[^ ]*}} <col:3, col:17> col:3 implicit constexpr operator auto (*)() 'auto (*() const noexcept)()' inline
   // CHECK-NEXT: CXXMethodDecl 0x{{[^ ]*}} <col:3, col:17> col:3 implicit __invoke 'auto ()' static inline
   // CHECK-NEXT: CompoundStmt 0x{{[^ ]*}} <col:16, col:17>
 
@@ -487,7 +487,7 @@ void PrimaryExpressions(Ts... a) {
   // CHECK-NEXT: Destructor
   // CHECK-NEXT: CXXMethodDecl 0x{{[^ ]*}} <col:8, col:18> col:3 operator() 'auto () const noexcept' inline
   // CHECK-NEXT: CompoundStmt
-  // CHECK-NEXT: CXXConversionDecl 0x{{[^ ]*}} <col:3, col:18> col:3 implicit constexpr operator auto (*)() noexcept 'auto (*() const)() noexcept' inline
+  // CHECK-NEXT: CXXConversionDecl 0x{{[^ ]*}} <col:3, col:18> col:3 implicit constexpr operator auto (*)() noexcept 'auto (*() const noexcept)() noexcept' inline
   // CHECK-NEXT: CXXMethodDecl 0x{{[^ ]*}} <col:3, col:18> col:3 implicit __invoke 'auto () noexcept' static inline
   // CHECK-NEXT: CompoundStmt 0x{{[^ ]*}} <col:17, col:18>
 
@@ -505,7 +505,7 @@ void PrimaryExpressions(Ts... a) {
   // CHECK-NEXT: CompoundStmt
   // CHECK-NEXT: ReturnStmt 0x{{[^ ]*}} <col:17, col:24>
   // CHECK-NEXT: IntegerLiteral 0x{{[^ ]*}} <col:24> 'int' 0
-  // CHECK-NEXT: CXXConversionDecl 0x{{[^ ]*}} <col:3, col:27> col:3 implicit constexpr operator int (*)() 'auto (*() const)() -> int' inline
+  // CHECK-NEXT: CXXConversionDecl 0x{{[^ ]*}} <col:3, col:27> col:3 implicit constexpr operator int (*)() 'auto (*() const noexcept)() -> int' inline
   // CHECK-NEXT: CXXMethodDecl 0x{{[^ ]*}} <col:3, col:27> col:3 implicit __invoke 'auto () -> int' static inline
   // CHECK-NEXT: CompoundStmt 0x{{[^ ]*}} <col:15, col:27>
   // CHECK-NEXT: ReturnStmt 0x{{[^ ]*}} <col:17, col:24>
@@ -568,4 +568,4 @@ void NonADLCall3() {
   // CHECK: CallExpr 0x{{[^ ]*}} <line:[[@LINE+1]]:{{[^>]+}}> 'void'{{$}}
   f(x);
 }
-} // namespace test_adl_call_three
\ No newline at end of file
+} // namespace test_adl_call_three
index a917412adcbdebb2f097b79304172511b038d7c7..9f67b242710b4e5a99e8f8d01b7934ca3c589d54 100644 (file)
@@ -76,3 +76,15 @@ namespace dr1758 { // dr1758: 3.7
   A a{b};
 #endif
 }
+
+namespace dr1722 { // dr1722: 9.0
+#if __cplusplus >= 201103L
+void f() {
+  const auto lambda = [](int x) { return x + 1; };
+  // Without the DR applied, this static_assert would fail.
+  static_assert(
+      noexcept((int (*)(int))(lambda)),
+      "Lambda-to-function-pointer conversion is expected to be noexcept");
+}
+#endif
+} // namespace dr1722
diff --git a/test/CXX/expr/expr.prim/expr.prim.lambda/p9.cpp b/test/CXX/expr/expr.prim/expr.prim.lambda/p9.cpp
new file mode 100644 (file)
index 0000000..2d3c69f
--- /dev/null
@@ -0,0 +1,8 @@
+// RUN: %clang_cc1 -fsyntax-only -std=c++17 %s -verify
+// expected-no-diagnostics
+
+void test_noexcept() {
+  const auto lambda = [](int x) { return x + 1; };
+  static_assert(noexcept((int (*)(int))(lambda)),
+                "Lambda-to-function-pointer conversion is expected to be noexcept");
+}
index d33234ac064d8c349cfebb1eadf18a35b99918f1..c0f6a9c340e9eeec85bb56a743b961780408db21 100755 (executable)
@@ -10147,7 +10147,7 @@ and <I>POD class</I></td>
     <td><a href="http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_defects.html#1722">1722</a></td>\r
     <td>CD4</td>\r
     <td>Should lambda to function pointer conversion function be <TT>noexcept</TT>?</td>\r
-    <td class="none" align="center">Unknown</td>\r
+    <td class="full" align="center">Clang 9.0</td>\r
   </tr>\r
   <tr class="open" id="1723">\r
     <td><a href="http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_active.html#1723">1723</a></td>\r