зеркало из https://github.com/microsoft/clang-1.git
Implement support for pack expansions whose pattern is a non-type
template argument (described by an expression, of course). For example: template<int...> struct int_tuple { }; template<int ...Values> struct square { typedef int_tuple<(Values*Values)...> type; }; It also lays the foundation for pack expansions in an initializer-list. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@122751 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
Родитель
9917401b32
Коммит
be230c36e3
|
@ -2571,6 +2571,61 @@ public:
|
|||
virtual child_iterator child_end();
|
||||
};
|
||||
|
||||
/// \brief Represents a C++0x pack expansion that produces a sequence of
|
||||
/// expressions.
|
||||
///
|
||||
/// A pack expansion expression contains a pattern (which itself is an
|
||||
/// expression) followed by an ellipsis. For example:
|
||||
///
|
||||
/// \code
|
||||
/// template<typename F, typename ...Types>
|
||||
/// void forward(F f, Types &&...args) {
|
||||
/// f(static_cast<Types&&>(args)...);
|
||||
/// }
|
||||
/// \endcode
|
||||
///
|
||||
/// Here, the argument to the function object \c f is a pack expansion whose
|
||||
/// pattern is \c static_cast<Types&&>(args). When the \c forward function
|
||||
/// template is instantiated, the pack expansion will instantiate to zero or
|
||||
/// or more function arguments to the function object \c f.
|
||||
class PackExpansionExpr : public Expr {
|
||||
SourceLocation EllipsisLoc;
|
||||
Stmt *Pattern;
|
||||
|
||||
friend class ASTStmtReader;
|
||||
|
||||
public:
|
||||
PackExpansionExpr(QualType T, Expr *Pattern, SourceLocation EllipsisLoc)
|
||||
: Expr(PackExpansionExprClass, T, Pattern->getValueKind(),
|
||||
Pattern->getObjectKind(), /*TypeDependent=*/true,
|
||||
/*ValueDependent=*/true, /*ContainsUnexpandedParameterPack=*/false),
|
||||
EllipsisLoc(EllipsisLoc),
|
||||
Pattern(Pattern) { }
|
||||
|
||||
PackExpansionExpr(EmptyShell Empty) : Expr(PackExpansionExprClass, Empty) { }
|
||||
|
||||
/// \brief Retrieve the pattern of the pack expansion.
|
||||
Expr *getPattern() { return reinterpret_cast<Expr *>(Pattern); }
|
||||
|
||||
/// \brief Retrieve the pattern of the pack expansion.
|
||||
const Expr *getPattern() const { return reinterpret_cast<Expr *>(Pattern); }
|
||||
|
||||
/// \brief Retrieve the location of the ellipsis that describes this pack
|
||||
/// expansion.
|
||||
SourceLocation getEllipsisLoc() const { return EllipsisLoc; }
|
||||
|
||||
virtual SourceRange getSourceRange() const;
|
||||
|
||||
static bool classof(const Stmt *T) {
|
||||
return T->getStmtClass() == PackExpansionExprClass;
|
||||
}
|
||||
static bool classof(const PackExpansionExpr *) { return true; }
|
||||
|
||||
// Iterators
|
||||
virtual child_iterator child_begin();
|
||||
virtual child_iterator child_end();
|
||||
};
|
||||
|
||||
inline ExplicitTemplateArgumentList &OverloadExpr::getExplicitTemplateArgs() {
|
||||
if (isa<UnresolvedLookupExpr>(this))
|
||||
return cast<UnresolvedLookupExpr>(this)->getExplicitTemplateArgs();
|
||||
|
|
|
@ -1820,6 +1820,7 @@ DEF_TRAVERSE_STMT(UnaryOperator, { })
|
|||
DEF_TRAVERSE_STMT(BinaryOperator, { })
|
||||
DEF_TRAVERSE_STMT(CompoundAssignOperator, { })
|
||||
DEF_TRAVERSE_STMT(CXXNoexceptExpr, { })
|
||||
DEF_TRAVERSE_STMT(PackExpansionExpr, { })
|
||||
|
||||
// These literals (all of them) do not need any action.
|
||||
DEF_TRAVERSE_STMT(IntegerLiteral, { })
|
||||
|
|
|
@ -1871,7 +1871,7 @@ def err_ellipsis_in_declarator_not_parameter : Error<
|
|||
|
||||
// Unsupported variadic templates features
|
||||
def err_pack_expansion_unsupported : Error<
|
||||
"clang does not yet support %select{non-type|template}0 pack expansions">;
|
||||
"clang does not yet support template pack expansions">;
|
||||
def err_pack_expansion_instantiation_unsupported : Error<
|
||||
"clang cannot yet instantiate pack expansions">;
|
||||
def err_pack_expansion_mismatch_unsupported : Error<
|
||||
|
|
|
@ -111,6 +111,7 @@ def OverloadExpr : DStmt<Expr, 1>;
|
|||
def UnresolvedLookupExpr : DStmt<OverloadExpr>;
|
||||
def UnresolvedMemberExpr : DStmt<OverloadExpr>;
|
||||
def CXXNoexceptExpr : DStmt<Expr>;
|
||||
def PackExpansionExpr : DStmt<Expr>;
|
||||
|
||||
// Obj-C Expressions.
|
||||
def ObjCStringLiteral : DStmt<Expr>;
|
||||
|
|
|
@ -3279,7 +3279,7 @@ public:
|
|||
ParsedTemplateArgument ActOnPackExpansion(const ParsedTemplateArgument &Arg,
|
||||
SourceLocation EllipsisLoc);
|
||||
|
||||
/// \brief Invoked when parsing a type follows by an ellipsis, which
|
||||
/// \brief Invoked when parsing a type followed by an ellipsis, which
|
||||
/// creates a pack expansion.
|
||||
///
|
||||
/// \param Type The type preceding the ellipsis, which will become
|
||||
|
@ -3293,6 +3293,15 @@ public:
|
|||
TypeSourceInfo *CheckPackExpansion(TypeSourceInfo *Pattern,
|
||||
SourceLocation EllipsisLoc);
|
||||
|
||||
/// \brief Invoked when parsing an expression followed by an ellipsis, which
|
||||
/// creates a pack expansion.
|
||||
///
|
||||
/// \param Pattern The expression preceding the ellipsis, which will become
|
||||
/// the pattern of the pack expansion.
|
||||
///
|
||||
/// \param EllipsisLoc The location of the ellipsis.
|
||||
ExprResult ActOnPackExpansion(Expr *Pattern, SourceLocation EllipsisLoc);
|
||||
|
||||
/// \brief Determine whether we could expand a pack expansion with the
|
||||
/// given set of parameter packs into separate arguments by repeatedly
|
||||
/// transforming the pattern.
|
||||
|
|
|
@ -929,7 +929,9 @@ namespace clang {
|
|||
EXPR_CXX_NOEXCEPT, // CXXNoexceptExpr
|
||||
|
||||
EXPR_OPAQUE_VALUE, // OpaqueValueExpr
|
||||
EXPR_BINARY_TYPE_TRAIT // BinaryTypeTraitExpr
|
||||
EXPR_BINARY_TYPE_TRAIT, // BinaryTypeTraitExpr
|
||||
|
||||
EXPR_PACK_EXPANSION // PackExpansionExpr
|
||||
};
|
||||
|
||||
/// \brief The kinds of designators that can occur in a
|
||||
|
|
|
@ -1025,3 +1025,15 @@ Stmt::child_iterator CXXNoexceptExpr::child_begin() {
|
|||
Stmt::child_iterator CXXNoexceptExpr::child_end() {
|
||||
return child_iterator(&Operand + 1);
|
||||
}
|
||||
|
||||
SourceRange PackExpansionExpr::getSourceRange() const {
|
||||
return SourceRange(Pattern->getLocStart(), EllipsisLoc);
|
||||
}
|
||||
|
||||
Stmt::child_iterator PackExpansionExpr::child_begin() {
|
||||
return child_iterator(&Pattern);
|
||||
}
|
||||
|
||||
Stmt::child_iterator PackExpansionExpr::child_end() {
|
||||
return child_iterator(&Pattern + 1);
|
||||
}
|
||||
|
|
|
@ -304,6 +304,9 @@ static Cl::Kinds ClassifyInternal(ASTContext &Ctx, const Expr *E) {
|
|||
|
||||
case Expr::CXXUuidofExprClass:
|
||||
return Cl::CL_LValue;
|
||||
|
||||
case Expr::PackExpansionExprClass:
|
||||
return ClassifyInternal(Ctx, cast<PackExpansionExpr>(E)->getPattern());
|
||||
}
|
||||
|
||||
llvm_unreachable("unhandled expression kind in classification");
|
||||
|
|
|
@ -2634,6 +2634,7 @@ static ICEDiag CheckICE(const Expr* E, ASTContext &Ctx) {
|
|||
case Expr::BlockDeclRefExprClass:
|
||||
case Expr::NoStmtClass:
|
||||
case Expr::OpaqueValueExprClass:
|
||||
case Expr::PackExpansionExprClass:
|
||||
return ICEDiag(2, E->getLocStart());
|
||||
|
||||
case Expr::GNUNullExprClass:
|
||||
|
|
|
@ -1246,6 +1246,11 @@ void StmtPrinter::VisitCXXNoexceptExpr(CXXNoexceptExpr *E) {
|
|||
OS << ")";
|
||||
}
|
||||
|
||||
void StmtPrinter::VisitPackExpansionExpr(clang::PackExpansionExpr *E) {
|
||||
PrintExpr(E->getPattern());
|
||||
OS << "...";
|
||||
}
|
||||
|
||||
// Obj-C
|
||||
|
||||
void StmtPrinter::VisitObjCStringLiteral(ObjCStringLiteral *Node) {
|
||||
|
|
|
@ -832,6 +832,10 @@ void StmtProfiler::VisitCXXNoexceptExpr(CXXNoexceptExpr *S) {
|
|||
VisitExpr(S);
|
||||
}
|
||||
|
||||
void StmtProfiler::VisitPackExpansionExpr(PackExpansionExpr *S) {
|
||||
VisitExpr(S);
|
||||
}
|
||||
|
||||
void StmtProfiler::VisitOpaqueValueExpr(OpaqueValueExpr *E) {
|
||||
VisitExpr(E);
|
||||
}
|
||||
|
|
|
@ -17,6 +17,7 @@
|
|||
#include "clang/AST/DeclBase.h"
|
||||
#include "clang/AST/DeclTemplate.h"
|
||||
#include "clang/AST/Expr.h"
|
||||
#include "clang/AST/ExprCXX.h"
|
||||
#include "clang/AST/TypeLoc.h"
|
||||
#include "clang/Basic/Diagnostic.h"
|
||||
#include "llvm/ADT/FoldingSet.h"
|
||||
|
@ -72,15 +73,14 @@ bool TemplateArgument::isPackExpansion() const {
|
|||
return false;
|
||||
|
||||
case Type:
|
||||
return llvm::isa<PackExpansionType>(getAsType());
|
||||
return isa<PackExpansionType>(getAsType());
|
||||
|
||||
case Template:
|
||||
// FIXME: Template template pack expansions.
|
||||
break;
|
||||
|
||||
case Expression:
|
||||
// FIXME: Expansion pack expansions.
|
||||
break;
|
||||
return isa<PackExpansionExpr>(getAsExpr());
|
||||
}
|
||||
|
||||
return false;
|
||||
|
@ -199,9 +199,11 @@ TemplateArgument TemplateArgument::getPackExpansionPattern() const {
|
|||
return getAsType()->getAs<PackExpansionType>()->getPattern();
|
||||
|
||||
case Expression:
|
||||
return cast<PackExpansionExpr>(getAsExpr())->getPattern();
|
||||
|
||||
case Template:
|
||||
// FIXME: Variadic templates.
|
||||
llvm_unreachable("Expression and template pack expansions unsupported");
|
||||
llvm_unreachable("Template pack expansions unsupported");
|
||||
|
||||
case Declaration:
|
||||
case Integral:
|
||||
|
@ -343,10 +345,14 @@ TemplateArgumentLoc::getPackExpansionPattern(SourceLocation &Ellipsis,
|
|||
PatternTSInfo);
|
||||
}
|
||||
|
||||
case TemplateArgument::Expression:
|
||||
case TemplateArgument::Expression: {
|
||||
Expr *Pattern = cast<PackExpansionExpr>(Argument.getAsExpr())->getPattern();
|
||||
return TemplateArgumentLoc(Pattern, Pattern);
|
||||
}
|
||||
|
||||
case TemplateArgument::Template:
|
||||
// FIXME: Variadic templates.
|
||||
llvm_unreachable("Expression and template pack expansions unsupported");
|
||||
llvm_unreachable("Template pack expansions unsupported");
|
||||
|
||||
case TemplateArgument::Declaration:
|
||||
case TemplateArgument::Integral:
|
||||
|
|
|
@ -2043,7 +2043,11 @@ void CXXNameMangler::mangleExpression(const Expr *E, unsigned Arity) {
|
|||
Out << "LDnE";
|
||||
break;
|
||||
}
|
||||
|
||||
|
||||
case Expr::PackExpansionExprClass:
|
||||
Out << "sp";
|
||||
mangleExpression(cast<PackExpansionExpr>(E)->getPattern());
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -2926,6 +2926,10 @@ MarkUsedTemplateParameters(Sema &SemaRef,
|
|||
bool OnlyDeduced,
|
||||
unsigned Depth,
|
||||
llvm::SmallVectorImpl<bool> &Used) {
|
||||
// We can deduce from a pack expansion.
|
||||
if (const PackExpansionExpr *Expansion = dyn_cast<PackExpansionExpr>(E))
|
||||
E = Expansion->getPattern();
|
||||
|
||||
// FIXME: if !OnlyDeduced, we have to walk the whole subexpression to
|
||||
// find other occurrences of template parameters.
|
||||
const DeclRefExpr *DRE = dyn_cast<DeclRefExpr>(E);
|
||||
|
|
|
@ -79,9 +79,6 @@ namespace {
|
|||
|
||||
// FIXME: Record occurrences of template template parameter packs.
|
||||
|
||||
// FIXME: Once we have pack expansions in the AST, block their
|
||||
// traversal.
|
||||
|
||||
//------------------------------------------------------------------------
|
||||
// Pruning the search for unexpanded parameter packs.
|
||||
//------------------------------------------------------------------------
|
||||
|
@ -299,14 +296,17 @@ Sema::ActOnPackExpansion(const ParsedTemplateArgument &Arg,
|
|||
Arg.getLocation());
|
||||
}
|
||||
|
||||
case ParsedTemplateArgument::NonType:
|
||||
Diag(EllipsisLoc, diag::err_pack_expansion_unsupported)
|
||||
<< 0;
|
||||
return ParsedTemplateArgument();
|
||||
|
||||
case ParsedTemplateArgument::NonType: {
|
||||
ExprResult Result = ActOnPackExpansion(Arg.getAsExpr(), EllipsisLoc);
|
||||
if (Result.isInvalid())
|
||||
return ParsedTemplateArgument();
|
||||
|
||||
return ParsedTemplateArgument(Arg.getKind(), Result.get(),
|
||||
Arg.getLocation());
|
||||
}
|
||||
|
||||
case ParsedTemplateArgument::Template:
|
||||
Diag(EllipsisLoc, diag::err_pack_expansion_unsupported)
|
||||
<< 1;
|
||||
Diag(EllipsisLoc, diag::err_pack_expansion_unsupported);
|
||||
return ParsedTemplateArgument();
|
||||
}
|
||||
llvm_unreachable("Unhandled template argument kind?");
|
||||
|
@ -352,6 +352,24 @@ TypeSourceInfo *Sema::CheckPackExpansion(TypeSourceInfo *Pattern,
|
|||
return TSResult;
|
||||
}
|
||||
|
||||
ExprResult Sema::ActOnPackExpansion(Expr *Pattern, SourceLocation EllipsisLoc) {
|
||||
if (!Pattern)
|
||||
return ExprError();
|
||||
|
||||
// C++0x [temp.variadic]p5:
|
||||
// The pattern of a pack expansion shall name one or more
|
||||
// parameter packs that are not expanded by a nested pack
|
||||
// expansion.
|
||||
if (!Pattern->containsUnexpandedParameterPack()) {
|
||||
Diag(EllipsisLoc, diag::err_pack_expansion_without_parameter_packs)
|
||||
<< Pattern->getSourceRange();
|
||||
return ExprError();
|
||||
}
|
||||
|
||||
// Create the pack expansion expression and source-location information.
|
||||
return Owned(new (Context) PackExpansionExpr(Context.DependentTy, Pattern,
|
||||
EllipsisLoc));
|
||||
}
|
||||
|
||||
bool Sema::CheckParameterPacksForExpansion(SourceLocation EllipsisLoc,
|
||||
SourceRange PatternRange,
|
||||
|
|
|
@ -6437,6 +6437,13 @@ TreeTransform<Derived>::TransformCXXNoexceptExpr(CXXNoexceptExpr *E) {
|
|||
return getDerived().RebuildCXXNoexceptExpr(E->getSourceRange(),SubExpr.get());
|
||||
}
|
||||
|
||||
template<typename Derived>
|
||||
ExprResult
|
||||
TreeTransform<Derived>::TransformPackExpansionExpr(PackExpansionExpr *E) {
|
||||
llvm_unreachable("pack expansion expression in unhandled context");
|
||||
return ExprError();
|
||||
}
|
||||
|
||||
template<typename Derived>
|
||||
ExprResult
|
||||
TreeTransform<Derived>::TransformObjCStringLiteral(ObjCStringLiteral *E) {
|
||||
|
|
|
@ -176,7 +176,8 @@ namespace clang {
|
|||
void VisitUnaryTypeTraitExpr(UnaryTypeTraitExpr *E);
|
||||
void VisitBinaryTypeTraitExpr(BinaryTypeTraitExpr *E);
|
||||
void VisitCXXNoexceptExpr(CXXNoexceptExpr *E);
|
||||
|
||||
void VisitPackExpansionExpr(PackExpansionExpr *E);
|
||||
|
||||
void VisitOpaqueValueExpr(OpaqueValueExpr *E);
|
||||
};
|
||||
}
|
||||
|
@ -1287,6 +1288,12 @@ void ASTStmtReader::VisitCXXNoexceptExpr(CXXNoexceptExpr *E) {
|
|||
E->Operand = Reader.ReadSubExpr();
|
||||
}
|
||||
|
||||
void ASTStmtReader::VisitPackExpansionExpr(PackExpansionExpr *E) {
|
||||
VisitExpr(E);
|
||||
E->EllipsisLoc = ReadSourceLocation(Record, Idx);
|
||||
E->Pattern = Reader.ReadSubExpr();
|
||||
}
|
||||
|
||||
void ASTStmtReader::VisitOpaqueValueExpr(OpaqueValueExpr *E) {
|
||||
VisitExpr(E);
|
||||
}
|
||||
|
@ -1809,6 +1816,10 @@ Stmt *ASTReader::ReadStmtFromStream(PerFileData &F) {
|
|||
S = new (Context) CXXNoexceptExpr(Empty);
|
||||
break;
|
||||
|
||||
case EXPR_PACK_EXPANSION:
|
||||
S = new (Context) PackExpansionExpr(Empty);
|
||||
break;
|
||||
|
||||
case EXPR_OPAQUE_VALUE:
|
||||
S = new (Context) OpaqueValueExpr(Empty);
|
||||
break;
|
||||
|
|
|
@ -150,7 +150,7 @@ namespace clang {
|
|||
void VisitUnaryTypeTraitExpr(UnaryTypeTraitExpr *E);
|
||||
void VisitBinaryTypeTraitExpr(BinaryTypeTraitExpr *E);
|
||||
void VisitCXXNoexceptExpr(CXXNoexceptExpr *E);
|
||||
|
||||
void VisitPackExpansionExpr(PackExpansionExpr *E);
|
||||
void VisitOpaqueValueExpr(OpaqueValueExpr *E);
|
||||
};
|
||||
}
|
||||
|
@ -1296,6 +1296,13 @@ void ASTStmtWriter::VisitCXXNoexceptExpr(CXXNoexceptExpr *E) {
|
|||
Code = serialization::EXPR_CXX_NOEXCEPT;
|
||||
}
|
||||
|
||||
void ASTStmtWriter::VisitPackExpansionExpr(PackExpansionExpr *E) {
|
||||
VisitExpr(E);
|
||||
Writer.AddSourceLocation(E->getEllipsisLoc(), Record);
|
||||
Writer.AddStmt(E->getPattern());
|
||||
Code = serialization::EXPR_PACK_EXPANSION;
|
||||
}
|
||||
|
||||
void ASTStmtWriter::VisitOpaqueValueExpr(OpaqueValueExpr *E) {
|
||||
VisitExpr(E);
|
||||
Code = serialization::EXPR_OPAQUE_VALUE;
|
||||
|
|
|
@ -771,6 +771,7 @@ void ExprEngine::Visit(const Stmt* S, ExplodedNode* Pred,
|
|||
case Stmt::UnresolvedLookupExprClass:
|
||||
case Stmt::UnresolvedMemberExprClass:
|
||||
case Stmt::CXXNoexceptExprClass:
|
||||
case Stmt::PackExpansionExprClass:
|
||||
{
|
||||
SaveAndRestore<bool> OldSink(Builder->BuildSinks);
|
||||
Builder->BuildSinks = true;
|
||||
|
|
|
@ -64,3 +64,52 @@ namespace Replace {
|
|||
int check0[is_same<EverythingToInt<tuple<double, float>>::type,
|
||||
tuple<int, int>>::value? 1 : -1];
|
||||
}
|
||||
|
||||
namespace Multiply {
|
||||
template<int ...Values>
|
||||
struct double_values {
|
||||
typedef int_tuple<Values*2 ...> type;
|
||||
};
|
||||
|
||||
int check0[is_same<double_values<1, 2, -3>::type,
|
||||
int_tuple<2, 4, -6>>::value? 1 : -1];
|
||||
|
||||
template<int ...Values>
|
||||
struct square {
|
||||
typedef int_tuple<(Values*Values)...> type;
|
||||
};
|
||||
|
||||
int check1[is_same<square<1, 2, -3>::type,
|
||||
int_tuple<1, 4, 9>>::value? 1 : -1];
|
||||
|
||||
template<typename IntTuple> struct square_tuple;
|
||||
|
||||
template<int ...Values>
|
||||
struct square_tuple<int_tuple<Values...>> {
|
||||
typedef int_tuple<(Values*Values)...> type;
|
||||
};
|
||||
|
||||
int check2[is_same<square_tuple<int_tuple<1, 2, -3>>::type,
|
||||
int_tuple<1, 4, 9>>::value? 1 : -1];
|
||||
}
|
||||
|
||||
namespace Indices {
|
||||
template<unsigned I, unsigned N, typename IntTuple>
|
||||
struct build_indices_impl;
|
||||
|
||||
template<unsigned I, unsigned N, int ...Indices>
|
||||
struct build_indices_impl<I, N, int_tuple<Indices...> >
|
||||
: build_indices_impl<I+1, N, int_tuple<Indices..., I> > {
|
||||
};
|
||||
|
||||
template<unsigned N, int ...Indices>
|
||||
struct build_indices_impl<N, N, int_tuple<Indices...> > {
|
||||
typedef int_tuple<Indices...> type;
|
||||
};
|
||||
|
||||
template<unsigned N>
|
||||
struct build_indices : build_indices_impl<0, N, int_tuple<> > { };
|
||||
|
||||
int check0[is_same<build_indices<5>::type,
|
||||
int_tuple<0, 1, 2, 3, 4>>::value? 1 : -1];
|
||||
}
|
||||
|
|
|
@ -164,6 +164,7 @@ CXCursor cxcursor::MakeCXCursor(Stmt *S, Decl *Parent,
|
|||
case Stmt::ShuffleVectorExprClass:
|
||||
case Stmt::BlockExprClass:
|
||||
case Stmt::OpaqueValueExprClass:
|
||||
case Stmt::PackExpansionExprClass:
|
||||
K = CXCursor_UnexposedExpr;
|
||||
break;
|
||||
|
||||
|
|
Загрузка…
Ссылка в новой задаче