aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--include/clang/AST/ExprCXX.h65
-rw-r--r--include/clang/AST/RecursiveASTVisitor.h1
-rw-r--r--include/clang/Basic/StmtNodes.td1
-rw-r--r--include/clang/Serialization/ASTBitCodes.h3
-rw-r--r--lib/AST/ExprCXX.cpp28
-rw-r--r--lib/AST/ExprClassification.cpp1
-rw-r--r--lib/AST/ExprConstant.cpp1
-rw-r--r--lib/AST/ItaniumMangle.cpp5
-rw-r--r--lib/AST/StmtPrinter.cpp6
-rw-r--r--lib/AST/StmtProfile.cpp7
-rw-r--r--lib/Sema/SemaTemplateInstantiate.cpp56
-rw-r--r--lib/Sema/TreeTransform.h8
-rw-r--r--lib/Serialization/ASTReaderStmt.cpp22
-rw-r--r--lib/Serialization/ASTWriterStmt.cpp12
-rw-r--r--lib/StaticAnalyzer/Checkers/ExprEngine.cpp1
-rw-r--r--test/CXX/temp/temp.decls/temp.variadic/multi-level-substitution.cpp23
-rw-r--r--tools/libclang/CIndex.cpp3
-rw-r--r--tools/libclang/CXCursor.cpp1
18 files changed, 237 insertions, 7 deletions
diff --git a/include/clang/AST/ExprCXX.h b/include/clang/AST/ExprCXX.h
index abc8c77a38..f6bbfbf361 100644
--- a/include/clang/AST/ExprCXX.h
+++ b/include/clang/AST/ExprCXX.h
@@ -2746,7 +2746,8 @@ public:
/// \brief Retrieve the length of the parameter pack.
///
- /// This routine may only be invoked when
+ /// This routine may only be invoked when the expression is not
+ /// value-dependent.
unsigned getPackLength() const {
assert(!isValueDependent() &&
"Cannot get the length of a value-dependent pack size expression");
@@ -2764,6 +2765,68 @@ public:
virtual child_iterator child_begin();
virtual child_iterator child_end();
};
+
+/// \brief Represents a reference to a non-type template parameter pack that
+/// has been substituted with a non-template argument pack.
+///
+/// When a pack expansion in the source code contains multiple parameter packs
+/// and those parameter packs correspond to different levels of template
+/// parameter lists, this node node is used to represent a non-type template
+/// parameter pack from an outer level, which has already had its argument pack
+/// substituted but that still lives within a pack expansion that itself
+/// could not be instantiated. When actually performing a substitution into
+/// that pack expansion (e.g., when all template parameters have corresponding
+/// arguments), this type will be replaced with the appropriate underlying
+/// expression at the current pack substitution index.
+class SubstNonTypeTemplateParmPackExpr : public Expr {
+ /// \brief The non-type template parameter pack itself.
+ NonTypeTemplateParmDecl *Param;
+
+ /// \brief A pointer to the set of template arguments that this
+ /// parameter pack is instantiated with.
+ const TemplateArgument *Arguments;
+
+ /// \brief The number of template arguments in \c Arguments.
+ unsigned NumArguments;
+
+ /// \brief The location of the non-type template parameter pack reference.
+ SourceLocation NameLoc;
+
+ friend class ASTStmtReader;
+ friend class ASTStmtWriter;
+
+public:
+ SubstNonTypeTemplateParmPackExpr(QualType T,
+ NonTypeTemplateParmDecl *Param,
+ SourceLocation NameLoc,
+ const TemplateArgument &ArgPack);
+
+ SubstNonTypeTemplateParmPackExpr(EmptyShell Empty)
+ : Expr(SubstNonTypeTemplateParmPackExprClass, Empty) { }
+
+ /// \brief Retrieve the non-type template parameter pack being substituted.
+ NonTypeTemplateParmDecl *getParameterPack() const { return Param; }
+
+ /// \brief Retrieve the location of the parameter pack name.
+ SourceLocation getParameterPackLocation() const { return NameLoc; }
+
+ /// \brief Retrieve the template argument pack containing the substituted
+ /// template arguments.
+ TemplateArgument getArgumentPack() const;
+
+ virtual SourceRange getSourceRange() const;
+
+ static bool classof(const Stmt *T) {
+ return T->getStmtClass() == SubstNonTypeTemplateParmPackExprClass;
+ }
+ static bool classof(const SubstNonTypeTemplateParmPackExpr *) {
+ return true;
+ }
+
+ // Iterators
+ virtual child_iterator child_begin();
+ virtual child_iterator child_end();
+};
} // end namespace clang
diff --git a/include/clang/AST/RecursiveASTVisitor.h b/include/clang/AST/RecursiveASTVisitor.h
index 3d1279b252..532759b033 100644
--- a/include/clang/AST/RecursiveASTVisitor.h
+++ b/include/clang/AST/RecursiveASTVisitor.h
@@ -1856,6 +1856,7 @@ DEF_TRAVERSE_STMT(CompoundAssignOperator, { })
DEF_TRAVERSE_STMT(CXXNoexceptExpr, { })
DEF_TRAVERSE_STMT(PackExpansionExpr, { })
DEF_TRAVERSE_STMT(SizeOfPackExpr, { })
+DEF_TRAVERSE_STMT(SubstNonTypeTemplateParmPackExpr, { })
// These literals (all of them) do not need any action.
DEF_TRAVERSE_STMT(IntegerLiteral, { })
diff --git a/include/clang/Basic/StmtNodes.td b/include/clang/Basic/StmtNodes.td
index 9322db12c5..58db87b4c2 100644
--- a/include/clang/Basic/StmtNodes.td
+++ b/include/clang/Basic/StmtNodes.td
@@ -113,6 +113,7 @@ def UnresolvedMemberExpr : DStmt<OverloadExpr>;
def CXXNoexceptExpr : DStmt<Expr>;
def PackExpansionExpr : DStmt<Expr>;
def SizeOfPackExpr : DStmt<Expr>;
+def SubstNonTypeTemplateParmPackExpr : DStmt<Expr>;
// Obj-C Expressions.
def ObjCStringLiteral : DStmt<Expr>;
diff --git a/include/clang/Serialization/ASTBitCodes.h b/include/clang/Serialization/ASTBitCodes.h
index 6ef4dbeb0c..7a9019f384 100644
--- a/include/clang/Serialization/ASTBitCodes.h
+++ b/include/clang/Serialization/ASTBitCodes.h
@@ -936,7 +936,8 @@ namespace clang {
EXPR_BINARY_TYPE_TRAIT, // BinaryTypeTraitExpr
EXPR_PACK_EXPANSION, // PackExpansionExpr
- EXPR_SIZEOF_PACK // SizeOfPackExpr
+ EXPR_SIZEOF_PACK, // SizeOfPackExpr
+ EXPR_SUBST_NON_TYPE_TEMPLATE_PARM_PACK // SubstNonTypeTemplateParmPackExpr
};
/// \brief The kinds of designators that can occur in a
diff --git a/lib/AST/ExprCXX.cpp b/lib/AST/ExprCXX.cpp
index 0426e59a74..2c790bd273 100644
--- a/lib/AST/ExprCXX.cpp
+++ b/lib/AST/ExprCXX.cpp
@@ -1056,3 +1056,31 @@ Stmt::child_iterator SizeOfPackExpr::child_begin() {
Stmt::child_iterator SizeOfPackExpr::child_end() {
return child_iterator();
}
+
+SubstNonTypeTemplateParmPackExpr::
+SubstNonTypeTemplateParmPackExpr(QualType T,
+ NonTypeTemplateParmDecl *Param,
+ SourceLocation NameLoc,
+ const TemplateArgument &ArgPack)
+ : Expr(SubstNonTypeTemplateParmPackExprClass, T, VK_RValue, OK_Ordinary,
+ true, false, true),
+ Param(Param), Arguments(ArgPack.pack_begin()),
+ NumArguments(ArgPack.pack_size()), NameLoc(NameLoc) { }
+
+TemplateArgument SubstNonTypeTemplateParmPackExpr::getArgumentPack() const {
+ return TemplateArgument(Arguments, NumArguments);
+}
+
+SourceRange SubstNonTypeTemplateParmPackExpr::getSourceRange() const {
+ return NameLoc;
+}
+
+Stmt::child_iterator SubstNonTypeTemplateParmPackExpr::child_begin() {
+ return child_iterator();
+}
+
+Stmt::child_iterator SubstNonTypeTemplateParmPackExpr::child_end() {
+ return child_iterator();
+}
+
+
diff --git a/lib/AST/ExprClassification.cpp b/lib/AST/ExprClassification.cpp
index a9ebe6fdb3..c9f4fa8daa 100644
--- a/lib/AST/ExprClassification.cpp
+++ b/lib/AST/ExprClassification.cpp
@@ -152,6 +152,7 @@ static Cl::Kinds ClassifyInternal(ASTContext &Ctx, const Expr *E) {
case Expr::ParenListExprClass:
case Expr::InitListExprClass:
case Expr::SizeOfPackExprClass:
+ case Expr::SubstNonTypeTemplateParmPackExprClass:
return Cl::CL_PRValue;
// Next come the complicated cases.
diff --git a/lib/AST/ExprConstant.cpp b/lib/AST/ExprConstant.cpp
index 57ceb3f481..cb73810163 100644
--- a/lib/AST/ExprConstant.cpp
+++ b/lib/AST/ExprConstant.cpp
@@ -2645,6 +2645,7 @@ static ICEDiag CheckICE(const Expr* E, ASTContext &Ctx) {
case Expr::NoStmtClass:
case Expr::OpaqueValueExprClass:
case Expr::PackExpansionExprClass:
+ case Expr::SubstNonTypeTemplateParmPackExprClass:
return ICEDiag(2, E->getLocStart());
case Expr::SizeOfPackExprClass:
diff --git a/lib/AST/ItaniumMangle.cpp b/lib/AST/ItaniumMangle.cpp
index 0ebd7da679..2f8be294f2 100644
--- a/lib/AST/ItaniumMangle.cpp
+++ b/lib/AST/ItaniumMangle.cpp
@@ -1948,6 +1948,11 @@ void CXXNameMangler::mangleExpression(const Expr *E, unsigned Arity) {
break;
}
+ case Expr::SubstNonTypeTemplateParmPackExprClass:
+ mangleTemplateParameter(
+ cast<SubstNonTypeTemplateParmPackExpr>(E)->getParameterPack()->getIndex());
+ break;
+
case Expr::DependentScopeDeclRefExprClass: {
const DependentScopeDeclRefExpr *DRE = cast<DependentScopeDeclRefExpr>(E);
NestedNameSpecifier *NNS = DRE->getQualifier();
diff --git a/lib/AST/StmtPrinter.cpp b/lib/AST/StmtPrinter.cpp
index 2c8504357e..4c18a526bb 100644
--- a/lib/AST/StmtPrinter.cpp
+++ b/lib/AST/StmtPrinter.cpp
@@ -15,6 +15,7 @@
#include "clang/AST/StmtVisitor.h"
#include "clang/AST/DeclCXX.h"
#include "clang/AST/DeclObjC.h"
+#include "clang/AST/DeclTemplate.h"
#include "clang/AST/PrettyPrinter.h"
#include "llvm/Support/Format.h"
#include "clang/AST/Expr.h"
@@ -1255,6 +1256,11 @@ void StmtPrinter::VisitSizeOfPackExpr(SizeOfPackExpr *E) {
OS << "sizeof...(" << E->getPack()->getNameAsString() << ")";
}
+void StmtPrinter::VisitSubstNonTypeTemplateParmPackExpr(
+ SubstNonTypeTemplateParmPackExpr *Node) {
+ OS << Node->getParameterPack()->getNameAsString();
+}
+
// Obj-C
void StmtPrinter::VisitObjCStringLiteral(ObjCStringLiteral *Node) {
diff --git a/lib/AST/StmtProfile.cpp b/lib/AST/StmtProfile.cpp
index 232f48e1ee..e75c274015 100644
--- a/lib/AST/StmtProfile.cpp
+++ b/lib/AST/StmtProfile.cpp
@@ -841,6 +841,13 @@ void StmtProfiler::VisitSizeOfPackExpr(SizeOfPackExpr *S) {
VisitDecl(S->getPack());
}
+void StmtProfiler::VisitSubstNonTypeTemplateParmPackExpr(
+ SubstNonTypeTemplateParmPackExpr *S) {
+ VisitExpr(S);
+ VisitDecl(S->getParameterPack());
+ VisitTemplateArgument(S->getArgumentPack());
+}
+
void StmtProfiler::VisitOpaqueValueExpr(OpaqueValueExpr *E) {
VisitExpr(E);
}
diff --git a/lib/Sema/SemaTemplateInstantiate.cpp b/lib/Sema/SemaTemplateInstantiate.cpp
index 17b38bc1de..8943daa369 100644
--- a/lib/Sema/SemaTemplateInstantiate.cpp
+++ b/lib/Sema/SemaTemplateInstantiate.cpp
@@ -702,7 +702,9 @@ namespace {
ExprResult TransformCXXDefaultArgExpr(CXXDefaultArgExpr *E);
ExprResult TransformTemplateParmRefExpr(DeclRefExpr *E,
NonTypeTemplateParmDecl *D);
-
+ ExprResult TransformSubstNonTypeTemplateParmPackExpr(
+ SubstNonTypeTemplateParmPackExpr *E);
+
QualType TransformFunctionProtoType(TypeLocBuilder &TLB,
FunctionProtoTypeLoc TL);
ParmVarDecl *TransformFunctionTypeParam(ParmVarDecl *OldParm,
@@ -924,9 +926,19 @@ TemplateInstantiator::TransformTemplateParmRefExpr(DeclRefExpr *E,
"Missing argument pack");
if (getSema().ArgumentPackSubstitutionIndex == -1) {
- // FIXME: Variadic templates fun case.
- getSema().Diag(Loc, diag::err_pack_expansion_mismatch_unsupported);
- return ExprError();
+ // We have an argument pack, but we can't select a particular argument
+ // out of it yet. Therefore, we'll build an expression to hold on to that
+ // argument pack.
+ QualType TargetType = SemaRef.SubstType(NTTP->getType(), TemplateArgs,
+ E->getLocation(),
+ NTTP->getDeclName());
+ if (TargetType.isNull())
+ return ExprError();
+
+ return new (SemaRef.Context) SubstNonTypeTemplateParmPackExpr(TargetType,
+ NTTP,
+ E->getLocation(),
+ Arg);
}
assert(getSema().ArgumentPackSubstitutionIndex < (int)Arg.pack_size());
@@ -965,6 +977,42 @@ TemplateInstantiator::TransformTemplateParmRefExpr(DeclRefExpr *E,
E->getSourceRange().getBegin());
}
+ExprResult
+TemplateInstantiator::TransformSubstNonTypeTemplateParmPackExpr(
+ SubstNonTypeTemplateParmPackExpr *E) {
+ if (getSema().ArgumentPackSubstitutionIndex == -1) {
+ // We aren't expanding the parameter pack, so just return ourselves.
+ return getSema().Owned(E);
+ }
+
+ // FIXME: Variadic templates select Nth from type?
+ const TemplateArgument &ArgPack = E->getArgumentPack();
+ unsigned Index = (unsigned)getSema().ArgumentPackSubstitutionIndex;
+ assert(Index < ArgPack.pack_size() && "Substitution index out-of-range");
+
+ const TemplateArgument &Arg = ArgPack.pack_begin()[Index];
+ if (Arg.getKind() == TemplateArgument::Expression)
+ return SemaRef.Owned(Arg.getAsExpr());
+
+ if (Arg.getKind() == TemplateArgument::Declaration) {
+ ValueDecl *VD = cast<ValueDecl>(Arg.getAsDecl());
+
+ // Find the instantiation of the template argument. This is
+ // required for nested templates.
+ VD = cast_or_null<ValueDecl>(
+ getSema().FindInstantiatedDecl(E->getParameterPackLocation(),
+ VD, TemplateArgs));
+ if (!VD)
+ return ExprError();
+
+ return SemaRef.BuildExpressionFromDeclTemplateArgument(Arg,
+ E->getType(),
+ E->getParameterPackLocation());
+ }
+
+ return SemaRef.BuildExpressionFromIntegralTemplateArgument(Arg,
+ E->getParameterPackLocation());
+}
ExprResult
TemplateInstantiator::TransformDeclRefExpr(DeclRefExpr *E) {
diff --git a/lib/Sema/TreeTransform.h b/lib/Sema/TreeTransform.h
index 02c95bdb13..73982a71c2 100644
--- a/lib/Sema/TreeTransform.h
+++ b/lib/Sema/TreeTransform.h
@@ -6894,6 +6894,14 @@ TreeTransform<Derived>::TransformSizeOfPackExpr(SizeOfPackExpr *E) {
template<typename Derived>
ExprResult
+TreeTransform<Derived>::TransformSubstNonTypeTemplateParmPackExpr(
+ SubstNonTypeTemplateParmPackExpr *E) {
+ // Default behavior is to do nothing with this transformation.
+ return SemaRef.Owned(E);
+}
+
+template<typename Derived>
+ExprResult
TreeTransform<Derived>::TransformObjCStringLiteral(ObjCStringLiteral *E) {
return SemaRef.Owned(E);
}
diff --git a/lib/Serialization/ASTReaderStmt.cpp b/lib/Serialization/ASTReaderStmt.cpp
index 022b619412..5fec238ab8 100644
--- a/lib/Serialization/ASTReaderStmt.cpp
+++ b/lib/Serialization/ASTReaderStmt.cpp
@@ -14,6 +14,7 @@
#include "clang/Serialization/ASTReader.h"
#include "clang/AST/DeclCXX.h"
+#include "clang/AST/DeclTemplate.h"
#include "clang/AST/StmtVisitor.h"
using namespace clang;
using namespace clang::serialization;
@@ -178,7 +179,8 @@ namespace clang {
void VisitCXXNoexceptExpr(CXXNoexceptExpr *E);
void VisitPackExpansionExpr(PackExpansionExpr *E);
void VisitSizeOfPackExpr(SizeOfPackExpr *E);
-
+ void VisitSubstNonTypeTemplateParmPackExpr(
+ SubstNonTypeTemplateParmPackExpr *E);
void VisitOpaqueValueExpr(OpaqueValueExpr *E);
};
}
@@ -1307,6 +1309,20 @@ void ASTStmtReader::VisitSizeOfPackExpr(SizeOfPackExpr *E) {
E->Pack = cast_or_null<NamedDecl>(Reader.GetDecl(Record[Idx++]));
}
+void ASTStmtReader::VisitSubstNonTypeTemplateParmPackExpr(
+ SubstNonTypeTemplateParmPackExpr *E) {
+ VisitExpr(E);
+ E->Param
+ = cast_or_null<NonTypeTemplateParmDecl>(Reader.GetDecl(Record[Idx++]));
+ TemplateArgument ArgPack = Reader.ReadTemplateArgument(F, Record, Idx);
+ if (ArgPack.getKind() != TemplateArgument::Pack)
+ return;
+
+ E->Arguments = ArgPack.pack_begin();
+ E->NumArguments = ArgPack.pack_size();
+ E->NameLoc = ReadSourceLocation(Record, Idx);
+}
+
void ASTStmtReader::VisitOpaqueValueExpr(OpaqueValueExpr *E) {
VisitExpr(E);
}
@@ -1837,6 +1853,10 @@ Stmt *ASTReader::ReadStmtFromStream(PerFileData &F) {
S = new (Context) SizeOfPackExpr(Empty);
break;
+ case EXPR_SUBST_NON_TYPE_TEMPLATE_PARM_PACK:
+ S = new (Context) SubstNonTypeTemplateParmPackExpr(Empty);
+ break;
+
case EXPR_OPAQUE_VALUE:
S = new (Context) OpaqueValueExpr(Empty);
break;
diff --git a/lib/Serialization/ASTWriterStmt.cpp b/lib/Serialization/ASTWriterStmt.cpp
index 205f4dc2a9..e03a780fad 100644
--- a/lib/Serialization/ASTWriterStmt.cpp
+++ b/lib/Serialization/ASTWriterStmt.cpp
@@ -14,6 +14,7 @@
#include "clang/Serialization/ASTWriter.h"
#include "clang/AST/DeclCXX.h"
#include "clang/AST/DeclObjC.h"
+#include "clang/AST/DeclTemplate.h"
#include "clang/AST/StmtVisitor.h"
#include "llvm/Bitcode/BitstreamWriter.h"
using namespace clang;
@@ -152,6 +153,8 @@ namespace clang {
void VisitCXXNoexceptExpr(CXXNoexceptExpr *E);
void VisitPackExpansionExpr(PackExpansionExpr *E);
void VisitSizeOfPackExpr(SizeOfPackExpr *E);
+ void VisitSubstNonTypeTemplateParmPackExpr(
+ SubstNonTypeTemplateParmPackExpr *E);
void VisitOpaqueValueExpr(OpaqueValueExpr *E);
};
}
@@ -1316,6 +1319,15 @@ void ASTStmtWriter::VisitSizeOfPackExpr(SizeOfPackExpr *E) {
Code = serialization::EXPR_SIZEOF_PACK;
}
+void ASTStmtWriter::VisitSubstNonTypeTemplateParmPackExpr(
+ SubstNonTypeTemplateParmPackExpr *E) {
+ VisitExpr(E);
+ Writer.AddDeclRef(E->Param, Record);
+ Writer.AddTemplateArgument(E->getArgumentPack(), Record);
+ Writer.AddSourceLocation(E->NameLoc, Record);
+ Code = serialization::EXPR_SUBST_NON_TYPE_TEMPLATE_PARM_PACK;
+}
+
void ASTStmtWriter::VisitOpaqueValueExpr(OpaqueValueExpr *E) {
VisitExpr(E);
Code = serialization::EXPR_OPAQUE_VALUE;
diff --git a/lib/StaticAnalyzer/Checkers/ExprEngine.cpp b/lib/StaticAnalyzer/Checkers/ExprEngine.cpp
index f3c305a388..f45041b73e 100644
--- a/lib/StaticAnalyzer/Checkers/ExprEngine.cpp
+++ b/lib/StaticAnalyzer/Checkers/ExprEngine.cpp
@@ -789,6 +789,7 @@ void ExprEngine::Visit(const Stmt* S, ExplodedNode* Pred,
case Stmt::UnresolvedMemberExprClass:
case Stmt::CXXNoexceptExprClass:
case Stmt::PackExpansionExprClass:
+ case Stmt::SubstNonTypeTemplateParmPackExprClass:
{
SaveAndRestore<bool> OldSink(Builder->BuildSinks);
Builder->BuildSinks = true;
diff --git a/test/CXX/temp/temp.decls/temp.variadic/multi-level-substitution.cpp b/test/CXX/temp/temp.decls/temp.variadic/multi-level-substitution.cpp
index 5ce5e63adb..01d5759188 100644
--- a/test/CXX/temp/temp.decls/temp.variadic/multi-level-substitution.cpp
+++ b/test/CXX/temp/temp.decls/temp.variadic/multi-level-substitution.cpp
@@ -126,4 +126,27 @@ namespace PacksAtDifferentLevels {
some_function_object<int, unsigned int>::result_of,
some_function_object<long, unsigned long>::result_of>
>::value == 0? 1 : -1];
+
+ template<unsigned I, unsigned J> struct unsigned_pair { };
+
+ template<unsigned ...Values1>
+ struct X4 {
+ template<typename> struct Inner {
+ static const unsigned value = 0;
+ };
+
+ template<unsigned ...Values2>
+ struct Inner<tuple<unsigned_pair<Values1, Values2>...>> {
+ static const unsigned value = 1;
+ };
+ };
+
+ int check8[X4<1, 3, 5>::Inner<tuple<unsigned_pair<1, 2>,
+ unsigned_pair<3, 4>,
+ unsigned_pair<5, 6>>
+ >::value == 1? 1 : -1];
+ int check9[X4<1, 3>::Inner<tuple<unsigned_pair<1, 2>,
+ unsigned_pair<3, 4>,
+ unsigned_pair<5, 6>>
+ >::value == 0? 1 : -1];
}
diff --git a/tools/libclang/CIndex.cpp b/tools/libclang/CIndex.cpp
index 38b86cd23f..574b4c8b4e 100644
--- a/tools/libclang/CIndex.cpp
+++ b/tools/libclang/CIndex.cpp
@@ -2649,6 +2649,9 @@ static Decl *getDeclFromExpr(Stmt *E) {
if (ObjCProtocolExpr *PE = dyn_cast<ObjCProtocolExpr>(E))
return PE->getProtocol();
+ if (SubstNonTypeTemplateParmPackExpr *NTTP
+ = dyn_cast<SubstNonTypeTemplateParmPackExpr>(E))
+ return NTTP->getParameterPack();
return 0;
}
diff --git a/tools/libclang/CXCursor.cpp b/tools/libclang/CXCursor.cpp
index 1a75284de3..7bcd1597ba 100644
--- a/tools/libclang/CXCursor.cpp
+++ b/tools/libclang/CXCursor.cpp
@@ -171,6 +171,7 @@ CXCursor cxcursor::MakeCXCursor(Stmt *S, Decl *Parent,
case Stmt::DeclRefExprClass:
case Stmt::BlockDeclRefExprClass:
+ case Stmt::SubstNonTypeTemplateParmPackExprClass:
// FIXME: UnresolvedLookupExpr?
// FIXME: DependentScopeDeclRefExpr?
K = CXCursor_DeclRefExpr;