faisalv updated the summary for this revision.
faisalv updated this revision to Diff 62814.
faisalv added a comment.

Mark the lambda's conversion to function-pointer as incontrovertibly constexpr.

auto L = [](auto a) { return a; };
constexpr int* (*fp)(int*) = L; // This is now allowed.

Instead of inserting the extension/compatibility-warning into the same list 
that houses the notes that identify errors that occurred during 
constant-folding (and subsequently modifying the logic to ignore such warnings 
when determining the result of constant folding), I resorted to the simple 
approach used to emit a warning for integer-overflow (during constant folding) 
by invoking getDiagnostics().Report.

Richard I hope you're OK with this approach - I know in Oulu I was leaning 
towards inserting the warning into the same list that houses the error-notes 
(or potentially creating another one, or having EvalInfo track whether an 
error-note truly occurred instead of relying simply on the size of the list) - 
and while doable (and potentially cleaner) - that change is a larger one that 
requires handing some subtleties, and can be done at a later time, if you feel 
strongly about it.


http://reviews.llvm.org/D18510

Files:
  include/clang/Basic/DiagnosticASTKinds.td
  lib/AST/ExprConstant.cpp
  lib/Sema/SemaLambda.cpp
  test/SemaCXX/cxx1z-constexpr-lambdas.cpp

Index: test/SemaCXX/cxx1z-constexpr-lambdas.cpp
===================================================================
--- test/SemaCXX/cxx1z-constexpr-lambdas.cpp
+++ test/SemaCXX/cxx1z-constexpr-lambdas.cpp
@@ -2,7 +2,9 @@
 // RUN: %clang_cc1 -std=c++1z -verify -fsyntax-only -fblocks 
-fdelayed-template-parsing %s 
 // RUN: %clang_cc1 -std=c++1z -verify -fsyntax-only -fblocks -fms-extensions 
%s 
 // RUN: %clang_cc1 -std=c++1z -verify -fsyntax-only -fblocks 
-fdelayed-template-parsing -fms-extensions %s 
+// RUN: %clang_cc1 -std=c++1z -verify -fsyntax-only -fblocks -Wc++14-compat %s 
-DCHECK_COMPATIBILITY_WARNING
 
+#ifndef CHECK_COMPATIBILITY_WARNING
 namespace test_constexpr_checking {
 
 namespace ns1 {
@@ -33,4 +35,17 @@
       L(3); //expected-note{{non-constexpr function}}
 } 
 
-} // end ns test_constexpr_call
\ No newline at end of file
+} // end ns test_constexpr_call
+#endif
+
+#ifdef CHECK_COMPATIBILITY_WARNING
+//expected-warning@+6{{incompatible with C++ standards before C++1z}}
+//expected-warning@+6{{incompatible with C++ standards before C++1z}}
+#endif
+
+namespace ns4 {
+auto L = [](auto a) { return a; };
+constexpr int (*fp1)(int) = L;  
+constexpr int* (*fp2)(int*) = L; 
+
+} // end ns4
\ No newline at end of file
Index: lib/Sema/SemaLambda.cpp
===================================================================
--- lib/Sema/SemaLambda.cpp
+++ lib/Sema/SemaLambda.cpp
@@ -1261,7 +1261,7 @@
                                 ConvTy, 
                                 ConvTSI,
                                 /*isInline=*/true, /*isExplicit=*/false,
-                                /*isConstexpr=*/false, 
+                                /*isConstexpr=*/true, 
                                 CallOperator->getBody()->getLocEnd());
   Conversion->setAccess(AS_public);
   Conversion->setImplicit(true);
Index: lib/AST/ExprConstant.cpp
===================================================================
--- lib/AST/ExprConstant.cpp
+++ lib/AST/ExprConstant.cpp
@@ -4353,6 +4353,17 @@
         if (!EvaluateObjectArgument(Info, ME->getBase(), ThisVal))
           return false;
         Member = ME->getMemberDecl();
