]> granicus.if.org Git - clang/commitdiff
PR13811: Add a FunctionParmPackExpr node to handle references to function
authorRichard Smith <richard-llvm@metafoo.co.uk>
Wed, 12 Sep 2012 00:56:43 +0000 (00:56 +0000)
committerRichard Smith <richard-llvm@metafoo.co.uk>
Wed, 12 Sep 2012 00:56:43 +0000 (00:56 +0000)
parameter packs where the reference is not being expanded but the pack has
been. Previously, Clang would segfault in such cases.

git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@163672 91177308-0d34-0410-b5e6-96231b3b80d8

23 files changed:
include/clang/AST/ExprCXX.h
include/clang/AST/RecursiveASTVisitor.h
include/clang/Basic/StmtNodes.td
include/clang/Serialization/ASTBitCodes.h
lib/AST/Expr.cpp
lib/AST/ExprCXX.cpp
lib/AST/ExprClassification.cpp
lib/AST/ExprConstant.cpp
lib/AST/ItaniumMangle.cpp
lib/AST/StmtPrinter.cpp
lib/AST/StmtProfile.cpp
lib/Sema/SemaExceptionSpec.cpp
lib/Sema/SemaTemplateInstantiate.cpp
lib/Sema/SemaTemplateInstantiateDecl.cpp
lib/Sema/TreeTransform.h
lib/Serialization/ASTReaderStmt.cpp
lib/Serialization/ASTWriterStmt.cpp
lib/StaticAnalyzer/Core/ExprEngine.cpp
test/CXX/temp/temp.decls/temp.variadic/multi-level-substitution.cpp
test/PCH/cxx-templates.cpp
test/PCH/cxx-templates.h
tools/libclang/CXCursor.cpp
tools/libclang/RecursiveASTVisitor.h

index eca0ff937952049a1abcc789e121b415b271ca07..0c4ca8e97984a222107615f2d3f180de43089d8c 100644 (file)
@@ -3616,6 +3616,73 @@ public:
   child_range children() { return child_range(); }
 };
 
+/// \brief Represents a reference to a function parameter pack that has been
+/// substituted but not yet expanded.
+///
+/// When a pack expansion contains multiple parameter packs at different levels,
+/// this node is used to represent a function parameter pack at an outer level
+/// which we have already substituted to refer to expanded parameters, but where
+/// the containing pack expansion cannot yet be expanded.
+///
+/// \code
+/// template<typename...Ts> struct S {
+///   template<typename...Us> auto f(Ts ...ts) -> decltype(g(Us(ts)...));
+/// };
+/// template struct S<int, int>;
+/// \endcode
+class FunctionParmPackExpr : public Expr {
+  /// \brief The function parameter pack which was referenced.
+  ParmVarDecl *ParamPack;
+
+  /// \brief The location of the function parameter pack reference.
+  SourceLocation NameLoc;
+
+  /// \brief The number of expansions of this pack.
+  unsigned NumParameters;
+
+  FunctionParmPackExpr(QualType T, ParmVarDecl *ParamPack,
+                       SourceLocation NameLoc, unsigned NumParams,
+                       Decl * const *Params);
+
+  friend class ASTReader;
+  friend class ASTStmtReader;
+
+public:
+  static FunctionParmPackExpr *Create(ASTContext &Context, QualType T,
+                                      ParmVarDecl *ParamPack,
+                                      SourceLocation NameLoc,
+                                      llvm::ArrayRef<Decl*> Params);
+  static FunctionParmPackExpr *CreateEmpty(ASTContext &Context,
+                                           unsigned NumParams);
+
+  /// \brief Get the parameter pack which this expression refers to.
+  ParmVarDecl *getParameterPack() const { return ParamPack; }
+
+  /// \brief Get the location of the parameter pack.
+  SourceLocation getParameterPackLocation() const { return NameLoc; }
+
+  /// \brief Iterators over the parameters which the parameter pack expanded
+  /// into.
+  typedef ParmVarDecl * const *iterator;
+  iterator begin() const { return reinterpret_cast<iterator>(this+1); }
+  iterator end() const { return begin() + NumParameters; }
+
+  /// \brief Get the number of parameters in this parameter pack.
+  unsigned getNumExpansions() const { return NumParameters; }
+
+  /// \brief Get an expansion of the parameter pack by index.
+  ParmVarDecl *getExpansion(unsigned I) const { return begin()[I]; }
+
+  SourceRange getSourceRange() const LLVM_READONLY { return NameLoc; }
+
+  static bool classof(const Stmt *T) {
+    return T->getStmtClass() == FunctionParmPackExprClass;
+  }
+  static bool classof(const FunctionParmPackExpr *) { return true; }
+
+  child_range children() { return child_range(); }
+};
+
 /// \brief Represents a prvalue temporary that written into memory so that
 /// a reference can bind to it.
 ///
