struct LambdaDefinitionData : public DefinitionData {
typedef LambdaExpr::Capture Capture;
- LambdaDefinitionData(CXXRecordDecl *D, TypeSourceInfo *Info,
- bool Dependent, bool IsGeneric,
- LambdaCaptureDefault CaptureDefault)
- : DefinitionData(D), Dependent(Dependent), IsGenericLambda(IsGeneric),
- CaptureDefault(CaptureDefault), NumCaptures(0), NumExplicitCaptures(0),
- ManglingNumber(0), ContextDecl(0), Captures(0), MethodTyInfo(Info)
+ LambdaDefinitionData(CXXRecordDecl *D, TypeSourceInfo *Info, bool Dependent)
+ : DefinitionData(D), Dependent(Dependent), NumCaptures(0),
+ NumExplicitCaptures(0), ManglingNumber(0), ContextDecl(0),
+ Captures(0), MethodTyInfo(Info), TheLambdaExpr(0)
{
IsLambda = true;
}
/// artifact of having to parse the default arguments before.
unsigned Dependent : 1;
- /// \brief Whether this lambda is a generic lambda.
- unsigned IsGenericLambda : 1;
-
- /// \brief The Default Capture.
- unsigned CaptureDefault : 2;
-
- /// \brief The number of captures in this lambda is limited 2^NumCaptures.
- unsigned NumCaptures : 15;
+ /// \brief The number of captures in this lambda.
+ unsigned NumCaptures : 16;
/// \brief The number of explicit captures in this lambda.
- unsigned NumExplicitCaptures : 13;
+ unsigned NumExplicitCaptures : 15;
/// \brief The number used to indicate this lambda expression for name
/// mangling in the Itanium C++ ABI.
/// \brief The type of the call method.
TypeSourceInfo *MethodTyInfo;
+
+ /// \brief The AST node of the lambda expression.
+ LambdaExpr *TheLambdaExpr;
};
bool DelayTypeCreation = false);
static CXXRecordDecl *CreateLambda(const ASTContext &C, DeclContext *DC,
TypeSourceInfo *Info, SourceLocation Loc,
- bool DependentLambda, bool IsGeneric,
- LambdaCaptureDefault CaptureDefault);
+ bool DependentLambda);
static CXXRecordDecl *CreateDeserialized(const ASTContext &C, unsigned ID);
bool isDynamicClass() const {
/// lambda.
TemplateParameterList *getGenericLambdaTemplateParameterList() const;
- LambdaCaptureDefault getLambdaCaptureDefault() const {
- assert(isLambda());
- return static_cast<LambdaCaptureDefault>(getLambdaData().CaptureDefault);
+ /// \brief Assign the member call operator of the lambda.
+ void setLambdaExpr(LambdaExpr *E) {
+ getLambdaData().TheLambdaExpr = E;
}
+ /// \brief Retrieve the parent lambda expression.
+ LambdaExpr *getLambdaExpr() const {
+ return isLambda() ? getLambdaData().TheLambdaExpr : 0;
+ }
+
+
/// \brief For a closure type, retrieve the mapping from captured
/// variables and \c this to the non-static data members that store the
/// values or references of the captures.
/// \brief Create a new lambda closure type.
CXXRecordDecl *createLambdaClosureType(SourceRange IntroducerRange,
TypeSourceInfo *Info,
- bool KnownDependent,
- LambdaCaptureDefault CaptureDefault);
+ bool KnownDependent);
/// \brief Start the definition of a lambda expression.
CXXMethodDecl *startLambdaDefinition(CXXRecordDecl *Class,
CXXRecordDecl *CXXRecordDecl::CreateLambda(const ASTContext &C, DeclContext *DC,
TypeSourceInfo *Info, SourceLocation Loc,
- bool Dependent, bool IsGeneric,
- LambdaCaptureDefault CaptureDefault) {
+ bool Dependent) {
CXXRecordDecl* R = new (C) CXXRecordDecl(CXXRecord, TTK_Class, DC, Loc, Loc,
0, 0);
R->IsBeingDefined = true;
- R->DefinitionData = new (C) struct LambdaDefinitionData(R, Info,
- Dependent,
- IsGeneric,
- CaptureDefault);
+ R->DefinitionData = new (C) struct LambdaDefinitionData(R, Info, Dependent);
R->MayHaveOutOfDateDef = false;
R->setImplicit(true);
C.getTypeDeclType(R, /*PrevDecl=*/0);
return isPOD() && data().HasOnlyCMembers;
}
-
+
bool CXXRecordDecl::isGenericLambda() const {
- if (!isLambda()) return false;
- return getLambdaData().IsGenericLambda;
+ return isLambda() &&
+ getLambdaCallOperator()->getDescribedFunctionTemplate();
}
CXXMethodDecl* CXXRecordDecl::getLambdaCallOperator() const {
Diag(Definition->getLocation(), diag::note_previous_definition);
FD->setInvalidDecl();
}
-static void RebuildLambdaScopeInfo(CXXMethodDecl *CallOperator,
- Sema &S) {
- CXXRecordDecl *const LambdaClass = CallOperator->getParent();
- S.PushLambdaScope();
- LambdaScopeInfo *LSI = S.getCurLambda();
- LSI->CallOperator = CallOperator;
- LSI->Lambda = LambdaClass;
- LSI->ReturnType = CallOperator->getResultType();
- const LambdaCaptureDefault LCD = LambdaClass->getLambdaCaptureDefault();
-
- if (LCD == LCD_None)
- LSI->ImpCaptureStyle = CapturingScopeInfo::ImpCap_None;
- else if (LCD == LCD_ByCopy)
- LSI->ImpCaptureStyle = CapturingScopeInfo::ImpCap_LambdaByval;
- else if (LCD == LCD_ByRef)
- LSI->ImpCaptureStyle = CapturingScopeInfo::ImpCap_LambdaByref;
- DeclarationNameInfo DNI = CallOperator->getNameInfo();
-
- LSI->IntroducerRange = DNI.getCXXOperatorNameRange();
- LSI->Mutable = !CallOperator->isConst();
-
- // FIXME: Add the captures to the LSI.
-}
Decl *Sema::ActOnStartOfFunctionDef(Scope *FnBodyScope, Decl *D) {
// Clear the last template instantiation error context.
FD = cast<FunctionDecl>(D);
// If we are instantiating a generic lambda call operator, push
// a LambdaScopeInfo onto the function stack. But use the information
- // that's already been calculated (ActOnLambdaExpr) to prime the current
- // LambdaScopeInfo.
- // When the template operator is being specialized, the LambdaScopeInfo,
- // has to be properly restored so that tryCaptureVariable doesn't try
- // and capture any new variables. In addition when calculating potential
- // captures during transformation of nested lambdas, it is necessary to
- // have the LSI properly restored.
+ // that's already been calculated (ActOnLambdaExpr) when analyzing the
+ // template version, to prime the current LambdaScopeInfo.
if (isGenericLambdaCallOperatorSpecialization(FD)) {
+ CXXMethodDecl *CallOperator = cast<CXXMethodDecl>(D);
+ CXXRecordDecl *LambdaClass = CallOperator->getParent();
+ LambdaExpr *LE = LambdaClass->getLambdaExpr();
+ assert(LE &&
+ "No LambdaExpr of closure class when instantiating a generic lambda!");
assert(ActiveTemplateInstantiations.size() &&
"There should be an active template instantiation on the stack "
"when instantiating a generic lambda!");
- RebuildLambdaScopeInfo(cast<CXXMethodDecl>(D), *this);
+ PushLambdaScope();
+ LambdaScopeInfo *LSI = getCurLambda();
+ LSI->CallOperator = CallOperator;
+ LSI->Lambda = LambdaClass;
+ LSI->ReturnType = CallOperator->getResultType();
+
+ if (LE->getCaptureDefault() == LCD_None)
+ LSI->ImpCaptureStyle = CapturingScopeInfo::ImpCap_None;
+ else if (LE->getCaptureDefault() == LCD_ByCopy)
+ LSI->ImpCaptureStyle = CapturingScopeInfo::ImpCap_LambdaByval;
+ else if (LE->getCaptureDefault() == LCD_ByRef)
+ LSI->ImpCaptureStyle = CapturingScopeInfo::ImpCap_LambdaByref;
+
+ LSI->IntroducerRange = LE->getIntroducerRange();
}
else
// Enter a new function scope
PopDeclContext();
PopFunctionScopeInfo(ActivePolicy, dcl);
+
// If any errors have occurred, clear out any temporaries that may have
// been leftover. This ensures that these temporaries won't be picked up for
// deletion in some later function.
using namespace clang;
using namespace sema;
-
-static inline TemplateParameterList *
-getGenericLambdaTemplateParameterList(LambdaScopeInfo *LSI, Sema &SemaRef) {
- if (LSI->GLTemplateParameterList)
- return LSI->GLTemplateParameterList;
-
- if (LSI->AutoTemplateParams.size()) {
- SourceRange IntroRange = LSI->IntroducerRange;
- SourceLocation LAngleLoc = IntroRange.getBegin();
- SourceLocation RAngleLoc = IntroRange.getEnd();
- LSI->GLTemplateParameterList = TemplateParameterList::Create(
- SemaRef.Context,
- /*Template kw loc*/SourceLocation(),
- LAngleLoc,
- (NamedDecl**)LSI->AutoTemplateParams.data(),
- LSI->AutoTemplateParams.size(), RAngleLoc);
- }
- return LSI->GLTemplateParameterList;
-}
-
-
-
CXXRecordDecl *Sema::createLambdaClosureType(SourceRange IntroducerRange,
TypeSourceInfo *Info,
- bool KnownDependent,
- LambdaCaptureDefault CaptureDefault) {
+ bool KnownDependent) {
DeclContext *DC = CurContext;
while (!(DC->isFunctionOrMethod() || DC->isRecord() || DC->isFileContext()))
DC = DC->getParent();
- bool IsGenericLambda = getGenericLambdaTemplateParameterList(getCurLambda(),
- *this);
+
// Start constructing the lambda class.
CXXRecordDecl *Class = CXXRecordDecl::CreateLambda(Context, DC, Info,
IntroducerRange.getBegin(),
- KnownDependent,
- IsGenericLambda,
- CaptureDefault);
+ KnownDependent);
DC->addDecl(Class);
return Class;
return *MangleNumbering;
}
+static inline TemplateParameterList *
+getGenericLambdaTemplateParameterList(LambdaScopeInfo *LSI, Sema &SemaRef) {
+ if (LSI->GLTemplateParameterList)
+ return LSI->GLTemplateParameterList;
+ else if (LSI->AutoTemplateParams.size()) {
+ SourceRange IntroRange = LSI->IntroducerRange;
+ SourceLocation LAngleLoc = IntroRange.getBegin();
+ SourceLocation RAngleLoc = IntroRange.getEnd();
+ LSI->GLTemplateParameterList =
+ TemplateParameterList::Create(SemaRef.Context,
+ /* Template kw loc */ SourceLocation(),
+ LAngleLoc,
+ (NamedDecl**)LSI->AutoTemplateParams.data(),
+ LSI->AutoTemplateParams.size(), RAngleLoc);
+ }
+ return LSI->GLTemplateParameterList;
+}
+
+
CXXMethodDecl *Sema::startLambdaDefinition(CXXRecordDecl *Class,
SourceRange IntroducerRange,
TypeSourceInfo *MethodTypeInfo,
bool ExplicitResultType,
bool Mutable) {
LSI->CallOperator = CallOperator;
- CXXRecordDecl *LambdaClass = CallOperator->getParent();
- LSI->Lambda = LambdaClass;
+ LSI->Lambda = CallOperator->getParent();
if (CaptureDefault == LCD_ByCopy)
LSI->ImpCaptureStyle = LambdaScopeInfo::ImpCap_LambdaByval;
else if (CaptureDefault == LCD_ByRef)
}
CXXRecordDecl *Class = createLambdaClosureType(Intro.Range, MethodTyInfo,
- KnownDependent, Intro.Default);
+ KnownDependent);
CXXMethodDecl *Method = startLambdaDefinition(Class, Intro.Range,
MethodTyInfo, EndLoc, Params);
CaptureInits, ArrayIndexVars,
ArrayIndexStarts, Body->getLocEnd(),
ContainsUnexpandedParameterPack);
+ Class->setLambdaExpr(Lambda);
// C++11 [expr.prim.lambda]p2:
// A lambda-expression shall not appear in an unevaluated operand
// (Clause 5).
#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"
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.
}
ExprResult TransformLambdaScope(LambdaExpr *E,
- CXXMethodDecl *NewCallOperator) {
- CXXMethodDecl *const OldCallOperator = E->getCallOperator();
- // In the generic lambda case, we set the NewTemplate to be considered
- // an "instantiation" of the OldTemplate.
- if (FunctionTemplateDecl *const NewCallOperatorTemplate =
- NewCallOperator->getDescribedFunctionTemplate()) {
-
- FunctionTemplateDecl *const OldCallOperatorTemplate =
- OldCallOperator->getDescribedFunctionTemplate();
- NewCallOperatorTemplate->setInstantiatedFromMemberTemplate(
- OldCallOperatorTemplate);
- // Mark the NewCallOperatorTemplate a specialization.
- NewCallOperatorTemplate->setMemberSpecialization();
- } else
- // For a non-generic lambda we set the NewCallOperator to
- // be an instantiation of the OldCallOperator.
- NewCallOperator->setInstantiationOfMemberFunction(OldCallOperator,
- TSK_ImplicitInstantiation);
-
- return inherited::TransformLambdaScope(E, NewCallOperator);
- }
- TemplateParameterList *TransformTemplateParameterList(\r
- TemplateParameterList *OrigTPL) {
- if (!OrigTPL || !OrigTPL->size()) return OrigTPL;
-
- DeclContext *Owner = OrigTPL->getParam(0)->getDeclContext();
- TemplateDeclInstantiator DeclInstantiator(getSema(),
- /* DeclContext *Owner */ Owner, TemplateArgs);
- return DeclInstantiator.SubstTemplateParams(OrigTPL);
+ CXXMethodDecl *CallOperator) {
+ CallOperator->setInstantiationOfMemberFunction(E->getCallOperator(),
+ TSK_ImplicitInstantiation);
+ return TreeTransform<TemplateInstantiator>::
+ TransformLambdaScope(E, CallOperator);
}
+
private:
ExprResult transformNonTypeTemplateParmRef(NonTypeTemplateParmDecl *parm,
SourceLocation loc,
NamedDecl *Sema::FindInstantiatedDecl(SourceLocation Loc, NamedDecl *D,
const MultiLevelTemplateArgumentList &TemplateArgs) {
DeclContext *ParentDC = D->getDeclContext();
-
- if (isa<NonTypeTemplateParmDecl>(D) ||
+ if (isa<ParmVarDecl>(D) || isa<NonTypeTemplateParmDecl>(D) ||
isa<TemplateTypeParmDecl>(D) || isa<TemplateTemplateParmDecl>(D) ||
(ParentDC->isFunctionOrMethod() && ParentDC->isDependentContext()) ||
(isa<CXXRecordDecl>(D) && cast<CXXRecordDecl>(D)->isLambda())) {
/// \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);
ExprResult
TreeTransform<Derived>::TransformLambdaExpr(LambdaExpr *E) {
- getSema().PushLambdaScope();
- LambdaScopeInfo *LSI = getSema().getCurLambda();
- // Transform the template parameters, and add them to the current
- // instantiation scope. The null case is handled correctly.
- LSI->GLTemplateParameterList = getDerived().TransformTemplateParameterList(
- E->getTemplateParameterList());
-
- // Check to see if the TypeSourceInfo of the call operator needs to
- // be transformed, and if so do the transformation in the
- // CurrentInstantiationScope.
-
- TypeSourceInfo *OldCallOpTSI = E->getCallOperator()->getTypeSourceInfo();
- FunctionProtoTypeLoc OldCallOpFPTL =
- OldCallOpTSI->getTypeLoc().getAs<FunctionProtoTypeLoc>();
- TypeSourceInfo *NewCallOpTSI = 0;
-
- const bool CallOpWasAlreadyTransformed =
- getDerived().AlreadyTransformed(OldCallOpTSI->getType());
-
- // Use the Old Call Operator's TypeSourceInfo if it is already transformed.
- if (CallOpWasAlreadyTransformed)
- NewCallOpTSI = OldCallOpTSI;
- else {
- // Transform the TypeSourceInfo of the Original Lambda's Call Operator.
- // The transformation MUST be done in the CurrentInstantiationScope since
- // it introduces a mapping of the original to the newly created
- // transformed parameters.
-
- TypeLocBuilder NewCallOpTLBuilder;
- QualType NewCallOpType = TransformFunctionProtoType(NewCallOpTLBuilder,
- OldCallOpFPTL,
- 0, 0);
- NewCallOpTSI = NewCallOpTLBuilder.getTypeSourceInfo(getSema().Context,
- NewCallOpType);
- }
- // Extract the ParmVarDecls from the NewCallOpTSI and add them to
- // the vector below - this will be used to synthesize the
- // NewCallOperator. Additionally, add the parameters of the untransformed
- // lambda call operator to the CurrentInstantiationScope.
- SmallVector<ParmVarDecl *, 4> Params;
- {
- FunctionProtoTypeLoc NewCallOpFPTL =
- NewCallOpTSI->getTypeLoc().castAs<FunctionProtoTypeLoc>();
- ParmVarDecl **NewParamDeclArray = NewCallOpFPTL.getParmArray();
- const unsigned NewNumArgs = NewCallOpFPTL.getNumArgs();
-
- for (unsigned I = 0; I < NewNumArgs; ++I) {
- // If this call operator's type does not require transformation,
- // the parameters do not get added to the current instantiation scope,
- // - so ADD them! This allows the following to compile when the enclosing
- // template is specialized and the entire lambda expression has to be
- // transformed.
- // 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 (CallOpWasAlreadyTransformed)
- getDerived().transformedLocalDecl(NewParamDeclArray[I],
- NewParamDeclArray[I]);
- // Add to Params array, so these parameters can be used to create
- // the newly transformed call operator.
- Params.push_back(NewParamDeclArray[I]);
- }
+ // 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();
}
-
- if (!NewCallOpTSI)
+ // Transform the type of the lambda parameters and start the definition of
+ // the lambda itself.
+ TypeSourceInfo *MethodTy
+ = TransformType(E->getCallOperator()->getTypeSourceInfo());
+ if (!MethodTy)
return ExprError();
// Create the local class that will describe the lambda.
CXXRecordDecl *Class
= getSema().createLambdaClosureType(E->getIntroducerRange(),
- NewCallOpTSI,
- /*KnownDependent=*/false,
- E->getCaptureDefault());
-
+ MethodTy,
+ /*KnownDependent=*/false);
getDerived().transformedLocalDecl(E->getLambdaClass(), Class);
+ // Transform lambda parameters.
+ SmallVector<QualType, 4> ParamTypes;
+ SmallVector<ParmVarDecl *, 4> Params;
+ if (getDerived().TransformFunctionTypeParams(E->getLocStart(),
+ E->getCallOperator()->param_begin(),
+ 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 *NewCallOperator
+ CXXMethodDecl *CallOperator
= getSema().startLambdaDefinition(Class, E->getIntroducerRange(),
- NewCallOpTSI,
+ MethodTy,
E->getCallOperator()->getLocEnd(),
Params);
- LSI->CallOperator = NewCallOperator;
-
- getDerived().transformAttrs(E->getCallOperator(), NewCallOperator);
+ getDerived().transformAttrs(E->getCallOperator(), CallOperator);
- return getDerived().TransformLambdaScope(E, NewCallOperator);
+ return getDerived().TransformLambdaScope(E, CallOperator);
}
template<typename Derived>
CXXRecordDecl::LambdaDefinitionData &Lambda
= static_cast<CXXRecordDecl::LambdaDefinitionData &>(Data);
Lambda.Dependent = Record[Idx++];
- Lambda.IsGenericLambda = Record[Idx++];
- Lambda.CaptureDefault = Record[Idx++];
Lambda.NumCaptures = Record[Idx++];
Lambda.NumExplicitCaptures = Record[Idx++];
Lambda.ManglingNumber = Record[Idx++];
= (Capture*)Reader.Context.Allocate(sizeof(Capture)*Lambda.NumCaptures);
Capture *ToCapture = Lambda.Captures;
Lambda.MethodTyInfo = GetTypeSourceInfo(Record, Idx);
+ Lambda.TheLambdaExpr = cast<LambdaExpr>(Reader.ReadExpr(F));
for (unsigned I = 0, N = Lambda.NumCaptures; I != N; ++I) {
SourceLocation Loc = ReadSourceLocation(Record, Idx);
bool IsImplicit = Record[Idx++];
bool IsLambda = Record[Idx++];
if (IsLambda)
D->DefinitionData = new (C) CXXRecordDecl::LambdaDefinitionData(D, 0,
- false,
- false, LCD_None);
+ false);
else
D->DefinitionData = new (C) struct CXXRecordDecl::DefinitionData(D);
if (Data.IsLambda) {
CXXRecordDecl::LambdaDefinitionData &Lambda = D->getLambdaData();
Record.push_back(Lambda.Dependent);
- Record.push_back(Lambda.IsGenericLambda);
- Record.push_back(Lambda.CaptureDefault);
Record.push_back(Lambda.NumCaptures);
Record.push_back(Lambda.NumExplicitCaptures);
Record.push_back(Lambda.ManglingNumber);
AddDeclRef(Lambda.ContextDecl, Record);
AddTypeSourceInfo(Lambda.MethodTyInfo, Record);
+ AddStmt(Lambda.TheLambdaExpr);
for (unsigned I = 0, N = Lambda.NumCaptures; I != N; ++I) {
LambdaExpr::Capture &Capture = Lambda.Captures[I];
AddSourceLocation(Capture.getLocation(), Record);
}
+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}}
+}
+
+
+++ /dev/null
-// RUN: %clang_cc1 -pedantic-errors -fblocks -std=c++1y -emit-pch %s -o %t-cxx1y\r
-// RUN: %clang_cc1 -ast-print -pedantic-errors -fblocks -std=c++1y -include-pch %t-cxx1y %s | FileCheck -check-prefix=CHECK-PRINT %s\r
-\r
-#ifndef HEADER_INCLUDED\r
-\r
-#define HEADER_INCLUDED\r
-template<typename T>\r
-T add_slowly(const T& x, const T &y) {\r
- return [](auto z, int y = 0) { return z + y; }(5);\r
-};\r
-\r
-inline int add_int_slowly_twice(int x, int y) {\r
- int i = add_slowly(x, y);\r
- auto lambda = [](auto z) { return z + z; };\r
- return i + lambda(y);\r
-}\r
-\r
-inline int sum_array(int n) {\r
- auto lambda = [](auto N) -> int {\r
- int sum = 0;\r
- int array[5] = { 1, 2, 3, 4, 5};\r
- \r
- for (unsigned I = 0; I < N; ++I)\r
- sum += array[N];\r
- return sum;\r
- };\r
-\r
- return lambda(n);\r
-}\r
-\r
-inline int to_block_pointer(int n) {\r
- auto lambda = [=](int m) { return n + m; };\r
- int (^block)(int) = lambda;\r
- return block(17);\r
-}\r
-\r
-template<typename T>\r
-int init_capture(T t) {\r
- return [&, x(t)] { return sizeof(x); };\r
-}\r
-\r
-#else\r
-\r
-// CHECK-PRINT: T add_slowly\r
-// CHECK-PRINT: return []\r
-template float add_slowly(const float&, const float&);\r
-\r
-int add(int x, int y) {\r
- return add_int_slowly_twice(x, y) + sum_array(4) + to_block_pointer(5);\r
-}\r
-\r
-// CHECK-PRINT: inline int add_int_slowly_twice \r
-// CHECK-PRINT: lambda = [] ($auto-0-0 z\r
-\r
-// CHECK-PRINT: init_capture\r
-// CHECK-PRINT: [&, x( t )]\r
-\r
-#endif\r
-// RUN: %clang_cc1 -std=c++1y -verify -fsyntax-only -fblocks -emit-llvm -o - %s
+// RUN: %clang_cc1 -std=c++1y -verify -fsyntax-only -fblocks %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
//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);
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
-
-namespace PR17476 {
-struct string {
- string(const char *__s) { }
- string &operator+=(const string &__str) { return *this; }
-};
-
-template <class T>
-void finalizeDefaultAtomValues() {
- auto startEnd = [](const char * sym) -> void {
- string start("__");
- start += sym;
- };
- startEnd("preinit_array");
-}
-
-void f() { finalizeDefaultAtomValues<char>(); }
-
-}
-
-namespace PR17476_variant {
-struct string {
- string(const char *__s) { }
- string &operator+=(const string &__str) { return *this; }
-};
-
-template <class T>
-void finalizeDefaultAtomValues() {
- auto startEnd = [](const T *sym) -> void {
- string start("__");
- start += sym;
- };
- startEnd("preinit_array");
-}
-
-void f() { finalizeDefaultAtomValues<char>(); }
-
-}
\ No newline at end of file