[PATCH] D55097: [constexpr][c++2a] Try-catch blocks in constexpr functions

2018-12-10 Thread Bruno Cardoso Lopes via Phabricator via cfe-commits
This revision was automatically updated to reflect the committed changes.
Closed by commit rL348789: [constexpr][c++2a] Try-catch blocks in constexpr 
functions (authored by bruno, committed by ).
Herald added a subscriber: llvm-commits.

Changed prior to commit:
  https://reviews.llvm.org/D55097?vs=177367=177564#toc

Repository:
  rL LLVM

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

https://reviews.llvm.org/D55097

Files:
  cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td
  cfe/trunk/lib/AST/ExprConstant.cpp
  cfe/trunk/lib/Sema/SemaDeclCXX.cpp
  cfe/trunk/test/CXX/dcl.dcl/dcl.spec/dcl.constexpr/p3.cpp
  cfe/trunk/test/CXX/dcl.dcl/dcl.spec/dcl.constexpr/p4.cpp
  cfe/trunk/test/CXX/drs/dr6xx.cpp
  cfe/trunk/www/cxx_status.html

Index: cfe/trunk/www/cxx_status.html
===
--- cfe/trunk/www/cxx_status.html
+++ cfe/trunk/www/cxx_status.html
@@ -953,13 +953,15 @@
 
   Relaxations of constexpr restrictions
   http://wg21.link/p1064r0;>P1064R0
-  No
+  No
 

 http://wg21.link/p1002r1;>P1002R1
+SVN
   
   
 http://wg21.link/p1327r1;>P1327R1
+No
   
   
 http://wg21.link/p1330r0;>P1330R0
Index: cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td
===
--- cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td
+++ cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td
@@ -2357,6 +2357,13 @@
   "use of this statement in a constexpr %select{function|constructor}0 "
   "is incompatible with C++ standards before C++14">,
   InGroup, DefaultIgnore;
+def ext_constexpr_body_invalid_stmt_cxx2a : ExtWarn<
+  "use of this statement in a constexpr %select{function|constructor}0 "
+  "is a C++2a extension">, InGroup;
+def warn_cxx17_compat_constexpr_body_invalid_stmt : Warning<
+  "use of this statement in a constexpr %select{function|constructor}0 "
+  "is incompatible with C++ standards before C++2a">,
+  InGroup, DefaultIgnore;
 def ext_constexpr_type_definition : ExtWarn<
   "type definition in a constexpr %select{function|constructor}0 "
   "is a C++14 extension">, InGroup;
@@ -2409,6 +2416,16 @@
   "previous return statement is here">;
 def err_constexpr_function_try_block : Error<
   "function try block not allowed in constexpr %select{function|constructor}0">;
+
+// c++2a function try blocks in constexpr
+def ext_constexpr_function_try_block_cxx2a : ExtWarn<
+  "function try block in constexpr %select{function|constructor}0 is "
+  "a C++2a extension">, InGroup;
+def warn_cxx17_compat_constexpr_function_try_block : Warning<
+  "function try block in constexpr %select{function|constructor}0 is "
+  "incompatible with C++ standards before C++2a">,
+  InGroup, DefaultIgnore;
+
 def err_constexpr_union_ctor_no_init : Error<
   "constexpr union constructor does not initialize any member">;
 def err_constexpr_ctor_missing_init : Error<
