[llvm-branch-commits] [cfe-branch] r196470 - Merging r196454:
NAKAMURA Takumi
geek4civic at gmail.com
Fri Dec 6 01:01:05 PST 2013
Bill, it requires merging r196459 to suppress warnings.
2013/12/5 Bill Wendling <isanbard at gmail.com>:
> Author: void
> Date: Wed Dec 4 23:25:04 2013
> New Revision: 196470
>
> URL: http://llvm.org/viewvc/llvm-project?rev=196470&view=rev
> Log:
> Merging r196454:
> ------------------------------------------------------------------------
> r196454 | faisalv | 2013-12-04 17:40:41 -0800 (Wed, 04 Dec 2013) | 43 lines
>
> Fix init-captures for generic lambdas.
>
> For an init capture, process the initialization expression
> right away. For lambda init-captures such as the following:
> const int x = 10;
> auto L = [i = x+1](int a) {
> return [j = x+2,
> &k = x](char b) { };
> };
> keep in mind that each lambda init-capture has to have:
> - its initialization expression executed in the context
> of the enclosing/parent decl-context.
> - but the variable itself has to be 'injected' into the
> decl-context of its lambda's call-operator (which has
> not yet been created).
> Each init-expression is a full-expression that has to get
> Sema-analyzed (for capturing etc.) before its lambda's
> call-operator's decl-context, scope & scopeinfo are pushed on their
> respective stacks. Thus if any variable is odr-used in the init-capture
> it will correctly get captured in the enclosing lambda, if one exists.
> The init-variables above are created later once the lambdascope and
> call-operators decl-context is pushed onto its respective stack.
>
> Since the lambda init-capture's initializer expression occurs in the
> context of the enclosing function or lambda, therefore we can not wait
> till a lambda scope has been pushed on before deciding whether the
> variable needs to be captured. We also need to process all
> lvalue-to-rvalue conversions and discarded-value conversions,
> so that we can avoid capturing certain constant variables.
> For e.g.,
> void test() {
> const int x = 10;
> auto L = [&z = x](char a) { <-- don't capture by the current lambda
> return [y = x](int i) { <-- don't capture by enclosing lambda
> return y;
> }
> };
> If x was not const, the second use would require 'L' to capture, and
> that would be an error.
> Make sure TranformLambdaExpr is also aware of this.
>
> Patch approved by Richard (Thanks!!)
> http://llvm-reviews.chandlerc.com/D2092
> ------------------------------------------------------------------------
>
> Modified:
> cfe/branches/release_34/ (props changed)
> cfe/branches/release_34/include/clang/Sema/DeclSpec.h
> cfe/branches/release_34/include/clang/Sema/Initialization.h
> cfe/branches/release_34/include/clang/Sema/Sema.h
> cfe/branches/release_34/lib/Parse/ParseExprCXX.cpp
> cfe/branches/release_34/lib/Sema/SemaAccess.cpp
> cfe/branches/release_34/lib/Sema/SemaExpr.cpp
> cfe/branches/release_34/lib/Sema/SemaExprCXX.cpp
> cfe/branches/release_34/lib/Sema/SemaInit.cpp
> cfe/branches/release_34/lib/Sema/SemaLambda.cpp
> cfe/branches/release_34/lib/Sema/SemaTemplateInstantiate.cpp
> cfe/branches/release_34/lib/Sema/TreeTransform.h
> cfe/branches/release_34/test/SemaCXX/cxx1y-init-captures.cpp
>
> Propchange: cfe/branches/release_34/
> ------------------------------------------------------------------------------
> --- svn:mergeinfo (original)
> +++ svn:mergeinfo Wed Dec 4 23:25:04 2013
> @@ -1,4 +1,4 @@
> /cfe/branches/type-system-rewrite:134693-134817
> -/cfe/trunk:195126,195128,195135-195136,195146,195149,195154,195158,195163,195168,195174,195249,195268,195283,195303,195326,195329,195367,195384,195409,195420,195422,195501,195547,195556,195558,195587,195620,195635,195669,195687,195693,195710,195713,195716,195756,195760,195768,195777,195789,195792,195804,195827,195843-195844,195877,195887-195888,195897,195903,195905-195906,195932,195936-195943,195970,195983,196045,196048,196050,196058,196114-196115,196153,196206,196215,196370,196423
> +/cfe/trunk:195126,195128,195135-195136,195146,195149,195154,195158,195163,195168,195174,195249,195268,195283,195303,195326,195329,195367,195384,195409,195420,195422,195501,195547,195556,195558,195587,195620,195635,195669,195687,195693,195710,195713,195716,195756,195760,195768,195777,195789,195792,195804,195827,195843-195844,195877,195887-195888,195897,195903,195905-195906,195932,195936-195943,195970,195983,196045,196048,196050,196058,196114-196115,196153,196206,196215,196370,196423,196454
> /cfe/trunk/test:170344
> /cfe/trunk/test/SemaTemplate:126920
>
> Modified: cfe/branches/release_34/include/clang/Sema/DeclSpec.h
> URL: http://llvm.org/viewvc/llvm-project/cfe/branches/release_34/include/clang/Sema/DeclSpec.h?rev=196470&r1=196469&r2=196470&view=diff
> ==============================================================================
> --- cfe/branches/release_34/include/clang/Sema/DeclSpec.h (original)
> +++ cfe/branches/release_34/include/clang/Sema/DeclSpec.h Wed Dec 4 23:25:04 2013
> @@ -2166,12 +2166,13 @@ struct LambdaCapture {
> IdentifierInfo *Id;
> SourceLocation EllipsisLoc;
> ExprResult Init;
> -
> + ParsedType InitCaptureType;
> LambdaCapture(LambdaCaptureKind Kind, SourceLocation Loc,
> - IdentifierInfo* Id = 0,
> - SourceLocation EllipsisLoc = SourceLocation(),
> - ExprResult Init = ExprResult())
> - : Kind(Kind), Loc(Loc), Id(Id), EllipsisLoc(EllipsisLoc), Init(Init)
> + IdentifierInfo* Id,
> + SourceLocation EllipsisLoc,
> + ExprResult Init, ParsedType InitCaptureType)
> + : Kind(Kind), Loc(Loc), Id(Id), EllipsisLoc(EllipsisLoc), Init(Init),
> + InitCaptureType(InitCaptureType)
> {}
> };
>
> @@ -2188,10 +2189,12 @@ struct LambdaIntroducer {
> /// \brief Append a capture in a lambda introducer.
> void addCapture(LambdaCaptureKind Kind,
> SourceLocation Loc,
> - IdentifierInfo* Id = 0,
> - SourceLocation EllipsisLoc = SourceLocation(),
> - ExprResult Init = ExprResult()) {
> - Captures.push_back(LambdaCapture(Kind, Loc, Id, EllipsisLoc, Init));
> + IdentifierInfo* Id,
> + SourceLocation EllipsisLoc,
> + ExprResult Init,
> + ParsedType InitCaptureType) {
> + Captures.push_back(LambdaCapture(Kind, Loc, Id, EllipsisLoc, Init,
> + InitCaptureType));
> }
> };
>
>
> Modified: cfe/branches/release_34/include/clang/Sema/Initialization.h
> URL: http://llvm.org/viewvc/llvm-project/cfe/branches/release_34/include/clang/Sema/Initialization.h?rev=196470&r1=196469&r2=196470&view=diff
> ==============================================================================
> --- cfe/branches/release_34/include/clang/Sema/Initialization.h (original)
> +++ cfe/branches/release_34/include/clang/Sema/Initialization.h Wed Dec 4 23:25:04 2013
> @@ -116,8 +116,8 @@ private:
> };
>
> struct C {
> - /// \brief The variable being captured by an EK_LambdaCapture.
> - VarDecl *Var;
> + /// \brief The name of the variable being captured by an EK_LambdaCapture.
> + IdentifierInfo *VarID;
>
> /// \brief The source location at which the capture occurs.
> unsigned Location;
> @@ -183,10 +183,10 @@ private:
> const InitializedEntity &Parent);
>
> /// \brief Create the initialization entity for a lambda capture.
> - InitializedEntity(VarDecl *Var, FieldDecl *Field, SourceLocation Loc)
> - : Kind(EK_LambdaCapture), Parent(0), Type(Field->getType())
> + InitializedEntity(IdentifierInfo *VarID, QualType FieldType, SourceLocation Loc)
> + : Kind(EK_LambdaCapture), Parent(0), Type(FieldType)
> {
> - Capture.Var = Var;
> + Capture.VarID = VarID;
> Capture.Location = Loc.getRawEncoding();
> }
>
> @@ -309,10 +309,10 @@ public:
> }
>
> /// \brief Create the initialization entity for a lambda capture.
> - static InitializedEntity InitializeLambdaCapture(VarDecl *Var,
> - FieldDecl *Field,
> + static InitializedEntity InitializeLambdaCapture(IdentifierInfo *VarID,
> + QualType FieldType,
> SourceLocation Loc) {
> - return InitializedEntity(Var, Field, Loc);
> + return InitializedEntity(VarID, FieldType, Loc);
> }
>
> /// \brief Create the entity for a compound literal initializer.
> @@ -402,13 +402,11 @@ public:
> getKind() == EK_ComplexElement);
> this->Index = Index;
> }
> -
> - /// \brief Retrieve the variable for a captured variable in a lambda.
> - VarDecl *getCapturedVar() const {
> + /// \brief For a lambda capture, return the capture's name.
> + StringRef getCapturedVarName() const {
> assert(getKind() == EK_LambdaCapture && "Not a lambda capture!");
> - return Capture.Var;
> + return Capture.VarID->getName();
> }
> -
> /// \brief Determine the location of the capture when initializing
> /// field from a captured variable in a lambda.
> SourceLocation getCaptureLoc() const {
>
> Modified: cfe/branches/release_34/include/clang/Sema/Sema.h
> URL: http://llvm.org/viewvc/llvm-project/cfe/branches/release_34/include/clang/Sema/Sema.h?rev=196470&r1=196469&r2=196470&view=diff
> ==============================================================================
> --- cfe/branches/release_34/include/clang/Sema/Sema.h (original)
> +++ cfe/branches/release_34/include/clang/Sema/Sema.h Wed Dec 4 23:25:04 2013
> @@ -281,6 +281,12 @@ public:
> /// element type here is ExprWithCleanups::Object.
> SmallVector<BlockDecl*, 8> ExprCleanupObjects;
>
> + /// \brief Store a list of either DeclRefExprs or MemberExprs
> + /// that contain a reference to a variable (constant) that may or may not
> + /// be odr-used in this Expr, and we won't know until all lvalue-to-rvalue
> + /// and discarded value conversions have been applied to all subexpressions
> + /// of the enclosing full expression. This is cleared at the end of each
> + /// full expression.
> llvm::SmallPtrSet<Expr*, 2> MaybeODRUseExprs;
>
> /// \brief Stack containing information about each of the nested
> @@ -4311,7 +4317,8 @@ public:
> }
> ExprResult ActOnFinishFullExpr(Expr *Expr, SourceLocation CC,
> bool DiscardedValue = false,
> - bool IsConstexpr = false);
> + bool IsConstexpr = false,
> + bool IsLambdaInitCaptureInitializer = false);
> StmtResult ActOnFinishFullStmt(Stmt *Stmt);
>
> // Marks SS invalid if it represents an incomplete type.
> @@ -4506,10 +4513,18 @@ public:
> bool ExplicitResultType,
> bool Mutable);
>
> - /// \brief Check an init-capture and build the implied variable declaration
> - /// with the specified name and initializer.
> - VarDecl *checkInitCapture(SourceLocation Loc, bool ByRef,
> - IdentifierInfo *Id, Expr *Init);
> + /// \brief Perform initialization analysis of the init-capture and perform
> + /// any implicit conversions such as an lvalue-to-rvalue conversion if
> + /// not being used to initialize a reference.
> + QualType performLambdaInitCaptureInitialization(SourceLocation Loc,
> + bool ByRef, IdentifierInfo *Id, Expr *&Init);
> + /// \brief Create a dummy variable within the declcontext of the lambda's
> + /// call operator, for name lookup purposes for a lambda init capture.
> + ///
> + /// CodeGen handles emission of lambda captures, ignoring these dummy
> + /// variables appropriately.
> + VarDecl *createLambdaInitCaptureVarDecl(SourceLocation Loc,
> + QualType InitCaptureType, IdentifierInfo *Id, Expr *Init);
>
> /// \brief Build the implicit field for an init-capture.
> FieldDecl *buildInitCaptureField(sema::LambdaScopeInfo *LSI, VarDecl *Var);
>
> Modified: cfe/branches/release_34/lib/Parse/ParseExprCXX.cpp
> URL: http://llvm.org/viewvc/llvm-project/cfe/branches/release_34/lib/Parse/ParseExprCXX.cpp?rev=196470&r1=196469&r2=196470&view=diff
> ==============================================================================
> --- cfe/branches/release_34/lib/Parse/ParseExprCXX.cpp (original)
> +++ cfe/branches/release_34/lib/Parse/ParseExprCXX.cpp Wed Dec 4 23:25:04 2013
> @@ -633,8 +633,7 @@ ExprResult Parser::ParseCXXIdExpression(
> ExprResult Parser::ParseLambdaExpression() {
> // Parse lambda-introducer.
> LambdaIntroducer Intro;
> -
> - Optional<unsigned> DiagID(ParseLambdaIntroducer(Intro));
> + Optional<unsigned> DiagID = ParseLambdaIntroducer(Intro);
> if (DiagID) {
> Diag(Tok, DiagID.getValue());
> SkipUntil(tok::r_square, StopAtSemi);
> @@ -674,7 +673,7 @@ ExprResult Parser::TryParseLambdaExpress
> if (Next.is(tok::identifier) && After.is(tok::identifier)) {
> return ExprEmpty();
> }
> -
> +
> // Here, we're stuck: lambda introducers and Objective-C message sends are
> // unambiguous, but it requires arbitrary lookhead. [a,b,c,d,e,f,g] is a
> // lambda, and [a,b,c,d,e,f,g h] is a Objective-C message send. Instead of
> @@ -684,6 +683,7 @@ ExprResult Parser::TryParseLambdaExpress
> LambdaIntroducer Intro;
> if (TryParseLambdaIntroducer(Intro))
> return ExprEmpty();
> +
> return ParseLambdaExpressionAfterIntroducer(Intro);
> }
>
> @@ -809,6 +809,11 @@ Optional<unsigned> Parser::ParseLambdaIn
> Exprs);
> }
> } else if (Tok.is(tok::l_brace) || Tok.is(tok::equal)) {
> + // Each lambda init-capture forms its own full expression, which clears
> + // Actions.MaybeODRUseExprs. So create an expression evaluation context
> + // to save the necessary state, and restore it later.
> + EnterExpressionEvaluationContext EC(Actions,
> + Sema::PotentiallyEvaluated);
> if (Tok.is(tok::equal))
> ConsumeToken();
>
> @@ -862,13 +867,61 @@ Optional<unsigned> Parser::ParseLambdaIn
> } else if (Tok.is(tok::ellipsis))
> EllipsisLoc = ConsumeToken();
> }
> -
> - Intro.addCapture(Kind, Loc, Id, EllipsisLoc, Init);
> + // If this is an init capture, process the initialization expression
> + // right away. For lambda init-captures such as the following:
> + // const int x = 10;
> + // auto L = [i = x+1](int a) {
> + // return [j = x+2,
> + // &k = x](char b) { };
> + // };
> + // keep in mind that each lambda init-capture has to have:
> + // - its initialization expression executed in the context
> + // of the enclosing/parent decl-context.
> + // - but the variable itself has to be 'injected' into the
> + // decl-context of its lambda's call-operator (which has
> + // not yet been created).
> + // Each init-expression is a full-expression that has to get
> + // Sema-analyzed (for capturing etc.) before its lambda's
> + // call-operator's decl-context, scope & scopeinfo are pushed on their
> + // respective stacks. Thus if any variable is odr-used in the init-capture
> + // it will correctly get captured in the enclosing lambda, if one exists.
> + // The init-variables above are created later once the lambdascope and
> + // call-operators decl-context is pushed onto its respective stack.
> +
> + // Since the lambda init-capture's initializer expression occurs in the
> + // context of the enclosing function or lambda, therefore we can not wait
> + // till a lambda scope has been pushed on before deciding whether the
> + // variable needs to be captured. We also need to process all
> + // lvalue-to-rvalue conversions and discarded-value conversions,
> + // so that we can avoid capturing certain constant variables.
> + // For e.g.,
> + // void test() {
> + // const int x = 10;
> + // auto L = [&z = x](char a) { <-- don't capture by the current lambda
> + // return [y = x](int i) { <-- don't capture by enclosing lambda
> + // return y;
> + // }
> + // };
> + // If x was not const, the second use would require 'L' to capture, and
> + // that would be an error.
> +
> + ParsedType InitCaptureParsedType;
> + if (Init.isUsable()) {
> + // Get the pointer and store it in an lvalue, so we can use it as an
> + // out argument.
> + Expr *InitExpr = Init.get();
> + // This performs any lvalue-to-rvalue conversions if necessary, which
> + // can affect what gets captured in the containing decl-context.
> + QualType InitCaptureType = Actions.performLambdaInitCaptureInitialization(
> + Loc, Kind == LCK_ByRef, Id, InitExpr);
> + Init = InitExpr;
> + InitCaptureParsedType.set(InitCaptureType);
> + }
> + Intro.addCapture(Kind, Loc, Id, EllipsisLoc, Init, InitCaptureParsedType);
> }
>
> T.consumeClose();
> Intro.Range.setEnd(T.getCloseLocation());
> -
> return DiagResult();
> }
>
>
> Modified: cfe/branches/release_34/lib/Sema/SemaAccess.cpp
> URL: http://llvm.org/viewvc/llvm-project/cfe/branches/release_34/lib/Sema/SemaAccess.cpp?rev=196470&r1=196469&r2=196470&view=diff
> ==============================================================================
> --- cfe/branches/release_34/lib/Sema/SemaAccess.cpp (original)
> +++ cfe/branches/release_34/lib/Sema/SemaAccess.cpp Wed Dec 4 23:25:04 2013
> @@ -1650,9 +1650,9 @@ Sema::AccessResult Sema::CheckConstructo
> }
>
> case InitializedEntity::EK_LambdaCapture: {
> - const VarDecl *Var = Entity.getCapturedVar();
> + StringRef VarName = Entity.getCapturedVarName();
> PD = PDiag(diag::err_access_lambda_capture);
> - PD << Var->getName() << Entity.getType() << getSpecialMember(Constructor);
> + PD << VarName << Entity.getType() << getSpecialMember(Constructor);
> break;
> }
>
>
> Modified: cfe/branches/release_34/lib/Sema/SemaExpr.cpp
> URL: http://llvm.org/viewvc/llvm-project/cfe/branches/release_34/lib/Sema/SemaExpr.cpp?rev=196470&r1=196469&r2=196470&view=diff
> ==============================================================================
> --- cfe/branches/release_34/lib/Sema/SemaExpr.cpp (original)
> +++ cfe/branches/release_34/lib/Sema/SemaExpr.cpp Wed Dec 4 23:25:04 2013
> @@ -11688,7 +11688,8 @@ static ExprResult addAsFieldToClosureTyp
> SmallVector<InitializedEntity, 4> Entities;
> Entities.reserve(1 + IndexVariables.size());
> Entities.push_back(
> - InitializedEntity::InitializeLambdaCapture(Var, Field, Loc));
> + InitializedEntity::InitializeLambdaCapture(Var->getIdentifier(),
> + Field->getType(), Loc));
> for (unsigned I = 0, N = IndexVariables.size(); I != N; ++I)
> Entities.push_back(InitializedEntity::InitializeElement(S.Context,
> 0,
>
> Modified: cfe/branches/release_34/lib/Sema/SemaExprCXX.cpp
> URL: http://llvm.org/viewvc/llvm-project/cfe/branches/release_34/lib/Sema/SemaExprCXX.cpp?rev=196470&r1=196469&r2=196470&view=diff
> ==============================================================================
> --- cfe/branches/release_34/lib/Sema/SemaExprCXX.cpp (original)
> +++ cfe/branches/release_34/lib/Sema/SemaExprCXX.cpp Wed Dec 4 23:25:04 2013
> @@ -5929,13 +5929,30 @@ static void CheckLambdaCaptures(Expr *co
>
> ExprResult Sema::ActOnFinishFullExpr(Expr *FE, SourceLocation CC,
> bool DiscardedValue,
> - bool IsConstexpr) {
> + bool IsConstexpr,
> + bool IsLambdaInitCaptureInitializer) {
> ExprResult FullExpr = Owned(FE);
>
> if (!FullExpr.get())
> return ExprError();
> -
> - if (DiagnoseUnexpandedParameterPack(FullExpr.get()))
> +
> + // If we are an init-expression in a lambdas init-capture, we should not
> + // diagnose an unexpanded pack now (will be diagnosed once lambda-expr
> + // containing full-expression is done).
> + // template<class ... Ts> void test(Ts ... t) {
> + // test([&a(t)]() { <-- (t) is an init-expr that shouldn't be diagnosed now.
> + // return a;
> + // }() ...);
> + // }
> + // FIXME: This is a hack. It would be better if we pushed the lambda scope
> + // when we parse the lambda introducer, and teach capturing (but not
> + // unexpanded pack detection) to walk over LambdaScopeInfos which don't have a
> + // corresponding class yet (that is, have LambdaScopeInfo either represent a
> + // lambda where we've entered the introducer but not the body, or represent a
> + // lambda where we've entered the body, depending on where the
> + // parser/instantiation has got to).
> + if (!IsLambdaInitCaptureInitializer &&
> + DiagnoseUnexpandedParameterPack(FullExpr.get()))
> return ExprError();
>
> // Top-level expressions default to 'id' when we're in a debugger.
>
> Modified: cfe/branches/release_34/lib/Sema/SemaInit.cpp
> URL: http://llvm.org/viewvc/llvm-project/cfe/branches/release_34/lib/Sema/SemaInit.cpp?rev=196470&r1=196469&r2=196470&view=diff
> ==============================================================================
> --- cfe/branches/release_34/lib/Sema/SemaInit.cpp (original)
> +++ cfe/branches/release_34/lib/Sema/SemaInit.cpp Wed Dec 4 23:25:04 2013
> @@ -2506,7 +2506,7 @@ DeclarationName InitializedEntity::getNa
> return VariableOrMember->getDeclName();
>
> case EK_LambdaCapture:
> - return Capture.Var->getDeclName();
> + return DeclarationName(Capture.VarID);
>
> case EK_Result:
> case EK_Exception:
> @@ -2608,7 +2608,7 @@ unsigned InitializedEntity::dumpImpl(raw
> case EK_BlockElement: OS << "Block"; break;
> case EK_LambdaCapture:
> OS << "LambdaCapture ";
> - getCapturedVar()->printName(OS);
> + OS << DeclarationName(Capture.VarID);
> break;
> }
>
>
> Modified: cfe/branches/release_34/lib/Sema/SemaLambda.cpp
> URL: http://llvm.org/viewvc/llvm-project/cfe/branches/release_34/lib/Sema/SemaLambda.cpp?rev=196470&r1=196469&r2=196470&view=diff
> ==============================================================================
> --- cfe/branches/release_34/lib/Sema/SemaLambda.cpp (original)
> +++ cfe/branches/release_34/lib/Sema/SemaLambda.cpp Wed Dec 4 23:25:04 2013
> @@ -609,12 +609,20 @@ void Sema::deduceClosureReturnType(Captu
> }
> }
>
> -VarDecl *Sema::checkInitCapture(SourceLocation Loc, bool ByRef,
> - IdentifierInfo *Id, Expr *Init) {
> - // C++1y [expr.prim.lambda]p11:
> - // An init-capture behaves as if it declares and explicitly captures
> - // a variable of the form
> - // "auto init-capture;"
> +QualType Sema::performLambdaInitCaptureInitialization(SourceLocation Loc,
> + bool ByRef,
> + IdentifierInfo *Id,
> + Expr *&Init) {
> +
> + // We do not need to distinguish between direct-list-initialization
> + // and copy-list-initialization here, because we will always deduce
> + // std::initializer_list<T>, and direct- and copy-list-initialization
> + // always behave the same for such a type.
> + // FIXME: We should model whether an '=' was present.
> + const bool IsDirectInit = isa<ParenListExpr>(Init) || isa<InitListExpr>(Init);
> +
> + // Create an 'auto' or 'auto&' TypeSourceInfo that we can use to
> + // deduce against.
> QualType DeductType = Context.getAutoDeductType();
> TypeLocBuilder TLB;
> TLB.pushTypeSpec(DeductType).setNameLoc(Loc);
> @@ -625,24 +633,100 @@ VarDecl *Sema::checkInitCapture(SourceLo
> }
> TypeSourceInfo *TSI = TLB.getTypeSourceInfo(Context, DeductType);
>
> + // Are we a non-list direct initialization?
> + ParenListExpr *CXXDirectInit = dyn_cast<ParenListExpr>(Init);
> +
> + Expr *DeduceInit = Init;
> + // Initializer could be a C++ direct-initializer. Deduction only works if it
> + // contains exactly one expression.
> + if (CXXDirectInit) {
> + if (CXXDirectInit->getNumExprs() == 0) {
> + Diag(CXXDirectInit->getLocStart(), diag::err_init_capture_no_expression)
> + << DeclarationName(Id) << TSI->getType() << Loc;
> + return QualType();
> + } else if (CXXDirectInit->getNumExprs() > 1) {
> + Diag(CXXDirectInit->getExpr(1)->getLocStart(),
> + diag::err_init_capture_multiple_expressions)
> + << DeclarationName(Id) << TSI->getType() << Loc;
> + return QualType();
> + } else {
> + DeduceInit = CXXDirectInit->getExpr(0);
> + }
> + }
> +
> + // Now deduce against the initialization expression and store the deduced
> + // type below.
> + QualType DeducedType;
> + if (DeduceAutoType(TSI, DeduceInit, DeducedType) == DAR_Failed) {
> + if (isa<InitListExpr>(Init))
> + Diag(Loc, diag::err_init_capture_deduction_failure_from_init_list)
> + << DeclarationName(Id)
> + << (DeduceInit->getType().isNull() ? TSI->getType()
> + : DeduceInit->getType())
> + << DeduceInit->getSourceRange();
> + else
> + Diag(Loc, diag::err_init_capture_deduction_failure)
> + << DeclarationName(Id) << TSI->getType()
> + << (DeduceInit->getType().isNull() ? TSI->getType()
> + : DeduceInit->getType())
> + << DeduceInit->getSourceRange();
> + }
> + if (DeducedType.isNull())
> + return QualType();
> +
> + // Perform initialization analysis and ensure any implicit conversions
> + // (such as lvalue-to-rvalue) are enforced.
> + InitializedEntity Entity =
> + InitializedEntity::InitializeLambdaCapture(Id, DeducedType, Loc);
> + InitializationKind Kind =
> + IsDirectInit
> + ? (CXXDirectInit ? InitializationKind::CreateDirect(
> + Loc, Init->getLocStart(), Init->getLocEnd())
> + : InitializationKind::CreateDirectList(Loc))
> + : InitializationKind::CreateCopy(Loc, Init->getLocStart());
> +
> + MultiExprArg Args = Init;
> + if (CXXDirectInit)
> + Args =
> + MultiExprArg(CXXDirectInit->getExprs(), CXXDirectInit->getNumExprs());
> + QualType DclT;
> + InitializationSequence InitSeq(*this, Entity, Kind, Args);
> + ExprResult Result = InitSeq.Perform(*this, Entity, Kind, Args, &DclT);
> +
> + if (Result.isInvalid())
> + return QualType();
> + Init = Result.takeAs<Expr>();
> +
> + // The init-capture initialization is a full-expression that must be
> + // processed as one before we enter the declcontext of the lambda's
> + // call-operator.
> + Result = ActOnFinishFullExpr(Init, Loc, /*DiscardedValue*/ false,
> + /*IsConstexpr*/ false,
> + /*IsLambdaInitCaptureInitalizer*/ true);
> + if (Result.isInvalid())
> + return QualType();
> +
> + Init = Result.takeAs<Expr>();
> + return DeducedType;
> +}
> +
> +VarDecl *Sema::createLambdaInitCaptureVarDecl(SourceLocation Loc,
> + QualType InitCaptureType, IdentifierInfo *Id, Expr *Init) {
> +
> + TypeSourceInfo *TSI = Context.getTrivialTypeSourceInfo(InitCaptureType,
> + Loc);
> // Create a dummy variable representing the init-capture. This is not actually
> // used as a variable, and only exists as a way to name and refer to the
> // init-capture.
> // FIXME: Pass in separate source locations for '&' and identifier.
> VarDecl *NewVD = VarDecl::Create(Context, CurContext, Loc,
> - Loc, Id, TSI->getType(), TSI, SC_Auto);
> + Loc, Id, InitCaptureType, TSI, SC_Auto);
> NewVD->setInitCapture(true);
> NewVD->setReferenced(true);
> NewVD->markUsed(Context);
> -
> - // We do not need to distinguish between direct-list-initialization
> - // and copy-list-initialization here, because we will always deduce
> - // std::initializer_list<T>, and direct- and copy-list-initialization
> - // always behave the same for such a type.
> - // FIXME: We should model whether an '=' was present.
> - bool DirectInit = isa<ParenListExpr>(Init) || isa<InitListExpr>(Init);
> - AddInitializerToDecl(NewVD, Init, DirectInit, /*ContainsAuto*/true);
> + NewVD->setInit(Init);
> return NewVD;
> +
> }
>
> FieldDecl *Sema::buildInitCaptureField(LambdaScopeInfo *LSI, VarDecl *Var) {
> @@ -816,7 +900,7 @@ void Sema::ActOnStartOfLambdaDefinition(
> if (C->Init.isInvalid())
> continue;
>
> - VarDecl *Var;
> + VarDecl *Var = 0;
> if (C->Init.isUsable()) {
> Diag(C->Loc, getLangOpts().CPlusPlus1y
> ? diag::warn_cxx11_compat_init_capture
> @@ -824,9 +908,15 @@ void Sema::ActOnStartOfLambdaDefinition(
>
> if (C->Init.get()->containsUnexpandedParameterPack())
> ContainsUnexpandedParameterPack = true;
> -
> - Var = checkInitCapture(C->Loc, C->Kind == LCK_ByRef,
> - C->Id, C->Init.take());
> + // If the initializer expression is usable, but the InitCaptureType
> + // is not, then an error has occurred - so ignore the capture for now.
> + // for e.g., [n{0}] { }; <-- if no <initializer_list> is included.
> + // FIXME: we should create the init capture variable and mark it invalid
> + // in this case.
> + if (C->InitCaptureType.get().isNull())
> + continue;
> + Var = createLambdaInitCaptureVarDecl(C->Loc, C->InitCaptureType.get(),
> + C->Id, C->Init.take());
> // C++1y [expr.prim.lambda]p11:
> // An init-capture behaves as if it declares and explicitly
> // captures a variable [...] whose declarative region is the
>
> Modified: cfe/branches/release_34/lib/Sema/SemaTemplateInstantiate.cpp
> URL: http://llvm.org/viewvc/llvm-project/cfe/branches/release_34/lib/Sema/SemaTemplateInstantiate.cpp?rev=196470&r1=196469&r2=196470&view=diff
> ==============================================================================
> --- cfe/branches/release_34/lib/Sema/SemaTemplateInstantiate.cpp (original)
> +++ cfe/branches/release_34/lib/Sema/SemaTemplateInstantiate.cpp Wed Dec 4 23:25:04 2013
> @@ -917,7 +917,8 @@ namespace {
> }
>
> ExprResult TransformLambdaScope(LambdaExpr *E,
> - CXXMethodDecl *NewCallOperator) {
> + CXXMethodDecl *NewCallOperator,
> + ArrayRef<InitCaptureInfoTy> InitCaptureExprsAndTypes) {
> CXXMethodDecl *const OldCallOperator = E->getCallOperator();
> // In the generic lambda case, we set the NewTemplate to be considered
> // an "instantiation" of the OldTemplate.
> @@ -936,7 +937,8 @@ namespace {
> NewCallOperator->setInstantiationOfMemberFunction(OldCallOperator,
> TSK_ImplicitInstantiation);
>
> - return inherited::TransformLambdaScope(E, NewCallOperator);
> + return inherited::TransformLambdaScope(E, NewCallOperator,
> + InitCaptureExprsAndTypes);
> }
> TemplateParameterList *TransformTemplateParameterList(
> TemplateParameterList *OrigTPL) {
>
> Modified: cfe/branches/release_34/lib/Sema/TreeTransform.h
> URL: http://llvm.org/viewvc/llvm-project/cfe/branches/release_34/lib/Sema/TreeTransform.h?rev=196470&r1=196469&r2=196470&view=diff
> ==============================================================================
> --- cfe/branches/release_34/lib/Sema/TreeTransform.h (original)
> +++ cfe/branches/release_34/lib/Sema/TreeTransform.h Wed Dec 4 23:25:04 2013
> @@ -593,9 +593,11 @@ public:
>
> StmtResult TransformCompoundStmt(CompoundStmt *S, bool IsStmtExpr);
> ExprResult TransformCXXNamedCastExpr(CXXNamedCastExpr *E);
> -
> +
> + typedef std::pair<ExprResult, QualType> InitCaptureInfoTy;
> /// \brief Transform the captures and body of a lambda expression.
> - ExprResult TransformLambdaScope(LambdaExpr *E, CXXMethodDecl *CallOperator);
> + ExprResult TransformLambdaScope(LambdaExpr *E, CXXMethodDecl *CallOperator,
> + ArrayRef<InitCaptureInfoTy> InitCaptureExprsAndTypes);
>
> TemplateParameterList *TransformTemplateParameterList(
> TemplateParameterList *TPL) {
> @@ -8275,7 +8277,40 @@ TreeTransform<Derived>::TransformCXXTemp
> template<typename Derived>
> ExprResult
> TreeTransform<Derived>::TransformLambdaExpr(LambdaExpr *E) {
> -
> +
> + // Transform any init-capture expressions before entering the scope of the
> + // lambda body, because they are not semantically within that scope.
> + SmallVector<InitCaptureInfoTy, 8> InitCaptureExprsAndTypes;
> + InitCaptureExprsAndTypes.resize(E->explicit_capture_end() -
> + E->explicit_capture_begin());
> +
> + for (LambdaExpr::capture_iterator C = E->capture_begin(),
> + CEnd = E->capture_end();
> + C != CEnd; ++C) {
> + if (!C->isInitCapture())
> + continue;
> + EnterExpressionEvaluationContext EEEC(getSema(),
> + Sema::PotentiallyEvaluated);
> + ExprResult NewExprInitResult = getDerived().TransformInitializer(
> + C->getCapturedVar()->getInit(),
> + C->getCapturedVar()->getInitStyle() == VarDecl::CallInit);
> +
> + if (NewExprInitResult.isInvalid())
> + return ExprError();
> + Expr *NewExprInit = NewExprInitResult.get();
> +
> + VarDecl *OldVD = C->getCapturedVar();
> + QualType NewInitCaptureType =
> + getSema().performLambdaInitCaptureInitialization(C->getLocation(),
> + OldVD->getType()->isReferenceType(), OldVD->getIdentifier(),
> + NewExprInit);
> + NewExprInitResult = NewExprInit;
> + VarDecl *NewVD = 0;
> + InitCaptureExprsAndTypes[C - E->capture_begin()] =
> + std::make_pair(NewExprInitResult, NewInitCaptureType);
> +
> + }
> +
> LambdaScopeInfo *LSI = getSema().PushLambdaScope();
> // Transform the template parameters, and add them to the current
> // instantiation scope. The null case is handled correctly.
> @@ -8370,31 +8405,17 @@ TreeTransform<Derived>::TransformLambdaE
>
> getDerived().transformAttrs(E->getCallOperator(), NewCallOperator);
>
> - return getDerived().TransformLambdaScope(E, NewCallOperator);
> + return getDerived().TransformLambdaScope(E, NewCallOperator,
> + InitCaptureExprsAndTypes);
> }
>
> template<typename Derived>
> ExprResult
> TreeTransform<Derived>::TransformLambdaScope(LambdaExpr *E,
> - CXXMethodDecl *CallOperator) {
> + CXXMethodDecl *CallOperator,
> + ArrayRef<InitCaptureInfoTy> InitCaptureExprsAndTypes) {
> bool Invalid = false;
>
> - // Transform any init-capture expressions before entering the scope of the
> - // lambda.
> - SmallVector<ExprResult, 8> InitCaptureExprs;
> - InitCaptureExprs.resize(E->explicit_capture_end() -
> - E->explicit_capture_begin());
> - for (LambdaExpr::capture_iterator C = E->capture_begin(),
> - CEnd = E->capture_end();
> - C != CEnd; ++C) {
> - if (!C->isInitCapture())
> - continue;
> - InitCaptureExprs[C - E->capture_begin()] =
> - getDerived().TransformInitializer(
> - C->getCapturedVar()->getInit(),
> - C->getCapturedVar()->getInitStyle() == VarDecl::CallInit);
> - }
> -
> // Introduce the context of the call operator.
> Sema::ContextRAII SavedContext(getSema(), CallOperator);
>
> @@ -8427,19 +8448,24 @@ TreeTransform<Derived>::TransformLambdaS
>
> // Rebuild init-captures, including the implied field declaration.
> if (C->isInitCapture()) {
> - ExprResult Init = InitCaptureExprs[C - E->capture_begin()];
> - if (Init.isInvalid()) {
> +
> + InitCaptureInfoTy InitExprTypePair =
> + InitCaptureExprsAndTypes[C - E->capture_begin()];
> + ExprResult Init = InitExprTypePair.first;
> + QualType InitQualType = InitExprTypePair.second;
> + if (Init.isInvalid() || InitQualType.isNull()) {
> Invalid = true;
> continue;
> }
> VarDecl *OldVD = C->getCapturedVar();
> - VarDecl *NewVD = getSema().checkInitCapture(
> - C->getLocation(), OldVD->getType()->isReferenceType(),
> - OldVD->getIdentifier(), Init.take());
> + VarDecl *NewVD = getSema().createLambdaInitCaptureVarDecl(
> + OldVD->getLocation(), InitExprTypePair.second,
> + OldVD->getIdentifier(), Init.get());
> if (!NewVD)
> Invalid = true;
> - else
> + else {
> getDerived().transformedLocalDecl(OldVD, NewVD);
> + }
> getSema().buildInitCaptureField(LSI, NewVD);
> continue;
> }
>
> Modified: cfe/branches/release_34/test/SemaCXX/cxx1y-init-captures.cpp
> URL: http://llvm.org/viewvc/llvm-project/cfe/branches/release_34/test/SemaCXX/cxx1y-init-captures.cpp?rev=196470&r1=196469&r2=196470&view=diff
> ==============================================================================
> --- cfe/branches/release_34/test/SemaCXX/cxx1y-init-captures.cpp (original)
> +++ cfe/branches/release_34/test/SemaCXX/cxx1y-init-captures.cpp Wed Dec 4 23:25:04 2013
> @@ -1,14 +1,169 @@
> -// RUN: %clang_cc1 -std=c++1y %s -verify
> +// RUN: %clang_cc1 -std=c++1y %s -verify -emit-llvm-only
>
> -// expected-no-diagnostics
> namespace variadic_expansion {
> - void f(int &, char &);
> -
> - template <typename ... T> void g(T &... t) {
> + int f(int &, char &) { return 0; }
> + template<class ... Ts> char fv(Ts ... ts) { return 0; }
> + // FIXME: why do we get 2 error messages
> + template <typename ... T> void g(T &... t) { //expected-note3{{declared here}}
> f([&a(t)]()->decltype(auto) {
> return a;
> }() ...);
> +
> + auto L = [x = f([&a(t)]()->decltype(auto) { return a; }()...)]() { return x; };
> + const int y = 10;
> + auto M = [x = y,
> + &z = y](T& ... t) { };
> + auto N = [x = y,
> + &z = y, n = f(t...),
> + o = f([&a(t)](T& ... t)->decltype(auto) { return a; }(t...)...), t...](T& ... s) {
> + fv([&a(t)]()->decltype(auto) {
> + return a;
> + }() ...);
> + };
> + auto N2 = [x = y, //expected-note3{{begins here}}
> + &z = y, n = f(t...),
> + o = f([&a(t)](T& ... t)->decltype(auto) { return a; }(t...)...)](T& ... s) {
> + fv([&a(t)]()->decltype(auto) { //expected-error 3{{captured}}
> + return a;
> + }() ...);
> + };
> +
> + }
> +
> + void h(int i, char c) { g(i, c); } //expected-note{{in instantiation}}
> +}
> +
> +namespace odr_use_within_init_capture {
> +
> +int test() {
> +
> + { // no captures
> + const int x = 10;
> + auto L = [z = x + 2](int a) {
> + auto M = [y = x - 2](char b) {
> + return y;
> + };
> + return M;
> + };
> +
> + }
> + { // should not capture
> + const int x = 10;
> + auto L = [&z = x](int a) {
> + return a;;
> + };
> +
> + }
> + {
> + const int x = 10;
> + auto L = [k = x](char a) { //expected-note {{declared}}
> + return [](int b) { //expected-note {{begins}}
> + return [j = k](int c) { //expected-error {{cannot be implicitly captured}}
> + return c;
> + };
> + };
> + };
> + }
> + {
> + const int x = 10;
> + auto L = [k = x](char a) {
> + return [=](int b) {
> + return [j = k](int c) {
> + return c;
> + };
> + };
> + };
> }
> + {
> + const int x = 10;
> + auto L = [k = x](char a) {
> + return [k](int b) {
> + return [j = k](int c) {
> + return c;
> + };
> + };
> + };
> + }
> +
> + return 0;
> +}
>
> - void h(int i, char c) { g(i, c); }
> +int run = test();
> +
> +}
> +
> +namespace odr_use_within_init_capture_template {
> +
> +template<class T = int>
> +int test(T t = T{}) {
> +
> + { // no captures
> + const T x = 10;
> + auto L = [z = x](char a) {
> + auto M = [y = x](T b) {
> + return y;
> + };
> + return M;
> + };
> +
> + }
> + { // should not capture
> + const T x = 10;
> + auto L = [&z = x](T a) {
> + return a;;
> + };
> +
> + }
> + { // will need to capture x in outer lambda
> + const T x = 10; //expected-note {{declared}}
> + auto L = [z = x](char a) { //expected-note {{begins}}
> + auto M = [&y = x](T b) { //expected-error {{cannot be implicitly captured}}
> + return y;
> + };
> + return M;
> + };
> +
> + }
> + { // will need to capture x in outer lambda
> + const T x = 10;
> + auto L = [=,z = x](char a) {
> + auto M = [&y = x](T b) {
> + return y;
> + };
> + return M;
> + };
> +
> + }
> + { // will need to capture x in outer lambda
> + const T x = 10;
> + auto L = [x, z = x](char a) {
> + auto M = [&y = x](T b) {
> + return y;
> + };
> + return M;
> + };
> + }
> + { // will need to capture x in outer lambda
> + const int x = 10; //expected-note 2{{declared}}
> + auto L = [z = x](char a) { //expected-note 2{{begins}}
> + auto M = [&y = x](T b) { //expected-error 2{{cannot be implicitly captured}}
> + return y;
> + };
> + return M;
> + };
> + }
> + {
> + // no captures
> + const T x = 10;
> + auto L = [z =
> + [z = x, &y = x](char a) { return z + y; }('a')](char a)
> + { return z; };
> +
> + }
> +
> + return 0;
> }
> +
> +int run = test(); //expected-note {{instantiation}}
> +
> +}
> \ No newline at end of file
>
>
> _______________________________________________
> llvm-branch-commits mailing list
> llvm-branch-commits at cs.uiuc.edu
> http://lists.cs.uiuc.edu/mailman/listinfo/llvm-branch-commits
More information about the llvm-branch-commits
mailing list