teak-llvm/clang/lib/Sema/SemaTemplateVariadic.cpp
Douglas Gregor ada4b79947 Start implementing support for substitution into pack expansions that
involve template parameter packs at multiple template levels that
occur within the signatures members of class templates (and partial
specializations thereof). This is a work-in-progress that is deficient
in several ways, notably:
  - It only works for template type parameter packs, but we need to
  also support non-type template parameter packs and template template
  parameter packs.
  - It doesn't keep track of the lengths of the substituted argument
  packs in the expansion, so it can't properly diagnose length
  mismatches.

However, this is a concrete step in the right direction.

llvm-svn: 123425
2011-01-14 02:55:32 +00:00

731 lines
27 KiB
C++

//===------- SemaTemplateVariadic.cpp - C++ Variadic Templates ------------===/
//
// The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//===----------------------------------------------------------------------===/
//
// This file implements semantic analysis for C++0x variadic templates.
//===----------------------------------------------------------------------===/
#include "clang/Sema/Sema.h"
#include "clang/Sema/Lookup.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"
using namespace clang;
//----------------------------------------------------------------------------
// Visitor that collects unexpanded parameter packs
//----------------------------------------------------------------------------
namespace {
/// \brief A class that collects unexpanded parameter packs.
class CollectUnexpandedParameterPacksVisitor :
public RecursiveASTVisitor<CollectUnexpandedParameterPacksVisitor>
{
typedef RecursiveASTVisitor<CollectUnexpandedParameterPacksVisitor>
inherited;
llvm::SmallVectorImpl<UnexpandedParameterPack> &Unexpanded;
public:
explicit CollectUnexpandedParameterPacksVisitor(
llvm::SmallVectorImpl<UnexpandedParameterPack> &Unexpanded)
: Unexpanded(Unexpanded) { }
bool shouldWalkTypesOfTypeLocs() const { return false; }
//------------------------------------------------------------------------
// Recording occurrences of (unexpanded) parameter packs.
//------------------------------------------------------------------------
/// \brief Record occurrences of template type parameter packs.
bool VisitTemplateTypeParmTypeLoc(TemplateTypeParmTypeLoc TL) {
if (TL.getTypePtr()->isParameterPack())
Unexpanded.push_back(std::make_pair(TL.getTypePtr(), TL.getNameLoc()));
return true;
}
/// \brief Record occurrences of template type parameter packs
/// when we don't have proper source-location information for
/// them.
///
/// Ideally, this routine would never be used.
bool VisitTemplateTypeParmType(TemplateTypeParmType *T) {
if (T->isParameterPack())
Unexpanded.push_back(std::make_pair(T, SourceLocation()));
return true;
}
/// \brief Record occurrences of (FIXME: function and) non-type template
/// parameter packs in an expression.
bool VisitDeclRefExpr(DeclRefExpr *E) {
if (E->getDecl()->isParameterPack())
Unexpanded.push_back(std::make_pair(E->getDecl(), E->getLocation()));
return true;
}
/// \brief Record occurrences of template template parameter packs.
bool TraverseTemplateName(TemplateName Template) {
if (TemplateTemplateParmDecl *TTP
= dyn_cast_or_null<TemplateTemplateParmDecl>(
Template.getAsTemplateDecl()))
if (TTP->isParameterPack())
Unexpanded.push_back(std::make_pair(TTP, SourceLocation()));
return inherited::TraverseTemplateName(Template);
}
//------------------------------------------------------------------------
// Pruning the search for unexpanded parameter packs.
//------------------------------------------------------------------------
/// \brief Suppress traversal into statements and expressions that
/// do not contain unexpanded parameter packs.
bool TraverseStmt(Stmt *S) {
if (Expr *E = dyn_cast_or_null<Expr>(S))
if (E->containsUnexpandedParameterPack())
return inherited::TraverseStmt(E);
return true;
}
/// \brief Suppress traversal into types that do not contain
/// unexpanded parameter packs.
bool TraverseType(QualType T) {
if (!T.isNull() && T->containsUnexpandedParameterPack())
return inherited::TraverseType(T);
return true;
}
/// \brief Suppress traversel into types with location information
/// that do not contain unexpanded parameter packs.
bool TraverseTypeLoc(TypeLoc TL) {
if (!TL.getType().isNull() &&
TL.getType()->containsUnexpandedParameterPack())
return inherited::TraverseTypeLoc(TL);
return true;
}
/// \brief Suppress traversal of non-parameter declarations, since
/// they cannot contain unexpanded parameter packs.
bool TraverseDecl(Decl *D) {
if (D && isa<ParmVarDecl>(D))
return inherited::TraverseDecl(D);
return true;
}
/// \brief Suppress traversal of template argument pack expansions.
bool TraverseTemplateArgument(const TemplateArgument &Arg) {
if (Arg.isPackExpansion())
return true;
return inherited::TraverseTemplateArgument(Arg);
}
/// \brief Suppress traversal of template argument pack expansions.
bool TraverseTemplateArgumentLoc(const TemplateArgumentLoc &ArgLoc) {
if (ArgLoc.getArgument().isPackExpansion())
return true;
return inherited::TraverseTemplateArgumentLoc(ArgLoc);
}
};
}
/// \brief Diagnose all of the unexpanded parameter packs in the given
/// vector.
static void
DiagnoseUnexpandedParameterPacks(Sema &S, SourceLocation Loc,
Sema::UnexpandedParameterPackContext UPPC,
const llvm::SmallVectorImpl<UnexpandedParameterPack> &Unexpanded) {
llvm::SmallVector<SourceLocation, 4> Locations;
llvm::SmallVector<IdentifierInfo *, 4> Names;
llvm::SmallPtrSet<IdentifierInfo *, 4> NamesKnown;
for (unsigned I = 0, N = Unexpanded.size(); I != N; ++I) {
IdentifierInfo *Name = 0;
if (const TemplateTypeParmType *TTP
= Unexpanded[I].first.dyn_cast<const TemplateTypeParmType *>())
Name = TTP->getName();
else
Name = Unexpanded[I].first.get<NamedDecl *>()->getIdentifier();
if (Name && NamesKnown.insert(Name))
Names.push_back(Name);
if (Unexpanded[I].second.isValid())
Locations.push_back(Unexpanded[I].second);
}
DiagnosticBuilder DB
= Names.size() == 0? S.Diag(Loc, diag::err_unexpanded_parameter_pack_0)
<< (int)UPPC
: Names.size() == 1? S.Diag(Loc, diag::err_unexpanded_parameter_pack_1)
<< (int)UPPC << Names[0]
: Names.size() == 2? S.Diag(Loc, diag::err_unexpanded_parameter_pack_2)
<< (int)UPPC << Names[0] << Names[1]
: S.Diag(Loc, diag::err_unexpanded_parameter_pack_3_or_more)
<< (int)UPPC << Names[0] << Names[1];
for (unsigned I = 0, N = Locations.size(); I != N; ++I)
DB << SourceRange(Locations[I]);
}
bool Sema::DiagnoseUnexpandedParameterPack(SourceLocation Loc,
TypeSourceInfo *T,
UnexpandedParameterPackContext UPPC) {
// C++0x [temp.variadic]p5:
// An appearance of a name of a parameter pack that is not expanded is
// ill-formed.
if (!T->getType()->containsUnexpandedParameterPack())
return false;
llvm::SmallVector<UnexpandedParameterPack, 2> Unexpanded;
CollectUnexpandedParameterPacksVisitor(Unexpanded).TraverseTypeLoc(
T->getTypeLoc());
assert(!Unexpanded.empty() && "Unable to find unexpanded parameter packs");
DiagnoseUnexpandedParameterPacks(*this, Loc, UPPC, Unexpanded);
return true;
}
bool Sema::DiagnoseUnexpandedParameterPack(Expr *E,
UnexpandedParameterPackContext UPPC) {
// C++0x [temp.variadic]p5:
// An appearance of a name of a parameter pack that is not expanded is
// ill-formed.
if (!E->containsUnexpandedParameterPack())
return false;
llvm::SmallVector<UnexpandedParameterPack, 2> Unexpanded;
CollectUnexpandedParameterPacksVisitor(Unexpanded).TraverseStmt(E);
assert(!Unexpanded.empty() && "Unable to find unexpanded parameter packs");
DiagnoseUnexpandedParameterPacks(*this, E->getLocStart(), UPPC, Unexpanded);
return true;
}
bool Sema::DiagnoseUnexpandedParameterPack(const CXXScopeSpec &SS,
UnexpandedParameterPackContext UPPC) {
// C++0x [temp.variadic]p5:
// An appearance of a name of a parameter pack that is not expanded is
// ill-formed.
if (!SS.getScopeRep() ||
!SS.getScopeRep()->containsUnexpandedParameterPack())
return false;
llvm::SmallVector<UnexpandedParameterPack, 2> Unexpanded;
CollectUnexpandedParameterPacksVisitor(Unexpanded)
.TraverseNestedNameSpecifier(SS.getScopeRep());
assert(!Unexpanded.empty() && "Unable to find unexpanded parameter packs");
DiagnoseUnexpandedParameterPacks(*this, SS.getRange().getBegin(),
UPPC, Unexpanded);
return true;
}
bool Sema::DiagnoseUnexpandedParameterPack(const DeclarationNameInfo &NameInfo,
UnexpandedParameterPackContext UPPC) {
// C++0x [temp.variadic]p5:
// An appearance of a name of a parameter pack that is not expanded is
// ill-formed.
switch (NameInfo.getName().getNameKind()) {
case DeclarationName::Identifier:
case DeclarationName::ObjCZeroArgSelector:
case DeclarationName::ObjCOneArgSelector:
case DeclarationName::ObjCMultiArgSelector:
case DeclarationName::CXXOperatorName:
case DeclarationName::CXXLiteralOperatorName:
case DeclarationName::CXXUsingDirective:
return false;
case DeclarationName::CXXConstructorName:
case DeclarationName::CXXDestructorName:
case DeclarationName::CXXConversionFunctionName:
// FIXME: We shouldn't need this null check!
if (TypeSourceInfo *TSInfo = NameInfo.getNamedTypeInfo())
return DiagnoseUnexpandedParameterPack(NameInfo.getLoc(), TSInfo, UPPC);
if (!NameInfo.getName().getCXXNameType()->containsUnexpandedParameterPack())
return false;
break;
}
llvm::SmallVector<UnexpandedParameterPack, 2> Unexpanded;
CollectUnexpandedParameterPacksVisitor(Unexpanded)
.TraverseType(NameInfo.getName().getCXXNameType());
assert(!Unexpanded.empty() && "Unable to find unexpanded parameter packs");
DiagnoseUnexpandedParameterPacks(*this, NameInfo.getLoc(), UPPC, Unexpanded);
return true;
}
bool Sema::DiagnoseUnexpandedParameterPack(SourceLocation Loc,
TemplateName Template,
UnexpandedParameterPackContext UPPC) {
if (Template.isNull() || !Template.containsUnexpandedParameterPack())
return false;
llvm::SmallVector<UnexpandedParameterPack, 2> Unexpanded;
CollectUnexpandedParameterPacksVisitor(Unexpanded)
.TraverseTemplateName(Template);
assert(!Unexpanded.empty() && "Unable to find unexpanded parameter packs");
DiagnoseUnexpandedParameterPacks(*this, Loc, UPPC, Unexpanded);
return true;
}
bool Sema::DiagnoseUnexpandedParameterPack(TemplateArgumentLoc Arg,
UnexpandedParameterPackContext UPPC) {
if (Arg.getArgument().isNull() ||
!Arg.getArgument().containsUnexpandedParameterPack())
return false;
llvm::SmallVector<UnexpandedParameterPack, 2> Unexpanded;
CollectUnexpandedParameterPacksVisitor(Unexpanded)
.TraverseTemplateArgumentLoc(Arg);
assert(!Unexpanded.empty() && "Unable to find unexpanded parameter packs");
DiagnoseUnexpandedParameterPacks(*this, Arg.getLocation(), UPPC, Unexpanded);
return true;
}
void Sema::collectUnexpandedParameterPacks(TemplateArgument Arg,
llvm::SmallVectorImpl<UnexpandedParameterPack> &Unexpanded) {
CollectUnexpandedParameterPacksVisitor(Unexpanded)
.TraverseTemplateArgument(Arg);
}
void Sema::collectUnexpandedParameterPacks(TemplateArgumentLoc Arg,
llvm::SmallVectorImpl<UnexpandedParameterPack> &Unexpanded) {
CollectUnexpandedParameterPacksVisitor(Unexpanded)
.TraverseTemplateArgumentLoc(Arg);
}
void Sema::collectUnexpandedParameterPacks(QualType T,
llvm::SmallVectorImpl<UnexpandedParameterPack> &Unexpanded) {
CollectUnexpandedParameterPacksVisitor(Unexpanded).TraverseType(T);
}
void Sema::collectUnexpandedParameterPacks(TypeLoc TL,
llvm::SmallVectorImpl<UnexpandedParameterPack> &Unexpanded) {
CollectUnexpandedParameterPacksVisitor(Unexpanded).TraverseTypeLoc(TL);
}
ParsedTemplateArgument
Sema::ActOnPackExpansion(const ParsedTemplateArgument &Arg,
SourceLocation EllipsisLoc) {
if (Arg.isInvalid())
return Arg;
switch (Arg.getKind()) {
case ParsedTemplateArgument::Type: {
TypeResult Result = ActOnPackExpansion(Arg.getAsType(), EllipsisLoc);
if (Result.isInvalid())
return ParsedTemplateArgument();
return ParsedTemplateArgument(Arg.getKind(), Result.get().getAsOpaquePtr(),
Arg.getLocation());
}
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:
if (!Arg.getAsTemplate().get().containsUnexpandedParameterPack()) {
SourceRange R(Arg.getLocation());
if (Arg.getScopeSpec().isValid())
R.setBegin(Arg.getScopeSpec().getBeginLoc());
Diag(EllipsisLoc, diag::err_pack_expansion_without_parameter_packs)
<< R;
return ParsedTemplateArgument();
}
return Arg.getTemplatePackExpansion(EllipsisLoc);
}
llvm_unreachable("Unhandled template argument kind?");
return ParsedTemplateArgument();
}
TypeResult Sema::ActOnPackExpansion(ParsedType Type,
SourceLocation EllipsisLoc) {
TypeSourceInfo *TSInfo;
GetTypeFromParser(Type, &TSInfo);
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) {
// Create the pack expansion type and source-location information.
QualType Result = CheckPackExpansion(Pattern->getType(),
Pattern->getTypeLoc().getSourceRange(),
EllipsisLoc);
if (Result.isNull())
return 0;
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(),
Pattern->getTypeLoc().getOpaqueData(),
Pattern->getTypeLoc().getFullDataSize());
return TSResult;
}
QualType Sema::CheckPackExpansion(QualType Pattern,
SourceRange PatternRange,
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 (!Pattern->containsUnexpandedParameterPack()) {
Diag(EllipsisLoc, diag::err_pack_expansion_without_parameter_packs)
<< PatternRange;
return QualType();
}
return Context.getPackExpansionType(Pattern);
}
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));
}
/// \brief Retrieve the depth and index of a parameter pack.
static std::pair<unsigned, unsigned>
getDepthAndIndex(NamedDecl *ND) {
if (TemplateTypeParmDecl *TTP = dyn_cast<TemplateTypeParmDecl>(ND))
return std::make_pair(TTP->getDepth(), TTP->getIndex());
if (NonTypeTemplateParmDecl *NTTP = dyn_cast<NonTypeTemplateParmDecl>(ND))
return std::make_pair(NTTP->getDepth(), NTTP->getIndex());
TemplateTemplateParmDecl *TTP = cast<TemplateTemplateParmDecl>(ND);
return std::make_pair(TTP->getDepth(), TTP->getIndex());
}
bool Sema::CheckParameterPacksForExpansion(SourceLocation EllipsisLoc,
SourceRange PatternRange,
const UnexpandedParameterPack *Unexpanded,
unsigned NumUnexpanded,
const MultiLevelTemplateArgumentList &TemplateArgs,
bool &ShouldExpand,
bool &RetainExpansion,
unsigned &NumExpansions) {
ShouldExpand = true;
RetainExpansion = false;
std::pair<IdentifierInfo *, SourceLocation> FirstPack;
bool HaveFirstPack = false;
// FIXME: Variadic templates. Even if we don't expand, we'd still like to
// return the number of expansions back to the caller, perhaps as an
// llvm::Optional, so that it can be embedded in the pack expansion. This
// is important for the multi-level substitution case.
for (unsigned I = 0; I != NumUnexpanded; ++I) {
// Compute the depth and index for this parameter pack.
unsigned Depth;
unsigned Index;
IdentifierInfo *Name;
bool IsFunctionParameterPack = false;
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 (isa<ParmVarDecl>(ND))
IsFunctionParameterPack = true;
else
llvm::tie(Depth, Index) = getDepthAndIndex(ND);
Name = ND->getIdentifier();
}
// Determine the size of this argument pack.
unsigned NewPackSize;
if (IsFunctionParameterPack) {
// Figure out whether we're instantiating to an argument pack or not.
typedef LocalInstantiationScope::DeclArgumentPack DeclArgumentPack;
llvm::PointerUnion<Decl *, DeclArgumentPack *> *Instantiation
= CurrentInstantiationScope->findInstantiationOf(
Unexpanded[I].first.get<NamedDecl *>());
if (Instantiation &&
Instantiation->is<DeclArgumentPack *>()) {
// We could expand this function parameter pack.
NewPackSize = Instantiation->get<DeclArgumentPack *>()->size();
} else {
// We can't expand this function parameter pack, so we can't expand
// the pack expansion.
ShouldExpand = false;
continue;
}
} else {
// 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 any parameter packs we *do* have arguments for.
if (Depth >= TemplateArgs.getNumLevels() ||
!TemplateArgs.hasTemplateArgument(Depth, Index)) {
ShouldExpand = false;
continue;
}
// Determine the size of the argument pack.
NewPackSize = TemplateArgs(Depth, Index).pack_size();
}
// C++0x [temp.arg.explicit]p9:
// Template argument deduction can extend the sequence of template
// arguments corresponding to a template parameter pack, even when the
// sequence contains explicitly specified template arguments.
if (NamedDecl *PartialPack
= CurrentInstantiationScope->getPartiallySubstitutedPack()) {
unsigned PartialDepth, PartialIndex;
llvm::tie(PartialDepth, PartialIndex) = getDepthAndIndex(PartialPack);
if (PartialDepth == Depth && PartialIndex == Index)
RetainExpansion = true;
}
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.
Diag(EllipsisLoc, diag::err_pack_expansion_length_conflict)
<< FirstPack.first << Name << NumExpansions << NewPackSize
<< SourceRange(FirstPack.second) << SourceRange(Unexpanded[I].second);
return true;
}
}
return false;
}
unsigned Sema::getNumArgumentsInExpansion(QualType T,
const MultiLevelTemplateArgumentList &TemplateArgs) {
QualType Pattern = cast<PackExpansionType>(T)->getPattern();
llvm::SmallVector<UnexpandedParameterPack, 2> Unexpanded;
CollectUnexpandedParameterPacksVisitor(Unexpanded).TraverseType(Pattern);
for (unsigned I = 0, N = Unexpanded.size(); I != N; ++I) {
// Compute the depth and index for this parameter pack.
unsigned Depth;
unsigned Index;
if (const TemplateTypeParmType *TTP
= Unexpanded[I].first.dyn_cast<const TemplateTypeParmType *>()) {
Depth = TTP->getDepth();
Index = TTP->getIndex();
} else {
NamedDecl *ND = Unexpanded[I].first.get<NamedDecl *>();
if (isa<ParmVarDecl>(ND)) {
// Function parameter pack.
typedef LocalInstantiationScope::DeclArgumentPack DeclArgumentPack;
llvm::PointerUnion<Decl *, DeclArgumentPack *> *Instantiation
= CurrentInstantiationScope->findInstantiationOf(
Unexpanded[I].first.get<NamedDecl *>());
if (Instantiation && Instantiation->is<DeclArgumentPack *>())
return Instantiation->get<DeclArgumentPack *>()->size();
continue;
}
llvm::tie(Depth, Index) = getDepthAndIndex(ND);
}
if (Depth >= TemplateArgs.getNumLevels() ||
!TemplateArgs.hasTemplateArgument(Depth, Index))
continue;
// Determine the size of the argument pack.
return TemplateArgs(Depth, Index).pack_size();
}
llvm_unreachable("No unexpanded parameter packs in type expansion.");
return 0;
}
bool Sema::containsUnexpandedParameterPacks(Declarator &D) {
const DeclSpec &DS = D.getDeclSpec();
switch (DS.getTypeSpecType()) {
case TST_typename:
case TST_typeofType: {
QualType T = DS.getRepAsType().get();
if (!T.isNull() && T->containsUnexpandedParameterPack())
return true;
break;
}
case TST_typeofExpr:
case TST_decltype:
if (DS.getRepAsExpr() &&
DS.getRepAsExpr()->containsUnexpandedParameterPack())
return true;
break;
case TST_unspecified:
case TST_void:
case TST_char:
case TST_wchar:
case TST_char16:
case TST_char32:
case TST_int:
case TST_float:
case TST_double:
case TST_bool:
case TST_decimal32:
case TST_decimal64:
case TST_decimal128:
case TST_enum:
case TST_union:
case TST_struct:
case TST_class:
case TST_auto:
case TST_error:
break;
}
for (unsigned I = 0, N = D.getNumTypeObjects(); I != N; ++I) {
const DeclaratorChunk &Chunk = D.getTypeObject(I);
switch (Chunk.Kind) {
case DeclaratorChunk::Pointer:
case DeclaratorChunk::Reference:
case DeclaratorChunk::Paren:
// These declarator chunks cannot contain any parameter packs.
break;
case DeclaratorChunk::Array:
case DeclaratorChunk::Function:
case DeclaratorChunk::BlockPointer:
// Syntactically, these kinds of declarator chunks all come after the
// declarator-id (conceptually), so the parser should not invoke this
// routine at this time.
llvm_unreachable("Could not have seen this kind of declarator chunk");
break;
case DeclaratorChunk::MemberPointer:
if (Chunk.Mem.Scope().getScopeRep() &&
Chunk.Mem.Scope().getScopeRep()->containsUnexpandedParameterPack())
return true;
break;
}
}
return false;
}
/// \brief Called when an expression computing the size of a parameter pack
/// is parsed.
///
/// \code
/// template<typename ...Types> struct count {
/// static const unsigned value = sizeof...(Types);
/// };
/// \endcode
///
//
/// \param OpLoc The location of the "sizeof" keyword.
/// \param Name The name of the parameter pack whose size will be determined.
/// \param NameLoc The source location of the name of the parameter pack.
/// \param RParenLoc The location of the closing parentheses.
ExprResult Sema::ActOnSizeofParameterPackExpr(Scope *S,
SourceLocation OpLoc,
IdentifierInfo &Name,
SourceLocation NameLoc,
SourceLocation RParenLoc) {
// C++0x [expr.sizeof]p5:
// The identifier in a sizeof... expression shall name a parameter pack.
LookupResult R(*this, &Name, NameLoc, LookupOrdinaryName);
LookupName(R, S);
NamedDecl *ParameterPack = 0;
switch (R.getResultKind()) {
case LookupResult::Found:
ParameterPack = R.getFoundDecl();
break;
case LookupResult::NotFound:
case LookupResult::NotFoundInCurrentInstantiation:
if (DeclarationName CorrectedName = CorrectTypo(R, S, 0, 0, false,
CTC_NoKeywords)) {
if (NamedDecl *CorrectedResult = R.getAsSingle<NamedDecl>())
if (CorrectedResult->isParameterPack()) {
ParameterPack = CorrectedResult;
Diag(NameLoc, diag::err_sizeof_pack_no_pack_name_suggest)
<< &Name << CorrectedName
<< FixItHint::CreateReplacement(NameLoc,
CorrectedName.getAsString());
Diag(ParameterPack->getLocation(), diag::note_parameter_pack_here)
<< CorrectedName;
}
}
case LookupResult::FoundOverloaded:
case LookupResult::FoundUnresolvedValue:
break;
case LookupResult::Ambiguous:
DiagnoseAmbiguousLookup(R);
return ExprError();
}
if (!ParameterPack || !ParameterPack->isParameterPack()) {
Diag(NameLoc, diag::err_sizeof_pack_no_pack_name)
<< &Name;
return ExprError();
}
return new (Context) SizeOfPackExpr(Context.getSizeType(), OpLoc,
ParameterPack, NameLoc, RParenLoc);
}