Index: cfe/trunk/test/CXX/dcl.dcl/dcl.spec/dcl.constexpr/p4.cpp
===
--- cfe/trunk/test/CXX/dcl.dcl/dcl.spec/dcl.constexpr/p4.cpp
+++ cfe/trunk/test/CXX/dcl.dcl/dcl.spec/dcl.constexpr/p4.cpp
@@ -1,5 +1,6 @@
-// RUN: %clang_cc1 -verify -std=c++11 -fcxx-exceptions -Werror=c++1y-extensions %s
-// RUN: %clang_cc1 -verify -std=c++1y -fcxx-exceptions -DCXX1Y %s
+// RUN: %clang_cc1 -verify -std=c++11 -fcxx-exceptions -Werror=c++1y-extensions -Werror=c++2a-extensions %s
+// RUN: %clang_cc1 -verify -std=c++1y -fcxx-exceptions -DCXX1Y -Werror=c++2a-extensions %s
+// RUN: %clang_cc1 -verify -std=c++2a -fcxx-exceptions -DCXX1Y -DCXX2A %s
 
 namespace N {
   typedef char C;
@@ -49,8 +50,14 @@
 // - its function-body shall not be a function-try-block;
 struct U {
   constexpr U()
-try // expected-error {{function try block not allowed in constexpr constructor}}
+try
+#ifndef CXX2A
+  // expected-error@-2 {{function try block in constexpr constructor is a C++2a extension}}
+#endif
 : u() {
+#ifndef CXX1Y
+  // expected-error@-2 {{use of this statement in a constexpr constructor is a C++14 extension}}
+#endif
   } catch (...) {
 throw;
   }
Index: cfe/trunk/test/CXX/dcl.dcl/dcl.spec/dcl.constexpr/p3.cpp
===
--- cfe/trunk/test/CXX/dcl.dcl/dcl.spec/dcl.constexpr/p3.cpp
+++ cfe/trunk/test/CXX/dcl.dcl/dcl.spec/dcl.constexpr/p3.cpp
@@ -1,5 +1,6 @@
-// RUN: %clang_cc1 -verify -fcxx-exceptions -triple=x86_64-linux-gnu -std=c++11 -Werror=c++1y-extensions %s
-// RUN: %clang_cc1 -verify -fcxx-exceptions -triple=x86_64-linux-gnu -std=c++1y -DCXX1Y %s
+// RUN: %clang_cc1 -verify -fcxx-exceptions -triple=x86_64-linux-gnu -std=c++11 -Werror=c++1y-extensions -Werror=c++2a-extensions %s
+// RUN: %clang_cc1 -verify -fcxx-exceptions -triple=x86_64-linux-gnu -std=c++1y -DCXX1Y -Werror=c++2a-extensions %s
+// RUN: %clang_cc1 -verify -fcxx-exceptions 

[PATCH] D55097: [constexpr][c++2a] Try-catch blocks in constexpr functions

2018-12-08 Thread Aaron Ballman via Phabricator via cfe-commits
aaron.ballman accepted this revision.
aaron.ballman added a comment.
This revision is now accepted and ready to land.

LGTM aside from a few other small nits.




Comment at: lib/Sema/SemaDeclCXX.cpp:1904
+  case Stmt::CXXTryStmtClass:
+if (!Cxx2aLoc.isValid())
+  Cxx2aLoc = S->getBeginLoc();

`Cxx2aLoc.isInvalid()`



Comment at: lib/Sema/SemaDeclCXX.cpp:1956
+//
+// In C++2a lifts this restriction, as long as inner statements do also
+// apply to general constexpr rules.

This restriction is lifted in C++2a, as long as inner statements also apply the 
general constexpr rules.


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

https://reviews.llvm.org/D55097



___
cfe-commits mailing list
cfe-commits@lists.llvm.org
http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D55097: [constexpr][c++2a] Try-catch blocks in constexpr functions

2018-12-07 Thread Bruno Cardoso Lopes via Phabricator via cfe-commits
bruno updated this revision to Diff 177367.
bruno marked an inline comment as done.
bruno added a comment.

Address @aaron.ballman and @erik.pilkington reviews.


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

https://reviews.llvm.org/D55097

Files:
  include/clang/Basic/DiagnosticSemaKinds.td
  lib/AST/ExprConstant.cpp
  lib/Sema/SemaDeclCXX.cpp
  test/CXX/dcl.dcl/dcl.spec/dcl.constexpr/p3.cpp
  test/CXX/dcl.dcl/dcl.spec/dcl.constexpr/p4.cpp
  test/CXX/drs/dr6xx.cpp
  www/cxx_status.html

Index: www/cxx_status.html
===
--- www/cxx_status.html
+++ www/cxx_status.html
@@ -953,13 +953,15 @@
 
   Relaxations of constexpr restrictions
   http://wg21.link/p1064r0;>P1064R0
-  No
+  No
 

 http://wg21.link/p1002r1;>P1002R1
+SVN
   
   
 http://wg21.link/p1327r1;>P1327R1
+No
   
   
 http://wg21.link/p1330r0;>P1330R0
Index: test/CXX/drs/dr6xx.cpp
===
--- test/CXX/drs/dr6xx.cpp
+++ test/CXX/drs/dr6xx.cpp
@@ -492,7 +492,13 @@
   struct C {
 constexpr C(NonLiteral);
 constexpr C(NonLiteral, int) {} // expected-error {{not a literal type}}
-constexpr C() try {} catch (...) {} // expected-error {{function try block}}
+constexpr C() try {} catch (...) {}
+#if __cplusplus <= 201703L
+// expected-error@-2 {{function try block in constexpr constructor is a C++2a extension}}
+#endif
+#if __cplusplus < 201402L
+// expected-error@-5 {{use of this statement in a constexpr constructor is a C++14 extension}}
+#endif
   };
 
   struct D {
Index: test/CXX/dcl.dcl/dcl.spec/dcl.constexpr/p4.cpp
===
--- test/CXX/dcl.dcl/dcl.spec/dcl.constexpr/p4.cpp
+++ test/CXX/dcl.dcl/dcl.spec/dcl.constexpr/p4.cpp
@@ -1,5 +1,6 @@
-// RUN: %clang_cc1 -verify -std=c++11 -fcxx-exceptions -Werror=c++1y-extensions %s
-// RUN: %clang_cc1 -verify -std=c++1y -fcxx-exceptions -DCXX1Y %s
+// RUN: %clang_cc1 -verify -std=c++11 -fcxx-exceptions -Werror=c++1y-extensions -Werror=c++2a-extensions %s
+// RUN: %clang_cc1 -verify -std=c++1y -fcxx-exceptions -DCXX1Y -Werror=c++2a-extensions %s
+// RUN: %clang_cc1 -verify -std=c++2a -fcxx-exceptions -DCXX1Y -DCXX2A %s
 
 namespace N {
   typedef char C;
@@ -49,8 +50,14 @@
 // - its function-body shall not be a function-try-block;
 struct U {
   constexpr U()
-try // expected-error {{function try block not allowed in constexpr constructor}}
+try
+#ifndef CXX2A
+  // expected-error@-2 {{function try block in constexpr constructor is a C++2a extension}}
+#endif
 : u() {
+#ifndef CXX1Y
+  // expected-error@-2 {{use of this statement in a constexpr constructor is a C++14 extension}}
+#endif
   } catch (...) {
 throw;
   }
Index: test/CXX/dcl.dcl/dcl.spec/dcl.constexpr/p3.cpp
===
--- test/CXX/dcl.dcl/dcl.spec/dcl.constexpr/p3.cpp
+++ test/CXX/dcl.dcl/dcl.spec/dcl.constexpr/p3.cpp
@@ -1,5 +1,6 @@
-// RUN: %clang_cc1 -verify -fcxx-exceptions -triple=x86_64-linux-gnu -std=c++11 -Werror=c++1y-extensions %s
-// RUN: %clang_cc1 -verify -fcxx-exceptions -triple=x86_64-linux-gnu -std=c++1y -DCXX1Y %s
+// RUN: %clang_cc1 -verify -fcxx-exceptions -triple=x86_64-linux-gnu -std=c++11 -Werror=c++1y-extensions -Werror=c++2a-extensions %s
+// RUN: %clang_cc1 -verify -fcxx-exceptions -triple=x86_64-linux-gnu -std=c++1y -DCXX1Y -Werror=c++2a-extensions %s
+// RUN: %clang_cc1 -verify -fcxx-exceptions -triple=x86_64-linux-gnu -std=c++2a -DCXX1Y -DCXX2A %s
 
 namespace N {
   typedef char C;
@@ -78,7 +79,12 @@
 };
 struct T3 {
   constexpr T3 =(const T3&) const = default;
-  // expected-error@-1 {{an explicitly-defaulted copy assignment operator may not have 'const' or 'volatile' qualifiers}}
+#ifndef CXX2A
+  // expected-error@-2 {{an explicitly-defaulted copy assignment operator may not have 'const' or 'volatile' qualifiers}}
+#else
+  // expected-warning@-4 {{explicitly defaulted copy assignment operator is implicitly deleted}}
+  // expected-note@-5 {{function is implicitly deleted because its declared type does not match the type of an implicit copy assignment operator}}
+#endif
 };
 #endif
 struct U {
@@ -129,9 +135,22 @@
 x:
   return 0;
 }
+constexpr int DisallowedStmtsCXX1Y_2_1() {
+  try {
+return 0;
+  } catch (...) {
+  merp: goto merp; // expected-error {{statement not allowed in constexpr function}}
+  }
+}
 constexpr int DisallowedStmtsCXX1Y_3() {
   //  - a try-block,
-  try {} catch (...) {} // expected-error {{statement not allowed in constexpr function}}
+  try {} catch (...) {}
+#ifndef CXX2A
+  // expected-error@-2 {{use of this statement in a constexpr function is a C++2a extension}}
+#ifndef CXX1Y
+  // expected-error@-4 {{use of this statement in a constexpr function is a C++14 extension}}
+#endif
+#endif
   return 0;
 

[PATCH] D55097: [constexpr][c++2a] Try-catch blocks in constexpr functions

2018-12-07 Thread Aaron Ballman via Phabricator via cfe-commits
aaron.ballman added a comment.

Some minor nits from the peanut gallery.




Comment at: lib/AST/ExprConstant.cpp:4278
+  case Stmt::CXXTryStmtClass:
+// Evaluate try blocks by evaluating all sub statements
+return EvaluateStmt(Result, Info, cast(S)->getTryBlock(), 
Case);

Missing full stop.



Comment at: lib/Sema/SemaDeclCXX.cpp:1906
+  Cxx2aLoc = S->getBeginLoc();
+for (Stmt *SubStmt : S->children())
+  if (SubStmt &&

I'd appreciate curly braces here, even though they're not strictly required by 
the coding standard. ;-)



Comment at: lib/Sema/SemaDeclCXX.cpp:1971
+  SourceLocation Cxx1yLoc, Cxx2aLoc;
+  for (Stmt *SubStmt : Body->children())
+if (SubStmt &&

Likewise here.


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

https://reviews.llvm.org/D55097



___
cfe-commits mailing list
cfe-commits@lists.llvm.org
http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D55097: [constexpr][c++2a] Try-catch blocks in constexpr functions

2018-12-07 Thread Erik Pilkington via Phabricator via cfe-commits
erik.pilkington added a comment.

LGTM, but you should probably let @rsmith have the final word!




Comment at: lib/Sema/SemaDeclCXX.cpp:1916-1919
+for (Stmt *SubStmt : S->children())
+  if (SubStmt &&
+  !CheckConstexprFunctionStmt(SemaRef, Dcl, SubStmt, ReturnStmts,
+  Cxx1yLoc, Cxx2aLoc))

Might be clearer to just write `if (!CheckConstexprFunctionStmt(SemaRef, Dcl, 
cast(SubStmt)->getHandlerBlock()))`, rather than looping over 1 
statement. Could you also add that example I posted as a testcase for this?


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

https://reviews.llvm.org/D55097



___
cfe-commits mailing list
cfe-commits@lists.llvm.org
http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D55097: [constexpr][c++2a] Try-catch blocks in constexpr functions

2018-12-04 Thread Bruno Cardoso Lopes via Phabricator via cfe-commits
bruno updated this revision to Diff 176733.
bruno added a comment.

Update patch after @erik.pilkington review!


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

https://reviews.llvm.org/D55097

Files:
  include/clang/Basic/DiagnosticSemaKinds.td
  lib/AST/ExprConstant.cpp
  lib/Sema/SemaDeclCXX.cpp
  test/CXX/dcl.dcl/dcl.spec/dcl.constexpr/p3.cpp
  test/CXX/dcl.dcl/dcl.spec/dcl.constexpr/p4.cpp
  test/CXX/drs/dr6xx.cpp
  www/cxx_status.html

Index: www/cxx_status.html
===
--- www/cxx_status.html
+++ www/cxx_status.html
@@ -953,13 +953,15 @@
 
   Relaxations of constexpr restrictions
   http://wg21.link/p1064r0;>P1064R0
-  No
+  No
 

 http://wg21.link/p1002r1;>P1002R1
+SVN
   
   
 http://wg21.link/p1327r1;>P1327R1
+No
   
   
 http://wg21.link/p1330r0;>P1330R0
Index: test/CXX/drs/dr6xx.cpp
===
--- test/CXX/drs/dr6xx.cpp
+++ test/CXX/drs/dr6xx.cpp
@@ -492,7 +492,13 @@
   struct C {
 constexpr C(NonLiteral);
 constexpr C(NonLiteral, int) {} // expected-error {{not a literal type}}
-constexpr C() try {} catch (...) {} // expected-error {{function try block}}
+constexpr C() try {} catch (...) {}
+#if __cplusplus <= 201703L
+// expected-error@-2 {{function try block in constexpr constructor is a C++2a extension}}
+#endif
+#if __cplusplus < 201402L
+// expected-error@-5 {{use of this statement in a constexpr constructor is a C++14 extension}}
+#endif
   };
 
   struct D {
Index: test/CXX/dcl.dcl/dcl.spec/dcl.constexpr/p4.cpp
===
--- test/CXX/dcl.dcl/dcl.spec/dcl.constexpr/p4.cpp
+++ test/CXX/dcl.dcl/dcl.spec/dcl.constexpr/p4.cpp
@@ -1,5 +1,6 @@
-// RUN: %clang_cc1 -verify -std=c++11 -fcxx-exceptions -Werror=c++1y-extensions %s
-// RUN: %clang_cc1 -verify -std=c++1y -fcxx-exceptions -DCXX1Y %s
+// RUN: %clang_cc1 -verify -std=c++11 -fcxx-exceptions -Werror=c++1y-extensions -Werror=c++2a-extensions %s
+// RUN: %clang_cc1 -verify -std=c++1y -fcxx-exceptions -DCXX1Y -Werror=c++2a-extensions %s
+// RUN: %clang_cc1 -verify -std=c++2a -fcxx-exceptions -DCXX1Y -DCXX2A %s
 
 namespace N {
   typedef char C;
@@ -49,8 +50,14 @@
 // - its function-body shall not be a function-try-block;
 struct U {
   constexpr U()
-try // expected-error {{function try block not allowed in constexpr constructor}}
+try
+#ifndef CXX2A
+  // expected-error@-2 {{function try block in constexpr constructor is a C++2a extension}}
+#endif
 : u() {
+#ifndef CXX1Y
+  // expected-error@-2 {{use of this statement in a constexpr constructor is a C++14 extension}}
+#endif
   } catch (...) {
 throw;
   }
Index: test/CXX/dcl.dcl/dcl.spec/dcl.constexpr/p3.cpp
===
--- test/CXX/dcl.dcl/dcl.spec/dcl.constexpr/p3.cpp
+++ test/CXX/dcl.dcl/dcl.spec/dcl.constexpr/p3.cpp
@@ -1,5 +1,6 @@
-// RUN: %clang_cc1 -verify -fcxx-exceptions -triple=x86_64-linux-gnu -std=c++11 -Werror=c++1y-extensions %s
-// RUN: %clang_cc1 -verify -fcxx-exceptions -triple=x86_64-linux-gnu -std=c++1y -DCXX1Y %s
+// RUN: %clang_cc1 -verify -fcxx-exceptions -triple=x86_64-linux-gnu -std=c++11 -Werror=c++1y-extensions -Werror=c++2a-extensions %s
+// RUN: %clang_cc1 -verify -fcxx-exceptions -triple=x86_64-linux-gnu -std=c++1y -DCXX1Y -Werror=c++2a-extensions %s
+// RUN: %clang_cc1 -verify -fcxx-exceptions -triple=x86_64-linux-gnu -std=c++2a -DCXX1Y -DCXX2A %s
 
 namespace N {
   typedef char C;
@@ -78,7 +79,12 @@
 };
 struct T3 {
   constexpr T3 =(const T3&) const = default;
-  // expected-error@-1 {{an explicitly-defaulted copy assignment operator may not have 'const' or 'volatile' qualifiers}}
+#ifndef CXX2A
+  // expected-error@-2 {{an explicitly-defaulted copy assignment operator may not have 'const' or 'volatile' qualifiers}}
+#else
+  // expected-warning@-4 {{explicitly defaulted copy assignment operator is implicitly deleted}}
+  // expected-note@-5 {{function is implicitly deleted because its declared type does not match the type of an implicit copy assignment operator}}
+#endif
 };
 #endif
 struct U {
@@ -131,7 +137,13 @@
 }
 constexpr int DisallowedStmtsCXX1Y_3() {
   //  - a try-block,
-  try {} catch (...) {} // expected-error {{statement not allowed in constexpr function}}
+  try {} catch (...) {}
+#ifndef CXX2A
+  // expected-error@-2 {{use of this statement in a constexpr function is a C++2a extension}}
+#ifndef CXX1Y
+  // expected-error@-4 {{use of this statement in a constexpr function is a C++14 extension}}
+#endif
+#endif
   return 0;
 }
 constexpr int DisallowedStmtsCXX1Y_4() {
Index: lib/Sema/SemaDeclCXX.cpp
===
--- lib/Sema/SemaDeclCXX.cpp
+++ lib/Sema/SemaDeclCXX.cpp
@@ -1803,7 +1803,7 @@
 static bool
 

[PATCH] D55097: [constexpr][c++2a] Try-catch blocks in constexpr functions

2018-12-04 Thread Erik Pilkington via Phabricator via cfe-commits
erik.pilkington added a comment.

Hi Bruno, thanks for working on this!




Comment at: include/clang/Basic/DiagnosticSemaKinds.td:2370
+  "use of this statement in a constexpr %select{function|constructor}0 "
+  "is incompatible with C++ standards before C++20">,
+  InGroup, DefaultIgnore;

I guess this should technically be C++2a



Comment at: include/clang/Basic/DiagnosticSemaKinds.td:2431
+  "function try block in constexpr %select{function|constructor}0 is "
+  "incompatible with C++ standards before C++20">,
+  InGroup, DefaultIgnore;

(ditto)



Comment at: lib/Sema/SemaDeclCXX.cpp:1913-1916
+  case Stmt::CXXCatchStmtClass:
+// In case we got a valid constexpr try block, the catch block can be
+// ignored since it will never be evaluated in a constexpr context.
+return true;

I think we still need to check out the catch stmt (even if it'll never be 
evaluated) to make sure that it doesn't have any prohibited statements. i.e., 
we should error here:
```
constexpr int f() { 
  try { return 0; }
  catch (...) {
merp: goto merp;
  }
}
```
But I believe that this patch will accept this.


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

https://reviews.llvm.org/D55097



___
cfe-commits mailing list
cfe-commits@lists.llvm.org
http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D55097: [constexpr][c++2a] Try-catch blocks in constexpr functions

2018-12-04 Thread Bruno Cardoso Lopes via Phabricator via cfe-commits
bruno updated this revision to Diff 176559.
bruno added a comment.

Address @rsmith comments


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

https://reviews.llvm.org/D55097

Files:
  include/clang/Basic/DiagnosticSemaKinds.td
  lib/AST/ExprConstant.cpp
  lib/Sema/SemaDeclCXX.cpp
  test/CXX/dcl.dcl/dcl.spec/dcl.constexpr/p3.cpp
  test/CXX/dcl.dcl/dcl.spec/dcl.constexpr/p4.cpp
  test/CXX/drs/dr6xx.cpp
  www/cxx_status.html

Index: www/cxx_status.html
===
--- www/cxx_status.html
+++ www/cxx_status.html
@@ -953,13 +953,15 @@
 
   Relaxations of constexpr restrictions
   http://wg21.link/p1064r0;>P1064R0
-  No
+  No
 

 http://wg21.link/p1002r1;>P1002R1
+SVN
   
   
 http://wg21.link/p1327r1;>P1327R1
+No
   
   
 http://wg21.link/p1330r0;>P1330R0
Index: test/CXX/drs/dr6xx.cpp
===
--- test/CXX/drs/dr6xx.cpp
+++ test/CXX/drs/dr6xx.cpp
@@ -492,7 +492,13 @@
   struct C {
 constexpr C(NonLiteral);
 constexpr C(NonLiteral, int) {} // expected-error {{not a literal type}}
-constexpr C() try {} catch (...) {} // expected-error {{function try block}}
+constexpr C() try {} catch (...) {}
+#if __cplusplus <= 201703L
+// expected-error@-2 {{function try block in constexpr constructor is a C++2a extension}}
+#endif
+#if __cplusplus < 201402L
+// expected-error@-5 {{use of this statement in a constexpr constructor is a C++14 extension}}
+#endif
   };
 
   struct D {
Index: test/CXX/dcl.dcl/dcl.spec/dcl.constexpr/p4.cpp
===
--- test/CXX/dcl.dcl/dcl.spec/dcl.constexpr/p4.cpp
+++ test/CXX/dcl.dcl/dcl.spec/dcl.constexpr/p4.cpp
@@ -1,5 +1,6 @@
-// RUN: %clang_cc1 -verify -std=c++11 -fcxx-exceptions -Werror=c++1y-extensions %s
-// RUN: %clang_cc1 -verify -std=c++1y -fcxx-exceptions -DCXX1Y %s
+// RUN: %clang_cc1 -verify -std=c++11 -fcxx-exceptions -Werror=c++1y-extensions -Werror=c++2a-extensions %s
+// RUN: %clang_cc1 -verify -std=c++1y -fcxx-exceptions -DCXX1Y -Werror=c++2a-extensions %s
+// RUN: %clang_cc1 -verify -std=c++2a -fcxx-exceptions -DCXX1Y -DCXX2A %s
 
 namespace N {
   typedef char C;
@@ -49,8 +50,14 @@
 // - its function-body shall not be a function-try-block;
 struct U {
   constexpr U()
-try // expected-error {{function try block not allowed in constexpr constructor}}
+try
+#ifndef CXX2A
+  // expected-error@-2 {{function try block in constexpr constructor is a C++2a extension}}
+#endif
 : u() {
+#ifndef CXX1Y
+  // expected-error@-2 {{use of this statement in a constexpr constructor is a C++14 extension}}
+#endif
   } catch (...) {
 throw;
   }
Index: test/CXX/dcl.dcl/dcl.spec/dcl.constexpr/p3.cpp
===
--- test/CXX/dcl.dcl/dcl.spec/dcl.constexpr/p3.cpp
+++ test/CXX/dcl.dcl/dcl.spec/dcl.constexpr/p3.cpp
@@ -1,5 +1,6 @@
-// RUN: %clang_cc1 -verify -fcxx-exceptions -triple=x86_64-linux-gnu -std=c++11 -Werror=c++1y-extensions %s
-// RUN: %clang_cc1 -verify -fcxx-exceptions -triple=x86_64-linux-gnu -std=c++1y -DCXX1Y %s
+// RUN: %clang_cc1 -verify -fcxx-exceptions -triple=x86_64-linux-gnu -std=c++11 -Werror=c++1y-extensions -Werror=c++2a-extensions %s
+// RUN: %clang_cc1 -verify -fcxx-exceptions -triple=x86_64-linux-gnu -std=c++1y -DCXX1Y -Werror=c++2a-extensions %s
+// RUN: %clang_cc1 -verify -fcxx-exceptions -triple=x86_64-linux-gnu -std=c++2a -DCXX1Y -DCXX2A %s
 
 namespace N {
   typedef char C;
@@ -78,7 +79,12 @@
 };
 struct T3 {
   constexpr T3 =(const T3&) const = default;
-  // expected-error@-1 {{an explicitly-defaulted copy assignment operator may not have 'const' or 'volatile' qualifiers}}
+#ifndef CXX2A
+  // expected-error@-2 {{an explicitly-defaulted copy assignment operator may not have 'const' or 'volatile' qualifiers}}
+#else
+  // expected-warning@-4 {{explicitly defaulted copy assignment operator is implicitly deleted}}
+  // expected-note@-5 {{function is implicitly deleted because its declared type does not match the type of an implicit copy assignment operator}}
+#endif
 };
 #endif
 struct U {
@@ -131,7 +137,13 @@
 }
 constexpr int DisallowedStmtsCXX1Y_3() {
   //  - a try-block,
-  try {} catch (...) {} // expected-error {{statement not allowed in constexpr function}}
+  try {} catch (...) {}
+#ifndef CXX2A
+  // expected-error@-2 {{use of this statement in a constexpr function is a C++2a extension}}
+#ifndef CXX1Y
+  // expected-error@-4 {{use of this statement in a constexpr function is a C++14 extension}}
+#endif
+#endif
   return 0;
 }
 constexpr int DisallowedStmtsCXX1Y_4() {
Index: lib/Sema/SemaDeclCXX.cpp
===
--- lib/Sema/SemaDeclCXX.cpp
+++ lib/Sema/SemaDeclCXX.cpp
@@ -1803,7 +1803,7 @@
 static bool
 

[PATCH] D55097: [constexpr][c++2a] Try-catch blocks in constexpr functions

2018-11-29 Thread Richard Smith - zygoloid via Phabricator via cfe-commits
rsmith added inline comments.



Comment at: lib/AST/ExprConstant.cpp:4278-4287
+// Evaluate try blocks by evaluating all sub statements and keep track
+// whether there's a return.
+EvalStmtResult ESR = ESR_Succeeded;
+for (const Stmt *SubStmt : S->children()) {
+  EvalStmtResult SubStmtESR = EvaluateStmt(Result, Info, SubStmt, Case);
+  if (SubStmtESR != ESR_Succeeded && SubStmtESR != ESR_Returned)
+return ESR_Failed;

The children of a `try` statement are the `try` body followed by the `catch` 
statements, in order. We only want to evaluate the normal body, so you should 
just recurse to evaluating `cast(S)->getTryBlock()`...



Comment at: lib/AST/ExprConstant.cpp:4290-4294
+  case Stmt::CXXCatchStmtClass:
+// No need to evaluate catch since it will be ignored in case the try block
+// is successfully evaluated.
+return ESR_Succeeded;
   }

... and this should then be unreachable.



Comment at: lib/Sema/SemaDeclCXX.cpp:1904-1905
+  case Stmt::CXXTryStmtClass:
+if (!SemaRef.getLangOpts().CPlusPlus2a)
+  break;
+if (!Cxx1yLoc.isValid())

Is there a reason to not allow this as an extension in earlier language modes?



Comment at: lib/Sema/SemaDeclCXX.cpp:1906-1907
+  break;
+if (!Cxx1yLoc.isValid())
+  Cxx1yLoc = S->getBeginLoc();
+for (Stmt *SubStmt : S->children())

`Cxx1yLoc` isn't right here; we should produce a -Wc++17-compat diagnostic, not 
a -Wc++14-compat diagnostic. We should probably prefer the `Cxx1zLoc` warning 
over the `Cxx1yLoc` warning if we have both.



Comment at: lib/Sema/SemaDeclCXX.cpp:1915-1922
+  case Stmt::CXXCatchStmtClass:
+if (!SemaRef.getLangOpts().CPlusPlus2a)
+  break;
+if (!Cxx1yLoc.isValid())
+  Cxx1yLoc = S->getBeginLoc();
+// In case we got a valid constexpr try block, the catch block can be
+// ignored since it will never be evaluated in a constexpr context.

We should just unconditionally allow `CXXCatchStmt`s (that is, don't bother 
checking the language mode, just walk the children), since whenever we 
encounter one we must also have a `CXXTryStmt`, which we'll already have 
checked.



Comment at: lib/Sema/SemaDeclCXX.cpp:1962-1983
+// constexpr function try blocks are allowed in c++2a, assuming that the
+// inner statements do also apply to general constexpr rules.
+SourceLocation Cxx1yLoc;
+for (Stmt *SubStmt : Body->children())
+  if (SubStmt &&
+  !CheckConstexprFunctionStmt(*this, Dcl, SubStmt, ReturnStmts,
+  Cxx1yLoc))

The repetition can be avoided here by walking the children of `Body` 
(regardless of what kind of statement it is), and checking them all. (We can't 
*quite* just pass `Body` directly to `CheckConstexprFunctionStmt` because 
(nested) compound statements aren't permitted until C++14.)



Comment at: lib/Sema/SemaDeclCXX.cpp:1973
+  << isa(Dcl);
+return true;
+  }

Don't return here: we still need to do the other checks below.


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

https://reviews.llvm.org/D55097



___
cfe-commits mailing list
cfe-commits@lists.llvm.org
http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D55097: [constexpr][c++2a] Try-catch blocks in constexpr functions

2018-11-29 Thread Bruno Cardoso Lopes via Phabricator via cfe-commits
bruno created this revision.
bruno added reviewers: rsmith, ahatanak, erik.pilkington.
Herald added subscribers: dexonsmith, jkorous.

Implement support for try-catch blocks in constexpr functions, as
proposed in http://wg21.link/P1002 and voted in San Diego for c++20.

The idea is that we can still never throw inside constexpr, so the catch
block is never entered. A try-catch block like this:

try { f(); } catch (...) { }

is then morally equivalent to just

{ f(); }

Same idea should apply for function/constructor try blocks.

rdar://problem/45530773


https://reviews.llvm.org/D55097

Files:
  lib/AST/ExprConstant.cpp
  lib/Sema/SemaDeclCXX.cpp
  test/CXX/dcl.dcl/dcl.spec/dcl.constexpr/p3.cpp
  test/CXX/dcl.dcl/dcl.spec/dcl.constexpr/p4.cpp
  test/CXX/drs/dr6xx.cpp
  www/cxx_status.html

Index: www/cxx_status.html
===
--- www/cxx_status.html
+++ www/cxx_status.html
@@ -953,13 +953,15 @@
 
   Relaxations of constexpr restrictions
   http://wg21.link/p1064r0;>P1064R0
-  No
+  No
 

 http://wg21.link/p1002r1;>P1002R1
+Clang 8
   
   
 http://wg21.link/p1327r1;>P1327R1
+No
   
   
 http://wg21.link/p1330r0;>P1330R0
Index: test/CXX/drs/dr6xx.cpp
===
--- test/CXX/drs/dr6xx.cpp
+++ test/CXX/drs/dr6xx.cpp
@@ -492,7 +492,10 @@
   struct C {
 constexpr C(NonLiteral);
 constexpr C(NonLiteral, int) {} // expected-error {{not a literal type}}
-constexpr C() try {} catch (...) {} // expected-error {{function try block}}
+constexpr C() try {} catch (...) {}
+#if __cplusplus <= 201703L
+// expected-error@-2 {{function try block}}
+#endif
   };
 
   struct D {
Index: test/CXX/dcl.dcl/dcl.spec/dcl.constexpr/p4.cpp
===
--- test/CXX/dcl.dcl/dcl.spec/dcl.constexpr/p4.cpp
+++ test/CXX/dcl.dcl/dcl.spec/dcl.constexpr/p4.cpp
@@ -1,5 +1,6 @@
 // RUN: %clang_cc1 -verify -std=c++11 -fcxx-exceptions -Werror=c++1y-extensions %s
 // RUN: %clang_cc1 -verify -std=c++1y -fcxx-exceptions -DCXX1Y %s
+// RUN: %clang_cc1 -verify -std=c++2a -fcxx-exceptions -DCXX1Y -DCXX2A %s
 
 namespace N {
   typedef char C;
@@ -49,7 +50,10 @@
 // - its function-body shall not be a function-try-block;
 struct U {
   constexpr U()
-try // expected-error {{function try block not allowed in constexpr constructor}}
+try
+#ifndef CXX2A
+// expected-error@-2 {{function try block not allowed in constexpr constructor}}
+#endif
 : u() {
   } catch (...) {
 throw;
Index: test/CXX/dcl.dcl/dcl.spec/dcl.constexpr/p3.cpp
===
--- test/CXX/dcl.dcl/dcl.spec/dcl.constexpr/p3.cpp
+++ test/CXX/dcl.dcl/dcl.spec/dcl.constexpr/p3.cpp
@@ -1,5 +1,6 @@
 // RUN: %clang_cc1 -verify -fcxx-exceptions -triple=x86_64-linux-gnu -std=c++11 -Werror=c++1y-extensions %s
 // RUN: %clang_cc1 -verify -fcxx-exceptions -triple=x86_64-linux-gnu -std=c++1y -DCXX1Y %s
+// RUN: %clang_cc1 -verify -fcxx-exceptions -triple=x86_64-linux-gnu -std=c++2a -DCXX1Y -DCXX2A %s
 
 namespace N {
   typedef char C;
@@ -78,7 +79,12 @@
 };
 struct T3 {
   constexpr T3 =(const T3&) const = default;
-  // expected-error@-1 {{an explicitly-defaulted copy assignment operator may not have 'const' or 'volatile' qualifiers}}
+#ifndef CXX2A
+  // expected-error@-2 {{an explicitly-defaulted copy assignment operator may not have 'const' or 'volatile' qualifiers}}
+#else
+  // expected-warning@-4 {{explicitly defaulted copy assignment operator is implicitly deleted}}
+  // expected-note@-5 {{function is implicitly deleted because its declared type does not match the type of an implicit copy assignment operator}}
+#endif
 };
 #endif
 struct U {
@@ -131,7 +137,10 @@
 }
 constexpr int DisallowedStmtsCXX1Y_3() {
   //  - a try-block,
-  try {} catch (...) {} // expected-error {{statement not allowed in constexpr function}}
+  try {} catch (...) {}
+#ifndef CXX2A
+  // expected-error@-2 {{statement not allowed in constexpr function}}
+#endif
   return 0;
 }
 constexpr int DisallowedStmtsCXX1Y_4() {
Index: lib/Sema/SemaDeclCXX.cpp
===
--- lib/Sema/SemaDeclCXX.cpp
+++ lib/Sema/SemaDeclCXX.cpp
@@ -1900,6 +1900,27 @@
 return false;
 return true;
 
+  case Stmt::CXXTryStmtClass:
+if (!SemaRef.getLangOpts().CPlusPlus2a)
+  break;
+if (!Cxx1yLoc.isValid())
+  Cxx1yLoc = S->getBeginLoc();
+for (Stmt *SubStmt : S->children())
+  if (SubStmt &&
+  !CheckConstexprFunctionStmt(SemaRef, Dcl, SubStmt, ReturnStmts,
+  Cxx1yLoc))
+return false;
+return true;
+
+  case Stmt::CXXCatchStmtClass:
+if (!SemaRef.getLangOpts().CPlusPlus2a)
+  break;
+if (!Cxx1yLoc.isValid())
+  Cxx1yLoc = S->getBeginLoc();
+