/// parameter pack.
bool containsUnexpandedParameterPack() const;
+ /// \brief Determine whether this template argument is a pack expansion.
+ bool isPackExpansion() const;
+
/// \brief Retrieve the template argument as a type.
QualType getAsType() const {
if (Kind != Type)
assert(Argument.getKind() == TemplateArgument::Template);
return LocInfo.getTemplateNameLoc();
}
+
+ /// \brief When the template argument is a pack expansion, returns
+ /// the pattern of the pack expansion.
+ ///
+ /// \param Ellipsis Will be set to the location of the ellipsis.
+ TemplateArgumentLoc getPackExpansionPattern(SourceLocation &Ellipsis,
+ ASTContext &Context) const;
};
/// A convenient class for passing around template argument
def err_pack_expansion_without_parameter_packs : Error<
"pack expansion does not contain any unexpanded parameter packs">;
+def err_pack_expansion_length_conflict : Error<
+ "pack expansion contains parameter packs %0 and %1 that have different "
+ "lengths (%2 vs. %3)">;
+
def err_pack_expansion_unsupported : Error<
"clang does not yet support %select{non-type|template}0 pack expansions">;
def err_pack_expansion_instantiation_unsupported : Error<
"clang cannot yet instantiate pack expansions">;
+def err_pack_expansion_mismatch_unsupported : Error<
+ "clang cannot yet instantiate pack expansions with mismatched pack levels">;
def err_unexpected_typedef : Error<
"unexpected type name %0: expected expression">;
static bool classof(const LocInfoType *) { return true; }
};
+// FIXME: No way to easily map from TemplateTypeParmTypes to
+// TemplateTypeParmDecls, so we have this horrible PointerUnion.
+typedef std::pair<llvm::PointerUnion<const TemplateTypeParmType*, NamedDecl*>,
+ SourceLocation> UnexpandedParameterPack;
+
/// Sema - This implements semantic analysis and AST building for C.
class Sema {
Sema(const Sema&); // DO NOT IMPLEMENT
TemplateName Template,
UnexpandedParameterPackContext UPPC);
+ /// \brief Collect the set of unexpanded parameter packs within the given
+ /// template argument.
+ ///
+ /// \param Arg The template argument that will be traversed to find
+ /// unexpanded parameter packs.
+ void collectUnexpandedParameterPacks(TemplateArgumentLoc Arg,
+ llvm::SmallVectorImpl<UnexpandedParameterPack> &Unexpanded);
+
/// \brief Invoked when parsing a template argument followed by an
/// ellipsis, which creates a pack expansion.
///
/// \param EllipsisLoc The location of the ellipsis.
TypeResult ActOnPackExpansion(ParsedType Type, SourceLocation EllipsisLoc);
+ /// \brief Construct a pack expansion type from the pattern of the pack
+ /// expansion.
+ TypeSourceInfo *CheckPackExpansion(TypeSourceInfo *Pattern,
+ SourceLocation EllipsisLoc);
+
/// \brief Describes the result of template argument deduction.
///
/// The TemplateDeductionResult enumeration describes the result of
/// to implement it anywhere else.
ActiveTemplateInstantiation LastTemplateInstantiationErrorContext;
+ /// \brief The current index into pack expansion arguments that will be
+ /// used for substitution of parameter packs.
+ ///
+ /// The pack expansion index will be -1 to indicate that parameter packs
+ /// should be instantiated as themselves. Otherwise, the index specifies
+ /// which argument within the parameter pack will be used for substitution.
+ int ArgumentPackSubstitutionIndex;
+
+ /// \brief RAII object used to change the argument pack substitution index
+ /// within a \c Sema object.
+ ///
+ /// See \c ArgumentPackSubstitutionIndex for more information.
+ class ArgumentPackSubstitutionIndexRAII {
+ Sema &Self;
+ int OldSubstitutionIndex;
+
+ public:
+ ArgumentPackSubstitutionIndexRAII(Sema &Self, int NewSubstitutionIndex)
+ : Self(Self), OldSubstitutionIndex(Self.ArgumentPackSubstitutionIndex) {
+ Self.ArgumentPackSubstitutionIndex = NewSubstitutionIndex;
+ }
+
+ ~ArgumentPackSubstitutionIndexRAII() {
+ Self.ArgumentPackSubstitutionIndex = OldSubstitutionIndex;
+ }
+ };
+
+ friend class ArgumentPackSubstitutionRAII;
+
/// \brief The stack of calls expression undergoing template instantiation.
///
/// The top of this stack is used by a fixit instantiating unresolved
};
class TemplateDeclInstantiator
- : public DeclVisitor<TemplateDeclInstantiator, Decl *> {
+ : public DeclVisitor<TemplateDeclInstantiator, Decl *>
+ {
Sema &SemaRef;
+ Sema::ArgumentPackSubstitutionIndexRAII SubstIndex;
DeclContext *Owner;
const MultiLevelTemplateArgumentList &TemplateArgs;
public:
TemplateDeclInstantiator(Sema &SemaRef, DeclContext *Owner,
const MultiLevelTemplateArgumentList &TemplateArgs)
- : SemaRef(SemaRef), Owner(Owner), TemplateArgs(TemplateArgs) { }
+ : SemaRef(SemaRef), SubstIndex(SemaRef, -1), Owner(Owner),
+ TemplateArgs(TemplateArgs) { }
// FIXME: Once we get closer to completion, replace these manually-written
// declarations with automatically-generated ones from
InstantiateClassTemplatePartialSpecialization(
ClassTemplateDecl *ClassTemplate,
ClassTemplatePartialSpecializationDecl *PartialSpec);
- };
+ };
}
#endif // LLVM_CLANG_SEMA_TEMPLATE_H
return false;
}
+bool TemplateArgument::isPackExpansion() const {
+ switch (getKind()) {
+ case Null:
+ case Declaration:
+ case Integral:
+ case Pack:
+ return false;
+
+ case Type:
+ return llvm::isa<PackExpansionType>(getAsType());
+
+ case Template:
+ // FIXME: Template template pack expansions.
+ break;
+
+ case Expression:
+ // FIXME: Expansion pack expansions.
+ break;
+ }
+
+ return false;
+}
+
bool TemplateArgument::containsUnexpandedParameterPack() const {
switch (getKind()) {
case Null:
return SourceRange();
}
+TemplateArgumentLoc
+TemplateArgumentLoc::getPackExpansionPattern(SourceLocation &Ellipsis,
+ ASTContext &Context) const {
+ assert(Argument.isPackExpansion());
+
+ switch (Argument.getKind()) {
+ case TemplateArgument::Type: {
+ PackExpansionTypeLoc Expansion
+ = cast<PackExpansionTypeLoc>(getTypeSourceInfo()->getTypeLoc());
+ Ellipsis = Expansion.getEllipsisLoc();
+
+ TypeLoc Pattern = Expansion.getPatternLoc();
+
+ // FIXME: This is horrible. We know where the source location data is for
+ // the pattern, and we have the pattern's type, but we are forced to copy
+ // them into an ASTContext because TypeSourceInfo bundles them together
+ // and TemplateArgumentLoc traffics in TypeSourceInfo pointers.
+ TypeSourceInfo *PatternTSInfo
+ = Context.CreateTypeSourceInfo(Pattern.getType(),
+ Pattern.getFullDataSize());
+ memcpy(PatternTSInfo->getTypeLoc().getOpaqueData(),
+ Pattern.getOpaqueData(), Pattern.getFullDataSize());
+ return TemplateArgumentLoc(TemplateArgument(Pattern.getType()),
+ PatternTSInfo);
+ }
+
+ case TemplateArgument::Expression:
+ case TemplateArgument::Template:
+ // FIXME: Variadic templates.
+ llvm_unreachable("Expression and template pack expansions unsupported");
+
+ case TemplateArgument::Declaration:
+ case TemplateArgument::Integral:
+ case TemplateArgument::Pack:
+ case TemplateArgument::Null:
+ return TemplateArgumentLoc();
+ }
+
+ return TemplateArgumentLoc();
+}
+
const DiagnosticBuilder &clang::operator<<(const DiagnosticBuilder &DB,
const TemplateArgument &Arg) {
switch (Arg.getKind()) {
GlobalNewDeleteDeclared(false),
CompleteTranslationUnit(CompleteTranslationUnit),
NumSFINAEErrors(0), SuppressAccessChecking(false),
- NonInstantiationEntries(0), CurrentInstantiationScope(0), TyposCorrected(0),
+ NonInstantiationEntries(0), ArgumentPackSubstitutionIndex(-1),
+ CurrentInstantiationScope(0), TyposCorrected(0),
AnalysisWarnings(*this)
{
TUScope = 0;
MultiLevelTemplateArgumentList(TemplateArgs)));
if (!TempParm)
return true;
-
- // FIXME: TempParam is leaked.
}
switch (Arg.getArgument().getKind()) {
this->Loc = Loc;
this->Entity = Entity;
}
-
+
+ bool TryExpandParameterPacks(SourceLocation EllipsisLoc,
+ SourceRange PatternRange,
+ const UnexpandedParameterPack *Unexpanded,
+ unsigned NumUnexpanded,
+ bool &ShouldExpand,
+ unsigned &NumExpansions);
+
/// \brief Transform the given declaration by instantiating a reference to
/// this declaration.
Decl *TransformDecl(SourceLocation Loc, Decl *D);
return true;
}
+bool TemplateInstantiator::TryExpandParameterPacks(SourceLocation EllipsisLoc,
+ SourceRange PatternRange,
+ const UnexpandedParameterPack *Unexpanded,
+ unsigned NumUnexpanded,
+ bool &ShouldExpand,
+ unsigned &NumExpansions) {
+ ShouldExpand = true;
+ std::pair<IdentifierInfo *, SourceLocation> FirstPack;
+ bool HaveFirstPack = false;
+
+ for (unsigned I = 0; I != NumUnexpanded; ++I) {
+ // Compute the depth and index for this parameter pack.
+ unsigned Depth;
+ unsigned Index;
+ IdentifierInfo *Name;
+
+ if (const TemplateTypeParmType *TTP
+ = Unexpanded[I].first.dyn_cast<const TemplateTypeParmType *>()) {
+ Depth = TTP->getDepth();
+ Index = TTP->getIndex();
+ Name = TTP->getName();
+ } else {
+ NamedDecl *ND = Unexpanded[I].first.get<NamedDecl *>();
+ if (TemplateTypeParmDecl *TTP = dyn_cast<TemplateTypeParmDecl>(ND)) {
+ Depth = TTP->getDepth();
+ Index = TTP->getIndex();
+ } else if (NonTypeTemplateParmDecl *NTTP
+ = dyn_cast<NonTypeTemplateParmDecl>(ND)) {
+ Depth = NTTP->getDepth();
+ Index = NTTP->getIndex();
+ } else {
+ TemplateTemplateParmDecl *TTP = cast<TemplateTemplateParmDecl>(ND);
+ Depth = TTP->getDepth();
+ Index = TTP->getIndex();
+ }
+ // FIXME: Variadic templates function parameter packs?
+ Name = ND->getIdentifier();
+ }
+
+ // If we don't have a template argument at this depth/index, then we
+ // cannot expand the pack expansion. Make a note of this, but we still
+ // want to check that any parameter packs we *do* have arguments for.
+ if (!TemplateArgs.hasTemplateArgument(Depth, Index)) {
+ ShouldExpand = false;
+ continue;
+ }
+
+ // Determine the size of the argument pack.
+ unsigned NewPackSize = TemplateArgs(Depth, Index).pack_size();
+ if (!HaveFirstPack) {
+ // The is the first pack we've seen for which we have an argument.
+ // Record it.
+ NumExpansions = NewPackSize;
+ FirstPack.first = Name;
+ FirstPack.second = Unexpanded[I].second;
+ HaveFirstPack = true;
+ continue;
+ }
+
+ if (NewPackSize != NumExpansions) {
+ // C++0x [temp.variadic]p5:
+ // All of the parameter packs expanded by a pack expansion shall have
+ // the same number of arguments specified.
+ getSema().Diag(EllipsisLoc, diag::err_pack_expansion_length_conflict)
+ << FirstPack.first << Name << NumExpansions << NewPackSize
+ << SourceRange(FirstPack.second) << SourceRange(Unexpanded[I].second);
+ return true;
+ }
+ }
+
+ return false;
+}
+
Decl *TemplateInstantiator::TransformDecl(SourceLocation Loc, Decl *D) {
if (!D)
return 0;
TTP->getPosition()))
return D;
+ // FIXME: Variadic templates index substitution.
TemplateName Template
= TemplateArgs(TTP->getDepth(), TTP->getPosition()).getAsTemplate();
assert(!Template.isNull() && Template.getAsTemplateDecl() &&
const TemplateTypeParmType *TTP
= cast<TemplateTypeParmType>(getSema().Context.getTypeDeclType(TTPD));
if (TTP->getDepth() < TemplateArgs.getNumLevels()) {
+ // FIXME: Variadic templates index substitution.
QualType T = TemplateArgs(TTP->getDepth(), TTP->getIndex()).getAsType();
if (T.isNull())
return cast_or_null<NamedDecl>(TransformDecl(Loc, D));
TemplateInstantiator::TransformDeclRefExpr(DeclRefExpr *E) {
NamedDecl *D = E->getDecl();
if (NonTypeTemplateParmDecl *NTTP = dyn_cast<NonTypeTemplateParmDecl>(D)) {
+ // FIXME: Variadic templates index substitution.
if (NTTP->getDepth() < TemplateArgs.getNumLevels())
return TransformTemplateParmRefExpr(E, NTTP);
return TL.getType();
}
- assert(TemplateArgs(T->getDepth(), T->getIndex()).getKind()
- == TemplateArgument::Type &&
+ TemplateArgument Arg = TemplateArgs(T->getDepth(), T->getIndex());
+
+ if (T->isParameterPack()) {
+ assert(Arg.getKind() == TemplateArgument::Pack &&
+ "Missing argument pack");
+
+ if (getSema().ArgumentPackSubstitutionIndex == -1) {
+ // FIXME: Variadic templates fun case.
+ getSema().Diag(TL.getSourceRange().getBegin(),
+ diag::err_pack_expansion_mismatch_unsupported);
+ return QualType();
+ }
+
+ Arg = Arg.pack_begin()[getSema().ArgumentPackSubstitutionIndex];
+ }
+
+ assert(Arg.getKind() == TemplateArgument::Type &&
"Template argument kind mismatch");
- QualType Replacement
- = TemplateArgs(T->getDepth(), T->getIndex()).getAsType();
+ QualType Replacement = Arg.getAsType();
// TODO: only do this uniquing once, at the start of instantiation.
QualType Result
#include "clang/Sema/Sema.h"
#include "clang/Sema/ParsedTemplate.h"
#include "clang/Sema/SemaInternal.h"
+#include "clang/Sema/Template.h"
#include "clang/AST/Expr.h"
#include "clang/AST/RecursiveASTVisitor.h"
#include "clang/AST/TypeLoc.h"
// Visitor that collects unexpanded parameter packs
//----------------------------------------------------------------------------
-// FIXME: No way to easily map from TemplateTypeParmTypes to
-// TemplateTypeParmDecls, so we have this horrible PointerUnion.
-typedef std::pair<llvm::PointerUnion<const TemplateTypeParmType*, NamedDecl*>,
- SourceLocation> UnexpandedParameterPack;
-
namespace {
/// \brief A class that collects unexpanded parameter packs.
class CollectUnexpandedParameterPacksVisitor :
return true;
}
+void Sema::collectUnexpandedParameterPacks(TemplateArgumentLoc Arg,
+ llvm::SmallVectorImpl<UnexpandedParameterPack> &Unexpanded) {
+ CollectUnexpandedParameterPacksVisitor(Unexpanded)
+ .TraverseTemplateArgumentLoc(Arg);
+}
+
ParsedTemplateArgument
Sema::ActOnPackExpansion(const ParsedTemplateArgument &Arg,
SourceLocation EllipsisLoc) {
if (!TSInfo)
return true;
+ TypeSourceInfo *TSResult = CheckPackExpansion(TSInfo, EllipsisLoc);
+ if (!TSResult)
+ return true;
+
+ return CreateParsedType(TSResult->getType(), TSResult);
+}
+
+TypeSourceInfo *Sema::CheckPackExpansion(TypeSourceInfo *Pattern,
+ SourceLocation EllipsisLoc) {
// 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 (!TSInfo->getType()->containsUnexpandedParameterPack()) {
+ if (!Pattern->getType()->containsUnexpandedParameterPack()) {
Diag(EllipsisLoc, diag::err_pack_expansion_without_parameter_packs)
- << TSInfo->getTypeLoc().getSourceRange();
- return true;
+ << Pattern->getTypeLoc().getSourceRange();
+ return 0;
}
-
+
// Create the pack expansion type and source-location information.
- QualType Result = Context.getPackExpansionType(TSInfo->getType());
+ QualType Result = Context.getPackExpansionType(Pattern->getType());
TypeSourceInfo *TSResult = Context.CreateTypeSourceInfo(Result);
PackExpansionTypeLoc TL = cast<PackExpansionTypeLoc>(TSResult->getTypeLoc());
TL.setEllipsisLoc(EllipsisLoc);
-
+
// Copy over the source-location information from the type.
memcpy(TL.getNextTypeLoc().getOpaqueData(),
- TSInfo->getTypeLoc().getOpaqueData(),
- TSInfo->getTypeLoc().getFullDataSize());
- return CreateParsedType(Result, TSResult);
+ Pattern->getTypeLoc().getOpaqueData(),
+ Pattern->getTypeLoc().getFullDataSize());
+ return TSResult;
}
#include "clang/Sema/SemaInternal.h"
#include "clang/Sema/Lookup.h"
+#include "clang/Sema/ParsedTemplate.h"
#include "clang/Sema/SemaDiagnostic.h"
#include "clang/Sema/ScopeInfo.h"
#include "clang/AST/Decl.h"
class TreeTransform {
protected:
Sema &SemaRef;
-
+ Sema::ArgumentPackSubstitutionIndexRAII SubstIndex;
+
public:
/// \brief Initializes a new tree transformer.
- TreeTransform(Sema &SemaRef) : SemaRef(SemaRef) { }
+ TreeTransform(Sema &SemaRef) : SemaRef(SemaRef), SubstIndex(SemaRef, -1) { }
/// \brief Retrieves a reference to the derived class.
Derived &getDerived() { return static_cast<Derived&>(*this); }
return E->isDefaultArgument();
}
+ /// \brief Determine whether we should expand a pack expansion with the
+ /// given set of parameter packs into separate arguments by repeatedly
+ /// transforming the pattern.
+ ///
+ /// By default, the transformed never tries to expand pack expansions.
+ /// Subclasses can override this routine to provide different behavior.
+ ///
+ /// \param EllipsisLoc The location of the ellipsis that identifies the
+ /// pack expansion.
+ ///
+ /// \param PatternRange The source range that covers the entire pattern of
+ /// the pack expansion.
+ ///
+ /// \param Unexpanded The set of unexpanded parameter packs within the
+ /// pattern.
+ ///
+ /// \param NumUnexpanded The number of unexpanded parameter packs in
+ /// \p Unexpanded.
+ ///
+ /// \param ShouldExpand Will be set to \c true if the transformer should
+ /// expand the corresponding pack expansions into separate arguments. When
+ /// set, \c NumExpansions must also be set.
+ ///
+ /// \param NumExpansions The number of separate arguments that will be in
+ /// the expanded form of the corresponding pack expansion. Must be set when
+ /// \c ShouldExpand is \c true.
+ ///
+ /// \returns true if an error occurred (e.g., because the parameter packs
+ /// are to be instantiated with arguments of different lengths), false
+ /// otherwise. If false, \c ShouldExpand (and possibly \c NumExpansions)
+ /// must be set.
+ bool TryExpandParameterPacks(SourceLocation EllipsisLoc,
+ SourceRange PatternRange,
+ const UnexpandedParameterPack *Unexpanded,
+ unsigned NumUnexpanded,
+ bool &ShouldExpand,
+ unsigned &NumExpansions) {
+ ShouldExpand = false;
+ return false;
+ }
+
/// \brief Transforms the given type into another type.
///
/// By default, this routine transforms a type by creating a
return move(Result);
}
+ /// \brief Build a new template argument pack expansion.
+ ///
+ /// By default, performs semantic analysis to build a new pack expansion
+ /// for a template argument. Subclasses may override this routine to provide
+ /// different behavior.
+ TemplateArgumentLoc RebuildPackExpansion(TemplateArgumentLoc Pattern,
+ SourceLocation EllipsisLoc) {
+ switch (Pattern.getArgument().getKind()) {
+ case TemplateArgument::Expression:
+ case TemplateArgument::Template:
+ llvm_unreachable("Unsupported pack expansion of expressions/templates");
+
+ case TemplateArgument::Null:
+ case TemplateArgument::Integral:
+ case TemplateArgument::Declaration:
+ case TemplateArgument::Pack:
+ llvm_unreachable("Pack expansion pattern has no parameter packs");
+
+ case TemplateArgument::Type:
+ if (TypeSourceInfo *Expansion
+ = getSema().CheckPackExpansion(Pattern.getTypeSourceInfo(),
+ EllipsisLoc))
+ return TemplateArgumentLoc(TemplateArgument(Expansion->getType()),
+ Expansion);
+ break;
+ }
+
+ return TemplateArgumentLoc();
+ }
+
private:
QualType TransformTypeInObjectScope(QualType T,
QualType ObjectType,
TemplateArgumentListInfo &Outputs) {
for (unsigned I = 0, N = Inputs.getNumArgs(); I != N; ++I) {
TemplateArgumentLoc Out;
- if (getDerived().TransformTemplateArgument(Inputs.getArgLoc(I), Out))
+ TemplateArgumentLoc In = Inputs.getArgLoc(I);
+
+ if (In.getArgument().getKind() == TemplateArgument::Pack) {
+ // Unpack argument packs, which we translate them into separate
+ // arguments.
+ // FIXME: It would be far better to make this a recursive call using
+ // some kind of argument-pack adaptor.
+ for (TemplateArgument::pack_iterator P = In.getArgument().pack_begin(),
+ PEnd = In.getArgument().pack_end();
+ P != PEnd; ++P) {
+ TemplateArgumentLoc PLoc;
+
+ // FIXME: We could do much better if we could guarantee that the
+ // TemplateArgumentLocInfo for the pack expansion would be usable for
+ // all of the template arguments in the argument pack.
+ getDerived().InventTemplateArgumentLoc(*P, PLoc);
+ if (getDerived().TransformTemplateArgument(PLoc, Out))
+ return true;
+
+ Outputs.addArgument(Out);
+ }
+
+ continue;
+ }
+
+ if (In.getArgument().isPackExpansion()) {
+ // We have a pack expansion, for which we will be substituting into
+ // the pattern.
+ SourceLocation Ellipsis;
+ TemplateArgumentLoc Pattern
+ = In.getPackExpansionPattern(Ellipsis, getSema().Context);
+
+ 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(Ellipsis,
+ 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.
+ TemplateArgumentLoc OutPattern;
+ Sema::ArgumentPackSubstitutionIndexRAII SubstIndex(getSema(), -1);
+ if (getDerived().TransformTemplateArgument(Pattern, OutPattern))
+ return true;
+
+ Out = getDerived().RebuildPackExpansion(OutPattern, Ellipsis);
+ if (Out.getArgument().isNull())
+ return true;
+
+ Outputs.addArgument(Out);
+ 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);
+
+ if (getDerived().TransformTemplateArgument(Pattern, Out))
+ return true;
+
+ Outputs.addArgument(Out);
+ }
+
+ continue;
+ }
+
+ // The simple case:
+ if (getDerived().TransformTemplateArgument(In, Out))
return true;
Outputs.addArgument(Out);
// Convert the condition to a boolean value.
if (S->getCond()) {
- ExprResult CondE = getSema().ActOnBooleanCondition(0,
- S->getIfLoc(),
- Cond.get());
+ ExprResult CondE = getSema().ActOnBooleanCondition(0, S->getIfLoc(),
+ Cond.get());
if (CondE.isInvalid())
return StmtError();
if (S->getCond()) {
// Convert the condition to a boolean value.
- ExprResult CondE = getSema().ActOnBooleanCondition(0,
- S->getWhileLoc(),
- Cond.get());
+ ExprResult CondE = getSema().ActOnBooleanCondition(0, S->getWhileLoc(),
+ Cond.get());
if (CondE.isInvalid())
return StmtError();
Cond = CondE;
if (S->getCond()) {
// Convert the condition to a boolean value.
- ExprResult CondE = getSema().ActOnBooleanCondition(0,
- S->getForLoc(),
- Cond.get());
+ ExprResult CondE = getSema().ActOnBooleanCondition(0, S->getForLoc(),
+ Cond.get());
if (CondE.isInvalid())
return StmtError();
--- /dev/null
+// RUN: %clang_cc1 -std=c++0x -fsyntax-only -verify %s
+
+template<typename... Types> struct Tuple;
+
+// FIXME: Many more bullets to go
+
+// In a template-argument-list (14.3); the pattern is a template-argument.
+template<typename ...Types>
+struct tuple_of_refs {
+ typedef Tuple<Types& ...> types;
+};
+
+Tuple<int&, float&> *t_int_ref_float_ref;
+tuple_of_refs<int&, float&>::types *t_int_ref_float_ref_2 = t_int_ref_float_ref;
+
// RUN: %clang_cc1 -std=c++0x -fblocks -fsyntax-only -verify %s
template<typename T, typename U> struct pair;
+template<typename ...> struct tuple;
// A parameter pack whose name appears within the pattern of a pack
// expansion is expanded by that pack expansion. An appearance of the
typedef pair<pair<Types..., int>..., int> expand_with_expanded_nested; // expected-error{{pack expansion does not contain any unexpanded parameter packs}}
};
+// All of the parameter packs expanded by a pack expansion shall have
+// the same number of arguments specified.
+template<typename ...Types>
+struct ExpansionLengthMismatch {
+ template<typename ...OtherTypes>
+ struct Inner {
+ typedef tuple<pair<Types, OtherTypes>...> type; // expected-error{{pack expansion contains parameter packs 'Types' and 'OtherTypes' that have different lengths (3 vs. 2)}}
+ };
+};
+
+ExpansionLengthMismatch<int, long>::Inner<unsigned int, unsigned long>::type
+ *il_pairs;
+tuple<pair<int, unsigned int>, pair<long, unsigned long> >*il_pairs_2 = il_pairs;
+
+ExpansionLengthMismatch<short, int, long>::Inner<unsigned int, unsigned long>::type // expected-note{{in instantiation of}}
+ *il_pairs_bad;
+
+
// An appearance of a name of a parameter pack that is not expanded is
// ill-formed.