[cfe-commits] r122764 - in /cfe/trunk: lib/Parse/ParseExpr.cpp lib/Parse/ParseInit.cpp lib/Sema/TreeTransform.h test/CXX/temp/temp.decls/temp.variadic/p4.cpp
Douglas Gregor
dgregor at apple.com
Mon Jan 3 11:31:53 PST 2011
Author: dgregor
Date: Mon Jan 3 13:31:53 2011
New Revision: 122764
URL: http://llvm.org/viewvc/llvm-project?rev=122764&view=rev
Log:
Implement support for pack expansions in initializer lists and
expression lists.
Modified:
cfe/trunk/lib/Parse/ParseExpr.cpp
cfe/trunk/lib/Parse/ParseInit.cpp
cfe/trunk/lib/Sema/TreeTransform.h
cfe/trunk/test/CXX/temp/temp.decls/temp.variadic/p4.cpp
Modified: cfe/trunk/lib/Parse/ParseExpr.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Parse/ParseExpr.cpp?rev=122764&r1=122763&r2=122764&view=diff
==============================================================================
--- cfe/trunk/lib/Parse/ParseExpr.cpp (original)
+++ cfe/trunk/lib/Parse/ParseExpr.cpp Mon Jan 3 13:31:53 2011
@@ -172,8 +172,8 @@
/// = *= /= %= += -= <<= >>= &= ^= |=
///
/// expression: [C99 6.5.17]
-/// assignment-expression
-/// expression ',' assignment-expression
+/// assignment-expression ...[opt]
+/// expression ',' assignment-expression ...[opt]
///
ExprResult Parser::ParseExpression() {
ExprResult LHS(ParseAssignmentExpression());
@@ -1030,8 +1030,8 @@
/// '(' type-name ')' '{' initializer-list ',' '}'
///
/// argument-expression-list: [C99 6.5.2]
-/// argument-expression
-/// argument-expression-list ',' assignment-expression
+/// argument-expression ...[opt]
+/// argument-expression-list ',' assignment-expression ...[opt]
///
ExprResult
Parser::ParsePostfixExpressionSuffix(ExprResult LHS) {
@@ -1692,8 +1692,8 @@
/// argument-expression-list , assignment-expression
///
/// [C++] expression-list:
-/// [C++] assignment-expression
-/// [C++] expression-list , assignment-expression
+/// [C++] assignment-expression ...[opt]
+/// [C++] expression-list , assignment-expression ...[opt]
///
bool Parser::ParseExpressionList(llvm::SmallVectorImpl<Expr*> &Exprs,
llvm::SmallVectorImpl<SourceLocation> &CommaLocs,
@@ -1710,6 +1710,8 @@
}
ExprResult Expr(ParseAssignmentExpression());
+ if (Tok.is(tok::ellipsis))
+ Expr = Actions.ActOnPackExpansion(Expr.get(), ConsumeToken());
if (Expr.isInvalid())
return true;
Modified: cfe/trunk/lib/Parse/ParseInit.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Parse/ParseInit.cpp?rev=122764&r1=122763&r2=122764&view=diff
==============================================================================
--- cfe/trunk/lib/Parse/ParseInit.cpp (original)
+++ cfe/trunk/lib/Parse/ParseInit.cpp Mon Jan 3 13:31:53 2011
@@ -310,8 +310,8 @@
/// [GNU] '{' '}'
///
/// initializer-list:
-/// designation[opt] initializer
-/// initializer-list ',' designation[opt] initializer
+/// designation[opt] initializer ...[opt]
+/// initializer-list ',' designation[opt] initializer ...[opt]
///
ExprResult Parser::ParseBraceInitializer() {
InMessageExpressionRAIIObject InMessage(*this, false);
@@ -344,6 +344,9 @@
else
SubElt = ParseInitializer();
+ if (Tok.is(tok::ellipsis))
+ SubElt = Actions.ActOnPackExpansion(SubElt.get(), ConsumeToken());
+
// If we couldn't parse the subelement, bail out.
if (!SubElt.isInvalid()) {
InitExprs.push_back(SubElt.release());
Modified: cfe/trunk/lib/Sema/TreeTransform.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/TreeTransform.h?rev=122764&r1=122763&r2=122764&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/TreeTransform.h (original)
+++ cfe/trunk/lib/Sema/TreeTransform.h Mon Jan 3 13:31:53 2011
@@ -2103,6 +2103,8 @@
SourceLocation EllipsisLoc) {
switch (Pattern.getArgument().getKind()) {
case TemplateArgument::Expression:
+ // FIXME: We should be able to handle this now!
+
case TemplateArgument::Template:
llvm_unreachable("Unsupported pack expansion of expressions/templates");
@@ -2124,6 +2126,15 @@
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:
QualType TransformTypeInObjectScope(QualType T,
QualType ObjectType,
@@ -2200,6 +2211,60 @@
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]);
if (Result.isInvalid())
return true;
Modified: cfe/trunk/test/CXX/temp/temp.decls/temp.variadic/p4.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CXX/temp/temp.decls/temp.variadic/p4.cpp?rev=122764&r1=122763&r2=122764&view=diff
==============================================================================
--- cfe/trunk/test/CXX/temp/temp.decls/temp.variadic/p4.cpp (original)
+++ cfe/trunk/test/CXX/temp/temp.decls/temp.variadic/p4.cpp Mon Jan 3 13:31:53 2011
@@ -20,6 +20,20 @@
// 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.
template<typename ...Types>
struct tuple_of_refs {
More information about the cfe-commits
mailing list