From b0bfcdc53727ae57145e9b90d83977c74bdfcbeb Mon Sep 17 00:00:00 2001 From: Akira Hatanaka Date: Fri, 16 Dec 2016 21:16:57 +0000 Subject: [PATCH] [Sema] Transform the default arguments of a lambda expression when the lambda expression is instantiated. Rather than waiting until Sema::CheckCXXDefaultArgExpr tries to transform the default arguments (which fails because it can't get the template arguments that are used), transform the default arguments earlier when the lambda expression is transformed in TransformLambdaExpr. rdar://problem/27535319 Differential Revision: https://reviews.llvm.org/D23096 git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@289990 91177308-0d34-0410-b5e6-96231b3b80d8 --- lib/Sema/TreeTransform.h | 12 ++++++++++++ test/SemaCXX/vartemplate-lambda.cpp | 20 +++++++++++++++++++- 2 files changed, 31 insertions(+), 1 deletion(-) diff --git a/lib/Sema/TreeTransform.h b/lib/Sema/TreeTransform.h index af60a56564..ebd33db160 100644 --- a/lib/Sema/TreeTransform.h +++ b/lib/Sema/TreeTransform.h @@ -10356,6 +10356,18 @@ TreeTransform::TransformLambdaExpr(LambdaExpr *E) { LSI->CallOperator = NewCallOperator; + for (unsigned I = 0, NumParams = NewCallOperator->getNumParams(); + I != NumParams; ++I) { + auto *P = NewCallOperator->getParamDecl(I); + if (P->hasUninstantiatedDefaultArg()) { + EnterExpressionEvaluationContext Eval( + getSema(), Sema::PotentiallyEvaluatedIfUsed, P); + ExprResult R = getDerived().TransformExpr( + E->getCallOperator()->getParamDecl(I)->getDefaultArg()); + P->setDefaultArg(R.get()); + } + } + getDerived().transformAttrs(E->getCallOperator(), NewCallOperator); getDerived().transformedLocalDecl(E->getCallOperator(), NewCallOperator); diff --git a/test/SemaCXX/vartemplate-lambda.cpp b/test/SemaCXX/vartemplate-lambda.cpp index 9dab6da3d1..5b91e232e3 100644 --- a/test/SemaCXX/vartemplate-lambda.cpp +++ b/test/SemaCXX/vartemplate-lambda.cpp @@ -1,18 +1,36 @@ // RUN: %clang_cc1 -std=c++14 -fsyntax-only -verify %s -// expected-no-diagnostics template auto fn0 = [] {}; template void foo0() { fn0(); } template auto fn1 = [](auto a) { return a + T(1); }; +template auto v1 = [](int a = T(1)) { return a; }(); + +struct S { + template + static constexpr T t = [](int f = T(7)){return f;}(); // expected-error{{constexpr variable 't' must be initialized by a constant expression}} expected-error{{a lambda expression may not appear inside of a constant expression}} expected-note{{cannot be used in a constant expression}} +}; template int foo2() { X a = 0x61; fn1(a); + (void)v1; + (void)S::t; // expected-note{{in instantiation of static data member 'S::t' requested here}} return 0; } +template +int foo3() { + C::m1(); // expected-error{{type 'long long' cannot be used prior to '::' because it has no members}} + return 1; +} + +template +auto v2 = [](int a = foo3()){}; // expected-note{{in instantiation of function template specialization 'foo3' requested here}} + int main() { + v2(); // This line causes foo3 to be instantiated. + v2(2); // This line does not. foo2(); } -- 2.40.0