summaryrefslogtreecommitdiffstats
path: root/contrib/llvm/tools/clang/lib/Sema/SemaTemplateVariadic.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'contrib/llvm/tools/clang/lib/Sema/SemaTemplateVariadic.cpp')
-rw-r--r--contrib/llvm/tools/clang/lib/Sema/SemaTemplateVariadic.cpp91
1 files changed, 77 insertions, 14 deletions
diff --git a/contrib/llvm/tools/clang/lib/Sema/SemaTemplateVariadic.cpp b/contrib/llvm/tools/clang/lib/Sema/SemaTemplateVariadic.cpp
index 06afe87..725a3e4 100644
--- a/contrib/llvm/tools/clang/lib/Sema/SemaTemplateVariadic.cpp
+++ b/contrib/llvm/tools/clang/lib/Sema/SemaTemplateVariadic.cpp
@@ -390,21 +390,18 @@ void Sema::collectUnexpandedParameterPacks(QualType T,
void Sema::collectUnexpandedParameterPacks(TypeLoc TL,
SmallVectorImpl<UnexpandedParameterPack> &Unexpanded) {
CollectUnexpandedParameterPacksVisitor(Unexpanded).TraverseTypeLoc(TL);
-}
+}
-void Sema::collectUnexpandedParameterPacks(CXXScopeSpec &SS,
- SmallVectorImpl<UnexpandedParameterPack> &Unexpanded) {
- NestedNameSpecifier *Qualifier = SS.getScopeRep();
- if (!Qualifier)
- return;
-
- NestedNameSpecifierLoc QualifierLoc(Qualifier, SS.location_data());
+void Sema::collectUnexpandedParameterPacks(
+ NestedNameSpecifierLoc NNS,
+ SmallVectorImpl<UnexpandedParameterPack> &Unexpanded) {
CollectUnexpandedParameterPacksVisitor(Unexpanded)
- .TraverseNestedNameSpecifierLoc(QualifierLoc);
+ .TraverseNestedNameSpecifierLoc(NNS);
}
-void Sema::collectUnexpandedParameterPacks(const DeclarationNameInfo &NameInfo,
- SmallVectorImpl<UnexpandedParameterPack> &Unexpanded) {
+void Sema::collectUnexpandedParameterPacks(
+ const DeclarationNameInfo &NameInfo,
+ SmallVectorImpl<UnexpandedParameterPack> &Unexpanded) {
CollectUnexpandedParameterPacksVisitor(Unexpanded)
.TraverseDeclarationNameInfo(NameInfo);
}
@@ -639,7 +636,7 @@ bool Sema::CheckParameterPacksForExpansion(
return true;
}
}
-
+
return false;
}
@@ -772,7 +769,7 @@ bool Sema::containsUnexpandedParameterPacks(Declarator &D) {
}
if (Chunk.Fun.getExceptionSpecType() == EST_Dynamic) {
- for (unsigned i = 0; i != Chunk.Fun.NumExceptions; ++i) {
+ for (unsigned i = 0; i != Chunk.Fun.getNumExceptions(); ++i) {
if (Chunk.Fun.Exceptions[i]
.Ty.get()
->containsUnexpandedParameterPack())
@@ -936,12 +933,71 @@ Sema::getTemplateArgumentPackExpansionPattern(
llvm_unreachable("Invalid TemplateArgument Kind!");
}
+Optional<unsigned> Sema::getFullyPackExpandedSize(TemplateArgument Arg) {
+ assert(Arg.containsUnexpandedParameterPack());
+
+ // If this is a substituted pack, grab that pack. If not, we don't know
+ // the size yet.
+ // FIXME: We could find a size in more cases by looking for a substituted
+ // pack anywhere within this argument, but that's not necessary in the common
+ // case for 'sizeof...(A)' handling.
+ TemplateArgument Pack;
+ switch (Arg.getKind()) {
+ case TemplateArgument::Type:
+ if (auto *Subst = Arg.getAsType()->getAs<SubstTemplateTypeParmPackType>())
+ Pack = Subst->getArgumentPack();
+ else
+ return None;
+ break;
+
+ case TemplateArgument::Expression:
+ if (auto *Subst =
+ dyn_cast<SubstNonTypeTemplateParmPackExpr>(Arg.getAsExpr()))
+ Pack = Subst->getArgumentPack();
+ else if (auto *Subst = dyn_cast<FunctionParmPackExpr>(Arg.getAsExpr())) {
+ for (ParmVarDecl *PD : *Subst)
+ if (PD->isParameterPack())
+ return None;
+ return Subst->getNumExpansions();
+ } else
+ return None;
+ break;
+
+ case TemplateArgument::Template:
+ if (SubstTemplateTemplateParmPackStorage *Subst =
+ Arg.getAsTemplate().getAsSubstTemplateTemplateParmPack())
+ Pack = Subst->getArgumentPack();
+ else
+ return None;
+ break;
+
+ case TemplateArgument::Declaration:
+ case TemplateArgument::NullPtr:
+ case TemplateArgument::TemplateExpansion:
+ case TemplateArgument::Integral:
+ case TemplateArgument::Pack:
+ case TemplateArgument::Null:
+ return None;
+ }
+
+ // Check that no argument in the pack is itself a pack expansion.
+ for (TemplateArgument Elem : Pack.pack_elements()) {
+ // There's no point recursing in this case; we would have already
+ // expanded this pack expansion into the enclosing pack if we could.
+ if (Elem.isPackExpansion())
+ return None;
+ }
+ return Pack.pack_size();
+}
+
static void CheckFoldOperand(Sema &S, Expr *E) {
if (!E)
return;
E = E->IgnoreImpCasts();
- if (isa<BinaryOperator>(E) || isa<AbstractConditionalOperator>(E)) {
+ auto *OCE = dyn_cast<CXXOperatorCallExpr>(E);
+ if ((OCE && OCE->isInfixBinaryOp()) || isa<BinaryOperator>(E) ||
+ isa<AbstractConditionalOperator>(E)) {
S.Diag(E->getExprLoc(), diag::err_fold_expression_bad_operand)
<< E->getSourceRange()
<< FixItHint::CreateInsertion(E->getLocStart(), "(")
@@ -958,6 +1014,11 @@ ExprResult Sema::ActOnCXXFoldExpr(SourceLocation LParenLoc, Expr *LHS,
CheckFoldOperand(*this, LHS);
CheckFoldOperand(*this, RHS);
+ auto DiscardOperands = [&] {
+ CorrectDelayedTyposInExpr(LHS);
+ CorrectDelayedTyposInExpr(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
@@ -965,6 +1026,7 @@ ExprResult Sema::ActOnCXXFoldExpr(SourceLocation LParenLoc, Expr *LHS,
if (LHS && RHS &&
LHS->containsUnexpandedParameterPack() ==
RHS->containsUnexpandedParameterPack()) {
+ DiscardOperands();
return Diag(EllipsisLoc,
LHS->containsUnexpandedParameterPack()
? diag::err_fold_expression_packs_both_sides
@@ -978,6 +1040,7 @@ ExprResult Sema::ActOnCXXFoldExpr(SourceLocation LParenLoc, Expr *LHS,
if (!LHS || !RHS) {
Expr *Pack = LHS ? LHS : RHS;
assert(Pack && "fold expression with neither LHS nor RHS");
+ DiscardOperands();
if (!Pack->containsUnexpandedParameterPack())
return Diag(EllipsisLoc, diag::err_pack_expansion_without_parameter_packs)
<< Pack->getSourceRange();
OpenPOWER on IntegriCloud