When extracting the callee declaration from a call expression, be sure
to look through SubstNonTypeTemplateParmExprs. Then, update the IR
generation of CallExprs to actually use CallExpr::getCalleeDecl()
rather than attempting to mimick its behavior (badly).

Fixes <rdar://problem/10063539>.



git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@139185 91177308-0d34-0410-b5e6-96231b3b80d8
diff --git a/lib/AST/Expr.cpp b/lib/AST/Expr.cpp
index 41fa850..26ff6f3 100644
--- a/lib/AST/Expr.cpp
+++ b/lib/AST/Expr.cpp
@@ -771,6 +771,12 @@
 
 Decl *CallExpr::getCalleeDecl() {
   Expr *CEE = getCallee()->IgnoreParenCasts();
+    
+  while (SubstNonTypeTemplateParmExpr *NTTP
+                                = dyn_cast<SubstNonTypeTemplateParmExpr>(CEE)) {
+    CEE = NTTP->getReplacement()->IgnoreParenCasts();
+  }
+  
   // If we're calling a dereference, look at the pointer instead.
   if (BinaryOperator *BO = dyn_cast<BinaryOperator>(CEE)) {
     if (BO->isPtrMemOp())
diff --git a/lib/CodeGen/CGExpr.cpp b/lib/CodeGen/CGExpr.cpp
index d26d787..0be3628 100644
--- a/lib/CodeGen/CGExpr.cpp
+++ b/lib/CodeGen/CGExpr.cpp
@@ -2174,14 +2174,10 @@
   if (const CXXMemberCallExpr *CE = dyn_cast<CXXMemberCallExpr>(E))
     return EmitCXXMemberCallExpr(CE, ReturnValue);
 
-  const Decl *TargetDecl = 0;
-  if (const ImplicitCastExpr *CE = dyn_cast<ImplicitCastExpr>(E->getCallee())) {
-    if (const DeclRefExpr *DRE = dyn_cast<DeclRefExpr>(CE->getSubExpr())) {
-      TargetDecl = DRE->getDecl();
-      if (const FunctionDecl *FD = dyn_cast<FunctionDecl>(TargetDecl))
-        if (unsigned builtinID = FD->getBuiltinID())
-          return EmitBuiltinExpr(FD, builtinID, E);
-    }
+  const Decl *TargetDecl = E->getCalleeDecl();
+  if (const FunctionDecl *FD = dyn_cast_or_null<FunctionDecl>(TargetDecl)) {
+    if (unsigned builtinID = FD->getBuiltinID())
+      return EmitBuiltinExpr(FD, builtinID, E);
   }
 
   if (const CXXOperatorCallExpr *CE = dyn_cast<CXXOperatorCallExpr>(E))
diff --git a/test/CodeGenCXX/builtins.cpp b/test/CodeGenCXX/builtins.cpp
index 0629c31..4542563 100644
--- a/test/CodeGenCXX/builtins.cpp
+++ b/test/CodeGenCXX/builtins.cpp
@@ -7,3 +7,15 @@
   // CHECK: call signext i8 @memmove()
   return memmove();
 }
+
+// <rdar://problem/10063539>
+
+template<int (*Compare)(const char *s1, const char *s2)>
+int equal(const char *s1, const char *s2) {
+  return Compare(s1, s2) == 0;
+}
+
+// CHECK: define weak_odr i32 @_Z5equalIXadL_Z16__builtin_strcmpPKcS1_EEEiS1_S1_
+// CHECK: call i32 @strcmp
+template int equal<&__builtin_strcmp>(const char*, const char*);
+