Set call attribute for direct calls (i.e. noreturn).
 - Remove an unused variant of EmitCallExpr overload.


git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@65130 91177308-0d34-0410-b5e6-96231b3b80d8
diff --git a/lib/CodeGen/CGCall.cpp b/lib/CodeGen/CGCall.cpp
index 42f671a..d0122fa 100644
--- a/lib/CodeGen/CGCall.cpp
+++ b/lib/CodeGen/CGCall.cpp
@@ -1676,7 +1676,8 @@
 
 RValue CodeGenFunction::EmitCall(const CGFunctionInfo &CallInfo,
                                  llvm::Value *Callee, 
-                                 const CallArgList &CallArgs) {
+                                 const CallArgList &CallArgs,
+                                 const Decl *TargetDecl) {
   // FIXME: We no longer need the types from CallArgs; lift up and
   // simplify.
   llvm::SmallVector<llvm::Value*, 16> Args;
@@ -1752,9 +1753,8 @@
   
   llvm::CallInst *CI = Builder.CreateCall(Callee,&Args[0],&Args[0]+Args.size());
 
-  // FIXME: Provide TargetDecl so nounwind, noreturn, etc, etc get set.
   CodeGen::AttributeListType AttributeList;
-  CGM.ConstructAttributeList(CallInfo, 0, AttributeList);
+  CGM.ConstructAttributeList(CallInfo, TargetDecl, AttributeList);
   CI->setAttributes(llvm::AttrListPtr::get(AttributeList.begin(), 
                                            AttributeList.size()));  
   
diff --git a/lib/CodeGen/CGExpr.cpp b/lib/CodeGen/CGExpr.cpp
index 5da0de9..22a6a2d 100644
--- a/lib/CodeGen/CGExpr.cpp
+++ b/lib/CodeGen/CGExpr.cpp
@@ -966,29 +966,25 @@
 
 
 RValue CodeGenFunction::EmitCallExpr(const CallExpr *E) {
-  if (const ImplicitCastExpr *IcExpr = 
-      dyn_cast<const ImplicitCastExpr>(E->getCallee()))
-    if (const DeclRefExpr *DRExpr = 
-        dyn_cast<const DeclRefExpr>(IcExpr->getSubExpr()))
-      if (const FunctionDecl *FDecl = 
-          dyn_cast<const FunctionDecl>(DRExpr->getDecl()))
-        if (unsigned builtinID = FDecl->getBuiltinID(getContext()))
-          return EmitBuiltinExpr(FDecl, builtinID, E);
-
+  // Builtins never have block type.
   if (E->getCallee()->getType()->isBlockPointerType())
     return EmitBlockCallExpr(E);
 
+  const Decl *TargetDecl = 0;
+  if (const ImplicitCastExpr *IcExpr = 
+      dyn_cast<ImplicitCastExpr>(E->getCallee())) {
+    if (const DeclRefExpr *DRExpr = 
+        dyn_cast<DeclRefExpr>(IcExpr->getSubExpr())) {
+      TargetDecl = DRExpr->getDecl();
+      if (const FunctionDecl *FDecl = dyn_cast<FunctionDecl>(TargetDecl))
+        if (unsigned builtinID = FDecl->getBuiltinID(getContext()))
+          return EmitBuiltinExpr(FDecl, builtinID, E);
+    }
+  }
+
   llvm::Value *Callee = EmitScalarExpr(E->getCallee());
   return EmitCallExpr(Callee, E->getCallee()->getType(),
-                      E->arg_begin(), E->arg_end());
-}
-
-RValue CodeGenFunction::EmitCallExpr(Expr *FnExpr,
-                                     CallExpr::const_arg_iterator ArgBeg,
-                                     CallExpr::const_arg_iterator ArgEnd) {
-
-  llvm::Value *Callee = EmitScalarExpr(FnExpr);
-  return EmitCallExpr(Callee, FnExpr->getType(), ArgBeg, ArgEnd);
+                      E->arg_begin(), E->arg_end(), TargetDecl);
 }
 
 LValue CodeGenFunction::EmitBinaryOperatorLValue(const BinaryOperator *E) {
@@ -1108,7 +1104,8 @@
 
 RValue CodeGenFunction::EmitCallExpr(llvm::Value *Callee, QualType CalleeType, 
                                      CallExpr::const_arg_iterator ArgBeg,
-                                     CallExpr::const_arg_iterator ArgEnd) {
+                                     CallExpr::const_arg_iterator ArgEnd,
+                                     const Decl *TargetDecl) {
   // Get the actual function type. The callee type will always be a
   // pointer to function type or a block pointer type.
   QualType ResultType;
@@ -1127,5 +1124,5 @@
                                   I->getType()));
 
   return EmitCall(CGM.getTypes().getFunctionInfo(ResultType, Args), 
-                  Callee, Args);
+                  Callee, Args, TargetDecl);
 }
