]> granicus.if.org Git - clang/commitdiff
When extracting the callee declaration from a call expression, be sure
authorDouglas Gregor <dgregor@apple.com>
Tue, 6 Sep 2011 21:41:04 +0000 (21:41 +0000)
committerDouglas Gregor <dgregor@apple.com>
Tue, 6 Sep 2011 21:41:04 +0000 (21:41 +0000)
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

lib/AST/Expr.cpp
lib/CodeGen/CGExpr.cpp
test/CodeGenCXX/builtins.cpp

index 41fa850184efe6ba2b25a0c525dfdcc71ac9d991..26ff6f3b7d5f185f438ae481ae48ad3daba4cfc7 100644 (file)
@@ -771,6 +771,12 @@ CallExpr::CallExpr(ASTContext &C, StmtClass SC, unsigned NumPreArgs,
 
 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())
index d26d787da693755e5da929b69d41d451e909679f..0be3628a6269002e55bf5ece965347862c3123c7 100644 (file)
@@ -2174,14 +2174,10 @@ RValue CodeGenFunction::EmitCallExpr(const CallExpr *E,
   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))
index 0629c31015c76b8c63b722286c33fb261e6c03a8..4542563717a11ccbd06308830e0f5a927066a2dc 100644 (file)
@@ -7,3 +7,15 @@ int main() {
   // 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*);
+