index ae4ff4b1f83c7f59a70e7f29d33c176ab0e19c50..22cd29085895610bbabe643c960ae79bc311f48a 100644 (file)
@@ -2221,6 +2221,7 @@ DEF_TRAVERSE_STMT(PackExpansionExpr, { })
 DEF_TRAVERSE_STMT(SizeOfPackExpr, { })
 DEF_TRAVERSE_STMT(SubstNonTypeTemplateParmPackExpr, { })
 DEF_TRAVERSE_STMT(SubstNonTypeTemplateParmExpr, { })
+DEF_TRAVERSE_STMT(FunctionParmPackExpr, { })
 DEF_TRAVERSE_STMT(MaterializeTemporaryExpr, { })
 DEF_TRAVERSE_STMT(AtomicExpr, { })
 
index 06da94708f19780cd7517f5059dd6e3e4aac2370..8f6a1c9f9890f312d06aa295d85cdba98537de7f 100644 (file)
@@ -131,6 +131,7 @@ def PackExpansionExpr : DStmt<Expr>;
 def SizeOfPackExpr : DStmt<Expr>;
 def SubstNonTypeTemplateParmExpr : DStmt<Expr>;
 def SubstNonTypeTemplateParmPackExpr : DStmt<Expr>;
+def FunctionParmPackExpr : DStmt<Expr>;
 def MaterializeTemporaryExpr : DStmt<Expr>;
 def LambdaExpr : DStmt<Expr>;
 
