Template instantiation for the various kinds of AST nodes that occur
due to C++ type construction of the form T(a1, a2, ..., aN).


git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@72183 91177308-0d34-0410-b5e6-96231b3b80d8
diff --git a/include/clang/AST/ExprCXX.h b/include/clang/AST/ExprCXX.h
index f3c8244..df01e9b 100644
--- a/include/clang/AST/ExprCXX.h
+++ b/include/clang/AST/ExprCXX.h
@@ -431,8 +431,11 @@
   
   void Destroy(ASTContext &C);
   
-  const VarDecl* getVarDecl() const { return VD; }
-  const CXXConstructorDecl* getConstructor() const { return Constructor; }
+  VarDecl* getVarDecl() const { return VD; }
+  CXXConstructorDecl* getConstructor() const { return Constructor; }
+
+  /// \brief Whether this construction is elidable.
+  bool isElidable() const { return Elidable; }
 
   typedef ExprIterator arg_iterator;
   typedef ConstExprIterator const_arg_iterator;
@@ -537,7 +540,7 @@
 public:
   CXXZeroInitValueExpr(QualType ty, SourceLocation tyBeginLoc,
                        SourceLocation rParenLoc ) : 
-    Expr(CXXZeroInitValueExprClass, ty),
+    Expr(CXXZeroInitValueExprClass, ty, false, false),
     TyBeginLoc(tyBeginLoc), RParenLoc(rParenLoc) {}
   
   SourceLocation getTypeBeginLoc() const { return TyBeginLoc; }
@@ -553,6 +556,8 @@
     return SourceRange(TyBeginLoc, RParenLoc);
   }
     
+  CXXZeroInitValueExpr* Clone(ASTContext &C) const;
+
   static bool classof(const Stmt *T) { 
     return T->getStmtClass() == CXXZeroInitValueExprClass;
   }
diff --git a/lib/AST/ExprCXX.cpp b/lib/AST/ExprCXX.cpp
index a73843c..cca391e 100644
--- a/lib/AST/ExprCXX.cpp
+++ b/lib/AST/ExprCXX.cpp
@@ -365,3 +365,7 @@
 CXXNullPtrLiteralExpr* CXXNullPtrLiteralExpr::Clone(ASTContext &C) const {
   return new (C) CXXNullPtrLiteralExpr(getType(), Loc);
 }
+
+CXXZeroInitValueExpr* CXXZeroInitValueExpr::Clone(ASTContext &C) const {
+  return new (C) CXXZeroInitValueExpr(getType(), TyBeginLoc, RParenLoc);
+}
diff --git a/lib/Sema/SemaTemplateInstantiateExpr.cpp b/lib/Sema/SemaTemplateInstantiateExpr.cpp
index 1dad862..1b2fa46 100644
--- a/lib/Sema/SemaTemplateInstantiateExpr.cpp
+++ b/lib/Sema/SemaTemplateInstantiateExpr.cpp
@@ -85,9 +85,9 @@
     // FIXME: CXXTypeIdExpr
     // FIXME: CXXThrowExpr
     // FIXME: CXXDefaultArgExpr
-    // FIXME: CXXConstructExpr
-    // FIXME: CXXFunctionalCastExpr
-    // FIXME: CXXZeroInitValueExpr
+    OwningExprResult VisitCXXConstructExpr(CXXConstructExpr *E);
+    OwningExprResult VisitCXXFunctionalCastExpr(CXXFunctionalCastExpr *E);
+    OwningExprResult VisitCXXZeroInitValueExpr(CXXZeroInitValueExpr *E);
     // FIXME: CXXNewExpr
     // FIXME: CXXDeleteExpr
     // FIXME: UnaryTypeTraitExpr
@@ -836,6 +836,87 @@
 }
 
 Sema::OwningExprResult 
