diff options
Diffstat (limited to 'contrib/llvm/tools/clang/lib/Sema/SemaTemplateVariadic.cpp')
-rw-r--r-- | contrib/llvm/tools/clang/lib/Sema/SemaTemplateVariadic.cpp | 167 |
1 files changed, 155 insertions, 12 deletions
diff --git a/contrib/llvm/tools/clang/lib/Sema/SemaTemplateVariadic.cpp b/contrib/llvm/tools/clang/lib/Sema/SemaTemplateVariadic.cpp index 8e4ce0d..e4fab71 100644 --- a/contrib/llvm/tools/clang/lib/Sema/SemaTemplateVariadic.cpp +++ b/contrib/llvm/tools/clang/lib/Sema/SemaTemplateVariadic.cpp @@ -197,6 +197,20 @@ namespace { }; } +/// \brief Determine whether it's possible for an unexpanded parameter pack to +/// be valid in this location. This only happens when we're in a declaration +/// that is nested within an expression that could be expanded, such as a +/// lambda-expression within a function call. +/// +/// This is conservatively correct, but may claim that some unexpanded packs are +/// permitted when they are not. +bool Sema::isUnexpandedParameterPackPermitted() { + for (auto *SI : FunctionScopes) + if (isa<sema::LambdaScopeInfo>(SI)) + return true; + return false; +} + /// \brief Diagnose all of the unexpanded parameter packs in the given /// vector. bool @@ -230,7 +244,7 @@ Sema::DiagnoseUnexpandedParameterPacks(SourceLocation Loc, else Name = Unexpanded[I].first.get<NamedDecl *>()->getIdentifier(); - if (Name && NamesKnown.insert(Name)) + if (Name && NamesKnown.insert(Name).second) Names.push_back(Name); if (Unexpanded[I].second.isValid()) @@ -733,24 +747,48 @@ bool Sema::containsUnexpandedParameterPacks(Declarator &D) { case TST_error: break; } - + for (unsigned I = 0, N = D.getNumTypeObjects(); I != N; ++I) { const DeclaratorChunk &Chunk = D.getTypeObject(I); switch (Chunk.Kind) { case DeclaratorChunk::Pointer: case DeclaratorChunk::Reference: case DeclaratorChunk::Paren: + case DeclaratorChunk::BlockPointer: // These declarator chunks cannot contain any parameter packs. break; case DeclaratorChunk::Array: + if (Chunk.Arr.NumElts && + Chunk.Arr.NumElts->containsUnexpandedParameterPack()) + return true; + break; case DeclaratorChunk::Function: - case DeclaratorChunk::BlockPointer: - // Syntactically, these kinds of declarator chunks all come after the - // declarator-id (conceptually), so the parser should not invoke this - // routine at this time. - llvm_unreachable("Could not have seen this kind of declarator chunk"); - + for (unsigned i = 0, e = Chunk.Fun.NumParams; i != e; ++i) { + ParmVarDecl *Param = cast<ParmVarDecl>(Chunk.Fun.Params[i].Param); + QualType ParamTy = Param->getType(); + assert(!ParamTy.isNull() && "Couldn't parse type?"); + if (ParamTy->containsUnexpandedParameterPack()) return true; + } + + if (Chunk.Fun.getExceptionSpecType() == EST_Dynamic) { + for (unsigned i = 0; i != Chunk.Fun.NumExceptions; ++i) { + if (Chunk.Fun.Exceptions[i] + .Ty.get() + ->containsUnexpandedParameterPack()) + return true; + } + } else if (Chunk.Fun.getExceptionSpecType() == EST_ComputedNoexcept && + Chunk.Fun.NoexceptExpr->containsUnexpandedParameterPack()) + return true; + + if (Chunk.Fun.hasTrailingReturnType()) { + QualType T = Chunk.Fun.getTrailingReturnType().get(); + if (!T.isNull() && T->containsUnexpandedParameterPack()) + return true; + } + break; + case DeclaratorChunk::MemberPointer: if (Chunk.Mem.Scope().getScopeRep() && Chunk.Mem.Scope().getScopeRep()->containsUnexpandedParameterPack()) @@ -800,7 +838,6 @@ ExprResult Sema::ActOnSizeofParameterPackExpr(Scope *S, LookupName(R, S); NamedDecl *ParameterPack = nullptr; - ParameterPackValidatorCCC Validator; switch (R.getResultKind()) { case LookupResult::Found: ParameterPack = R.getFoundDecl(); @@ -808,9 +845,10 @@ ExprResult Sema::ActOnSizeofParameterPackExpr(Scope *S, case LookupResult::NotFound: case LookupResult::NotFoundInCurrentInstantiation: - if (TypoCorrection Corrected = CorrectTypo(R.getLookupNameInfo(), - R.getLookupKind(), S, nullptr, - Validator, CTK_ErrorRecovery)) { + if (TypoCorrection Corrected = + CorrectTypo(R.getLookupNameInfo(), R.getLookupKind(), S, nullptr, + llvm::make_unique<ParameterPackValidatorCCC>(), + CTK_ErrorRecovery)) { diagnoseTypo(Corrected, PDiag(diag::err_sizeof_pack_no_pack_name_suggest) << &Name, PDiag(diag::note_parameter_pack_here)); @@ -897,3 +935,108 @@ Sema::getTemplateArgumentPackExpansionPattern( llvm_unreachable("Invalid TemplateArgument Kind!"); } + +static void CheckFoldOperand(Sema &S, Expr *E) { + if (!E) + return; + + E = E->IgnoreImpCasts(); + if (isa<BinaryOperator>(E) || isa<AbstractConditionalOperator>(E)) { + S.Diag(E->getExprLoc(), diag::err_fold_expression_bad_operand) + << E->getSourceRange() + << FixItHint::CreateInsertion(E->getLocStart(), "(") + << FixItHint::CreateInsertion(E->getLocEnd(), ")"); + } +} + +ExprResult Sema::ActOnCXXFoldExpr(SourceLocation LParenLoc, Expr *LHS, + tok::TokenKind Operator, + SourceLocation EllipsisLoc, Expr *RHS, + SourceLocation RParenLoc) { + // LHS and RHS must be cast-expressions. We allow an arbitrary expression + // in the parser and reduce down to just cast-expressions here. + CheckFoldOperand(*this, LHS); + CheckFoldOperand(*this, RHS); + + // [expr.prim.fold]p3: + // In a binary fold, op1 and op2 shall be the same fold-operator, and + // either e1 shall contain an unexpanded parameter pack or e2 shall contain + // an unexpanded parameter pack, but not both. + if (LHS && RHS && + LHS->containsUnexpandedParameterPack() == + RHS->containsUnexpandedParameterPack()) { + return Diag(EllipsisLoc, + LHS->containsUnexpandedParameterPack() + ? diag::err_fold_expression_packs_both_sides + : diag::err_pack_expansion_without_parameter_packs) + << LHS->getSourceRange() << RHS->getSourceRange(); + } + + // [expr.prim.fold]p2: + // In a unary fold, the cast-expression shall contain an unexpanded + // parameter pack. + if (!LHS || !RHS) { + Expr *Pack = LHS ? LHS : RHS; + assert(Pack && "fold expression with neither LHS nor RHS"); + if (!Pack->containsUnexpandedParameterPack()) + return Diag(EllipsisLoc, diag::err_pack_expansion_without_parameter_packs) + << Pack->getSourceRange(); + } + + BinaryOperatorKind Opc = ConvertTokenKindToBinaryOpcode(Operator); + return BuildCXXFoldExpr(LParenLoc, LHS, Opc, EllipsisLoc, RHS, RParenLoc); +} + +ExprResult Sema::BuildCXXFoldExpr(SourceLocation LParenLoc, Expr *LHS, + BinaryOperatorKind Operator, + SourceLocation EllipsisLoc, Expr *RHS, + SourceLocation RParenLoc) { + return new (Context) CXXFoldExpr(Context.DependentTy, LParenLoc, LHS, + Operator, EllipsisLoc, RHS, RParenLoc); +} + +ExprResult Sema::BuildEmptyCXXFoldExpr(SourceLocation EllipsisLoc, + BinaryOperatorKind Operator) { + // [temp.variadic]p9: + // If N is zero for a unary fold-expression, the value of the expression is + // * -> 1 + // + -> int() + // & -> -1 + // | -> int() + // && -> true + // || -> false + // , -> void() + // if the operator is not listed [above], the instantiation is ill-formed. + // + // Note that we need to use something like int() here, not merely 0, to + // prevent the result from being a null pointer constant. + QualType ScalarType; + switch (Operator) { + case BO_Add: + ScalarType = Context.IntTy; + break; + case BO_Mul: + return ActOnIntegerConstant(EllipsisLoc, 1); + case BO_Or: + ScalarType = Context.IntTy; + break; + case BO_And: + return CreateBuiltinUnaryOp(EllipsisLoc, UO_Minus, + ActOnIntegerConstant(EllipsisLoc, 1).get()); + case BO_LOr: + return ActOnCXXBoolLiteral(EllipsisLoc, tok::kw_false); + case BO_LAnd: + return ActOnCXXBoolLiteral(EllipsisLoc, tok::kw_true); + case BO_Comma: + ScalarType = Context.VoidTy; + break; + + default: + return Diag(EllipsisLoc, diag::err_fold_expression_empty) + << BinaryOperator::getOpcodeStr(Operator); + } + + return new (Context) CXXScalarValueInitExpr( + ScalarType, Context.getTrivialTypeSourceInfo(ScalarType, EllipsisLoc), + EllipsisLoc); +} |