diff options
Diffstat (limited to 'lib/Sema')
-rw-r--r-- | lib/Sema/SemaLambda.cpp | 28 | ||||
-rw-r--r-- | lib/Sema/SemaTemplateInstantiate.cpp | 13 | ||||
-rw-r--r-- | lib/Sema/SemaTemplateVariadic.cpp | 89 | ||||
-rw-r--r-- | lib/Sema/TreeTransform.h | 18 |
4 files changed, 99 insertions, 49 deletions
diff --git a/lib/Sema/SemaLambda.cpp b/lib/Sema/SemaLambda.cpp index 25d27f44ee..3a10c2af91 100644 --- a/lib/Sema/SemaLambda.cpp +++ b/lib/Sema/SemaLambda.cpp @@ -375,6 +375,7 @@ void Sema::ActOnStartOfLambdaDefinition(LambdaIntroducer &Intro, TypeSourceInfo *MethodTyInfo; bool ExplicitParams = true; bool ExplicitResultType = true; + bool ContainsUnexpandedParameterPack = false; SourceLocation EndLoc; llvm::ArrayRef<ParmVarDecl *> Params; if (ParamInfo.getNumTypeObjects() == 0) { @@ -416,21 +417,8 @@ void Sema::ActOnStartOfLambdaDefinition(LambdaIntroducer &Intro, Proto.getNumArgs()); // Check for unexpanded parameter packs in the method type. - // FIXME: We should allow unexpanded parameter packs here, but that would, - // in turn, make the lambda expression contain unexpanded parameter packs. - if (DiagnoseUnexpandedParameterPack(Intro.Range.getBegin(), MethodTyInfo, - UPPC_Lambda)) { - // Drop the parameters. - Params = llvm::ArrayRef<ParmVarDecl *>(); - FunctionProtoType::ExtProtoInfo EPI; - EPI.HasTrailingReturn = false; - EPI.TypeQuals |= DeclSpec::TQ_const; - QualType MethodTy = Context.getFunctionType(Context.DependentTy, - /*Args=*/0, /*NumArgs=*/0, EPI); - MethodTyInfo = Context.getTrivialTypeSourceInfo(MethodTy); - ExplicitParams = false; - ExplicitResultType = false; - } + if (MethodTyInfo->getType()->containsUnexpandedParameterPack()) + ContainsUnexpandedParameterPack = true; } CXXMethodDecl *Method = startLambdaDefinition(Class, Intro.Range, @@ -571,8 +559,7 @@ void Sema::ActOnStartOfLambdaDefinition(LambdaIntroducer &Intro, // Just ignore the ellipsis. } } else if (Var->isParameterPack()) { - Diag(C->Loc, diag::err_lambda_unexpanded_pack); - continue; + ContainsUnexpandedParameterPack = true; } TryCaptureKind Kind = C->Kind == LCK_ByRef ? TryCapture_ExplicitByRef : @@ -581,6 +568,8 @@ void Sema::ActOnStartOfLambdaDefinition(LambdaIntroducer &Intro, } finishLambdaExplicitCaptures(LSI); + LSI->ContainsUnexpandedParameterPack = ContainsUnexpandedParameterPack; + // Add lambda parameters into scope. addLambdaParameters(Method, CurScope); @@ -743,6 +732,7 @@ ExprResult Sema::ActOnLambdaExpr(SourceLocation StartLoc, Stmt *Body, bool ExplicitParams; bool ExplicitResultType; bool LambdaExprNeedsCleanups; + bool ContainsUnexpandedParameterPack; llvm::SmallVector<VarDecl *, 4> ArrayIndexVars; llvm::SmallVector<unsigned, 4> ArrayIndexStarts; { @@ -753,6 +743,7 @@ ExprResult Sema::ActOnLambdaExpr(SourceLocation StartLoc, Stmt *Body, ExplicitParams = LSI->ExplicitParams; ExplicitResultType = !LSI->HasImplicitReturnType; LambdaExprNeedsCleanups = LSI->ExprNeedsCleanups; + ContainsUnexpandedParameterPack = LSI->ContainsUnexpandedParameterPack; ArrayIndexVars.swap(LSI->ArrayIndexVars); ArrayIndexStarts.swap(LSI->ArrayIndexStarts); @@ -867,7 +858,8 @@ ExprResult Sema::ActOnLambdaExpr(SourceLocation StartLoc, Stmt *Body, CaptureDefault, Captures, ExplicitParams, ExplicitResultType, CaptureInits, ArrayIndexVars, - ArrayIndexStarts, Body->getLocEnd()); + ArrayIndexStarts, Body->getLocEnd(), + ContainsUnexpandedParameterPack); // C++11 [expr.prim.lambda]p2: // A lambda-expression shall not appear in an unevaluated operand diff --git a/lib/Sema/SemaTemplateInstantiate.cpp b/lib/Sema/SemaTemplateInstantiate.cpp index d009e2f81b..082b2e847f 100644 --- a/lib/Sema/SemaTemplateInstantiate.cpp +++ b/lib/Sema/SemaTemplateInstantiate.cpp @@ -838,6 +838,19 @@ namespace { return move(Result); } + ExprResult TransformLambdaExpr(LambdaExpr *E) { + LocalInstantiationScope Scope(SemaRef, /*CombineWithOuterScope=*/true); + return TreeTransform<TemplateInstantiator>::TransformLambdaExpr(E); + } + + ExprResult TransformLambdaScope(LambdaExpr *E, + CXXMethodDecl *CallOperator) { + CallOperator->setInstantiationOfMemberFunction(E->getCallOperator(), + TSK_ImplicitInstantiation); + return TreeTransform<TemplateInstantiator>:: + TransformLambdaScope(E, CallOperator); + } + private: ExprResult transformNonTypeTemplateParmRef(NonTypeTemplateParmDecl *parm, SourceLocation loc, diff --git a/lib/Sema/SemaTemplateVariadic.cpp b/lib/Sema/SemaTemplateVariadic.cpp index 0d0f992bed..aece90b785 100644 --- a/lib/Sema/SemaTemplateVariadic.cpp +++ b/lib/Sema/SemaTemplateVariadic.cpp @@ -12,6 +12,7 @@ #include "clang/Sema/Sema.h" #include "clang/Sema/Lookup.h" #include "clang/Sema/ParsedTemplate.h" +#include "clang/Sema/ScopeInfo.h" #include "clang/Sema/SemaInternal.h" #include "clang/Sema/Template.h" #include "clang/AST/Expr.h" @@ -34,10 +35,12 @@ namespace { SmallVectorImpl<UnexpandedParameterPack> &Unexpanded; + bool InLambda; + public: explicit CollectUnexpandedParameterPacksVisitor( SmallVectorImpl<UnexpandedParameterPack> &Unexpanded) - : Unexpanded(Unexpanded) { } + : Unexpanded(Unexpanded), InLambda(false) { } bool shouldWalkTypesOfTypeLocs() const { return false; } @@ -107,17 +110,17 @@ namespace { /// \brief Suppress traversal into statements and expressions that /// do not contain unexpanded parameter packs. bool TraverseStmt(Stmt *S) { - if (Expr *E = dyn_cast_or_null<Expr>(S)) - if (E->containsUnexpandedParameterPack()) - return inherited::TraverseStmt(E); + Expr *E = dyn_cast_or_null<Expr>(S); + if ((E && E->containsUnexpandedParameterPack()) || InLambda) + return inherited::TraverseStmt(S); - return true; + return true; } /// \brief Suppress traversal into types that do not contain /// unexpanded parameter packs. bool TraverseType(QualType T) { - if (!T.isNull() && T->containsUnexpandedParameterPack()) + if ((!T.isNull() && T->containsUnexpandedParameterPack()) || InLambda) return inherited::TraverseType(T); return true; @@ -126,8 +129,9 @@ namespace { /// \brief Suppress traversel into types with location information /// that do not contain unexpanded parameter packs. bool TraverseTypeLoc(TypeLoc TL) { - if (!TL.getType().isNull() && - TL.getType()->containsUnexpandedParameterPack()) + if ((!TL.getType().isNull() && + TL.getType()->containsUnexpandedParameterPack()) || + InLambda) return inherited::TraverseTypeLoc(TL); return true; @@ -136,10 +140,10 @@ namespace { /// \brief Suppress traversal of non-parameter declarations, since /// they cannot contain unexpanded parameter packs. bool TraverseDecl(Decl *D) { - if (D && isa<ParmVarDecl>(D)) + if ((D && isa<ParmVarDecl>(D)) || InLambda) return inherited::TraverseDecl(D); - return true; + return true; } /// \brief Suppress traversal of template argument pack expansions. @@ -157,17 +161,57 @@ namespace { return inherited::TraverseTemplateArgumentLoc(ArgLoc); } + + /// \brief Note whether we're traversing a lambda containing an unexpanded + /// parameter pack. In this case, the unexpanded pack can occur anywhere, + /// including all the places where we normally wouldn't look. Within a + /// lambda, we don't propagate the 'contains unexpanded parameter pack' bit + /// outside an expression. + bool TraverseLambdaExpr(LambdaExpr *Lambda) { + // The ContainsUnexpandedParameterPack bit on a lambda is always correct, + // even if it's contained within another lambda. + if (!Lambda->containsUnexpandedParameterPack()) + return true; + + bool WasInLambda = InLambda; + InLambda = true; + + // If any capture names a function parameter pack, that pack is expanded + // when the lambda is expanded. + for (LambdaExpr::capture_iterator I = Lambda->capture_begin(), + E = Lambda->capture_end(); I != E; ++I) + if (VarDecl *VD = I->getCapturedVar()) + if (VD->isParameterPack()) + Unexpanded.push_back(std::make_pair(VD, I->getLocation())); + + inherited::TraverseLambdaExpr(Lambda); + + InLambda = WasInLambda; + return true; + } }; } /// \brief Diagnose all of the unexpanded parameter packs in the given /// vector. -void +bool Sema::DiagnoseUnexpandedParameterPacks(SourceLocation Loc, UnexpandedParameterPackContext UPPC, ArrayRef<UnexpandedParameterPack> Unexpanded) { if (Unexpanded.empty()) - return; + return false; + + // If we are within a lambda expression, that lambda contains an unexpanded + // parameter pack, and we are done. + // FIXME: Store 'Unexpanded' on the lambda so we don't need to recompute it + // later. + for (unsigned N = FunctionScopes.size(); N; --N) { + if (sema::LambdaScopeInfo *LSI = + dyn_cast<sema::LambdaScopeInfo>(FunctionScopes[N-1])) { + LSI->ContainsUnexpandedParameterPack = true; + return false; + } + } SmallVector<SourceLocation, 4> Locations; SmallVector<IdentifierInfo *, 4> Names; @@ -200,6 +244,7 @@ Sema::DiagnoseUnexpandedParameterPacks(SourceLocation Loc, for (unsigned I = 0, N = Locations.size(); I != N; ++I) DB << SourceRange(Locations[I]); + return true; } bool Sema::DiagnoseUnexpandedParameterPack(SourceLocation Loc, @@ -215,8 +260,7 @@ bool Sema::DiagnoseUnexpandedParameterPack(SourceLocation Loc, CollectUnexpandedParameterPacksVisitor(Unexpanded).TraverseTypeLoc( T->getTypeLoc()); assert(!Unexpanded.empty() && "Unable to find unexpanded parameter packs"); - DiagnoseUnexpandedParameterPacks(Loc, UPPC, Unexpanded); - return true; + return DiagnoseUnexpandedParameterPacks(Loc, UPPC, Unexpanded); } bool Sema::DiagnoseUnexpandedParameterPack(Expr *E, @@ -230,8 +274,7 @@ bool Sema::DiagnoseUnexpandedParameterPack(Expr *E, SmallVector<UnexpandedParameterPack, 2> Unexpanded; CollectUnexpandedParameterPacksVisitor(Unexpanded).TraverseStmt(E); assert(!Unexpanded.empty() && "Unable to find unexpanded parameter packs"); - DiagnoseUnexpandedParameterPacks(E->getLocStart(), UPPC, Unexpanded); - return true; + return DiagnoseUnexpandedParameterPacks(E->getLocStart(), UPPC, Unexpanded); } bool Sema::DiagnoseUnexpandedParameterPack(const CXXScopeSpec &SS, @@ -247,9 +290,8 @@ bool Sema::DiagnoseUnexpandedParameterPack(const CXXScopeSpec &SS, CollectUnexpandedParameterPacksVisitor(Unexpanded) .TraverseNestedNameSpecifier(SS.getScopeRep()); assert(!Unexpanded.empty() && "Unable to find unexpanded parameter packs"); - DiagnoseUnexpandedParameterPacks(SS.getRange().getBegin(), - UPPC, Unexpanded); - return true; + return DiagnoseUnexpandedParameterPacks(SS.getRange().getBegin(), + UPPC, Unexpanded); } bool Sema::DiagnoseUnexpandedParameterPack(const DeclarationNameInfo &NameInfo, @@ -284,8 +326,7 @@ bool Sema::DiagnoseUnexpandedParameterPack(const DeclarationNameInfo &NameInfo, CollectUnexpandedParameterPacksVisitor(Unexpanded) .TraverseType(NameInfo.getName().getCXXNameType()); assert(!Unexpanded.empty() && "Unable to find unexpanded parameter packs"); - DiagnoseUnexpandedParameterPacks(NameInfo.getLoc(), UPPC, Unexpanded); - return true; + return DiagnoseUnexpandedParameterPacks(NameInfo.getLoc(), UPPC, Unexpanded); } bool Sema::DiagnoseUnexpandedParameterPack(SourceLocation Loc, @@ -299,8 +340,7 @@ bool Sema::DiagnoseUnexpandedParameterPack(SourceLocation Loc, CollectUnexpandedParameterPacksVisitor(Unexpanded) .TraverseTemplateName(Template); assert(!Unexpanded.empty() && "Unable to find unexpanded parameter packs"); - DiagnoseUnexpandedParameterPacks(Loc, UPPC, Unexpanded); - return true; + return DiagnoseUnexpandedParameterPacks(Loc, UPPC, Unexpanded); } bool Sema::DiagnoseUnexpandedParameterPack(TemplateArgumentLoc Arg, @@ -313,8 +353,7 @@ bool Sema::DiagnoseUnexpandedParameterPack(TemplateArgumentLoc Arg, CollectUnexpandedParameterPacksVisitor(Unexpanded) .TraverseTemplateArgumentLoc(Arg); assert(!Unexpanded.empty() && "Unable to find unexpanded parameter packs"); - DiagnoseUnexpandedParameterPacks(Arg.getLocation(), UPPC, Unexpanded); - return true; + return DiagnoseUnexpandedParameterPacks(Arg.getLocation(), UPPC, Unexpanded); } void Sema::collectUnexpandedParameterPacks(TemplateArgument Arg, diff --git a/lib/Sema/TreeTransform.h b/lib/Sema/TreeTransform.h index fff3b3f4bf..0dd9d9c191 100644 --- a/lib/Sema/TreeTransform.h +++ b/lib/Sema/TreeTransform.h @@ -571,6 +571,9 @@ public: StmtResult TransformCompoundStmt(CompoundStmt *S, bool IsStmtExpr); ExprResult TransformCXXNamedCastExpr(CXXNamedCastExpr *E); + /// \brief Transform the captures and body of a lambda expression. + ExprResult TransformLambdaScope(LambdaExpr *E, CXXMethodDecl *CallOperator); + #define STMT(Node, Parent) \ StmtResult Transform##Node(Node *S); #define EXPR(Node, Parent) \ @@ -7894,14 +7897,13 @@ TreeTransform<Derived>::TransformLambdaExpr(LambdaExpr *E) { return ExprError(); // Transform lambda parameters. - bool Invalid = false; llvm::SmallVector<QualType, 4> ParamTypes; llvm::SmallVector<ParmVarDecl *, 4> Params; if (getDerived().TransformFunctionTypeParams(E->getLocStart(), E->getCallOperator()->param_begin(), E->getCallOperator()->param_size(), 0, ParamTypes, &Params)) - Invalid = true; + return ExprError(); // Build the call operator. CXXMethodDecl *CallOperator @@ -7910,11 +7912,14 @@ TreeTransform<Derived>::TransformLambdaExpr(LambdaExpr *E) { E->getCallOperator()->getLocEnd(), Params); getDerived().transformAttrs(E->getCallOperator(), CallOperator); - - // FIXME: Instantiation-specific. - CallOperator->setInstantiationOfMemberFunction(E->getCallOperator(), - TSK_ImplicitInstantiation); + return getDerived().TransformLambdaScope(E, CallOperator); +} + +template<typename Derived> +ExprResult +TreeTransform<Derived>::TransformLambdaScope(LambdaExpr *E, + CXXMethodDecl *CallOperator) { // Introduce the context of the call operator. Sema::ContextRAII SavedContext(getSema(), CallOperator); @@ -7927,6 +7932,7 @@ TreeTransform<Derived>::TransformLambdaExpr(LambdaExpr *E) { E->isMutable()); // Transform captures. + bool Invalid = false; bool FinishedExplicitCaptures = false; for (LambdaExpr::capture_iterator C = E->capture_begin(), CEnd = E->capture_end(); |