+        // If this is a non-capturing lambda's closure type's conversion
+        // operator that results in a pointer-to-function, remind users that 
the
+        // conversion operator itself was made 'constexpr' in C++1z.
+        if (const CXXConversionDecl *Conv = 
dyn_cast<CXXConversionDecl>(Member))
+          if (Conv->getParent()->isLambda()) {
+            Info.Ctx.getDiagnostics().Report(
+                E->getExprLoc(),
+                !Info.Ctx.getLangOpts().CPlusPlus1z
+                    ? diag::ext_constexpr_conversion_on_lambda_cxx1z
+                    : diag::warn_cxx14_compat_constexpr_conversion_on_lambda);
+          }
         This = &ThisVal;
         HasQualifier = ME->hasQualifier();
       } else if (const BinaryOperator *BE = dyn_cast<BinaryOperator>(Callee)) {
Index: include/clang/Basic/DiagnosticASTKinds.td
===================================================================
--- include/clang/Basic/DiagnosticASTKinds.td
+++ include/clang/Basic/DiagnosticASTKinds.td
@@ -162,8 +162,17 @@
 // implementation is complete, and like the preceding constexpr notes belongs
 // in Sema.
 def note_unimplemented_constexpr_lambda_feature_ast : Note<
-    "unimplemented constexpr lambda feature: %0 (coming soon!)">;
+  "unimplemented constexpr lambda feature: %0 (coming soon!)">;
 
+// C++1z constexpr lambda expressions
+def warn_cxx14_compat_constexpr_conversion_on_lambda : Warning<
+  "constexpr conversion to pointer-to-function on lambdas is "
+  "incompatible with C++ standards before C++1z">,
+  InGroup<CXXPre1zCompat>, DefaultIgnore;
+def ext_constexpr_conversion_on_lambda_cxx1z : ExtWarn<
+  "constexpr conversion to pointer-to-function on lambdas is "
+  "a C++1z extension">, InGroup<CXX1z>;
+
 // inline asm related.
 let CategoryName = "Inline Assembly Issue" in {
   def err_asm_invalid_escape : Error<


Index: test/SemaCXX/cxx1z-constexpr-lambdas.cpp
===================================================================
--- test/SemaCXX/cxx1z-constexpr-lambdas.cpp
+++ test/SemaCXX/cxx1z-constexpr-lambdas.cpp
@@ -2,7 +2,9 @@
 // RUN: %clang_cc1 -std=c++1z -verify -fsyntax-only -fblocks -fdelayed-template-parsing %s 
 // RUN: %clang_cc1 -std=c++1z -verify -fsyntax-only -fblocks -fms-extensions %s 
 // RUN: %clang_cc1 -std=c++1z -verify -fsyntax-only -fblocks -fdelayed-template-parsing -fms-extensions %s 
+// RUN: %clang_cc1 -std=c++1z -verify -fsyntax-only -fblocks -Wc++14-compat %s -DCHECK_COMPATIBILITY_WARNING
 
+#ifndef CHECK_COMPATIBILITY_WARNING
 namespace test_constexpr_checking {
 
 namespace ns1 {
@@ -33,4 +35,17 @@
       L(3); //expected-note{{non-constexpr function}}
 } 
 
-} // end ns test_constexpr_call
\ No newline at end of file
+} // end ns test_constexpr_call
+#endif
+
+#ifdef CHECK_COMPATIBILITY_WARNING
+//expected-warning@+6{{incompatible with C++ standards before C++1z}}
+//expected-warning@+6{{incompatible with C++ standards before C++1z}}
+#endif
+
+namespace ns4 {
+auto L = [](auto a) { return a; };
+constexpr int (*fp1)(int) = L;  
+constexpr int* (*fp2)(int*) = L; 
+
+} // end ns4
\ No newline at end of file
Index: lib/Sema/SemaLambda.cpp
===================================================================
--- lib/Sema/SemaLambda.cpp
+++ lib/Sema/SemaLambda.cpp
@@ -1261,7 +1261,7 @@
                                 ConvTy, 
                                 ConvTSI,
                                 /*isInline=*/true, /*isExplicit=*/false,
-                                /*isConstexpr=*/false, 
+                                /*isConstexpr=*/true, 
                                 CallOperator->getBody()->getLocEnd());
   Conversion->setAccess(AS_public);
   Conversion->setImplicit(true);
Index: lib/AST/ExprConstant.cpp
===================================================================
--- lib/AST/ExprConstant.cpp
+++ lib/AST/ExprConstant.cpp
@@ -4353,6 +4353,17 @@
         if (!EvaluateObjectArgument(Info, ME->getBase(), ThisVal))
           return false;
         Member = ME->getMemberDecl();
+        // If this is a non-capturing lambda's closure type's conversion
+        // operator that results in a pointer-to-function, remind users that the
+        // conversion operator itself was made 'constexpr' in C++1z.
+        if (const CXXConversionDecl *Conv = dyn_cast<CXXConversionDecl>(Member))
+          if (Conv->getParent()->isLambda()) {
+            Info.Ctx.getDiagnostics().Report(
+                E->getExprLoc(),
+                !Info.Ctx.getLangOpts().CPlusPlus1z
+                    ? diag::ext_constexpr_conversion_on_lambda_cxx1z
+                    : diag::warn_cxx14_compat_constexpr_conversion_on_lambda);
+          }
         This = &ThisVal;
         HasQualifier = ME->hasQualifier();
       } else if (const BinaryOperator *BE = dyn_cast<BinaryOperator>(Callee)) {
Index: include/clang/Basic/DiagnosticASTKinds.td
===================================================================
--- include/clang/Basic/DiagnosticASTKinds.td
+++ include/clang/Basic/DiagnosticASTKinds.td
@@ -162,8 +162,17 @@
 // implementation is complete, and like the preceding constexpr notes belongs
 // in Sema.
 def note_unimplemented_constexpr_lambda_feature_ast : Note<
-    "unimplemented constexpr lambda feature: %0 (coming soon!)">;
+  "unimplemented constexpr lambda feature: %0 (coming soon!)">;
 
+// C++1z constexpr lambda expressions
+def warn_cxx14_compat_constexpr_conversion_on_lambda : Warning<
+  "constexpr conversion to pointer-to-function on lambdas is "
+  "incompatible with C++ standards before C++1z">,
+  InGroup<CXXPre1zCompat>, DefaultIgnore;
+def ext_constexpr_conversion_on_lambda_cxx1z : ExtWarn<
+  "constexpr conversion to pointer-to-function on lambdas is "
+  "a C++1z extension">, InGroup<CXX1z>;
+
 // inline asm related.
 let CategoryName = "Inline Assembly Issue" in {
   def err_asm_invalid_escape : Error<
_______________________________________________
cfe-commits mailing list
cfe-commits@lists.llvm.org
http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to