summaryrefslogtreecommitdiffstats
path: root/clang
diff options
context:
space:
mode:
authorFaisal Vali <faisalv@yahoo.com>2017-01-09 03:02:53 +0000
committerFaisal Vali <faisalv@yahoo.com>2017-01-09 03:02:53 +0000
commitc72a08c1f6f42d1999ca481aba75cd9a2ae2fc53 (patch)
treeeed393d95cf11792d9acc99782734a8a1a3fe181 /clang
parent6393afce978a30737e170150b7c34de4986cd2a8 (diff)
downloadbcm5719-llvm-c72a08c1f6f42d1999ca481aba75cd9a2ae2fc53.tar.gz
bcm5719-llvm-c72a08c1f6f42d1999ca481aba75cd9a2ae2fc53.zip
[cxx1z-constexpr-lambda] Implement constant evaluation of non-capturing lambda expressions.
Add a visitor for lambda expressions to RecordExprEvaluator in ExprConstant.cpp that creates an empty APValue of Struct type to represent the closure object. Additionally, add a LambdaExpr visitor to the TemporaryExprEvaluator that forwards constant evaluation of immediately-called-lambda-expressions to the one in RecordExprEvaluator through VisitConstructExpr. This patch supports: constexpr auto ID = [] (auto a) { return a; }; static_assert(ID(3.14) == 3.14); static_assert([](auto a) { return a + 1; }(10) == 11); Lambda captures are still not supported for constexpr lambdas. llvm-svn: 291416
Diffstat (limited to 'clang')
-rw-r--r--clang/lib/AST/ExprConstant.cpp19
-rw-r--r--clang/lib/Sema/SemaExpr.cpp6
-rw-r--r--clang/test/SemaCXX/cxx1z-constexpr-lambdas.cpp77
3 files changed, 100 insertions, 2 deletions
diff --git a/clang/lib/AST/ExprConstant.cpp b/clang/lib/AST/ExprConstant.cpp
index bb0b8ba5c8b..18206e5e0ee 100644
--- a/clang/lib/AST/ExprConstant.cpp
+++ b/clang/lib/AST/ExprConstant.cpp
@@ -5868,6 +5868,7 @@ namespace {
bool VisitCXXConstructExpr(const CXXConstructExpr *E) {
return VisitCXXConstructExpr(E, E->getType());
}
+ bool VisitLambdaExpr(const LambdaExpr *E);
bool VisitCXXInheritedCtorInitExpr(const CXXInheritedCtorInitExpr *E);
bool VisitCXXConstructExpr(const CXXConstructExpr *E, QualType T);
bool VisitCXXStdInitializerListExpr(const CXXStdInitializerListExpr *E);
@@ -6202,6 +6203,21 @@ bool RecordExprEvaluator::VisitCXXStdInitializerListExpr(
return true;
}
+bool RecordExprEvaluator::VisitLambdaExpr(const LambdaExpr *E) {
+ const CXXRecordDecl *ClosureClass = E->getLambdaClass();
+ if (ClosureClass->isInvalidDecl()) return false;
+
+ if (Info.checkingPotentialConstantExpression()) return true;
+ if (E->capture_size()) {
+ Info.FFDiag(E, diag::note_unimplemented_constexpr_lambda_feature_ast)
+ << "can not evaluate lambda expressions with captures";
+ return false;
+ }
+ // FIXME: Implement captures.
+ Result = APValue(APValue::UninitStruct(), /*NumBases*/0, /*NumFields*/0);
+ return true;
+}
+
static bool EvaluateRecord(const Expr *E, const LValue &This,
APValue &Result, EvalInfo &Info) {
assert(E->isRValue() && E->getType()->isRecordType() &&
@@ -6251,6 +6267,9 @@ public:
bool VisitCXXStdInitializerListExpr(const CXXStdInitializerListExpr *E) {
return VisitConstructExpr(E);
}
+ bool VisitLambdaExpr(const LambdaExpr *E) {
+ return VisitConstructExpr(E);
+ }
};
} // end anonymous namespace
diff --git a/clang/lib/Sema/SemaExpr.cpp b/clang/lib/Sema/SemaExpr.cpp
index 023d6f678d5..65e8236952f 100644
--- a/clang/lib/Sema/SemaExpr.cpp
+++ b/clang/lib/Sema/SemaExpr.cpp
@@ -13097,8 +13097,10 @@ void Sema::PopExpressionEvaluationContext() {
// evaluate [...] a lambda-expression.
D = diag::err_lambda_in_constant_expression;
}
- for (const auto *L : Rec.Lambdas)
- Diag(L->getLocStart(), D);
+ // C++1z allows lambda expressions as core constant expressions.
+ if (Rec.Context != ConstantEvaluated || !getLangOpts().CPlusPlus1z)
+ for (const auto *L : Rec.Lambdas)
+ Diag(L->getLocStart(), D);
} else {
// Mark the capture expressions odr-used. This was deferred
// during lambda expression creation.
diff --git a/clang/test/SemaCXX/cxx1z-constexpr-lambdas.cpp b/clang/test/SemaCXX/cxx1z-constexpr-lambdas.cpp
index f1f4cfe66c2..16d5730d3d4 100644
--- a/clang/test/SemaCXX/cxx1z-constexpr-lambdas.cpp
+++ b/clang/test/SemaCXX/cxx1z-constexpr-lambdas.cpp
@@ -96,4 +96,81 @@ decltype(deduced_return_type(0)) d; //expected-note{{requested here}}
} // end ns test_conversion_function_for_non_capturing_lambdas
+namespace test_lambda_is_cce {
+namespace ns1_simple_lambda {
+
+namespace ns0 {
+constexpr int I = [](auto a) { return a; }(10);
+
+static_assert(I == 10);
+static_assert(10 == [](auto a) { return a; }(10));
+static_assert(3.14 == [](auto a) { return a; }(3.14));
+
+} //end ns0
+
+namespace ns1 {
+constexpr auto f(int i) {
+ double d = 3.14;
+ auto L = [=](auto a) {
+ int Isz = sizeof(i);
+ return sizeof(i) + sizeof(a) + sizeof(d);
+ };
+ int I = L("abc") + L(nullptr);
+ return L;
+}
+constexpr auto L = f(3);
+constexpr auto M = L("abc") + L(nullptr);
+
+static_assert(M == sizeof(int) * 2 + sizeof(double) * 2 + sizeof(nullptr) + sizeof(const char*));
+
+} // end ns1
+
+namespace ns2 {
+constexpr auto f(int i) {
+ auto L = [](auto a) { return a + a; };
+ return L;
+}
+constexpr auto L = f(3);
+constexpr int I = L(6);
+static_assert(I == 12);
+} // end ns2
+
+namespace contained_lambdas_call_operator_is_not_constexpr {
+constexpr auto f(int i) {
+ double d = 3.14;
+ auto L = [=](auto a) { //expected-note{{declared here}}
+ int Isz = sizeof(i);
+ asm("hello");
+ return sizeof(i) + sizeof(a) + sizeof(d);
+ };
+ return L;
+}
+
+constexpr auto L = f(3);
+
+constexpr auto M = // expected-error{{must be initialized by}}
+ L("abc"); //expected-note{{non-constexpr function}}
+
+} // end ns contained_lambdas_call_operator_is_not_constexpr
+
+
+
+} // end ns1_simple_lambda
+
+namespace ns1_unimplemented {
+namespace ns1_captures {
+constexpr auto f(int i) {
+ double d = 3.14;
+ auto L = [=](auto a) { //expected-note{{coming soon}}
+ int Isz = i + d;
+ return sizeof(i) + sizeof(a) + sizeof(d);
+ };
+ return L;
+}
+constexpr auto M = f(3); //expected-error{{constant expression}} expected-note{{in call to}}
+} // end ns1_captures
+} // end ns1_unimplemented
+
+} // end ns test_lambda_is_cce
+
#endif // ndef CPP14_AND_EARLIER
OpenPOWER on IntegriCloud