Implement template instantiation for several more kinds of expressions:
  - C++ function casts, e.g., T(foo)
  - sizeof(), alignof()

More importantly, this allows us to verify that we're performing
overload resolution during template instantiation, with
argument-dependent lookup and the "cached" results of name lookup from
the template definition.



git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@66947 91177308-0d34-0410-b5e6-96231b3b80d8
diff --git a/lib/Sema/SemaTemplateInstantiate.cpp b/lib/Sema/SemaTemplateInstantiate.cpp
index b3e4148..4bd7ad4 100644
--- a/lib/Sema/SemaTemplateInstantiate.cpp
+++ b/lib/Sema/SemaTemplateInstantiate.cpp
@@ -17,6 +17,7 @@
 #include "clang/AST/DeclTemplate.h"
 #include "clang/AST/StmtVisitor.h"
 #include "clang/Parse/DeclSpec.h"
+#include "clang/Lex/Preprocessor.h" // for the identifier table
 #include "clang/Basic/LangOptions.h"
 #include "llvm/Support/Compiler.h"
 
@@ -441,7 +442,12 @@
       break;
 
     case TemplateArgument::Expression:
-      assert(false && "Cannot instantiate expressions yet");
+      Sema::OwningExprResult E 
+        = SemaRef.InstantiateExpr(Arg->getAsExpr(), TemplateArgs,
+                                  NumTemplateArgs);
+      if (E.isInvalid())
+        return QualType();
+      InstantiatedTemplateArgs.push_back((Expr *)E.release());
       break;
     }
   }
@@ -564,6 +570,8 @@
     unsigned NumTemplateArgs;
 
   public:
+    typedef Sema::OwningExprResult OwningExprResult;
+
     TemplateExprInstantiator(Sema &SemaRef, 
                              const TemplateArgument *TemplateArgs,
                              unsigned NumTemplateArgs)
@@ -573,11 +581,13 @@
     // FIXME: Once we get closer to completion, replace these
     // manually-written declarations with automatically-generated ones
     // from clang/AST/StmtNodes.def.
-    Sema::OwningExprResult VisitIntegerLiteral(IntegerLiteral *E);
-    Sema::OwningExprResult VisitDeclRefExpr(DeclRefExpr *E);
-    Sema::OwningExprResult VisitParenExpr(ParenExpr *E);
-    Sema::OwningExprResult VisitBinaryOperator(BinaryOperator *E);
-    Sema::OwningExprResult VisitCXXOperatorCallExpr(CXXOperatorCallExpr *E);
+    OwningExprResult VisitIntegerLiteral(IntegerLiteral *E);
+    OwningExprResult VisitDeclRefExpr(DeclRefExpr *E);
+    OwningExprResult VisitParenExpr(ParenExpr *E);
+    OwningExprResult VisitBinaryOperator(BinaryOperator *E);
+    OwningExprResult VisitCXXOperatorCallExpr(CXXOperatorCallExpr *E);
+    OwningExprResult VisitSizeOfAlignOfExpr(SizeOfAlignOfExpr *E);
+    OwningExprResult VisitCXXTemporaryObjectExpr(CXXTemporaryObjectExpr *E);
 
     // Base case. I'm supposed to ignore this.
     Sema::OwningExprResult VisitStmt(Stmt *) { 
@@ -692,6 +702,9 @@
     DeclRefExpr *DRE = cast<DeclRefExpr>(E->getCallee());
     OverloadedFunctionDecl *Overloads 
       = cast<OverloadedFunctionDecl>(DRE->getDecl());
+
+    // FIXME: Do we have to check
+    // IsAcceptableNonMemberOperatorCandidate for each of these?
     for (OverloadedFunctionDecl::function_iterator 
            F = Overloads->function_begin(),
            FEnd = Overloads->function_end();
@@ -717,6 +730,90 @@
 }
 
 Sema::OwningExprResult 
+TemplateExprInstantiator::VisitSizeOfAlignOfExpr(SizeOfAlignOfExpr *E) {
+  bool isSizeOf = E->isSizeOf();
+
+  if (E->isArgumentType()) {
+    QualType T = E->getArgumentType();
+    if (T->isDependentType()) {
+      T = SemaRef.InstantiateType(T, TemplateArgs, NumTemplateArgs,
+                                  /*FIXME*/E->getOperatorLoc(),
+                                  &SemaRef.PP.getIdentifierTable().get("sizeof"));
+      if (T.isNull())
+        return SemaRef.ExprError();
+    }
+
+    return SemaRef.CreateSizeOfAlignOfExpr(T, E->getOperatorLoc(), isSizeOf,
+                                           E->getSourceRange());
+  } 
+
+  Sema::OwningExprResult Arg = Visit(E->getArgumentExpr());
+  if (Arg.isInvalid())
+    return SemaRef.ExprError();
+
+  Sema::OwningExprResult Result
+    = SemaRef.CreateSizeOfAlignOfExpr((Expr *)Arg.get(), E->getOperatorLoc(),
+                                      isSizeOf, E->getSourceRange());
+  if (Result.isInvalid())
+    return SemaRef.ExprError();
+
+  Arg.release();
+  return move(Result);
+}
+
+Sema::OwningExprResult 
+TemplateExprInstantiator::VisitCXXTemporaryObjectExpr(
+                                                  CXXTemporaryObjectExpr *E) {
+  QualType T = E->getType();
+  if (T->isDependentType()) {
+    T = SemaRef.InstantiateType(T, TemplateArgs, NumTemplateArgs,
+                                E->getTypeBeginLoc(), DeclarationName());
+    if (T.isNull())
+      return SemaRef.ExprError();
+  }
+
+  llvm::SmallVector<Expr *, 16> Args;
+  Args.reserve(E->getNumArgs());
+  bool Invalid = false;
+  for (CXXTemporaryObjectExpr::arg_iterator Arg = E->arg_begin(), 
+                                         ArgEnd = E->arg_end();
+       Arg != ArgEnd; ++Arg) {
+    OwningExprResult InstantiatedArg = Visit(*Arg);
+    if (InstantiatedArg.isInvalid()) {
+      Invalid = true;
+      break;
+    }
+
+    Args.push_back((Expr *)InstantiatedArg.release());
+  }
+
+  if (!Invalid) {
+    SourceLocation CommaLoc;
+    // FIXME: HACK!
+    if (Args.size() > 1)
+      CommaLoc 
+        = SemaRef.PP.getLocForEndOfToken(Args[0]->getSourceRange().getEnd());
+    Sema::ExprResult Result 
+      = SemaRef.ActOnCXXTypeConstructExpr(SourceRange(E->getTypeBeginLoc()
+                                                      /*, FIXME*/),
+                                          T.getAsOpaquePtr(),
+                                          /*FIXME*/E->getTypeBeginLoc(),
+                                          (void**)&Args[0], Args.size(),
+                                          /*HACK*/&CommaLoc,
+                                          E->getSourceRange().getEnd());
+    if (!Result.isInvalid())
+      return SemaRef.Owned(Result);
+  }
+
+  // Clean up the instantiated arguments.
+  // FIXME: Would rather do this with RAII.
+  for (unsigned Idx = 0; Idx < Args.size(); ++Idx)
+    SemaRef.DeleteExpr(Args[Idx]);
+
+  return SemaRef.ExprError();
+}
+
+Sema::OwningExprResult 
 Sema::InstantiateExpr(Expr *E, const TemplateArgument *TemplateArgs,
                       unsigned NumTemplateArgs) {
   TemplateExprInstantiator Instantiator(*this, TemplateArgs, NumTemplateArgs);