aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDouglas Gregor <dgregor@apple.com>2011-01-07 19:35:17 +0000
committerDouglas Gregor <dgregor@apple.com>2011-01-07 19:35:17 +0000
commit91fc73e7ffb1fa1da0276518359d3bd4ed11c843 (patch)
tree48ed64396d9978bd7cc4a569416ed1d1cfb5b078
parentbd5f9f708aa31920d3bd73aa10fcb5de424c657a (diff)
When instantiating the arguments to an initializer, use the
TreeTransform version of TransformExprs() rather than explicit loop, so that we expand pack expansions properly. Test cast coming soon... git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@123014 91177308-0d34-0410-b5e6-96231b3b80d8
-rw-r--r--include/clang/Sema/Sema.h19
-rw-r--r--lib/Sema/SemaTemplateInstantiate.cpp12
-rw-r--r--lib/Sema/SemaTemplateInstantiateDecl.cpp34
3 files changed, 35 insertions, 30 deletions
diff --git a/include/clang/Sema/Sema.h b/include/clang/Sema/Sema.h
index 096a8e2564..bcb7666f43 100644
--- a/include/clang/Sema/Sema.h
+++ b/include/clang/Sema/Sema.h
@@ -3897,6 +3897,25 @@ public:
llvm::SmallVectorImpl<ParmVarDecl *> *OutParams = 0);
ExprResult SubstExpr(Expr *E,
const MultiLevelTemplateArgumentList &TemplateArgs);
+
+ /// \brief Substitute the given template arguments into a list of
+ /// expressions, expanding pack expansions if required.
+ ///
+ /// \param Exprs The list of expressions to substitute into.
+ ///
+ /// \param NumExprs The number of expressions in \p Exprs.
+ ///
+ /// \param IsCall Whether this is some form of call, in which case
+ /// default arguments will be dropped.
+ ///
+ /// \param TemplateArgs The set of template arguments to substitute.
+ ///
+ /// \param Outputs Will receive all of the substituted arguments.
+ ///
+ /// \returns true if an error occurred, false otherwise.
+ bool SubstExprs(Expr **Exprs, unsigned NumExprs, bool IsCall,
+ const MultiLevelTemplateArgumentList &TemplateArgs,
+ llvm::SmallVectorImpl<Expr *> &Outputs);
StmtResult SubstStmt(Stmt *S,
const MultiLevelTemplateArgumentList &TemplateArgs);
diff --git a/lib/Sema/SemaTemplateInstantiate.cpp b/lib/Sema/SemaTemplateInstantiate.cpp
index 71ccb06212..394f50ef69 100644
--- a/lib/Sema/SemaTemplateInstantiate.cpp
+++ b/lib/Sema/SemaTemplateInstantiate.cpp
@@ -1868,6 +1868,18 @@ Sema::SubstExpr(Expr *E, const MultiLevelTemplateArgumentList &TemplateArgs) {
return Instantiator.TransformExpr(E);
}
+bool Sema::SubstExprs(Expr **Exprs, unsigned NumExprs, bool IsCall,
+ const MultiLevelTemplateArgumentList &TemplateArgs,
+ llvm::SmallVectorImpl<Expr *> &Outputs) {
+ if (NumExprs == 0)
+ return false;
+
+ TemplateInstantiator Instantiator(*this, TemplateArgs,
+ SourceLocation(),
+ DeclarationName());
+ return Instantiator.TransformExprs(Exprs, NumExprs, IsCall, Outputs);
+}
+
/// \brief Do template substitution on a nested-name-specifier.
NestedNameSpecifier *
Sema::SubstNestedNameSpecifier(NestedNameSpecifier *NNS,
diff --git a/lib/Sema/SemaTemplateInstantiateDecl.cpp b/lib/Sema/SemaTemplateInstantiateDecl.cpp
index 2ef688b0eb..649fbf6625 100644
--- a/lib/Sema/SemaTemplateInstantiateDecl.cpp
+++ b/lib/Sema/SemaTemplateInstantiateDecl.cpp
@@ -166,29 +166,6 @@ Decl *TemplateDeclInstantiator::VisitTypedefDecl(TypedefDecl *D) {
return Typedef;
}
-/// \brief Instantiate the arguments provided as part of initialization.
-///
-/// \returns true if an error occurred, false otherwise.
-static bool InstantiateInitializationArguments(Sema &SemaRef,
- Expr **Args, unsigned NumArgs,
- const MultiLevelTemplateArgumentList &TemplateArgs,
- ASTOwningVector<Expr*> &InitArgs) {
- for (unsigned I = 0; I != NumArgs; ++I) {
- // When we hit the first defaulted argument, break out of the loop:
- // we don't pass those default arguments on.
- if (Args[I]->isDefaultArgument())
- break;
-
- ExprResult Arg = SemaRef.SubstExpr(Args[I], TemplateArgs);
- if (Arg.isInvalid())
- return true;
-
- InitArgs.push_back(Arg.release());
- }
-
- return false;
-}
-
/// \brief Instantiate an initializer, breaking it into separate
/// initialization arguments.
///
@@ -226,17 +203,14 @@ static bool InstantiateInitializer(Sema &S, Expr *Init,
if (ParenListExpr *ParenList = dyn_cast<ParenListExpr>(Init)) {
LParenLoc = ParenList->getLParenLoc();
RParenLoc = ParenList->getRParenLoc();
- return InstantiateInitializationArguments(S, ParenList->getExprs(),
- ParenList->getNumExprs(),
- TemplateArgs, NewArgs);
+ return S.SubstExprs(ParenList->getExprs(), ParenList->getNumExprs(),
+ true, TemplateArgs, NewArgs);
}
if (CXXConstructExpr *Construct = dyn_cast<CXXConstructExpr>(Init)) {
if (!isa<CXXTemporaryObjectExpr>(Construct)) {
- if (InstantiateInitializationArguments(S,
- Construct->getArgs(),
- Construct->getNumArgs(),
- TemplateArgs, NewArgs))
+ if (S.SubstExprs(Construct->getArgs(), Construct->getNumArgs(), true,
+ TemplateArgs, NewArgs))
return true;
// FIXME: Fake locations!