Sorry, I reverted this because of llvm.org/pr17476. On 3 October 2013 02:29, Faisal Vali <[email protected]> wrote: > Author: faisalv > Date: Thu Oct 3 01:29:33 2013 > New Revision: 191879 > > URL: http://llvm.org/viewvc/llvm-project?rev=191879&view=rev > Log: > Teach TreeTransform and family how to transform generic lambdas within > templates and nested within themselves. > > This does not yet include capturing (that is next). > > Please see test file for examples. > > This patch was LGTM'd by Doug: > http://llvm-reviews.chandlerc.com/D1784 > http://lists.cs.uiuc.edu/pipermail/cfe-commits/Week-of-Mon-20130930/090048.html > > When I first committed this patch - a bunch of buildbots were unable to > compile the code that VS2010 seemed to compile. Seems like there was a > dependency on Sema/Template.h which VS did not seem to need, but I have now > added for the other compilers. It still compiles on Visual Studio 2010 - > lets hope the buildbots remain quiet (please!) > > Modified: > cfe/trunk/lib/Sema/SemaTemplateInstantiate.cpp > cfe/trunk/lib/Sema/SemaTemplateInstantiateDecl.cpp > cfe/trunk/lib/Sema/TreeTransform.h > > cfe/trunk/test/CXX/expr/expr.prim/expr.prim.lambda/generic-lambda-unimplemented-1y.cpp > cfe/trunk/test/SemaCXX/cxx1y-generic-lambdas.cpp > > Modified: cfe/trunk/lib/Sema/SemaTemplateInstantiate.cpp > URL: > http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaTemplateInstantiate.cpp?rev=191879&r1=191878&r2=191879&view=diff > ============================================================================== > --- cfe/trunk/lib/Sema/SemaTemplateInstantiate.cpp (original) > +++ cfe/trunk/lib/Sema/SemaTemplateInstantiate.cpp Thu Oct 3 01:29:33 2013 > @@ -14,6 +14,7 @@ > #include "TreeTransform.h" > #include "clang/AST/ASTConsumer.h" > #include "clang/AST/ASTContext.h" > +#include "clang/AST/ASTLambda.h" > #include "clang/AST/DeclTemplate.h" > #include "clang/AST/Expr.h" > #include "clang/Basic/LangOptions.h" > @@ -130,6 +131,11 @@ Sema::getTemplateInstantiationArgs(Named > assert(Function->getPrimaryTemplate() && "No function template?"); > if (Function->getPrimaryTemplate()->isMemberSpecialization()) > break; > + > + // If this function is a generic lambda specialization, we are done. > + if (isGenericLambdaCallOperatorSpecialization(Function)) > + break; > + > } else if (FunctionTemplateDecl *FunTmpl > = > Function->getDescribedFunctionTemplate()) { > // Add the "injected" template arguments. > @@ -911,13 +917,56 @@ namespace { > } > > ExprResult TransformLambdaScope(LambdaExpr *E, > - CXXMethodDecl *CallOperator) { > - CallOperator->setInstantiationOfMemberFunction(E->getCallOperator(), > - > TSK_ImplicitInstantiation); > - return TreeTransform<TemplateInstantiator>:: > - TransformLambdaScope(E, CallOperator); > + CXXMethodDecl *NewCallOperator) { > + // If a lambda is undergoing transformation for instance in the > + // call to foo('a') below: > + // template<class T> void foo(T t) { > + // auto L1 = [](T a) { return a; }; > + // auto L2 = [](char b) { return b; }; > + // auto L3 = [](auto c) { return c; }; > + // } > + // The AST nodes of the OldCallOperators within the primary template > foo > + // are connected to the NewCallOperators within the specialization of > foo. > + // - In the case of L1 and L2 we set the NewCallOperator to be > considered > + // an instantiation of the OldCallOperator. > + // - In the generic lambda case, we set the NewTemplate to be > considered > + // an "instantiation" of the OldTemplate. > + // See the documentation and use of > get/setInstantiationOfMemberFunction > + // and get/setInstantiatedFromMemberTemplate to appreciate the > relevance > + // of creating these links. > + // And so it goes on and on with nested generic lambdas. > + CXXMethodDecl *const OldCallOperator = E->getCallOperator(); > + FunctionTemplateDecl *const NewCallOperatorTemplate = > + NewCallOperator->getDescribedFunctionTemplate(); > + FunctionTemplateDecl *const OldCallOperatorTemplate = > + OldCallOperator->getDescribedFunctionTemplate(); > + > + if (!NewCallOperatorTemplate) > + NewCallOperator->setInstantiationOfMemberFunction(OldCallOperator, > + > TSK_ImplicitInstantiation); > + else { > + NewCallOperatorTemplate->setInstantiatedFromMemberTemplate( > + > OldCallOperatorTemplate); > + // Set this as a specialization so we don't go digging into the > + // OldCallOperatorTemplate when retrieving the > + // 'FunctionDecl::getTemplateInstantiationPattern()' > + NewCallOperatorTemplate->setMemberSpecialization(); > + } > + return inherited::TransformLambdaScope(E, NewCallOperator); > + } > + TemplateParameterList *TransformTemplateParameterList( > + TemplateParameterList *OrigTPL) { > + TemplateParameterList *NewTPL = 0; > + if (OrigTPL) { > + if (!OrigTPL->size()) return OrigTPL; // size 0, do nothing > + > + DeclContext *Owner = OrigTPL->getParam(0)->getDeclContext(); > + TemplateDeclInstantiator DeclInstantiator(getSema(), > + /* DeclContext *Owner */ Owner, TemplateArgs); > + NewTPL = DeclInstantiator.SubstTemplateParams(OrigTPL); > + } > + return NewTPL; > } > - > private: > ExprResult transformNonTypeTemplateParmRef(NonTypeTemplateParmDecl *parm, > SourceLocation loc, > > Modified: cfe/trunk/lib/Sema/SemaTemplateInstantiateDecl.cpp > URL: > http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaTemplateInstantiateDecl.cpp?rev=191879&r1=191878&r2=191879&view=diff > ============================================================================== > --- cfe/trunk/lib/Sema/SemaTemplateInstantiateDecl.cpp (original) > +++ cfe/trunk/lib/Sema/SemaTemplateInstantiateDecl.cpp Thu Oct 3 01:29:33 > 2013 > @@ -4171,6 +4171,30 @@ DeclContext *Sema::FindInstantiatedConte > NamedDecl *Sema::FindInstantiatedDecl(SourceLocation Loc, NamedDecl *D, > const MultiLevelTemplateArgumentList > &TemplateArgs) { > DeclContext *ParentDC = D->getDeclContext(); > + > + // If we have a parameter from a non-dependent context with a non-dependent > + // type it obviously can not be mapped to a different instantiated decl. > + // Consider the code below, with explicit return types, when N gets > + // specialized ...: > + // template<class T> void fooT(T t) { > + // auto L = [](auto a) -> void { > + // auto M = [](char b) -> void { > + // auto N = [](auto c) -> void { > + // int x = sizeof(a) + sizeof(b) + > + // sizeof(c); > + // }; > + // N('a'); > + // }; > + // }; > + // L(3.14); > + // } > + // fooT('a'); > + // ... without this check below, findInstantiationOf fails with > + // an assertion violation. > + if (isa<ParmVarDecl>(D) && !ParentDC->isDependentContext() && > + !cast<ParmVarDecl>(D)->getType()->isInstantiationDependentType()) > + return D; > + > if (isa<ParmVarDecl>(D) || isa<NonTypeTemplateParmDecl>(D) || > isa<TemplateTypeParmDecl>(D) || isa<TemplateTemplateParmDecl>(D) || > (ParentDC->isFunctionOrMethod() && ParentDC->isDependentContext()) || > > Modified: cfe/trunk/lib/Sema/TreeTransform.h > URL: > http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/TreeTransform.h?rev=191879&r1=191878&r2=191879&view=diff > ============================================================================== > --- cfe/trunk/lib/Sema/TreeTransform.h (original) > +++ cfe/trunk/lib/Sema/TreeTransform.h Thu Oct 3 01:29:33 2013 > @@ -33,6 +33,7 @@ > #include "clang/Sema/ScopeInfo.h" > #include "clang/Sema/SemaDiagnostic.h" > #include "clang/Sema/SemaInternal.h" > +#include "clang/Sema/Template.h" > #include "llvm/ADT/ArrayRef.h" > #include "llvm/Support/ErrorHandling.h" > #include <algorithm> > @@ -594,6 +595,11 @@ public: > /// \brief Transform the captures and body of a lambda expression. > ExprResult TransformLambdaScope(LambdaExpr *E, CXXMethodDecl > *CallOperator); > > + TemplateParameterList *TransformTemplateParameterList( > + TemplateParameterList *TPL) { > + return TPL; > + } > + > ExprResult TransformAddressOfOperand(Expr *E); > ExprResult TransformDependentScopeDeclRefExpr(DependentScopeDeclRefExpr *E, > bool IsAddressOfOperand); > @@ -4573,6 +4579,19 @@ template<typename Derived> > QualType TreeTransform<Derived>::TransformDecltypeType(TypeLocBuilder &TLB, > DecltypeTypeLoc TL) { > const DecltypeType *T = TL.getTypePtr(); > + // Don't transform a decltype construct that has already been transformed > + // into a non-dependent type. > + // Allows the following to compile: > + // auto L = [](auto a) { > + // return [](auto b) ->decltype(a) { > + // return b; > + // }; > + //}; > + if (!T->isInstantiationDependentType()) { > + DecltypeTypeLoc NewTL = TLB.push<DecltypeTypeLoc>(TL.getType()); > + NewTL.setNameLoc(TL.getNameLoc()); > + return NewTL.getType(); > + } > > // decltype expressions are not potentially evaluated contexts > EnterExpressionEvaluationContext Unevaluated(SemaRef, Sema::Unevaluated, 0, > @@ -8284,24 +8303,27 @@ template<typename Derived> > ExprResult > TreeTransform<Derived>::TransformLambdaExpr(LambdaExpr *E) { > > - // FIXME: Implement nested generic lambda transformations. > - if (E->isGenericLambda()) { > - getSema().Diag(E->getIntroducerRange().getBegin(), > - diag::err_glambda_not_fully_implemented) > - << " template transformation of generic lambdas not implemented yet"; > - return ExprError(); > - } > - // Transform the type of the lambda parameters and start the definition of > - // the lambda itself. > - TypeSourceInfo *MethodTy > - = TransformType(E->getCallOperator()->getTypeSourceInfo()); > - if (!MethodTy) > + getSema().PushLambdaScope(); > + LambdaScopeInfo *LSI = getSema().getCurLambda(); > + TemplateParameterList *const OrigTPL = E->getTemplateParameterList(); > + TemplateParameterList *NewTPL = 0; > + // Transform the template parameters, and add them to the > + // current instantiation scope. > + if (OrigTPL) { > + NewTPL = getDerived().TransformTemplateParameterList(OrigTPL); > + } > + LSI->GLTemplateParameterList = NewTPL; > + // Transform the type of the lambda parameters and start the definition of > + // the lambda itself. > + TypeSourceInfo *OldCallOpTSI = E->getCallOperator()->getTypeSourceInfo(); > + TypeSourceInfo *NewCallOpTSI = TransformType(OldCallOpTSI); > + if (!NewCallOpTSI) > return ExprError(); > > // Create the local class that will describe the lambda. > CXXRecordDecl *Class > = getSema().createLambdaClosureType(E->getIntroducerRange(), > - MethodTy, > + NewCallOpTSI, > /*KnownDependent=*/false); > getDerived().transformedLocalDecl(E->getLambdaClass(), Class); > > @@ -8313,19 +8335,49 @@ TreeTransform<Derived>::TransformLambdaE > E->getCallOperator()->param_size(), > 0, ParamTypes, &Params)) > return ExprError(); > - getSema().PushLambdaScope(); > - LambdaScopeInfo *LSI = getSema().getCurLambda(); > - // TODO: Fix for nested lambdas > - LSI->GLTemplateParameterList = 0; > + > // Build the call operator. > - CXXMethodDecl *CallOperator > + CXXMethodDecl *NewCallOperator > = getSema().startLambdaDefinition(Class, E->getIntroducerRange(), > - MethodTy, > + NewCallOpTSI, > E->getCallOperator()->getLocEnd(), > Params); > - getDerived().transformAttrs(E->getCallOperator(), CallOperator); > - > - return getDerived().TransformLambdaScope(E, CallOperator); > + LSI->CallOperator = NewCallOperator; > + // Fix the Decl Contexts of the parameters within the call op function > + // prototype. > + getDerived().transformAttrs(E->getCallOperator(), NewCallOperator); > + > + TypeLoc NewCallOpTL = NewCallOpTSI->getTypeLoc(); > + FunctionProtoTypeLoc NewFPTL = NewCallOpTL.castAs<FunctionProtoTypeLoc>(); > + ParmVarDecl **NewParamDeclArray = NewFPTL.getParmArray(); > + const unsigned NewNumArgs = NewFPTL.getNumArgs(); > + for (unsigned I = 0; I < NewNumArgs; ++I) { > + NewParamDeclArray[I]->setOwningFunction(NewCallOperator); > + } > + // If this is a non-generic lambda, the parameters do not get added to the > + // current instantiation scope, so add them. This feels kludgey. > + // Anyway, it allows the following to compile when the enclosing template > + // is specialized and the entire lambda expression has to be > + // transformed. Without this FindInstantiatedDecl causes an assertion. > + // template<class T> void foo(T t) { > + // auto L = [](auto a) { > + // auto M = [](char b) { <-- note: non-generic lambda > + // auto N = [](auto c) { > + // int x = sizeof(a); > + // x = sizeof(b); <-- specifically this line > + // x = sizeof(c); > + // }; > + // }; > + // }; > + // } > + // foo('a'); > + // > + if (!E->isGenericLambda()) { > + for (unsigned I = 0; I < NewNumArgs; ++I) > + SemaRef.CurrentInstantiationScope->InstantiatedLocal( > + NewParamDeclArray[I], > NewParamDeclArray[I]); > + } > + return getDerived().TransformLambdaScope(E, NewCallOperator); > } > > template<typename Derived> > > Modified: > cfe/trunk/test/CXX/expr/expr.prim/expr.prim.lambda/generic-lambda-unimplemented-1y.cpp > URL: > http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CXX/expr/expr.prim/expr.prim.lambda/generic-lambda-unimplemented-1y.cpp?rev=191879&r1=191878&r2=191879&view=diff > ============================================================================== > --- > cfe/trunk/test/CXX/expr/expr.prim/expr.prim.lambda/generic-lambda-unimplemented-1y.cpp > (original) > +++ > cfe/trunk/test/CXX/expr/expr.prim/expr.prim.lambda/generic-lambda-unimplemented-1y.cpp > Thu Oct 3 01:29:33 2013 > @@ -29,20 +29,3 @@ void test() { > > } > > -namespace nested_generic_lambdas { > -void test() { > - auto L = [](auto a) -> int { > - auto M = [](auto b, decltype(a) b2) -> int { > //expected-error{{unimplemented}} > - return 1; > - }; > - M(a, a); > - }; > - L(3); //expected-note{{in instantiation of}} > -} > -template<class T> void foo(T) { > - auto L = [](auto a) { return a; }; //expected-error{{unimplemented}} > -} > -template void foo(int); //expected-note{{in instantiation of}} > -} > - > - > > Modified: cfe/trunk/test/SemaCXX/cxx1y-generic-lambdas.cpp > URL: > http://llvm.org/viewvc/llvm-project/cfe/trunk/test/SemaCXX/cxx1y-generic-lambdas.cpp?rev=191879&r1=191878&r2=191879&view=diff > ============================================================================== > --- cfe/trunk/test/SemaCXX/cxx1y-generic-lambdas.cpp (original) > +++ cfe/trunk/test/SemaCXX/cxx1y-generic-lambdas.cpp Thu Oct 3 01:29:33 2013 > @@ -1,4 +1,4 @@ > -// RUN: %clang_cc1 -std=c++1y -verify -fsyntax-only -fblocks %s > +// RUN: %clang_cc1 -std=c++1y -verify -fsyntax-only -fblocks -emit-llvm -o - > %s > // DONTRUNYET: %clang_cc1 -std=c++1y -verify -fsyntax-only -fblocks > -fdelayed-template-parsing %s -DDELAYED_TEMPLATE_PARSING > // DONTRUNYET: %clang_cc1 -std=c++1y -verify -fsyntax-only -fblocks > -fms-extensions %s -DMS_EXTENSIONS > // DONTRUNYET: %clang_cc1 -std=c++1y -verify -fsyntax-only -fblocks > -fdelayed-template-parsing -fms-extensions %s -DMS_EXTENSIONS > -DDELAYED_TEMPLATE_PARSING > @@ -99,10 +99,8 @@ void test() { > > //expected-note{{candidate}} > } > } > - > } > > - > namespace return_type_deduction_ok { > auto l = [](auto a) ->auto { return a; }(2); > auto l2 = [](auto a) ->decltype(auto) { return a; }(2); > @@ -114,3 +112,479 @@ namespace generic_lambda_as_default_argu > void test(int i = [](auto a)->int { return a; }(3)) { > } > } > + > +namespace nested_non_capturing_lambda_tests { > +template<class ... Ts> void print(Ts ...) { } > +int test() { > +{ > + auto L = [](auto a) { > + return [](auto b) { > + return b; > + }; > + }; > + auto M = L(3); > + M(4.15); > + } > +{ > + int i = 10; //expected-note{{declared here}} > + auto L = [](auto a) { > + return [](auto b) { //expected-note{{begins here}} > + i = b; //expected-error{{cannot be implicitly captured}} > + return b; > + }; > + }; > + auto M = L(3); > + M(4.15); //expected-note{{instantiation}} > + } > + { > + auto L = [](auto a) { > + print("a = ", a, "\n"); > + return [](auto b) ->decltype(a) { > + print("b = ", b, "\n"); > + return b; > + }; > + }; > + auto M = L(3); > + M(4.15); > + } > + > +{ > + auto L = [](auto a) ->decltype(a) { > + print("a = ", a, "\n"); > + return [](auto b) ->decltype(a) { //expected-error{{no viable > conversion}}\ > + //expected-note{{candidate template > ignored}} > + print("b = ", b, "\n"); > + return b; > + }; > + }; > + auto M = L(3); //expected-note{{in instantiation of}} > + } > +{ > + auto L = [](auto a) { > + print("a = ", a, "\n"); > + return [](auto ... b) ->decltype(a) { > + print("b = ", b ..., "\n"); > + return 4; > + }; > + }; > + auto M = L(3); > + M(4.15, 3, "fv"); > +} > + > +{ > + auto L = [](auto a) { > + print("a = ", a, "\n"); > + return [](auto ... b) ->decltype(a) { > + print("b = ", b ..., "\n"); > + return 4; > + }; > + }; > + auto M = L(3); > + int (*fp)(double, int, const char*) = M; > + fp(4.15, 3, "fv"); > +} > + > +{ > + auto L = [](auto a) { > + print("a = ", a, "\n"); > + return [](char b) { > + return [](auto ... c) ->decltype(b) { > + print("c = ", c ..., "\n"); > + return 42; > + }; > + }; > + }; > + L(4); > + auto M = L(3); > + M('a'); > + auto N = M('x'); > + N("\n3 = ", 3, "\n6.14 = ", 6.14, "\n4'123'456 = ", 4'123'456); > + char (*np)(const char*, int, const char*, double, const char*, int) = N; > + np("\n3 = ", 3, "\n6.14 = ", 6.14, "\n4'123'456 = ", 4'123'456); > +} > + > + > +{ > + auto L = [](auto a) { > + print("a = ", a, "\n"); > + return [](decltype(a) b) { > + return [](auto ... c) ->decltype(b) { > + print("c = ", c ..., "\n"); > + return 42; > + }; > + }; > + }; > + L('4'); > + auto M = L('3'); > + M('a'); > + auto N = M('x'); > + N("\n3 = ", 3, "\n6.14 = ", 6.14, "\n4'123'456 = ", 4'123'456); > + char (*np)(const char*, int, const char*, double, const char*, int) = N; > + np("\n3 = ", 3, "\n6.14 = ", 6.14, "\n4'123'456 = ", 4'123'456); > +} > + > + > +{ > + struct X { > + static void foo(double d) { } > + void test() { > + auto L = [](auto a) { > + print("a = ", a, "\n"); > + foo(a); > + return [](decltype(a) b) { > + foo(b); > + foo(sizeof(a) + sizeof(b)); > + return [](auto ... c) ->decltype(b) { > + print("c = ", c ..., "\n"); > + foo(decltype(b){}); > + foo(sizeof(decltype(a)*) + sizeof(decltype(b)*)); > + return 42; > + }; > + }; > + }; > + L('4'); > + auto M = L('3'); > + M('a'); > + auto N = M('x'); > + N("\n3 = ", 3, "\n6.14 = ", 6.14, "\n4'123'456 = ", 4'123'456); > + char (*np)(const char*, int, const char*, double, const char*, int) = N; > + np("\n3 = ", 3, "\n6.14 = ", 6.14, "\n4'123'456 = ", 4'123'456); > + } > +}; > +X x; > +x.test(); > +} > +// Make sure we can escape the function > +{ > + struct X { > + static void foo(double d) { } > + auto test() { > + auto L = [](auto a) { > + print("a = ", a, "\n"); > + foo(a); > + return [](decltype(a) b) { > + foo(b); > + foo(sizeof(a) + sizeof(b)); > + return [](auto ... c) ->decltype(b) { > + print("c = ", c ..., "\n"); > + foo(decltype(b){}); > + foo(sizeof(decltype(a)*) + sizeof(decltype(b)*)); > + return 42; > + }; > + }; > + }; > + return L; > + } > +}; > + X x; > + auto L = x.test(); > + L('4'); > + auto M = L('3'); > + M('a'); > + auto N = M('x'); > + N("\n3 = ", 3, "\n6.14 = ", 6.14, "\n4'123'456 = ", 4'123'456); > + char (*np)(const char*, int, const char*, double, const char*, int) = N; > + np("\n3 = ", 3, "\n6.14 = ", 6.14, "\n4'123'456 = ", 4'123'456); > +} > + > +{ > + struct X { > + static void foo(double d) { } > + auto test() { > + auto L = [](auto a) { > + print("a = ", a, "\n"); > + foo(a); > + return [](decltype(a) b) { > + foo(b); > + foo(sizeof(a) + sizeof(b)); > + return [](auto ... c) { > + print("c = ", c ..., "\n"); > + foo(decltype(b){}); > + foo(sizeof(decltype(a)*) + sizeof(decltype(b)*)); > + return [](decltype(c) ... d) ->decltype(a) { > //expected-note{{candidate}} > + print("d = ", d ..., "\n"); > + foo(decltype(b){}); > + foo(sizeof(decltype(a)*) + sizeof(decltype(b)*)); > + return decltype(a){}; > + }; > + }; > + }; > + }; > + return L; > + } > +}; > + X x; > + auto L = x.test(); > + L('4'); > + auto M = L('3'); > + M('a'); > + auto N = M('x'); > + auto O = N("\n3 = ", 3, "\n6.14 = ", 6.14, "\n4'123'456 = ", 4'123'456); > + char (*np)(const char*, int, const char*, double, const char*, int) = O; > + np("\n3 = ", 3, "\n6.14 = ", 6.14, "\n4'123'456 = ", 4'123'456); > + int (*np2)(const char*, int, const char*, double, const char*, int) = O; > // expected-error{{no viable conversion}} > + > +} > +} // end test() > + > +namespace wrapped_within_templates { > + > +namespace explicit_return { > +template<class T> int fooT(T t) { > + auto L = [](auto a) -> void { > + auto M = [](char b) -> void { > + auto N = [](auto c) -> void { > + int x = 0; > + x = sizeof(a); > + x = sizeof(b); > + x = sizeof(c); > + }; > + N('a'); > + N(decltype(a){}); > + }; > + }; > + L(t); > + L(3.14); > + return 0; > +} > + > +int run = fooT('a') + fooT(3.14); > + > +} // end explicit_return > + > +namespace implicit_return_deduction { > +template<class T> auto fooT(T t) { > + auto L = [](auto a) { > + auto M = [](char b) { > + auto N = [](auto c) { > + int x = 0; > + x = sizeof(a); > + x = sizeof(b); > + x = sizeof(c); > + }; > + N('a'); > + N(decltype(a){}); > + }; > + }; > + L(t); > + L(3.14); > + return 0; > +} > + > +int run = fooT('a') + fooT(3.14); > + > +template<class ... Ts> void print(Ts ... ts) { } > + > +template<class F, class ... Rest> using first = F; > + > +template<class ... Ts> auto fooV(Ts ... ts) { > + auto L = [](auto ... a) { > + auto M = [](decltype(a) ... b) { > + auto N = [](auto c) { > + int x = 0; > + x = sizeof...(a); > + x = sizeof...(b); > + x = sizeof(c); > + }; > + N('a'); > + N(N); > + N(first<Ts...>{}); > + }; > + M(a...); > + print("a = ", a..., "\n"); > + }; > + L(L, ts...); > + print("ts = ", ts..., "\n"); > + return 0; > +} > + > +int run2 = fooV(3.14, " ", '4', 5) + fooV("BC", 3, 2.77, 'A', float{}, > short{}, unsigned{}); > + > +} //implicit_return_deduction > + > + > +} //wrapped_within_templates > + > +namespace at_ns_scope { > + void foo(double d) { } > + auto test() { > + auto L = [](auto a) { > + print("a = ", a, "\n"); > + foo(a); > + return [](decltype(a) b) { > + foo(b); > + foo(sizeof(a) + sizeof(b)); > + return [](auto ... c) { > + print("c = ", c ..., "\n"); > + foo(decltype(b){}); > + foo(sizeof(decltype(a)*) + sizeof(decltype(b)*)); > + return [](decltype(c) ... d) ->decltype(a) { > //expected-note{{candidate}} > + print("d = ", d ..., "\n"); > + foo(decltype(b){}); > + foo(sizeof(decltype(a)*) + sizeof(decltype(b)*)); > + return decltype(a){}; > + }; > + }; > + }; > + }; > + return L; > + } > +auto L = test(); > +auto L_test = L('4'); > +auto M = L('3'); > +auto M_test = M('a'); > +auto N = M('x'); > +auto O = N("\n3 = ", 3, "\n6.14 = ", 6.14, "\n4'123'456 = ", 4'123'456); > +char (*np)(const char*, int, const char*, double, const char*, int) = O; > +auto NP_result = np("\n3 = ", 3, "\n6.14 = ", 6.14, "\n4'123'456 = ", > 4'123'456); > +int (*np2)(const char*, int, const char*, double, const char*, int) = O; // > expected-error{{no viable conversion}} > + > + > + > +} > + > +namespace variadic_tests_1 { > +template<class ... Ts> void print(Ts ... ts) { } > + > +template<class F, class ... Rest> using FirstType = F; > +template<class F, class ... Rest> F& FirstArg(F& f, Rest...) { return f; } > + > +template<class ... Ts> int fooV(Ts ... ts) { > + auto L = [](auto ... a) -> void { > + auto M = [](decltype(a) ... b) -> void { > + auto N = [](auto c) -> void { > + int x = 0; > + x = sizeof...(a); > + x = sizeof...(b); > + x = sizeof(c); > + }; > + N('a'); > + N(N); > + N(FirstType<Ts...>{}); > + }; > + M(a...); > + print("a = ", a..., "\n"); > + }; > + L(L, ts...); > + print("ts = ", ts..., "\n"); > + return 0; > +} > + > +int run2 = fooV(3.14, " ", '4', 5) + fooV("BC", 3, 2.77, 'A', float{}, > short{}, unsigned{}); > + > +namespace more_variadic_1 { > + > +template<class ... Ts> int fooV(Ts ... ts) { > + auto L = [](auto ... a) { > + auto M = [](decltype(a) ... b) -> void { > + auto N = [](auto c) -> void { > + int x = 0; > + x = sizeof...(a); > + x = sizeof...(b); > + x = sizeof(c); > + }; > + N('a'); > + N(N); > + N(FirstType<Ts...>{}); > + }; > + M(a...); > + return M; > + }; > + auto M = L(L, ts...); > + decltype(L(L, ts...)) (*fp)(decltype(L), decltype(ts) ...) = L; > + void (*fp2)(decltype(L), decltype(ts) ...) = L(L, ts...); > + > + { > + auto L = [](auto ... a) { > + auto M = [](decltype(a) ... b) { > + auto N = [](auto c) -> void { > + int x = 0; > + x = sizeof...(a); > + x = sizeof...(b); > + x = sizeof(c); > + }; > + N('a'); > + N(N); > + N(FirstType<Ts...>{}); > + return N; > + }; > + M(a...); > + return M; > + }; > + auto M = L(L, ts...); > + decltype(L(L, ts...)) (*fp)(decltype(L), decltype(ts) ...) = L; > + fp(L, ts...); > + decltype(L(L, ts...)(L, ts...)) (*fp2)(decltype(L), decltype(ts) ...) = > L(L, ts...); > + fp2 = fp(L, ts...); > + void (*fp3)(char) = fp2(L, ts...); > + fp3('a'); > + } > + return 0; > +} > + > +int run2 = fooV(3.14, " ", '4', 5) + fooV("BC", 3, 2.77, 'A', float{}, > short{}, unsigned{}); > + > + > +} //end ns more_variadic_1 > + > +} // end ns variadic_tests_1 > + > +namespace at_ns_scope_within_class_member { > + struct X { > + static void foo(double d) { } > + auto test() { > + auto L = [](auto a) { > + print("a = ", a, "\n"); > + foo(a); > + return [](decltype(a) b) { > + foo(b); > + foo(sizeof(a) + sizeof(b)); > + return [](auto ... c) { > + print("c = ", c ..., "\n"); > + foo(decltype(b){}); > + foo(sizeof(decltype(a)*) + sizeof(decltype(b)*)); > + return [](decltype(c) ... d) ->decltype(a) { > //expected-note{{candidate}} > + print("d = ", d ..., "\n"); > + foo(decltype(b){}); > + foo(sizeof(decltype(a)*) + sizeof(decltype(b)*)); > + return decltype(a){}; > + }; > + }; > + }; > + }; > + return L; > + } > +}; > +X x; > +auto L = x.test(); > +auto L_test = L('4'); > +auto M = L('3'); > +auto M_test = M('a'); > +auto N = M('x'); > +auto O = N("\n3 = ", 3, "\n6.14 = ", 6.14, "\n4'123'456 = ", 4'123'456); > +char (*np)(const char*, int, const char*, double, const char*, int) = O; > +auto NP_result = np("\n3 = ", 3, "\n6.14 = ", 6.14, "\n4'123'456 = ", > 4'123'456); > +int (*np2)(const char*, int, const char*, double, const char*, int) = O; // > expected-error{{no viable conversion}} > + > +} //end at_ns_scope_within_class_member > + > + > +namespace nested_generic_lambdas_123 { > +void test() { > + auto L = [](auto a) -> int { > + auto M = [](auto b, decltype(a) b2) -> int { > + return 1; > + }; > + M(a, a); > + }; > + L(3); > +} > +template<class T> void foo(T) { > + auto L = [](auto a) { return a; }; > +} > +template void foo(int); > +} // end ns nested_generic_lambdas_123 > + > + > +} // end ns nested_non_capturing_lambda_tests > + > \ No newline at end of file > > > _______________________________________________ > cfe-commits mailing list > [email protected] > http://lists.cs.uiuc.edu/mailman/listinfo/cfe-commits
_______________________________________________ cfe-commits mailing list [email protected] http://lists.cs.uiuc.edu/mailman/listinfo/cfe-commits
