[cfe-commits] r72081 - in /cfe/trunk: include/clang/AST/ExprCXX.h lib/AST/ExprCXX.cpp lib/Sema/SemaTemplateInstantiateExpr.cpp test/SemaTemplate/instantiate-call.cpp

Douglas Gregor dgregor at apple.com
Mon May 18 17:38:19 PDT 2009


Author: dgregor
Date: Mon May 18 19:38:01 2009
New Revision: 72081

URL: http://llvm.org/viewvc/llvm-project?rev=72081&view=rev
Log:
Template instantiation for call expressions.

Added:
    cfe/trunk/test/SemaTemplate/instantiate-call.cpp
Modified:
    cfe/trunk/include/clang/AST/ExprCXX.h
    cfe/trunk/lib/AST/ExprCXX.cpp
    cfe/trunk/lib/Sema/SemaTemplateInstantiateExpr.cpp

Modified: cfe/trunk/include/clang/AST/ExprCXX.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/AST/ExprCXX.h?rev=72081&r1=72080&r2=72081&view=diff

==============================================================================
--- cfe/trunk/include/clang/AST/ExprCXX.h (original)
+++ cfe/trunk/include/clang/AST/ExprCXX.h Mon May 18 19:38:01 2009
@@ -800,6 +800,8 @@
 
   virtual SourceRange getSourceRange() const { return SourceRange(Loc); }
 
+  UnresolvedFunctionNameExpr* Clone(ASTContext &C) const;
+
   static bool classof(const Stmt *T) { 
     return T->getStmtClass() == UnresolvedFunctionNameExprClass;
   }

Modified: cfe/trunk/lib/AST/ExprCXX.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/AST/ExprCXX.cpp?rev=72081&r1=72080&r2=72081&view=diff

==============================================================================
--- cfe/trunk/lib/AST/ExprCXX.cpp (original)
+++ cfe/trunk/lib/AST/ExprCXX.cpp Mon May 18 19:38:01 2009
@@ -131,6 +131,11 @@
   return child_iterator();
 }
 
+UnresolvedFunctionNameExpr* 
+UnresolvedFunctionNameExpr::Clone(ASTContext &C) const {
+  return new (C) UnresolvedFunctionNameExpr(Name, getType(), Loc);
+}
+
 // UnaryTypeTraitExpr
 Stmt::child_iterator UnaryTypeTraitExpr::child_begin() {
   return child_iterator();

Modified: cfe/trunk/lib/Sema/SemaTemplateInstantiateExpr.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaTemplateInstantiateExpr.cpp?rev=72081&r1=72080&r2=72081&view=diff

==============================================================================
--- cfe/trunk/lib/Sema/SemaTemplateInstantiateExpr.cpp (original)
+++ cfe/trunk/lib/Sema/SemaTemplateInstantiateExpr.cpp Mon May 18 19:38:01 2009
@@ -46,6 +46,7 @@
     OwningExprResult VisitParenExpr(ParenExpr *E);
     OwningExprResult VisitUnaryOperator(UnaryOperator *E);
     OwningExprResult VisitArraySubscriptExpr(ArraySubscriptExpr *E);
+    OwningExprResult VisitCallExpr(CallExpr *E);
     OwningExprResult VisitBinaryOperator(BinaryOperator *E);
     OwningExprResult VisitCXXOperatorCallExpr(CXXOperatorCallExpr *E);
     OwningExprResult VisitCXXConditionDeclExpr(CXXConditionDeclExpr *E);
@@ -58,6 +59,8 @@
     OwningExprResult VisitCXXBoolLiteralExpr(CXXBoolLiteralExpr *E);
     OwningExprResult VisitCXXNullPtrLiteralExpr(CXXNullPtrLiteralExpr *E);
     OwningExprResult VisitGNUNullExpr(GNUNullExpr *E);
+    OwningExprResult VisitUnresolvedFunctionNameExpr(
+                                              UnresolvedFunctionNameExpr *E);
 
     // Base case. I'm supposed to ignore this.
     Sema::OwningExprResult VisitStmt(Stmt *S) { 
@@ -113,9 +116,16 @@
   return SemaRef.Clone(E);
 }
 
+Sema::OwningExprResult 
+TemplateExprInstantiator::VisitUnresolvedFunctionNameExpr(
+                                              UnresolvedFunctionNameExpr *E) {
+  return SemaRef.Clone(E);
+}
+
 Sema::OwningExprResult
 TemplateExprInstantiator::VisitDeclRefExpr(DeclRefExpr *E) {
   Decl *D = E->getDecl();
+  ValueDecl *NewD = 0;
   if (NonTypeTemplateParmDecl *NTTP = dyn_cast<NonTypeTemplateParmDecl>(D)) {
     assert(NTTP->getDepth() == 0 && "No nested templates yet");
     const TemplateArgument &Arg = TemplateArgs[NTTP->getPosition()]; 
@@ -136,19 +146,23 @@
                                                  *Arg.getAsIntegral(),
                                                  T, 
                                        E->getSourceRange().getBegin()));
-  } else if (ParmVarDecl *Parm = dyn_cast<ParmVarDecl>(D)) {
-    ParmVarDecl *ParmInst 
-      = SemaRef.CurrentInstantiationScope->getInstantiationOf(Parm);
-    QualType T = ParmInst->getType();
-    return SemaRef.Owned(new (SemaRef.Context) DeclRefExpr(ParmInst,
+  } else if (ParmVarDecl *Parm = dyn_cast<ParmVarDecl>(D))
+    NewD = SemaRef.CurrentInstantiationScope->getInstantiationOf(Parm);
+  else if (isa<FunctionDecl>(D) || isa<OverloadedFunctionDecl>(D))
+    // FIXME: Instantiate decl!
+    NewD = cast<ValueDecl>(D);
+  else
+    assert(false && "Unhandled declaratrion reference kind");
+
+  if (!NewD)
+    return SemaRef.ExprError();
+
+  QualType T = NewD->getType();
+  return SemaRef.Owned(new (SemaRef.Context) DeclRefExpr(NewD,
                                                       T.getNonReferenceType(),
                                                            E->getLocation(),
                                                         T->isDependentType(),
                                                         T->isDependentType()));
-  } else
-    assert(false && "Can't handle arbitrary declaration references");
-
-  return SemaRef.ExprError();
 }
 
 Sema::OwningExprResult