diff --git a/lib/CodeGen/CodeGenFunction.h b/lib/CodeGen/CodeGenFunction.h
index bc602f3..7072be8 100644
--- a/lib/CodeGen/CodeGenFunction.h
+++ b/lib/CodeGen/CodeGenFunction.h
@@ -618,18 +618,21 @@
   /// EmitCall - Generate a call of the given function, expecting the given
   /// result type, and using the given argument list which specifies both the
   /// LLVM arguments and the types they were derived from.
+  ///
+  /// \param TargetDecl - If given, the decl of the function in a
+  /// direct call; used to set attributes on the call (noreturn,
+  /// etc.).
   RValue EmitCall(const CGFunctionInfo &FnInfo,
                   llvm::Value *Callee,
-                  const CallArgList &Args);
+                  const CallArgList &Args,
+                  const Decl *TargetDecl = 0);
 
   RValue EmitCallExpr(const CallExpr *E);
 
-  RValue EmitCallExpr(Expr *FnExpr, CallExpr::const_arg_iterator ArgBeg,
-                      CallExpr::const_arg_iterator ArgEnd);
-
   RValue EmitCallExpr(llvm::Value *Callee, QualType FnType,
                       CallExpr::const_arg_iterator ArgBeg,
-                      CallExpr::const_arg_iterator ArgEnd);
+                      CallExpr::const_arg_iterator ArgEnd,
+                      const Decl *TargetDecl = 0);
 
   RValue EmitBuiltinExpr(const FunctionDecl *FD, 
                          unsigned BuiltinID, const CallExpr *E);
diff --git a/test/CodeGen/function-attributes.c b/test/CodeGen/function-attributes.c
index dacfdd9..ca16459 100644
--- a/test/CodeGen/function-attributes.c
+++ b/test/CodeGen/function-attributes.c
@@ -7,7 +7,7 @@
 // RUN: grep 'define zeroext i16 @f5(i32 %x) nounwind' %t &&
 // RUN: grep 'define void @f6(i16 signext %x) nounwind' %t &&
 // RUN: grep 'define void @f7(i16 zeroext %x) nounwind' %t &&
-// RUN: grep 'define void @f8() nounwind alwaysinline' %t
+// RUN: grep 'define void @f8() nounwind alwaysinline' %t &&
 
 signed char f0(int x) { return x; }
 
@@ -26,3 +26,14 @@
 void f7(unsigned short x) { }
 
 void __attribute__((always_inline)) f8(void) { }
+
+// RUN: grep 'call void @f9_t() noreturn' %t &&
+void __attribute__((noreturn)) f9_t(void);
+void f9(void) { f9_t(); }
+
+// FIXME: We should be setting nounwind on calls.
+// RUN: grep 'call i32 @f10_t() readnone' %t &&
+int __attribute__((const)) f10_t(void);
+int f10(void) { return f10_t(); }
+
+// RUN: true