forked from OSchip/llvm-project
				
			
		
			
				
	
	
		
			751 lines
		
	
	
		
			28 KiB
		
	
	
	
		
			C++
		
	
	
	
			
		
		
	
	
			751 lines
		
	
	
		
			28 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 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 function and non-type template parameter
 | 
						|
    // packs in a block-captured expression.
 | 
						|
    bool VisitBlockDeclRefExpr(BlockDeclRefExpr *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->getIdentifier();
 | 
						|
    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,
 | 
						|
                                                llvm::Optional<unsigned>());
 | 
						|
  if (!TSResult)
 | 
						|
    return true;
 | 
						|
  
 | 
						|
  return CreateParsedType(TSResult->getType(), TSResult);
 | 
						|
}
 | 
						|
 | 
						|
TypeSourceInfo *Sema::CheckPackExpansion(TypeSourceInfo *Pattern,
 | 
						|
                                         SourceLocation EllipsisLoc,
 | 
						|
                                       llvm::Optional<unsigned> NumExpansions) {
 | 
						|
  // Create the pack expansion type and source-location information.
 | 
						|
  QualType Result = CheckPackExpansion(Pattern->getType(), 
 | 
						|
                                       Pattern->getTypeLoc().getSourceRange(),
 | 
						|
                                       EllipsisLoc, NumExpansions);
 | 
						|
  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,
 | 
						|
                                  llvm::Optional<unsigned> NumExpansions) {
 | 
						|
  // 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, NumExpansions);
 | 
						|
}
 | 
						|
 | 
						|
ExprResult Sema::ActOnPackExpansion(Expr *Pattern, SourceLocation EllipsisLoc) {
 | 
						|
  return CheckPackExpansion(Pattern, EllipsisLoc, llvm::Optional<unsigned>());
 | 
						|
}
 | 
						|
 | 
						|
ExprResult Sema::CheckPackExpansion(Expr *Pattern, SourceLocation EllipsisLoc,
 | 
						|
                                    llvm::Optional<unsigned> NumExpansions) {
 | 
						|
  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, NumExpansions));
 | 
						|
}
 | 
						|
 | 
						|
/// \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,
 | 
						|
                                     llvm::Optional<unsigned> &NumExpansions) {                                        
 | 
						|
  ShouldExpand = true;
 | 
						|
  RetainExpansion = false;
 | 
						|
  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 = 0, Index = 0;
 | 
						|
    IdentifierInfo *Name;
 | 
						|
    bool IsFunctionParameterPack = false;
 | 
						|
    
 | 
						|
    if (const TemplateTypeParmType *TTP
 | 
						|
        = Unexpanded[I].first.dyn_cast<const TemplateTypeParmType *>()) {
 | 
						|
      Depth = TTP->getDepth();
 | 
						|
      Index = TTP->getIndex();
 | 
						|
      Name = TTP->getIdentifier();
 | 
						|
    } 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->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 (!IsFunctionParameterPack) {
 | 
						|
      if (NamedDecl *PartialPack 
 | 
						|
                    = CurrentInstantiationScope->getPartiallySubstitutedPack()){
 | 
						|
        unsigned PartialDepth, PartialIndex;
 | 
						|
        llvm::tie(PartialDepth, PartialIndex) = getDepthAndIndex(PartialPack);
 | 
						|
        if (PartialDepth == Depth && PartialIndex == Index)
 | 
						|
          RetainExpansion = true;
 | 
						|
      }
 | 
						|
    }
 | 
						|
    
 | 
						|
    if (!NumExpansions) {
 | 
						|
      // 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.
 | 
						|
      if (HaveFirstPack)
 | 
						|
        Diag(EllipsisLoc, diag::err_pack_expansion_length_conflict)
 | 
						|
          << FirstPack.first << Name << *NumExpansions << NewPackSize
 | 
						|
          << SourceRange(FirstPack.second) << SourceRange(Unexpanded[I].second);
 | 
						|
      else
 | 
						|
        Diag(EllipsisLoc, diag::err_pack_expansion_length_conflict_multilevel)
 | 
						|
          << Name << *NumExpansions << NewPackSize
 | 
						|
          << 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->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:
 | 
						|
  case TST_underlying_type: {
 | 
						|
    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_unknown_anytype:
 | 
						|
  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);
 | 
						|
}
 |