]> granicus.if.org Git - clang/commitdiff
When instantiating the arguments to an initializer, use the
authorDouglas Gregor <dgregor@apple.com>
Fri, 7 Jan 2011 19:35:17 +0000 (19:35 +0000)
committerDouglas Gregor <dgregor@apple.com>
Fri, 7 Jan 2011 19:35:17 +0000 (19:35 +0000)
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

include/clang/Sema/Sema.h
lib/Sema/SemaTemplateInstantiate.cpp
lib/Sema/SemaTemplateInstantiateDecl.cpp

index 096a8e256400f6e3ddc21fea1d21c6b8bf55826b..bcb7666f43958ff18f71a2b44013e9a5dd7bc140 100644 (file)
@@ -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);
index 71ccb06212ee3030dd6b062ebfee12c3c94b5325..394f50ef6985eb44a8ab7630d9b43df9b47d6333 100644 (file)
@@ -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,
index 2ef688b0ebc9b74e8407a704cfb883845b251072..649fbf66251ab6af95e0177d35fd25f14e7a4303 100644 (file)
@@ -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!