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