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