+TemplateExprInstantiator::VisitCXXConstructExpr(CXXConstructExpr *E) {
+  assert(!cast<CXXRecordDecl>(E->getConstructor()->getDeclContext())
+           ->isDependentType() && "Dependent constructor shouldn't be here");
+
+  QualType T = SemaRef.InstantiateType(E->getType(), TemplateArgs,
+                                       /*FIXME*/E->getSourceRange().getBegin(),
+                                       DeclarationName());
+  if (T.isNull())
+    return SemaRef.ExprError();
+
+  bool Invalid = false;
+  llvm::SmallVector<Expr *, 8> Args;
+  for (CXXConstructExpr::arg_iterator Arg = E->arg_begin(), 
+                                   ArgEnd = E->arg_end();
+       Arg != ArgEnd; ++Arg) {
+    OwningExprResult ArgInst = Visit(*Arg);
+    if (ArgInst.isInvalid()) {
+      Invalid = true;
+      break;
+    }
+
+    Args.push_back(ArgInst.takeAs<Expr>());
+  }
+
+
+  VarDecl *Var = 0;
+  if (!Invalid) {
+    Var = cast_or_null<VarDecl>(SemaRef.InstantiateDecl(E->getVarDecl(),
+                                                        SemaRef.CurContext,
+                                                        TemplateArgs));
+    if (!Var)
+      Invalid = true;
+  }
+
+  if (Invalid) {
+    for (unsigned I = 0, N = Args.size(); I != N; ++I)
+      Args[I]->Destroy(SemaRef.Context);
+
+    return SemaRef.ExprError();
+  }
+
+  return SemaRef.Owned(CXXConstructExpr::Create(SemaRef.Context, Var, T,
+                                                E->getConstructor(), 
+                                                E->isElidable(),
+                                                &Args.front(), Args.size()));
+}
+
+Sema::OwningExprResult 
+TemplateExprInstantiator::VisitCXXFunctionalCastExpr(
+                                                   CXXFunctionalCastExpr *E) {
+  // Instantiate the type that we're casting to.
+  QualType ExplicitTy = SemaRef.InstantiateType(E->getTypeAsWritten(),
+                                                TemplateArgs,
+                                                E->getTypeBeginLoc(),
+                                                DeclarationName());
+  if (ExplicitTy.isNull())
+    return SemaRef.ExprError();
+
+  // Instantiate the subexpression.
+  OwningExprResult SubExpr = Visit(E->getSubExpr());
+  if (SubExpr.isInvalid())
+    return SemaRef.ExprError();
+  
+  // FIXME: The end of the type's source range is wrong
+  Expr *Sub = SubExpr.takeAs<Expr>();
+  return SemaRef.ActOnCXXTypeConstructExpr(SourceRange(E->getTypeBeginLoc()),
+                                           ExplicitTy.getAsOpaquePtr(),
+                                           /*FIXME:*/E->getTypeBeginLoc(),
+                                           Sema::MultiExprArg(SemaRef,
+                                                              (void **)&Sub,
+                                                              1),
+                                           0, 
+                                           E->getRParenLoc());
+}
+
+Sema::OwningExprResult 
+TemplateExprInstantiator::VisitCXXZeroInitValueExpr(CXXZeroInitValueExpr *E) {
+  return SemaRef.Clone(E);
+}
+
+Sema::OwningExprResult 
 TemplateExprInstantiator::VisitCXXUnresolvedConstructExpr(
                                               CXXUnresolvedConstructExpr *E) {
   QualType T = SemaRef.InstantiateType(E->getTypeAsWritten(), TemplateArgs,
diff --git a/test/SemaTemplate/instantiate-expr-4.cpp b/test/SemaTemplate/instantiate-expr-4.cpp
new file mode 100644
index 0000000..a5b55b3
--- /dev/null
+++ b/test/SemaTemplate/instantiate-expr-4.cpp
@@ -0,0 +1,35 @@
+// RUN: clang-cc -fsyntax-only -verify %s
+
+// ---------------------------------------------------------------------
+// C++ Functional Casts
+// ---------------------------------------------------------------------
+template<int N>
+struct ValueInit0 {
+  int f() {
+    return int();
+  }
+};
+
+template struct ValueInit0<5>;
+
+template<int N>
+struct FunctionalCast0 {
+  int f() {
+    return int(N);
+  }
+};
+
+template struct FunctionalCast0<5>;
+
+struct X {
+  X(int, int);
+};
+
+template<int N, int M>
+struct BuildTemporary0 {
+  X f() {
+    return X(N, M);
+  }
+};
+
+template struct BuildTemporary0<5, 7>;