forked from OSchip/llvm-project
Implement support for pack expansions in initializer lists and
expression lists. llvm-svn: 122764
This commit is contained in:
parent
8e666510f6
commit
968f23ab97
|
@ -172,8 +172,8 @@ static prec::Level getBinOpPrecedence(tok::TokenKind Kind,
|
||||||
/// = *= /= %= += -= <<= >>= &= ^= |=
|
/// = *= /= %= += -= <<= >>= &= ^= |=
|
||||||
///
|
///
|
||||||
/// expression: [C99 6.5.17]
|
/// expression: [C99 6.5.17]
|
||||||
/// assignment-expression
|
/// assignment-expression ...[opt]
|
||||||
/// expression ',' assignment-expression
|
/// expression ',' assignment-expression ...[opt]
|
||||||
///
|
///
|
||||||
ExprResult Parser::ParseExpression() {
|
ExprResult Parser::ParseExpression() {
|
||||||
ExprResult LHS(ParseAssignmentExpression());
|
ExprResult LHS(ParseAssignmentExpression());
|
||||||
|
@ -1030,8 +1030,8 @@ ExprResult Parser::ParseCastExpression(bool isUnaryExpression,
|
||||||
/// '(' type-name ')' '{' initializer-list ',' '}'
|
/// '(' type-name ')' '{' initializer-list ',' '}'
|
||||||
///
|
///
|
||||||
/// argument-expression-list: [C99 6.5.2]
|
/// argument-expression-list: [C99 6.5.2]
|
||||||
/// argument-expression
|
/// argument-expression ...[opt]
|
||||||
/// argument-expression-list ',' assignment-expression
|
/// argument-expression-list ',' assignment-expression ...[opt]
|
||||||
///
|
///
|
||||||
ExprResult
|
ExprResult
|
||||||
Parser::ParsePostfixExpressionSuffix(ExprResult LHS) {
|
Parser::ParsePostfixExpressionSuffix(ExprResult LHS) {
|
||||||
|
@ -1692,8 +1692,8 @@ ExprResult Parser::ParseStringLiteralExpression() {
|
||||||
/// argument-expression-list , assignment-expression
|
/// argument-expression-list , assignment-expression
|
||||||
///
|
///
|
||||||
/// [C++] expression-list:
|
/// [C++] expression-list:
|
||||||
/// [C++] assignment-expression
|
/// [C++] assignment-expression ...[opt]
|
||||||
/// [C++] expression-list , assignment-expression
|
/// [C++] expression-list , assignment-expression ...[opt]
|
||||||
///
|
///
|
||||||
bool Parser::ParseExpressionList(llvm::SmallVectorImpl<Expr*> &Exprs,
|
bool Parser::ParseExpressionList(llvm::SmallVectorImpl<Expr*> &Exprs,
|
||||||
llvm::SmallVectorImpl<SourceLocation> &CommaLocs,
|
llvm::SmallVectorImpl<SourceLocation> &CommaLocs,
|
||||||
|
@ -1710,6 +1710,8 @@ bool Parser::ParseExpressionList(llvm::SmallVectorImpl<Expr*> &Exprs,
|
||||||
}
|
}
|
||||||
|
|
||||||
ExprResult Expr(ParseAssignmentExpression());
|
ExprResult Expr(ParseAssignmentExpression());
|
||||||
|
if (Tok.is(tok::ellipsis))
|
||||||
|
Expr = Actions.ActOnPackExpansion(Expr.get(), ConsumeToken());
|
||||||
if (Expr.isInvalid())
|
if (Expr.isInvalid())
|
||||||
return true;
|
return true;
|
||||||
|
|
||||||
|
|
|
@ -310,8 +310,8 @@ ExprResult Parser::ParseInitializerWithPotentialDesignator() {
|
||||||
/// [GNU] '{' '}'
|
/// [GNU] '{' '}'
|
||||||
///
|
///
|
||||||
/// initializer-list:
|
/// initializer-list:
|
||||||
/// designation[opt] initializer
|
/// designation[opt] initializer ...[opt]
|
||||||
/// initializer-list ',' designation[opt] initializer
|
/// initializer-list ',' designation[opt] initializer ...[opt]
|
||||||
///
|
///
|
||||||
ExprResult Parser::ParseBraceInitializer() {
|
ExprResult Parser::ParseBraceInitializer() {
|
||||||
InMessageExpressionRAIIObject InMessage(*this, false);
|
InMessageExpressionRAIIObject InMessage(*this, false);
|
||||||
|
@ -344,6 +344,9 @@ ExprResult Parser::ParseBraceInitializer() {
|
||||||
else
|
else
|
||||||
SubElt = ParseInitializer();
|
SubElt = ParseInitializer();
|
||||||
|
|
||||||
|
if (Tok.is(tok::ellipsis))
|
||||||
|
SubElt = Actions.ActOnPackExpansion(SubElt.get(), ConsumeToken());
|
||||||
|
|
||||||
// If we couldn't parse the subelement, bail out.
|
// If we couldn't parse the subelement, bail out.
|
||||||
if (!SubElt.isInvalid()) {
|
if (!SubElt.isInvalid()) {
|
||||||
InitExprs.push_back(SubElt.release());
|
InitExprs.push_back(SubElt.release());
|
||||||
|
|
|
@ -2103,6 +2103,8 @@ public:
|
||||||
SourceLocation EllipsisLoc) {
|
SourceLocation EllipsisLoc) {
|
||||||
switch (Pattern.getArgument().getKind()) {
|
switch (Pattern.getArgument().getKind()) {
|
||||||
case TemplateArgument::Expression:
|
case TemplateArgument::Expression:
|
||||||
|
// FIXME: We should be able to handle this now!
|
||||||
|
|
||||||
case TemplateArgument::Template:
|
case TemplateArgument::Template:
|
||||||
llvm_unreachable("Unsupported pack expansion of expressions/templates");
|
llvm_unreachable("Unsupported pack expansion of expressions/templates");
|
||||||
|
|
||||||
|
@ -2124,6 +2126,15 @@ public:
|
||||||
return TemplateArgumentLoc();
|
return TemplateArgumentLoc();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// \brief Build a new expression pack expansion.
|
||||||
|
///
|
||||||
|
/// By default, performs semantic analysis to build a new pack expansion
|
||||||
|
/// for an expression. Subclasses may override this routine to provide
|
||||||
|
/// different behavior.
|
||||||
|
ExprResult RebuildPackExpansion(Expr *Pattern, SourceLocation EllipsisLoc) {
|
||||||
|
return getSema().ActOnPackExpansion(Pattern, EllipsisLoc);
|
||||||
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
QualType TransformTypeInObjectScope(QualType T,
|
QualType TransformTypeInObjectScope(QualType T,
|
||||||
QualType ObjectType,
|
QualType ObjectType,
|
||||||
|
@ -2200,6 +2211,60 @@ bool TreeTransform<Derived>::TransformExprs(Expr **Inputs,
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (PackExpansionExpr *Expansion = dyn_cast<PackExpansionExpr>(Inputs[I])) {
|
||||||
|
Expr *Pattern = Expansion->getPattern();
|
||||||
|
|
||||||
|
llvm::SmallVector<UnexpandedParameterPack, 2> Unexpanded;
|
||||||
|
getSema().collectUnexpandedParameterPacks(Pattern, Unexpanded);
|
||||||
|
assert(!Unexpanded.empty() && "Pack expansion without parameter packs?");
|
||||||
|
|
||||||
|
// Determine whether the set of unexpanded parameter packs can and should
|
||||||
|
// be expanded.
|
||||||
|
bool Expand = true;
|
||||||
|
unsigned NumExpansions = 0;
|
||||||
|
if (getDerived().TryExpandParameterPacks(Expansion->getEllipsisLoc(),
|
||||||
|
Pattern->getSourceRange(),
|
||||||
|
Unexpanded.data(),
|
||||||
|
Unexpanded.size(),
|
||||||
|
Expand, NumExpansions))
|
||||||
|
return true;
|
||||||
|
|
||||||
|
if (!Expand) {
|
||||||
|
// The transform has determined that we should perform a simple
|
||||||
|
// transformation on the pack expansion, producing another pack
|
||||||
|
// expansion.
|
||||||
|
Sema::ArgumentPackSubstitutionIndexRAII SubstIndex(getSema(), -1);
|
||||||
|
ExprResult OutPattern = getDerived().TransformExpr(Pattern);
|
||||||
|
if (OutPattern.isInvalid())
|
||||||
|
return true;
|
||||||
|
|
||||||
|
ExprResult Out = getDerived().RebuildPackExpansion(OutPattern.get(),
|
||||||
|
Expansion->getEllipsisLoc());
|
||||||
|
if (Out.isInvalid())
|
||||||
|
return true;
|
||||||
|
|
||||||
|
if (ArgChanged)
|
||||||
|
*ArgChanged = true;
|
||||||
|
Outputs.push_back(Out.get());
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
// The transform has determined that we should perform an elementwise
|
||||||
|
// expansion of the pattern. Do so.
|
||||||
|
for (unsigned I = 0; I != NumExpansions; ++I) {
|
||||||
|
Sema::ArgumentPackSubstitutionIndexRAII SubstIndex(getSema(), I);
|
||||||
|
ExprResult Out = getDerived().TransformExpr(Pattern);
|
||||||
|
if (Out.isInvalid())
|
||||||
|
return true;
|
||||||
|
|
||||||
|
if (ArgChanged)
|
||||||
|
*ArgChanged = true;
|
||||||
|
Outputs.push_back(Out.get());
|
||||||
|
}
|
||||||
|
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
ExprResult Result = getDerived().TransformExpr(Inputs[I]);
|
ExprResult Result = getDerived().TransformExpr(Inputs[I]);
|
||||||
if (Result.isInvalid())
|
if (Result.isInvalid())
|
||||||
return true;
|
return true;
|
||||||
|
|
|
@ -20,6 +20,20 @@ struct is_same<T, T> {
|
||||||
|
|
||||||
// FIXME: Many more bullets to go
|
// FIXME: Many more bullets to go
|
||||||
|
|
||||||
|
// In an initializer-list (8.5); the pattern is an initializer-clause.
|
||||||
|
// Note: this also covers expression-lists, since expression-list is
|
||||||
|
// just defined as initializer-list.
|
||||||
|
void five_args(int, int, int, int, int); // expected-note{{candidate function not viable: requires 5 arguments, but 6 were provided}}
|
||||||
|
|
||||||
|
template<int ...Values>
|
||||||
|
void initializer_list_expansion() {
|
||||||
|
int values[5] = { Values... }; // expected-error{{excess elements in array initializer}}
|
||||||
|
five_args(Values...); // expected-error{{no matching function for call to 'five_args'}}
|
||||||
|
}
|
||||||
|
|
||||||
|
template void initializer_list_expansion<1, 2, 3, 4, 5>();
|
||||||
|
template void initializer_list_expansion<1, 2, 3, 4, 5, 6>(); // expected-note{{in instantiation of function template specialization 'initializer_list_expansion<1, 2, 3, 4, 5, 6>' requested here}}
|
||||||
|
|
||||||
// In a template-argument-list (14.3); the pattern is a template-argument.
|
// In a template-argument-list (14.3); the pattern is a template-argument.
|
||||||
template<typename ...Types>
|
template<typename ...Types>
|
||||||
struct tuple_of_refs {
|
struct tuple_of_refs {
|
||||||
|
|
Loading…
Reference in New Issue