@@ -203,6 +217,39 @@
                                          E->getRBracketLoc());
 }
 
+Sema::OwningExprResult TemplateExprInstantiator::VisitCallExpr(CallExpr *E) {
+  // Instantiate callee
+  OwningExprResult Callee = Visit(E->getCallee());
+  if (Callee.isInvalid())
+    return SemaRef.ExprError();
+
+  // Instantiate arguments
+  llvm::SmallVector<Expr*, 8> Args;
+  llvm::SmallVector<SourceLocation, 4> FakeCommaLocs;
+  for (unsigned I = 0, N = E->getNumArgs(); I != N; ++I) {
+    OwningExprResult Arg = Visit(E->getArg(I));
+    if (Arg.isInvalid()) {
+      for (unsigned Victim = 0; Victim != I; ++Victim)
+        Args[Victim]->Destroy(SemaRef.Context);
+      return SemaRef.ExprError();
+    }
+
+    FakeCommaLocs.push_back(
+     SemaRef.PP.getLocForEndOfToken(E->getArg(I)->getSourceRange().getEnd()));
+    Args.push_back(Arg.takeAs<Expr>());
+  }
+
+  SourceLocation FakeLParenLoc 
+    = ((Expr *)Callee.get())->getSourceRange().getBegin();
+  return SemaRef.ActOnCallExpr(/*Scope=*/0, move(Callee), 
+                               /*FIXME:*/FakeLParenLoc,
+                               Sema::MultiExprArg(SemaRef,
+                                                  (void **)&Args.front(),
+                                                  Args.size()),
+                               /*FIXME:*/&FakeCommaLocs.front(), 
+                               E->getRParenLoc());
+}
+
 Sema::OwningExprResult 
 TemplateExprInstantiator::VisitBinaryOperator(BinaryOperator *E) {
   Sema::OwningExprResult LHS = Visit(E->getLHS());

Added: cfe/trunk/test/SemaTemplate/instantiate-call.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/SemaTemplate/instantiate-call.cpp?rev=72081&view=auto

==============================================================================
--- cfe/trunk/test/SemaTemplate/instantiate-call.cpp (added)
+++ cfe/trunk/test/SemaTemplate/instantiate-call.cpp Mon May 18 19:38:01 2009
@@ -0,0 +1,50 @@
+// RUN: clang-cc -fsyntax-only -verify %s
+
+namespace N1 {
+  struct X0 { };
+
+  int& f0(X0);
+}
+
+namespace N2 {
+  char& f0(char);
+
+  template<typename T, typename Result>
+  struct call_f0 {
+    void test_f0(T t) {
+      Result result = f0(t);
+    }
+  };
+}
+
+template struct N2::call_f0<int, char&>;
+template struct N2::call_f0<N1::X0, int&>;
+
+namespace N3 {
+  template<typename T, typename Result>
+  struct call_f0 {
+    void test_f0(T t) {
+      Result &result = f0(t); // expected-error 2{{no matching}}
+    }
+  };
+}
+
+template struct N3::call_f0<int, char&>; // expected-note{{instantiation}}
+template struct N3::call_f0<N1::X0, int&>;
+
+short& f0(char);
+namespace N4 {
+  template<typename T, typename Result>
+  struct call_f0 {
+    void test_f0(T t) {
+      Result &result = f0(t);
+    }
+  };
+}
+
+template struct N4::call_f0<int, short&>;
+template struct N4::call_f0<N1::X0, int&>;
+template struct N3::call_f0<int, short&>; // expected-note{{instantiation}}
+
+// FIXME: test overloaded function call operators, calls to member
+// functions, etc.





More information about the cfe-commits mailing list