diff options
author | Douglas Gregor <dgregor@apple.com> | 2010-12-23 22:44:42 +0000 |
---|---|---|
committer | Douglas Gregor <dgregor@apple.com> | 2010-12-23 22:44:42 +0000 |
commit | a8bc8c9e9ba5bffebde00340786fe8542469c435 (patch) | |
tree | 75be85d4dd770d5f44b6c43b54d38747e8de8e8b /lib/Sema/SemaType.cpp | |
parent | c32647d111e516593b9ba242cad7b8ff4016c155 (diff) |
Implement parsing of function parameter packs and non-type template
parameter packs (C++0x [dcl.fct]p13), including disambiguation between
unnamed function parameter packs and varargs (C++0x [dcl.fct]p14) for
cases like
void f(T...)
where T may or may not contain unexpanded parameter packs.
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@122520 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'lib/Sema/SemaType.cpp')
-rw-r--r-- | lib/Sema/SemaType.cpp | 64 |
1 files changed, 64 insertions, 0 deletions
diff --git a/lib/Sema/SemaType.cpp b/lib/Sema/SemaType.cpp index 09b187b0d0..e693c8d4da 100644 --- a/lib/Sema/SemaType.cpp +++ b/lib/Sema/SemaType.cpp @@ -1465,6 +1465,64 @@ TypeSourceInfo *Sema::GetTypeForDeclarator(Declarator &D, Scope *S, T.addConst(); } + // If there was an ellipsis in the declarator, the declaration declares a + // parameter pack whose type may be a pack expansion type. + if (D.hasEllipsis() && !T.isNull()) { + // C++0x [dcl.fct]p13: + // A declarator-id or abstract-declarator containing an ellipsis shall + // only be used in a parameter-declaration. Such a parameter-declaration + // is a parameter pack (14.5.3). [...] + switch (D.getContext()) { + case Declarator::PrototypeContext: + // C++0x [dcl.fct]p13: + // [...] When it is part of a parameter-declaration-clause, the + // parameter pack is a function parameter pack (14.5.3). The type T + // of the declarator-id of the function parameter pack shall contain + // a template parameter pack; each template parameter pack in T is + // expanded by the function parameter pack. + // + // We represent function parameter packs as function parameters whose + // type is a pack expansion. + if (!T->containsUnexpandedParameterPack()) { + Diag(D.getEllipsisLoc(), + diag::err_function_parameter_pack_without_parameter_packs) + << T << D.getSourceRange(); + D.setEllipsisLoc(SourceLocation()); + } else { + T = Context.getPackExpansionType(T); + } + break; + + case Declarator::TemplateParamContext: + // C++0x [temp.param]p15: + // If a template-parameter is a [...] is a parameter-declaration that + // declares a parameter pack (8.3.5), then the template-parameter is a + // template parameter pack (14.5.3). + // + // Note: core issue 778 clarifies that, if there are any unexpanded + // parameter packs in the type of the non-type template parameter, then + // it expands those parameter packs. + if (T->containsUnexpandedParameterPack()) + T = Context.getPackExpansionType(T); + break; + + case Declarator::FileContext: + case Declarator::KNRTypeListContext: + case Declarator::TypeNameContext: + case Declarator::MemberContext: + case Declarator::BlockContext: + case Declarator::ForContext: + case Declarator::ConditionContext: + case Declarator::CXXCatchContext: + case Declarator::BlockLiteralContext: + // FIXME: We may want to allow parameter packs in block-literal contexts + // in the future. + Diag(D.getEllipsisLoc(), diag::err_ellipsis_in_declarator_not_parameter); + D.setEllipsisLoc(SourceLocation()); + break; + } + } + // Process any function attributes we might have delayed from the // declaration-specifiers. ProcessDelayedFnAttrs(*this, T, FnAttrsFromDeclSpec); @@ -1729,6 +1787,12 @@ Sema::GetTypeSourceInfoForDeclarator(Declarator &D, QualType T, TypeSourceInfo *TInfo = Context.CreateTypeSourceInfo(T); UnqualTypeLoc CurrTL = TInfo->getTypeLoc().getUnqualifiedLoc(); + // Handle parameter packs whose type is a pack expansion. + if (isa<PackExpansionType>(T)) { + cast<PackExpansionTypeLoc>(CurrTL).setEllipsisLoc(D.getEllipsisLoc()); + CurrTL = CurrTL.getNextTypeLoc().getUnqualifiedLoc(); + } + for (unsigned i = 0, e = D.getNumTypeObjects(); i != e; ++i) { DeclaratorLocFiller(D.getTypeObject(i)).Visit(CurrTL); CurrTL = CurrTL.getNextTypeLoc().getUnqualifiedLoc(); |