r289990 - [Sema] Transform the default arguments of a lambda expression when the

Akira Hatanaka via cfe-commits cfe-commits at lists.llvm.org
Fri Dec 16 13:16:57 PST 2016


Author: ahatanak
Date: Fri Dec 16 15:16:57 2016
New Revision: 289990

URL: http://llvm.org/viewvc/llvm-project?rev=289990&view=rev
Log:
[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

Modified:
    cfe/trunk/lib/Sema/TreeTransform.h
    cfe/trunk/test/SemaCXX/vartemplate-lambda.cpp

Modified: cfe/trunk/lib/Sema/TreeTransform.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/TreeTransform.h?rev=289990&r1=289989&r2=289990&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/TreeTransform.h (original)
+++ cfe/trunk/lib/Sema/TreeTransform.h Fri Dec 16 15:16:57 2016
@@ -10356,6 +10356,18 @@ TreeTransform<Derived>::TransformLambdaE
 
   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);
 

Modified: cfe/trunk/test/SemaCXX/vartemplate-lambda.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/SemaCXX/vartemplate-lambda.cpp?rev=289990&r1=289989&r2=289990&view=diff
==============================================================================
--- cfe/trunk/test/SemaCXX/vartemplate-lambda.cpp (original)
+++ cfe/trunk/test/SemaCXX/vartemplate-lambda.cpp Fri Dec 16 15:16:57 2016
@@ -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>();
 }




More information about the cfe-commits mailing list