index e714da771bf09796e21c644b6da53bb7c9b7bbe9..5f127d252f4d33d05d1e54c4aa4529327250a659 100644 (file)
@@ -1193,6 +1193,7 @@ namespace clang {
       EXPR_SIZEOF_PACK,           // SizeOfPackExpr
       EXPR_SUBST_NON_TYPE_TEMPLATE_PARM, // SubstNonTypeTemplateParmExpr
       EXPR_SUBST_NON_TYPE_TEMPLATE_PARM_PACK,// SubstNonTypeTemplateParmPackExpr
+      EXPR_FUNCTION_PARM_PACK,    // FunctionParmPackExpr
       EXPR_MATERIALIZE_TEMPORARY, // MaterializeTemporaryExpr
       
       // CUDA
index 2ede77ec0385683142afc42d41320c64f635f37b..ea82cf7531a2b1bd20d26ec1f7e4334b53e8a063 100644 (file)
@@ -2646,6 +2646,7 @@ bool Expr::HasSideEffects(const ASTContext &Ctx) const {
   case UnresolvedMemberExprClass:
   case PackExpansionExprClass:
   case SubstNonTypeTemplateParmPackExprClass:
+  case FunctionParmPackExprClass:
     llvm_unreachable("shouldn't see dependent / unresolved nodes here");
 
   case DeclRefExprClass:
index 72e17b74171514599bf237120b5470ab8a1770af..e6076f007fa3265df5cf093c6ab314e56efa4b66 100644 (file)
@@ -1299,6 +1299,34 @@ TemplateArgument SubstNonTypeTemplateParmPackExpr::getArgumentPack() const {
   return TemplateArgument(Arguments, NumArguments);
 }
 
+FunctionParmPackExpr::FunctionParmPackExpr(QualType T, ParmVarDecl *ParamPack,
+                                           SourceLocation NameLoc,
+                                           unsigned NumParams,
+                                           Decl * const *Params)
+  : Expr(FunctionParmPackExprClass, T, VK_LValue, OK_Ordinary,
+         true, true, true, true),
+    ParamPack(ParamPack), NameLoc(NameLoc), NumParameters(NumParams) {
+  if (Params)
+    std::uninitialized_copy(Params, Params + NumParams,
+                            reinterpret_cast<Decl**>(this+1));
+}
+
+FunctionParmPackExpr *
+FunctionParmPackExpr::Create(ASTContext &Context, QualType T,
+                             ParmVarDecl *ParamPack, SourceLocation NameLoc,
+                             llvm::ArrayRef<Decl*> Params) {
+  return new (Context.Allocate(sizeof(FunctionParmPackExpr) +
+                               sizeof(ParmVarDecl*) * Params.size()))
+    FunctionParmPackExpr(T, ParamPack, NameLoc, Params.size(), Params.data());
+}
+
+FunctionParmPackExpr *
+FunctionParmPackExpr::CreateEmpty(ASTContext &Context, unsigned NumParams) {
+  return new (Context.Allocate(sizeof(FunctionParmPackExpr) +
+                               sizeof(ParmVarDecl*) * NumParams))
+    FunctionParmPackExpr(QualType(), 0, SourceLocation(), 0, 0);
+}
+
 TypeTraitExpr::TypeTraitExpr(QualType T, SourceLocation Loc, TypeTrait Kind,
                              ArrayRef<TypeSourceInfo *> Args,
                              SourceLocation RParenLoc,
index f16d70b5da1be85a2237414ef487af498448e647..24ec6bb020740aeccbc40993118668585448740c 100644 (file)
@@ -134,6 +134,7 @@ static Cl::Kinds ClassifyInternal(ASTContext &Ctx, const Expr *E) {
     // ObjC instance variables are lvalues
     // FIXME: ObjC++0x might have different rules
   case Expr::ObjCIvarRefExprClass:
+  case Expr::FunctionParmPackExprClass:
     return Cl::CL_LValue;
 
     // C99 6.5.2.5p5 says that compound literals are lvalues.
index 2cd7f04e9270d8a47cdfc5220da88949a2bc8fd5..8f3f84d07d7a5dca3a2e2d355b755510e2bbbe8d 100644 (file)
@@ -6480,6 +6480,7 @@ static ICEDiag CheckICE(const Expr* E, ASTContext &Ctx) {
   case Expr::OpaqueValueExprClass:
   case Expr::PackExpansionExprClass:
   case Expr::SubstNonTypeTemplateParmPackExprClass:
+  case Expr::FunctionParmPackExprClass:
   case Expr::AsTypeExprClass:
   case Expr::ObjCIndirectCopyRestoreExprClass:
   case Expr::MaterializeTemporaryExprClass:
index 0b8a4c89f86732ff4d70393014f6f8151c30e700..1a663a055da715c7ac012450c57d5f056b5d8cb7 100644 (file)
@@ -2809,7 +2809,15 @@ recurse:
     // };
     Out << "_SUBSTPACK_";
     break;
-      
+
+  case Expr::FunctionParmPackExprClass: {
+    // FIXME: not clear how to mangle this!
+    const FunctionParmPackExpr *FPPE = cast<FunctionParmPackExpr>(E);
+    Out << "v110_SUBSTPACK";
+    mangleFunctionParam(FPPE->getParameterPack());
+    break;
+  }
+
   case Expr::DependentScopeDeclRefExprClass: {
     const DependentScopeDeclRefExpr *DRE = cast<DependentScopeDeclRefExpr>(E);
     mangleUnresolvedName(DRE->getQualifier(), 0, DRE->getDeclName(), Arity);
index 0cf3aaf5580c4fa0cba499e2f6263c0124fc952c..a64049b8d284623a523fb4b929e6240101732a1d 100644 (file)
@@ -1647,6 +1647,10 @@ void StmtPrinter::VisitSubstNonTypeTemplateParmExpr(
   Visit(Node->getReplacement());
 }
 
+void StmtPrinter::VisitFunctionParmPackExpr(FunctionParmPackExpr *E) {
+  OS << *E->getParameterPack();
+}
+
 void StmtPrinter::VisitMaterializeTemporaryExpr(MaterializeTemporaryExpr *Node){
   PrintExpr(Node->GetTemporaryExpr());
 }
index 5d7f9f8edee217a362693010d6e394b4980de800..0c3186fec24439d43a984a57196a9abcfffee7e7 100644 (file)
@@ -973,6 +973,14 @@ void StmtProfiler::VisitSubstNonTypeTemplateParmExpr(
   Visit(E->getReplacement());
 }
 
+void StmtProfiler::VisitFunctionParmPackExpr(const FunctionParmPackExpr *S) {
+  VisitExpr(S);
+  VisitDecl(S->getParameterPack());
+  ID.AddInteger(S->getNumExpansions());
+  for (FunctionParmPackExpr::iterator I = S->begin(), E = S->end(); I != E; ++I)
+    VisitDecl(*I);
+}
+
 void StmtProfiler::VisitMaterializeTemporaryExpr(
                                            const MaterializeTemporaryExpr *S) {
   VisitExpr(S);
index e6266fb0863a2331e677f815581de54b26840792..e0e0d203105962c288a528a3b76e7566f9ee0001 100644 (file)
@@ -1029,6 +1029,7 @@ CanThrowResult Sema::canThrow(const Expr *E) {
   case Expr::PseudoObjectExprClass:
   case Expr::SubstNonTypeTemplateParmExprClass:
   case Expr::SubstNonTypeTemplateParmPackExprClass:
+  case Expr::FunctionParmPackExprClass:
   case Expr::UnaryExprOrTypeTraitExprClass:
   case Expr::UnresolvedLookupExprClass:
   case Expr::UnresolvedMemberExprClass:
index d3367c4ee90a899909d38760fa876087e85411fd..fc8371bf21cf241c7ad544f834656be582f4eff4 100644 (file)
@@ -802,11 +802,24 @@ namespace {
     ExprResult TransformPredefinedExpr(PredefinedExpr *E);
     ExprResult TransformDeclRefExpr(DeclRefExpr *E);
     ExprResult TransformCXXDefaultArgExpr(CXXDefaultArgExpr *E);
+
     ExprResult TransformTemplateParmRefExpr(DeclRefExpr *E,
                                             NonTypeTemplateParmDecl *D);
     ExprResult TransformSubstNonTypeTemplateParmPackExpr(
                                            SubstNonTypeTemplateParmPackExpr *E);
-    
+
+    /// \brief Rebuild a DeclRefExpr for a ParmVarDecl reference.
+    ExprResult RebuildParmVarDeclRefExpr(ParmVarDecl *PD, SourceLocation Loc);
+
+    /// \brief Transform a reference to a function parameter pack.
+    ExprResult TransformFunctionParmPackRefExpr(DeclRefExpr *E,
+                                                ParmVarDecl *PD);
+
+    /// \brief Transform a FunctionParmPackExpr which was built when we couldn't
+    /// expand a function parameter pack reference which refers to an expanded
+    /// pack.
+    ExprResult TransformFunctionParmPackExpr(FunctionParmPackExpr *E);
+
     QualType TransformFunctionProtoType(TypeLocBuilder &TLB,
                                         FunctionProtoTypeLoc TL);
     QualType TransformFunctionProtoType(TypeLocBuilder &TLB,
@@ -1229,9 +1242,82 @@ TemplateInstantiator::TransformSubstNonTypeTemplateParmPackExpr(
                                          Arg);
 }
 
+ExprResult
+TemplateInstantiator::RebuildParmVarDeclRefExpr(ParmVarDecl *PD,
+                                                SourceLocation Loc) {
+  DeclarationNameInfo NameInfo(PD->getDeclName(), Loc);
+  return getSema().BuildDeclarationNameExpr(CXXScopeSpec(), NameInfo, PD);
+}
+
+ExprResult
+TemplateInstantiator::TransformFunctionParmPackExpr(FunctionParmPackExpr *E) {
+  if (getSema().ArgumentPackSubstitutionIndex != -1) {
+    // We can expand this parameter pack now.
+    ParmVarDecl *D = E->getExpansion(getSema().ArgumentPackSubstitutionIndex);
+    ValueDecl *VD = cast_or_null<ValueDecl>(TransformDecl(E->getExprLoc(), D));
+    if (!VD)
+      return ExprError();
+    return RebuildParmVarDeclRefExpr(cast<ParmVarDecl>(VD), E->getExprLoc());
+  }
+
+  QualType T = TransformType(E->getType());
+  if (T.isNull())
+    return ExprError();
+
+  // Transform each of the parameter expansions into the corresponding
+  // parameters in the instantiation of the function decl.
+  llvm::SmallVector<Decl*, 8> Parms;
+  Parms.reserve(E->getNumExpansions());
+  for (FunctionParmPackExpr::iterator I = E->begin(), End = E->end();
+       I != End; ++I) {
+    ParmVarDecl *D =
+        cast_or_null<ParmVarDecl>(TransformDecl(E->getExprLoc(), *I));
+    if (!D)
+      return ExprError();
+    Parms.push_back(D);
+  }
+
+  return FunctionParmPackExpr::Create(getSema().Context, T,
+                                      E->getParameterPack(),
+                                      E->getParameterPackLocation(), Parms);
+}
+
+ExprResult
+TemplateInstantiator::TransformFunctionParmPackRefExpr(DeclRefExpr *E,
+                                                       ParmVarDecl *PD) {
+  typedef LocalInstantiationScope::DeclArgumentPack DeclArgumentPack;
+  llvm::PointerUnion<Decl *, DeclArgumentPack *> *Found
+    = getSema().CurrentInstantiationScope->findInstantiationOf(PD);
+  assert(Found && "no instantiation for parameter pack");
+
+  Decl *TransformedDecl;
+  if (DeclArgumentPack *Pack = Found->dyn_cast<DeclArgumentPack *>()) {
+    // If this is a reference to a function parameter pack which we can substitute
+    // but can't yet expand, build a FunctionParmPackExpr for it.
+    if (getSema().ArgumentPackSubstitutionIndex == -1) {
+      QualType T = TransformType(E->getType());
+      if (T.isNull())
+        return ExprError();
+      return FunctionParmPackExpr::Create(getSema().Context, T, PD,
+                                          E->getExprLoc(), *Pack);
+    }
+
+    TransformedDecl = (*Pack)[getSema().ArgumentPackSubstitutionIndex];
+  } else {
+    TransformedDecl = Found->get<Decl*>();
+  }
+
+  // We have either an unexpanded pack or a specific expansion.
+  return RebuildParmVarDeclRefExpr(cast<ParmVarDecl>(TransformedDecl),
+                                   E->getExprLoc());
+}
+
 ExprResult
 TemplateInstantiator::TransformDeclRefExpr(DeclRefExpr *E) {
   NamedDecl *D = E->getDecl();
+
+  // Handle references to non-type template parameters and non-type template
+  // parameter packs.
   if (NonTypeTemplateParmDecl *NTTP = dyn_cast<NonTypeTemplateParmDecl>(D)) {
     if (NTTP->getDepth() < TemplateArgs.getNumLevels())
       return TransformTemplateParmRefExpr(E, NTTP);
@@ -1240,6 +1326,11 @@ TemplateInstantiator::TransformDeclRefExpr(DeclRefExpr *E) {
     // FindInstantiatedDecl will find it in the local instantiation scope.
   }
 
+  // Handle references to function parameter packs.
+  if (ParmVarDecl *PD = dyn_cast<ParmVarDecl>(D))
+    if (PD->isParameterPack())
+      return TransformFunctionParmPackRefExpr(E, PD);
+
   return TreeTransform<TemplateInstantiator>::TransformDeclRefExpr(E);
 }
 
index 55462ff09b8642650bfd462c2d9656170b582137..15afd1f6c9950bf2d7bcf458cbfffd5c6f98e062 100644 (file)
@@ -3397,7 +3397,8 @@ NamedDecl *Sema::FindInstantiatedDecl(SourceLocation Loc, NamedDecl *D,
       if (Decl *FD = Found->dyn_cast<Decl *>())
         return cast<NamedDecl>(FD);
 
-      unsigned PackIdx = ArgumentPackSubstitutionIndex;
+      int PackIdx = ArgumentPackSubstitutionIndex;
+      assert(PackIdx != -1 && "found declaration pack but not pack expanding");
       return cast<NamedDecl>((*Found->get<DeclArgumentPack *>())[PackIdx]);
     }
 
index 0c1f1a42a04123a9faa815d61b39761871ce1c18..3d9a6ca11b44676ac4168bb55698b149520f815f 100644 (file)
@@ -8319,6 +8319,13 @@ TreeTransform<Derived>::TransformSubstNonTypeTemplateParmExpr(
   return SemaRef.Owned(E);
 }
 
+template<typename Derived>
+ExprResult
+TreeTransform<Derived>::TransformFunctionParmPackExpr(FunctionParmPackExpr *E) {
+  // Default behavior is to do nothing with this transformation.
+  return SemaRef.Owned(E);
+}
+
 template<typename Derived>
 ExprResult
 TreeTransform<Derived>::TransformMaterializeTemporaryExpr(
index 6ca450b9fb48582c87fa88050768841644ec213f..cfe22b5208e7c3abaa485ef9a2b3afa9c5966791 100644 (file)
@@ -1468,6 +1468,16 @@ void ASTStmtReader::VisitSubstNonTypeTemplateParmPackExpr(
   E->NameLoc = ReadSourceLocation(Record, Idx);
 }
 
+void ASTStmtReader::VisitFunctionParmPackExpr(FunctionParmPackExpr *E) {
+  VisitExpr(E);
+  E->NumParameters = Record[Idx++];
+  E->ParamPack = ReadDeclAs<ParmVarDecl>(Record, Idx);
+  E->NameLoc = ReadSourceLocation(Record, Idx);
+  ParmVarDecl **Parms = reinterpret_cast<ParmVarDecl**>(E+1);
+  for (unsigned i = 0, n = E->NumParameters; i != n; ++i)
+    Parms[i] = ReadDeclAs<ParmVarDecl>(Record, Idx);
+}
+
 void ASTStmtReader::VisitMaterializeTemporaryExpr(MaterializeTemporaryExpr *E) {
   VisitExpr(E);
   E->Temporary = Reader.ReadSubExpr();
@@ -2183,6 +2193,11 @@ Stmt *ASTReader::ReadStmtFromStream(ModuleFile &F) {
     case EXPR_SUBST_NON_TYPE_TEMPLATE_PARM_PACK:
       S = new (Context) SubstNonTypeTemplateParmPackExpr(Empty);
       break;
+
+    case EXPR_FUNCTION_PARM_PACK:
+      S = FunctionParmPackExpr::CreateEmpty(Context,
+                                          Record[ASTStmtReader::NumExprFields]);
+      break;
         
     case EXPR_MATERIALIZE_TEMPORARY:
       S = new (Context) MaterializeTemporaryExpr(Empty);
index 5fa08d256cdcf612993e129b646b3d9f19beddbb..9ca8130586f56754df95da52caa87b6bd2e5a19f 100644 (file)
@@ -1481,6 +1481,17 @@ void ASTStmtWriter::VisitSubstNonTypeTemplateParmPackExpr(
   Code = serialization::EXPR_SUBST_NON_TYPE_TEMPLATE_PARM_PACK;
 }
 
+void ASTStmtWriter::VisitFunctionParmPackExpr(FunctionParmPackExpr *E) {
+  VisitExpr(E);
+  Record.push_back(E->getNumExpansions());
+  Writer.AddDeclRef(E->getParameterPack(), Record);
+  Writer.AddSourceLocation(E->getParameterPackLocation(), Record);
+  for (FunctionParmPackExpr::iterator I = E->begin(), End = E->end();
+       I != End; ++I)
+    Writer.AddDeclRef(*I, Record);
+  Code = serialization::EXPR_FUNCTION_PARM_PACK;
+}
+
 void ASTStmtWriter::VisitMaterializeTemporaryExpr(MaterializeTemporaryExpr *E) {
   VisitExpr(E);
   Writer.AddStmt(E->Temporary);
index d177b60a502ffbd8a00708e1986c0f8838e7556c..4d4faf6d0b8b35ad4314dd0f97adcb91ed8e3999 100644 (file)
@@ -526,6 +526,7 @@ void ExprEngine::Visit(const Stmt *S, ExplodedNode *Pred,
     case Stmt::CXXNoexceptExprClass:
     case Stmt::PackExpansionExprClass:
     case Stmt::SubstNonTypeTemplateParmPackExprClass:
+    case Stmt::FunctionParmPackExprClass:
     case Stmt::SEHTryStmtClass:
     case Stmt::SEHExceptStmtClass:
     case Stmt::LambdaExprClass:
index 485068e6486ada4d08e5970042726ff907e484f4..e0ffef5007a176e10cf3172c111d2f1d4147af70 100644 (file)
@@ -187,6 +187,30 @@ namespace PacksAtDifferentLevels {
                               add_pointer<float>,
                               add_const<double>>>::value == 0? 1 : -1];
 
+  namespace PR13811 {
+    constexpr int g(int n, int m) { return n * 10 + m; }
+
+    template<typename...A>
+    struct X6 {
+      template<typename...B>
+      constexpr auto f1(A ...a) -> decltype(g(A(a + B())...)) { return g(A(a + B())...); }
+
+      template<typename...B>
+      constexpr auto f2(A ...a, B ...b) -> decltype(g((&a)[b] ...)) { return g((&a)[b] ...); } // expected-note {{past-the-end}}
+
+      template<typename...B> struct Inner {
+        template<typename...C>
+        constexpr auto f(A ...a, B ...b, C ...c) -> decltype(g(a+b+c...)) { return g(a+b+c...); }
+      };
+    };
+    struct A { constexpr operator int() { return 2; } };
+    struct B { constexpr operator int() { return 1; } };
+
+    static_assert(X6<unsigned char, int>().f1<A, B>(255, 1) == 12, "");
+    static_assert(X6<int, int>().f2(3, 4, 0, 0) == 34, "");
+    static_assert(X6<int, int>().f2(3, 4, 0, 1) == 34, ""); // expected-error {{constant expression}} expected-note {{in call}}
+    static_assert(X6<int, int>::Inner<int, int>().f(1, 2, 3, 4, 5, 6) == 102, "");
+  }
 }
 
 namespace ExpandingNonTypeTemplateParameters {
index 7ce247721f8f0b7d2124344252566fa43bc8d5a1..6312ca97882eee04207617215673612f61eb2645 100644 (file)
@@ -1,11 +1,11 @@
 // Test this without pch.
-// RUN: %clang_cc1 -fcxx-exceptions -fexceptions -include %S/cxx-templates.h -verify %s -ast-dump -o -
-// RUN: %clang_cc1 -fcxx-exceptions -fexceptions -include %S/cxx-templates.h %s -emit-llvm -o - | FileCheck %s
+// RUN: %clang_cc1 -std=c++11 -fcxx-exceptions -fexceptions -include %S/cxx-templates.h -verify %s -ast-dump -o -
+// RUN: %clang_cc1 -std=c++11 -fcxx-exceptions -fexceptions -include %S/cxx-templates.h %s -emit-llvm -o - | FileCheck %s
 
 // Test with pch.
-// RUN: %clang_cc1 -fcxx-exceptions -fexceptions -x c++-header -emit-pch -o %t %S/cxx-templates.h
-// RUN: %clang_cc1 -fcxx-exceptions -fexceptions -include-pch %t -verify %s -ast-dump  -o -
-// RUN: %clang_cc1 -fcxx-exceptions -fexceptions -include-pch %t %s -emit-llvm -o - | FileCheck %s
+// RUN: %clang_cc1 -std=c++11 -fcxx-exceptions -fexceptions -x c++-header -emit-pch -o %t %S/cxx-templates.h
+// RUN: %clang_cc1 -std=c++11 -fcxx-exceptions -fexceptions -include-pch %t -verify %s -ast-dump  -o -
+// RUN: %clang_cc1 -std=c++11 -fcxx-exceptions -fexceptions -include-pch %t %s -emit-llvm -o - | FileCheck %s
 
 // CHECK: define weak_odr void @_ZN2S4IiE1mEv
 // CHECK: define linkonce_odr void @_ZN2S3IiE1mEv
@@ -68,3 +68,12 @@ Foo< D >& Foo< D >::operator=( const Foo& other )
 {
    return *this;
 }
+
+namespace TestNestedExpansion {
+  struct Int {
+    Int(int);
+    friend Int operator+(Int, Int);
+  };
+  Int &g(Int, int, double);
+  Int &test = NestedExpansion<char, char, char>().f(0, 1, 2, Int(3), 4, 5.0);
+}
index 152e8cef546475e584d9f4b131397dd75e20a58d..756f208b76fd3667660b6e045e3c96e500f6e852 100644 (file)
@@ -215,3 +215,8 @@ class Foo : protected T
  public:
   Foo& operator=( const Foo& other );
 };
+
+template<typename...A> struct NestedExpansion {
+  template<typename...B> auto f(A...a, B...b) -> decltype(g(a + b...));
+};
+template struct NestedExpansion<char, char, char>;
index e219f948eaf26ced77d724e23201634052a365fb..a8cb1f96d4d617762ff2b9417c73ef3e29ebc385 100644 (file)
@@ -432,6 +432,7 @@ CXCursor cxcursor::MakeCXCursor(Stmt *S, Decl *Parent, CXTranslationUnit TU,
   case Stmt::DependentScopeDeclRefExprClass:
   case Stmt::SubstNonTypeTemplateParmExprClass:
   case Stmt::SubstNonTypeTemplateParmPackExprClass:
+  case Stmt::FunctionParmPackExprClass:
   case Stmt::UnresolvedLookupExprClass:
     K = CXCursor_DeclRefExpr;
     break;
index ab96f36205b9606ab851ed8afb2cf67063291fe4..571bb82082379d3b122b0d6f1d4636e9bcfd530b 100644 (file)
@@ -2141,6 +2141,7 @@ DEF_TRAVERSE_STMT(PackExpansionExpr, { })
 DEF_TRAVERSE_STMT(SizeOfPackExpr, { })
 DEF_TRAVERSE_STMT(SubstNonTypeTemplateParmPackExpr, { })
 DEF_TRAVERSE_STMT(SubstNonTypeTemplateParmExpr, { })
+DEF_TRAVERSE_STMT(FunctionParmPackExpr, { })
 DEF_TRAVERSE_STMT(MaterializeTemporaryExpr, { })
 DEF_TRAVERSE_STMT(AtomicExpr, { })