]> granicus.if.org Git - clang/commitdiff
[Sema] Transform the default arguments of a lambda expression when the
authorAkira Hatanaka <ahatanaka@apple.com>
Fri, 16 Dec 2016 21:16:57 +0000 (21:16 +0000)
committerAkira Hatanaka <ahatanaka@apple.com>
Fri, 16 Dec 2016 21:16:57 +0000 (21:16 +0000)
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
test/SemaCXX/vartemplate-lambda.cpp

index af60a56564c9568620547f89a13a12986b5ff1f3..ebd33db1602875d918e1da0b1ab03ebeaefdfa75 100644 (file)
@@ -10356,6 +10356,18 @@ TreeTransform<Derived>::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);
 
index 9dab6da3d1e3d44dea40ec285f3dc9779b735e06..5b91e232e3a674002ab7af75be279142cb78cc5c 100644 (file)
@@ -1,18 +1,36 @@
 // RUN: %clang_cc1 -std=c++14 -fsyntax-only -verify %s
-// expected-no-diagnostics
 
 template <class> auto fn0 = [] {};
 template <typename> void foo0() { fn0<char>(); }
 
 template<typename T> auto fn1 = [](auto a) { return a + T(1); };
+template<typename T> auto v1 = [](int a = T(1)) { return a; }();
+
+struct S {
+  template<class T>
+  static constexpr T t = [](int f = T(7)){return f;}(); // expected-error{{constexpr variable 't<int>' 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 <typename X>
 int foo2() {
   X a = 0x61;
   fn1<char>(a);
+  (void)v1<int>;
+  (void)S::t<int>; // expected-note{{in instantiation of static data member 'S::t<int>' requested here}}
   return 0;
 }
 
+template<class C>
+int foo3() {
+  C::m1(); // expected-error{{type 'long long' cannot be used prior to '::' because it has no members}}
+  return 1;
+}
+
+template<class C>
+auto v2 = [](int a = foo3<C>()){};  // expected-note{{in instantiation of function template specialization 'foo3<long long>' requested here}}
+
 int main() {
+  v2<long long>();  // This line causes foo3<long long> to be instantiated.
+  v2<long long>(2); // This line does not.
   foo2<int>();
 }