[cfe-commits] r95436 - in /cfe/trunk: include/clang/AST/ include/clang/Basic/ lib/AST/ lib/CodeGen/ lib/Sema/ test/CodeGen/ test/Sema/
John McCall
rjmccall at apple.com
Fri Feb 5 13:31:56 PST 2010
Author: rjmccall
Date: Fri Feb 5 15:31:56 2010
New Revision: 95436
URL: http://llvm.org/viewvc/llvm-project?rev=95436&view=rev
Log:
Standardize the parsing of function type attributes in a way that
follows (as conservatively as possible) gcc's current behavior: attributes
written on return types that don't apply there are applied to the function
instead, etc. Only parse CC attributes as type attributes, not as decl attributes;
don't accepet noreturn as a decl attribute on ValueDecls, either (it still
needs to apply to other decls, like blocks). Consistently consume CC/noreturn
information throughout codegen; enforce this by removing their default values
in CodeGenTypes::getFunctionInfo().
Modified:
cfe/trunk/include/clang/AST/ASTContext.h
cfe/trunk/include/clang/AST/Type.h
cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td
cfe/trunk/lib/AST/ASTContext.cpp
cfe/trunk/lib/AST/Type.cpp
cfe/trunk/lib/CodeGen/CGBlocks.cpp
cfe/trunk/lib/CodeGen/CGCXX.cpp
cfe/trunk/lib/CodeGen/CGCall.cpp
cfe/trunk/lib/CodeGen/CGCall.h
cfe/trunk/lib/CodeGen/CGClass.cpp
cfe/trunk/lib/CodeGen/CGException.cpp
cfe/trunk/lib/CodeGen/CGExpr.cpp
cfe/trunk/lib/CodeGen/CGExprCXX.cpp
cfe/trunk/lib/CodeGen/CGObjC.cpp
cfe/trunk/lib/CodeGen/CGObjCGNU.cpp
cfe/trunk/lib/CodeGen/CGObjCMac.cpp
cfe/trunk/lib/CodeGen/CodeGenFunction.cpp
cfe/trunk/lib/CodeGen/CodeGenTypes.h
cfe/trunk/lib/Sema/Sema.h
cfe/trunk/lib/Sema/SemaChecking.cpp
cfe/trunk/lib/Sema/SemaDecl.cpp
cfe/trunk/lib/Sema/SemaDeclAttr.cpp
cfe/trunk/lib/Sema/SemaStmt.cpp
cfe/trunk/lib/Sema/SemaType.cpp
cfe/trunk/test/CodeGen/attributes.c
cfe/trunk/test/CodeGen/stdcall-fastcall.c
cfe/trunk/test/Sema/attr-noreturn.c
cfe/trunk/test/Sema/callingconv.c
cfe/trunk/test/Sema/stdcall-fastcall.c
Modified: cfe/trunk/include/clang/AST/ASTContext.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/AST/ASTContext.h?rev=95436&r1=95435&r2=95436&view=diff
==============================================================================
--- cfe/trunk/include/clang/AST/ASTContext.h (original)
+++ cfe/trunk/include/clang/AST/ASTContext.h Fri Feb 5 15:31:56 2010
@@ -971,6 +971,20 @@
NestedNameSpecifier *
getCanonicalNestedNameSpecifier(NestedNameSpecifier *NNS);
+ /// \brief Retrieves the canonical representation of the given
+ /// calling convention.
+ CallingConv getCanonicalCallConv(CallingConv CC) {
+ if (CC == CC_C)
+ return CC_Default;
+ return CC;
+ }
+
+ /// \brief Determines whether two calling conventions name the same
+ /// calling convention.
+ bool isSameCallConv(CallingConv lcc, CallingConv rcc) {
+ return (getCanonicalCallConv(lcc) == getCanonicalCallConv(rcc));
+ }
+
/// \brief Retrieves the "canonical" template name that refers to a
/// given template.
///
Modified: cfe/trunk/include/clang/AST/Type.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/AST/Type.h?rev=95436&r1=95435&r2=95436&view=diff
==============================================================================
--- cfe/trunk/include/clang/AST/Type.h (original)
+++ cfe/trunk/include/clang/AST/Type.h Fri Feb 5 15:31:56 2010
@@ -1761,6 +1761,8 @@
bool getNoReturnAttr() const { return NoReturn; }
CallingConv getCallConv() const { return (CallingConv)CallConv; }
+ static llvm::StringRef getNameForCallConv(CallingConv CC);
+
static bool classof(const Type *T) {
return T->getTypeClass() == FunctionNoProto ||
T->getTypeClass() == FunctionProto;
Modified: cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td?rev=95436&r1=95435&r2=95436&view=diff
==============================================================================
--- cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td (original)
+++ cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td Fri Feb 5 15:31:56 2010
@@ -741,13 +741,18 @@
"parameter or Objective-C method |function, method or block|"
"virtual method or class|function, method, or parameter|class|virtual method"
"|member}1 types">;
+def warn_function_attribute_wrong_type : Warning<
+ "%0 only applies to function types; type here is %1">;
def warn_gnu_inline_attribute_requires_inline : Warning<
"'gnu_inline' attribute requires function to be marked 'inline',"
" attribute ignored">;
+def err_cconv_change : Error<
+ "function declared '%0' here was previously declared "
+ "%select{'%2'|without calling convention}1">;
def err_cconv_knr : Error<
- "function with no prototype cannot use '%0' calling convention">;
+ "function with no prototype cannot use %0 calling convention">;
def err_cconv_varargs : Error<
- "variadic function cannot use '%0' calling convention">;
+ "variadic function cannot use %0 calling convention">;
def warn_impcast_vector_scalar : Warning<
"implicit cast turns vector to scalar: %0 to %1">,
Modified: cfe/trunk/lib/AST/ASTContext.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/AST/ASTContext.cpp?rev=95436&r1=95435&r2=95436&view=diff
==============================================================================
--- cfe/trunk/lib/AST/ASTContext.cpp (original)
+++ cfe/trunk/lib/AST/ASTContext.cpp Fri Feb 5 15:31:56 2010
@@ -1716,12 +1716,6 @@
return QualType(New, 0);
}
-static CallingConv getCanonicalCallingConv(CallingConv CC) {
- if (CC == CC_C)
- return CC_Default;
- return CC;
-}
-
/// getFunctionNoProtoType - Return a K&R style C function type like 'int()'.
///
QualType ASTContext::getFunctionNoProtoType(QualType ResultTy, bool NoReturn,
@@ -1738,9 +1732,9 @@
QualType Canonical;
if (!ResultTy.isCanonical() ||
- getCanonicalCallingConv(CallConv) != CallConv) {
+ getCanonicalCallConv(CallConv) != CallConv) {
Canonical = getFunctionNoProtoType(getCanonicalType(ResultTy), NoReturn,
- getCanonicalCallingConv(CallConv));
+ getCanonicalCallConv(CallConv));
// Get the new insert position for the node we care about.
FunctionNoProtoType *NewIP =
@@ -1784,7 +1778,7 @@
// If this type isn't canonical, get the canonical version of it.
// The exception spec is not part of the canonical type.
QualType Canonical;
- if (!isCanonical || getCanonicalCallingConv(CallConv) != CallConv) {
+ if (!isCanonical || getCanonicalCallConv(CallConv) != CallConv) {
llvm::SmallVector<QualType, 16> CanonicalArgs;
CanonicalArgs.reserve(NumArgs);
for (unsigned i = 0; i != NumArgs; ++i)
@@ -1794,7 +1788,7 @@
CanonicalArgs.data(), NumArgs,
isVariadic, TypeQuals, false,
false, 0, 0, NoReturn,
- getCanonicalCallingConv(CallConv));
+ getCanonicalCallConv(CallConv));
// Get the new insert position for the node we care about.
FunctionProtoType *NewIP =
@@ -4300,10 +4294,6 @@
return !mergeTypes(LHS, RHS).isNull();
}
-static bool isSameCallingConvention(CallingConv lcc, CallingConv rcc) {
- return (getCanonicalCallingConv(lcc) == getCanonicalCallingConv(rcc));
-}
-
QualType ASTContext::mergeFunctionTypes(QualType lhs, QualType rhs) {
const FunctionType *lbase = lhs->getAs<FunctionType>();
const FunctionType *rbase = rhs->getAs<FunctionType>();
@@ -4328,7 +4318,7 @@
CallingConv lcc = lbase->getCallConv();
CallingConv rcc = rbase->getCallConv();
// Compatible functions must have compatible calling conventions
- if (!isSameCallingConvention(lcc, rcc))
+ if (!isSameCallConv(lcc, rcc))
return QualType();
if (lproto && rproto) { // two C99 style function prototypes
Modified: cfe/trunk/lib/AST/Type.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/AST/Type.cpp?rev=95436&r1=95435&r2=95436&view=diff
==============================================================================
--- cfe/trunk/lib/AST/Type.cpp (original)
+++ cfe/trunk/lib/AST/Type.cpp Fri Feb 5 15:31:56 2010
@@ -810,6 +810,17 @@
}
}
+llvm::StringRef FunctionType::getNameForCallConv(CallingConv CC) {
+ switch (CC) {
+ case CC_Default: llvm_unreachable("no name for default cc");
+ default: return "";
+
+ case CC_C: return "cdecl";
+ case CC_X86StdCall: return "stdcall";
+ case CC_X86FastCall: return "fastcall";
+ }
+}
+
void FunctionProtoType::Profile(llvm::FoldingSetNodeID &ID, QualType Result,
arg_type_iterator ArgTys,
unsigned NumArgs, bool isVariadic,
Modified: cfe/trunk/lib/CodeGen/CGBlocks.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/CGBlocks.cpp?rev=95436&r1=95435&r2=95436&view=diff
==============================================================================
--- cfe/trunk/lib/CodeGen/CGBlocks.cpp (original)
+++ cfe/trunk/lib/CodeGen/CGBlocks.cpp Fri Feb 5 15:31:56 2010
@@ -496,10 +496,12 @@
// Load the function.
llvm::Value *Func = Builder.CreateLoad(FuncPtr, "tmp");
- QualType ResultType = FnType->getAs<FunctionType>()->getResultType();
+ const FunctionType *FuncTy = FnType->getAs<FunctionType>();
+ QualType ResultType = FuncTy->getResultType();
const CGFunctionInfo &FnInfo =
- CGM.getTypes().getFunctionInfo(ResultType, Args);
+ CGM.getTypes().getFunctionInfo(ResultType, Args, FuncTy->getCallConv(),
+ FuncTy->getNoReturnAttr());
// Cast the function pointer to the right type.
const llvm::Type *BlockFTy =
@@ -704,6 +706,8 @@
const FunctionType *BlockFunctionType = BExpr->getFunctionType();
QualType ResultType;
+ CallingConv CC = BlockFunctionType->getCallConv();
+ bool NoReturn = BlockFunctionType->getNoReturnAttr();
bool IsVariadic;
if (const FunctionProtoType *FTy =
dyn_cast<FunctionProtoType>(BlockFunctionType)) {
@@ -742,7 +746,7 @@
Args.push_back(std::make_pair(*i, (*i)->getType()));
const CGFunctionInfo &FI =
- CGM.getTypes().getFunctionInfo(ResultType, Args);
+ CGM.getTypes().getFunctionInfo(ResultType, Args, CC, NoReturn);
CodeGenTypes &Types = CGM.getTypes();
const llvm::FunctionType *LTy = Types.GetFunctionType(FI, IsVariadic);
@@ -867,7 +871,7 @@
Args.push_back(std::make_pair(Src, Src->getType()));
const CGFunctionInfo &FI =
- CGM.getTypes().getFunctionInfo(R, Args);
+ CGM.getTypes().getFunctionInfo(R, Args, CC_Default, false);
// FIXME: We'd like to put these into a mergable by content, with
// internal linkage.
@@ -948,7 +952,7 @@
Args.push_back(std::make_pair(Src, Src->getType()));
const CGFunctionInfo &FI =
- CGM.getTypes().getFunctionInfo(R, Args);
+ CGM.getTypes().getFunctionInfo(R, Args, CC_Default, false);
// FIXME: We'd like to put these into a mergable by content, with
// internal linkage.
@@ -1032,7 +1036,7 @@
Args.push_back(std::make_pair(Src, Src->getType()));
const CGFunctionInfo &FI =
- CGM.getTypes().getFunctionInfo(R, Args);
+ CGM.getTypes().getFunctionInfo(R, Args, CC_Default, false);
CodeGenTypes &Types = CGM.getTypes();
const llvm::FunctionType *LTy = Types.GetFunctionType(FI, false);
@@ -1095,7 +1099,7 @@
Args.push_back(std::make_pair(Src, Src->getType()));
const CGFunctionInfo &FI =
- CGM.getTypes().getFunctionInfo(R, Args);
+ CGM.getTypes().getFunctionInfo(R, Args, CC_Default, false);
CodeGenTypes &Types = CGM.getTypes();
const llvm::FunctionType *LTy = Types.GetFunctionType(FI, false);
Modified: cfe/trunk/lib/CodeGen/CGCXX.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/CGCXX.cpp?rev=95436&r1=95435&r2=95436&view=diff
==============================================================================
--- cfe/trunk/lib/CodeGen/CGCXX.cpp (original)
+++ cfe/trunk/lib/CodeGen/CGCXX.cpp Fri Feb 5 15:31:56 2010
@@ -165,7 +165,8 @@
GlobalDecl GD, bool Extern,
const CovariantThunkAdjustment &Adjustment) {
const CXXMethodDecl *MD = cast<CXXMethodDecl>(GD.getDecl());
- QualType ResultType = MD->getType()->getAs<FunctionType>()->getResultType();
+ const FunctionProtoType *FPT = MD->getType()->getAs<FunctionProtoType>();
+ QualType ResultType = FPT->getResultType();
FunctionArgList Args;
ImplicitParamDecl *ThisDecl =
@@ -190,7 +191,6 @@
StartFunction(FD, ResultType, Fn, Args, SourceLocation());
// generate body
- const FunctionProtoType *FPT = MD->getType()->getAs<FunctionProtoType>();
const llvm::Type *Ty =
CGM.getTypes().GetFunctionType(CGM.getTypes().getFunctionInfo(MD),
FPT->isVariadic());
@@ -232,7 +232,9 @@
CallArgs.push_back(std::make_pair(EmitCallArg(Arg, ArgType), ArgType));
}
- RValue RV = EmitCall(CGM.getTypes().getFunctionInfo(ResultType, CallArgs),
+ RValue RV = EmitCall(CGM.getTypes().getFunctionInfo(ResultType, CallArgs,
+ FPT->getCallConv(),
+ FPT->getNoReturnAttr()),
Callee, ReturnValueSlot(), CallArgs, MD);
if (ShouldAdjustReturnPointer && !Adjustment.ReturnAdjustment.isEmpty()) {
bool CanBeZero = !(ResultType->isReferenceType()
Modified: cfe/trunk/lib/CodeGen/CGCall.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/CGCall.cpp?rev=95436&r1=95435&r2=95436&view=diff
==============================================================================
--- cfe/trunk/lib/CodeGen/CGCall.cpp (original)
+++ cfe/trunk/lib/CodeGen/CGCall.cpp Fri Feb 5 15:31:56 2010
@@ -33,12 +33,19 @@
// FIXME: Use iterator and sidestep silly type array creation.
+static unsigned ClangCallConvToLLVMCallConv(CallingConv CC) {
+ switch (CC) {
+ default: return llvm::CallingConv::C;
+ case CC_X86StdCall: return llvm::CallingConv::X86_StdCall;
+ case CC_X86FastCall: return llvm::CallingConv::X86_FastCall;
+ }
+}
+
const
CGFunctionInfo &CodeGenTypes::getFunctionInfo(const FunctionNoProtoType *FTNP) {
- // FIXME: Set calling convention correctly, it needs to be associated with the
- // type somehow.
return getFunctionInfo(FTNP->getResultType(),
- llvm::SmallVector<QualType, 16>(), 0);
+ llvm::SmallVector<QualType, 16>(),
+ FTNP->getCallConv(), FTNP->getNoReturnAttr());
}
const
@@ -47,20 +54,19 @@
// FIXME: Kill copy.
for (unsigned i = 0, e = FTP->getNumArgs(); i != e; ++i)
ArgTys.push_back(FTP->getArgType(i));
- // FIXME: Set calling convention correctly, it needs to be associated with the
- // type somehow.
- return getFunctionInfo(FTP->getResultType(), ArgTys, 0);
+ return getFunctionInfo(FTP->getResultType(), ArgTys,
+ FTP->getCallConv(), FTP->getNoReturnAttr());
}
-static unsigned getCallingConventionForDecl(const Decl *D) {
+static CallingConv getCallingConventionForDecl(const Decl *D) {
// Set the appropriate calling convention for the Function.
if (D->hasAttr<StdCallAttr>())
- return llvm::CallingConv::X86_StdCall;
+ return CC_X86StdCall;
if (D->hasAttr<FastCallAttr>())
- return llvm::CallingConv::X86_FastCall;
+ return CC_X86FastCall;
- return llvm::CallingConv::C;
+ return CC_C;
}
const CGFunctionInfo &CodeGenTypes::getFunctionInfo(const CXXRecordDecl *RD,
@@ -75,7 +81,8 @@
// FIXME: Set calling convention correctly, it needs to be associated with the
// type somehow.
- return getFunctionInfo(FTP->getResultType(), ArgTys, 0);
+ return getFunctionInfo(FTP->getResultType(), ArgTys,
+ FTP->getCallConv(), FTP->getNoReturnAttr());
}
const CGFunctionInfo &CodeGenTypes::getFunctionInfo(const CXXMethodDecl *MD) {
@@ -87,8 +94,8 @@
const FunctionProtoType *FTP = MD->getType()->getAs<FunctionProtoType>();
for (unsigned i = 0, e = FTP->getNumArgs(); i != e; ++i)
ArgTys.push_back(FTP->getArgType(i));
- return getFunctionInfo(FTP->getResultType(), ArgTys,
- getCallingConventionForDecl(MD));
+ return getFunctionInfo(FTP->getResultType(), ArgTys, FTP->getCallConv(),
+ FTP->getNoReturnAttr());
}
const CGFunctionInfo &CodeGenTypes::getFunctionInfo(const CXXConstructorDecl *D,
@@ -105,8 +112,8 @@
const FunctionProtoType *FTP = D->getType()->getAs<FunctionProtoType>();
for (unsigned i = 0, e = FTP->getNumArgs(); i != e; ++i)
ArgTys.push_back(FTP->getArgType(i));
- return getFunctionInfo(FTP->getResultType(), ArgTys,
- getCallingConventionForDecl(D));
+ return getFunctionInfo(FTP->getResultType(), ArgTys, FTP->getCallConv(),
+ FTP->getNoReturnAttr());
}
const CGFunctionInfo &CodeGenTypes::getFunctionInfo(const CXXDestructorDecl *D,
@@ -123,8 +130,8 @@
const FunctionProtoType *FTP = D->getType()->getAs<FunctionProtoType>();
for (unsigned i = 0, e = FTP->getNumArgs(); i != e; ++i)
ArgTys.push_back(FTP->getArgType(i));
- return getFunctionInfo(FTP->getResultType(), ArgTys,
- getCallingConventionForDecl(D));
+ return getFunctionInfo(FTP->getResultType(), ArgTys, FTP->getCallConv(),
+ FTP->getNoReturnAttr());
}
const CGFunctionInfo &CodeGenTypes::getFunctionInfo(const FunctionDecl *FD) {
@@ -132,19 +139,19 @@
if (MD->isInstance())
return getFunctionInfo(MD);
- unsigned CallingConvention = getCallingConventionForDecl(FD);
const FunctionType *FTy = FD->getType()->getAs<FunctionType>();
if (const FunctionNoProtoType *FNTP = dyn_cast<FunctionNoProtoType>(FTy))
return getFunctionInfo(FNTP->getResultType(),
llvm::SmallVector<QualType, 16>(),
- CallingConvention);
+ FNTP->getCallConv(), FNTP->getNoReturnAttr());
const FunctionProtoType *FPT = cast<FunctionProtoType>(FTy);
llvm::SmallVector<QualType, 16> ArgTys;
// FIXME: Kill copy.
for (unsigned i = 0, e = FPT->getNumArgs(); i != e; ++i)
ArgTys.push_back(FPT->getArgType(i));
- return getFunctionInfo(FPT->getResultType(), ArgTys, CallingConvention);
+ return getFunctionInfo(FPT->getResultType(), ArgTys,
+ FPT->getCallConv(), FPT->getNoReturnAttr());
}
const CGFunctionInfo &CodeGenTypes::getFunctionInfo(const ObjCMethodDecl *MD) {
@@ -156,37 +163,43 @@
e = MD->param_end(); i != e; ++i)
ArgTys.push_back((*i)->getType());
return getFunctionInfo(MD->getResultType(), ArgTys,
- getCallingConventionForDecl(MD));
+ getCallingConventionForDecl(MD),
+ /*NoReturn*/ false);
}
const CGFunctionInfo &CodeGenTypes::getFunctionInfo(QualType ResTy,
const CallArgList &Args,
- unsigned CallingConvention){
+ CallingConv CC,
+ bool NoReturn) {
// FIXME: Kill copy.
llvm::SmallVector<QualType, 16> ArgTys;
for (CallArgList::const_iterator i = Args.begin(), e = Args.end();
i != e; ++i)
ArgTys.push_back(i->second);
- return getFunctionInfo(ResTy, ArgTys, CallingConvention);
+ return getFunctionInfo(ResTy, ArgTys, CC, NoReturn);
}
const CGFunctionInfo &CodeGenTypes::getFunctionInfo(QualType ResTy,
const FunctionArgList &Args,
- unsigned CallingConvention){
+ CallingConv CC,
+ bool NoReturn) {
// FIXME: Kill copy.
llvm::SmallVector<QualType, 16> ArgTys;
for (FunctionArgList::const_iterator i = Args.begin(), e = Args.end();
i != e; ++i)
ArgTys.push_back(i->second);
- return getFunctionInfo(ResTy, ArgTys, CallingConvention);
+ return getFunctionInfo(ResTy, ArgTys, CC, NoReturn);
}
const CGFunctionInfo &CodeGenTypes::getFunctionInfo(QualType ResTy,
const llvm::SmallVector<QualType, 16> &ArgTys,
- unsigned CallingConvention){
+ CallingConv CallConv,
+ bool NoReturn) {
+ unsigned CC = ClangCallConvToLLVMCallConv(CallConv);
+
// Lookup or create unique function info.
llvm::FoldingSetNodeID ID;
- CGFunctionInfo::Profile(ID, CallingConvention, ResTy,
+ CGFunctionInfo::Profile(ID, CC, NoReturn, ResTy,
ArgTys.begin(), ArgTys.end());
void *InsertPos = 0;
@@ -195,7 +208,7 @@
return *FI;
// Construct the function info.
- FI = new CGFunctionInfo(CallingConvention, ResTy, ArgTys);
+ FI = new CGFunctionInfo(CC, NoReturn, ResTy, ArgTys);
FunctionInfos.InsertNode(FI, InsertPos);
// Compute ABI information.
@@ -205,10 +218,12 @@
}
CGFunctionInfo::CGFunctionInfo(unsigned _CallingConvention,
+ bool _NoReturn,
QualType ResTy,
const llvm::SmallVector<QualType, 16> &ArgTys)
: CallingConvention(_CallingConvention),
- EffectiveCallingConvention(_CallingConvention)
+ EffectiveCallingConvention(_CallingConvention),
+ NoReturn(_NoReturn)
{
NumArgs = ArgTys.size();
Args = new ArgInfo[1 + NumArgs];
@@ -490,6 +505,9 @@
CallingConv = FI.getEffectiveCallingConvention();
+ if (FI.isNoReturn())
+ FuncAttrs |= llvm::Attribute::NoReturn;
+
// FIXME: handle sseregparm someday...
if (TargetDecl) {
if (TargetDecl->hasAttr<NoThrowAttr>())
Modified: cfe/trunk/lib/CodeGen/CGCall.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/CGCall.h?rev=95436&r1=95435&r2=95436&view=diff
==============================================================================
--- cfe/trunk/lib/CodeGen/CGCall.h (original)
+++ cfe/trunk/lib/CodeGen/CGCall.h Fri Feb 5 15:31:56 2010
@@ -69,6 +69,9 @@
/// depend on the ABI.
unsigned EffectiveCallingConvention;
+ /// Whether this function is noreturn.
+ bool NoReturn;
+
unsigned NumArgs;
ArgInfo *Args;
@@ -77,6 +80,7 @@
typedef ArgInfo *arg_iterator;
CGFunctionInfo(unsigned CallingConvention,
+ bool NoReturn,
QualType ResTy,
const llvm::SmallVector<QualType, 16> &ArgTys);
~CGFunctionInfo() { delete[] Args; }
@@ -88,6 +92,8 @@
unsigned arg_size() const { return NumArgs; }
+ bool isNoReturn() const { return NoReturn; }
+
/// getCallingConvention - Return the user specified calling
/// convention.
unsigned getCallingConvention() const { return CallingConvention; }
@@ -108,6 +114,7 @@
void Profile(llvm::FoldingSetNodeID &ID) {
ID.AddInteger(getCallingConvention());
+ ID.AddBoolean(NoReturn);
getReturnType().Profile(ID);
for (arg_iterator it = arg_begin(), ie = arg_end(); it != ie; ++it)
it->type.Profile(ID);
@@ -115,10 +122,12 @@
template<class Iterator>
static void Profile(llvm::FoldingSetNodeID &ID,
unsigned CallingConvention,
+ bool NoReturn,
QualType ResTy,
Iterator begin,
Iterator end) {
ID.AddInteger(CallingConvention);
+ ID.AddBoolean(NoReturn);
ResTy.Profile(ID);
for (; begin != end; ++begin)
begin->Profile(ID);
Modified: cfe/trunk/lib/CodeGen/CGClass.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/CGClass.cpp?rev=95436&r1=95435&r2=95436&view=diff
==============================================================================
--- cfe/trunk/lib/CodeGen/CGClass.cpp (original)
+++ cfe/trunk/lib/CodeGen/CGClass.cpp Fri Feb 5 15:31:56 2010
@@ -327,9 +327,9 @@
// Push the Src ptr.
CallArgs.push_back(std::make_pair(RValue::get(Src),
BaseCopyCtor->getParamDecl(0)->getType()));
- QualType ResultType =
- BaseCopyCtor->getType()->getAs<FunctionType>()->getResultType();
- EmitCall(CGM.getTypes().getFunctionInfo(ResultType, CallArgs),
+ const FunctionProtoType *FPT
+ = BaseCopyCtor->getType()->getAs<FunctionProtoType>();
+ EmitCall(CGM.getTypes().getFunctionInfo(CallArgs, FPT),
Callee, ReturnValueSlot(), CallArgs, BaseCopyCtor);
}
EmitBlock(ContinueBlock);
@@ -412,8 +412,7 @@
RValue SrcValue = SrcTy->isReferenceType() ? RValue::get(Src) :
RValue::getAggregate(Src);
CallArgs.push_back(std::make_pair(SrcValue, SrcTy));
- QualType ResultType = MD->getType()->getAs<FunctionType>()->getResultType();
- EmitCall(CGM.getTypes().getFunctionInfo(ResultType, CallArgs),
+ EmitCall(CGM.getTypes().getFunctionInfo(CallArgs, FPT),
Callee, ReturnValueSlot(), CallArgs, MD);
}
EmitBlock(ContinueBlock);
@@ -503,9 +502,9 @@
// Push the Src ptr.
CallArgs.push_back(std::make_pair(RValue::get(Src),
BaseCopyCtor->getParamDecl(0)->getType()));
- QualType ResultType =
- BaseCopyCtor->getType()->getAs<FunctionType>()->getResultType();
- EmitCall(CGM.getTypes().getFunctionInfo(ResultType, CallArgs),
+ const FunctionProtoType *FPT =
+ BaseCopyCtor->getType()->getAs<FunctionProtoType>();
+ EmitCall(CGM.getTypes().getFunctionInfo(CallArgs, FPT),
Callee, ReturnValueSlot(), CallArgs, BaseCopyCtor);
}
}
@@ -550,9 +549,7 @@
RValue SrcValue = SrcTy->isReferenceType() ? RValue::get(Src) :
RValue::getAggregate(Src);
CallArgs.push_back(std::make_pair(SrcValue, SrcTy));
- QualType ResultType =
- MD->getType()->getAs<FunctionType>()->getResultType();
- EmitCall(CGM.getTypes().getFunctionInfo(ResultType, CallArgs),
+ EmitCall(CGM.getTypes().getFunctionInfo(CallArgs, FPT),
Callee, ReturnValueSlot(), CallArgs, MD);
}
@@ -1197,7 +1194,8 @@
llvm::SmallString<16> Name;
llvm::raw_svector_ostream(Name) << "__tcf_" << (++UniqueAggrDestructorCount);
QualType R = getContext().VoidTy;
- const CGFunctionInfo &FI = CGM.getTypes().getFunctionInfo(R, Args);
+ const CGFunctionInfo &FI
+ = CGM.getTypes().getFunctionInfo(R, Args, CC_Default, false);
const llvm::FunctionType *FTy = CGM.getTypes().GetFunctionType(FI, false);
llvm::Function *Fn =
llvm::Function::Create(FTy, llvm::GlobalValue::InternalLinkage,
Modified: cfe/trunk/lib/CodeGen/CGException.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/CGException.cpp?rev=95436&r1=95435&r2=95436&view=diff
==============================================================================
--- cfe/trunk/lib/CodeGen/CGException.cpp (original)
+++ cfe/trunk/lib/CodeGen/CGException.cpp Fri Feb 5 15:31:56 2010
@@ -194,9 +194,9 @@
// Push the Src ptr.
CallArgs.push_back(std::make_pair(RValue::get(Src),
CopyCtor->getParamDecl(0)->getType()));
- QualType ResultType =
- CopyCtor->getType()->getAs<FunctionType>()->getResultType();
- CGF.EmitCall(CGF.CGM.getTypes().getFunctionInfo(ResultType, CallArgs),
+ const FunctionProtoType *FPT
+ = CopyCtor->getType()->getAs<FunctionProtoType>();
+ CGF.EmitCall(CGF.CGM.getTypes().getFunctionInfo(CallArgs, FPT),
Callee, ReturnValueSlot(), CallArgs, CopyCtor);
CGF.setInvokeDest(PrevLandingPad);
} else
@@ -244,9 +244,10 @@
// Push the Src ptr.
CallArgs.push_back(std::make_pair(RValue::get(Src),
CopyCtor->getParamDecl(0)->getType()));
- QualType ResultType =
- CopyCtor->getType()->getAs<FunctionType>()->getResultType();
- CGF.EmitCall(CGF.CGM.getTypes().getFunctionInfo(ResultType, CallArgs),
+
+ const FunctionProtoType *FPT
+ = CopyCtor->getType()->getAs<FunctionProtoType>();
+ CGF.EmitCall(CGF.CGM.getTypes().getFunctionInfo(CallArgs, FPT),
Callee, ReturnValueSlot(), CallArgs, CopyCtor);
} else
llvm_unreachable("uncopyable object");
Modified: cfe/trunk/lib/CodeGen/CGExpr.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/CGExpr.cpp?rev=95436&r1=95435&r2=95436&view=diff
==============================================================================
--- cfe/trunk/lib/CodeGen/CGExpr.cpp (original)
+++ cfe/trunk/lib/CodeGen/CGExpr.cpp Fri Feb 5 15:31:56 2010
@@ -1853,14 +1853,6 @@
return LValue::MakeAddr(RV.getAggregateAddr(), MakeQualifiers(E->getType()));
}
-static unsigned ClangCallConvToLLVMCallConv(CallingConv CC) {
- switch (CC) {
- default: return llvm::CallingConv::C;
- case CC_X86StdCall: return llvm::CallingConv::X86_StdCall;
- case CC_X86FastCall: return llvm::CallingConv::X86_FastCall;
- }
-}
-
RValue CodeGenFunction::EmitCall(QualType CalleeType, llvm::Value *Callee,
ReturnValueSlot ReturnValue,
CallExpr::const_arg_iterator ArgBeg,
@@ -1873,16 +1865,14 @@
CalleeType = getContext().getCanonicalType(CalleeType);
- QualType FnType = cast<PointerType>(CalleeType)->getPointeeType();
- QualType ResultType = cast<FunctionType>(FnType)->getResultType();
+ const FunctionType *FnType
+ = cast<FunctionType>(cast<PointerType>(CalleeType)->getPointeeType());
+ QualType ResultType = FnType->getResultType();
CallArgList Args;
EmitCallArgs(Args, dyn_cast<FunctionProtoType>(FnType), ArgBeg, ArgEnd);
- unsigned CallingConvention =
- ClangCallConvToLLVMCallConv(FnType->getAs<FunctionType>()->getCallConv());
- return EmitCall(CGM.getTypes().getFunctionInfo(ResultType, Args,
- CallingConvention),
+ return EmitCall(CGM.getTypes().getFunctionInfo(Args, FnType),
Callee, ReturnValue, Args, TargetDecl);
}
Modified: cfe/trunk/lib/CodeGen/CGExprCXX.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/CGExprCXX.cpp?rev=95436&r1=95435&r2=95436&view=diff
==============================================================================
--- cfe/trunk/lib/CodeGen/CGExprCXX.cpp (original)
+++ cfe/trunk/lib/CodeGen/CGExprCXX.cpp Fri Feb 5 15:31:56 2010
@@ -42,8 +42,10 @@
// And the rest of the call args
EmitCallArgs(Args, FPT, ArgBeg, ArgEnd);
- QualType ResultType = MD->getType()->getAs<FunctionType>()->getResultType();
- return EmitCall(CGM.getTypes().getFunctionInfo(ResultType, Args), Callee,
+ QualType ResultType = FPT->getResultType();
+ return EmitCall(CGM.getTypes().getFunctionInfo(ResultType, Args,
+ FPT->getCallConv(),
+ FPT->getNoReturnAttr()), Callee,
ReturnValue, Args, MD);
}
@@ -244,8 +246,8 @@
// And the rest of the call args
EmitCallArgs(Args, FPT, E->arg_begin(), E->arg_end());
- QualType ResultType = BO->getType()->getAs<FunctionType>()->getResultType();
- return EmitCall(CGM.getTypes().getFunctionInfo(ResultType, Args), Callee,
+ const FunctionType *BO_FPT = BO->getType()->getAs<FunctionProtoType>();
+ return EmitCall(CGM.getTypes().getFunctionInfo(Args, BO_FPT), Callee,
ReturnValue, Args);
}
@@ -542,7 +544,7 @@
// Emit the call to new.
RValue RV =
- EmitCall(CGM.getTypes().getFunctionInfo(NewFTy->getResultType(), NewArgs),
+ EmitCall(CGM.getTypes().getFunctionInfo(NewArgs, NewFTy),
CGM.GetAddrOfFunction(NewFD), ReturnValueSlot(), NewArgs, NewFD);
// If an allocation function is declared with an empty exception specification
@@ -686,8 +688,7 @@
DeleteArgs.push_back(std::make_pair(RValue::get(Size), SizeTy));
// Emit the call to delete.
- EmitCall(CGM.getTypes().getFunctionInfo(DeleteFTy->getResultType(),
- DeleteArgs),
+ EmitCall(CGM.getTypes().getFunctionInfo(DeleteArgs, DeleteFTy),
CGM.GetAddrOfFunction(DeleteFD), ReturnValueSlot(),
DeleteArgs, DeleteFD);
}
Modified: cfe/trunk/lib/CodeGen/CGObjC.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/CGObjC.cpp?rev=95436&r1=95435&r2=95436&view=diff
==============================================================================
--- cfe/trunk/lib/CodeGen/CGObjC.cpp (original)
+++ cfe/trunk/lib/CodeGen/CGObjC.cpp Fri Feb 5 15:31:56 2010
@@ -190,7 +190,8 @@
Args.push_back(std::make_pair(RValue::get(True), getContext().BoolTy));
// FIXME: We shouldn't need to get the function info here, the
// runtime already should have computed it to build the function.
- RValue RV = EmitCall(Types.getFunctionInfo(PD->getType(), Args),
+ RValue RV = EmitCall(Types.getFunctionInfo(PD->getType(), Args,
+ CC_Default, false),
GetPropertyFn, ReturnValueSlot(), Args);
// We need to fix the type here. Ivars with copy & retain are
// always objects so we don't need to worry about complex or
@@ -278,7 +279,8 @@
getContext().BoolTy));
// FIXME: We shouldn't need to get the function info here, the runtime
// already should have computed it to build the function.
- EmitCall(Types.getFunctionInfo(getContext().VoidTy, Args), SetPropertyFn,
+ EmitCall(Types.getFunctionInfo(getContext().VoidTy, Args,
+ CC_Default, false), SetPropertyFn,
ReturnValueSlot(), Args);
} else {
// FIXME: Find a clean way to avoid AST node creation.
@@ -554,7 +556,8 @@
getContext().getObjCIdType()));
// FIXME: We shouldn't need to get the function info here, the runtime already
// should have computed it to build the function.
- EmitCall(CGM.getTypes().getFunctionInfo(getContext().VoidTy, Args2),
+ EmitCall(CGM.getTypes().getFunctionInfo(getContext().VoidTy, Args2,
+ CC_Default, false),
EnumerationMutationFn, ReturnValueSlot(), Args2);
EmitBlock(WasNotMutated);
Modified: cfe/trunk/lib/CodeGen/CGObjCGNU.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/CGObjCGNU.cpp?rev=95436&r1=95435&r2=95436&view=diff
==============================================================================
--- cfe/trunk/lib/CodeGen/CGObjCGNU.cpp (original)
+++ cfe/trunk/lib/CodeGen/CGObjCGNU.cpp Fri Feb 5 15:31:56 2010
@@ -464,7 +464,8 @@
ActualArgs.insert(ActualArgs.end(), CallArgs.begin(), CallArgs.end());
CodeGenTypes &Types = CGM.getTypes();
- const CGFunctionInfo &FnInfo = Types.getFunctionInfo(ResultType, ActualArgs);
+ const CGFunctionInfo &FnInfo = Types.getFunctionInfo(ResultType, ActualArgs,
+ CC_Default, false);
const llvm::FunctionType *impType =
Types.GetFunctionType(FnInfo, Method ? Method->isVariadic() : false);
@@ -571,7 +572,8 @@
ActualArgs.insert(ActualArgs.end(), CallArgs.begin(), CallArgs.end());
CodeGenTypes &Types = CGM.getTypes();
- const CGFunctionInfo &FnInfo = Types.getFunctionInfo(ResultType, ActualArgs);
+ const CGFunctionInfo &FnInfo = Types.getFunctionInfo(ResultType, ActualArgs,
+ CC_Default, false);
const llvm::FunctionType *impType =
Types.GetFunctionType(FnInfo, Method ? Method->isVariadic() : false);
@@ -1686,7 +1688,8 @@
llvm::SmallVector<QualType,16> Params;
Params.push_back(ASTIdTy);
const llvm::FunctionType *FTy =
- Types.GetFunctionType(Types.getFunctionInfo(Ctx.VoidTy, Params), false);
+ Types.GetFunctionType(Types.getFunctionInfo(Ctx.VoidTy, Params,
+ CC_Default, false), false);
return CGM.CreateRuntimeFunction(FTy, "objc_enumerationMutation");
}
Modified: cfe/trunk/lib/CodeGen/CGObjCMac.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/CGObjCMac.cpp?rev=95436&r1=95435&r2=95436&view=diff
==============================================================================
--- cfe/trunk/lib/CodeGen/CGObjCMac.cpp (original)
+++ cfe/trunk/lib/CodeGen/CGObjCMac.cpp Fri Feb 5 15:31:56 2010
@@ -305,7 +305,8 @@
Params.push_back(Ctx.LongTy);
Params.push_back(Ctx.BoolTy);
const llvm::FunctionType *FTy =
- Types.GetFunctionType(Types.getFunctionInfo(IdType, Params), false);
+ Types.GetFunctionType(Types.getFunctionInfo(IdType, Params,
+ CC_Default, false), false);
return CGM.CreateRuntimeFunction(FTy, "objc_getProperty");
}
@@ -323,7 +324,8 @@
Params.push_back(Ctx.BoolTy);
Params.push_back(Ctx.BoolTy);
const llvm::FunctionType *FTy =
- Types.GetFunctionType(Types.getFunctionInfo(Ctx.VoidTy, Params), false);
+ Types.GetFunctionType(Types.getFunctionInfo(Ctx.VoidTy, Params,
+ CC_Default, false), false);
return CGM.CreateRuntimeFunction(FTy, "objc_setProperty");
}
@@ -334,7 +336,8 @@
llvm::SmallVector<QualType,16> Params;
Params.push_back(Ctx.getObjCIdType());
const llvm::FunctionType *FTy =
- Types.GetFunctionType(Types.getFunctionInfo(Ctx.VoidTy, Params), false);
+ Types.GetFunctionType(Types.getFunctionInfo(Ctx.VoidTy, Params,
+ CC_Default, false), false);
return CGM.CreateRuntimeFunction(FTy, "objc_enumerationMutation");
}
@@ -1554,7 +1557,8 @@
ActualArgs.insert(ActualArgs.end(), CallArgs.begin(), CallArgs.end());
CodeGenTypes &Types = CGM.getTypes();
- const CGFunctionInfo &FnInfo = Types.getFunctionInfo(ResultType, ActualArgs);
+ const CGFunctionInfo &FnInfo = Types.getFunctionInfo(ResultType, ActualArgs,
+ CC_Default, false);
const llvm::FunctionType *FTy =
Types.GetFunctionType(FnInfo, Method ? Method->isVariadic() : false);
@@ -5089,7 +5093,8 @@
// FIXME. This is too much work to get the ABI-specific result type needed to
// find the message name.
const CGFunctionInfo &FnInfo = Types.getFunctionInfo(ResultType,
- llvm::SmallVector<QualType, 16>());
+ llvm::SmallVector<QualType, 16>(),
+ CC_Default, false);
llvm::Constant *Fn = 0;
std::string Name("\01l_");
if (CGM.ReturnTypeUsesSret(FnInfo)) {
@@ -5163,7 +5168,8 @@
ActualArgs.push_back(std::make_pair(RValue::get(Arg1),
ObjCTypes.MessageRefCPtrTy));
ActualArgs.insert(ActualArgs.end(), CallArgs.begin(), CallArgs.end());
- const CGFunctionInfo &FnInfo1 = Types.getFunctionInfo(ResultType, ActualArgs);
+ const CGFunctionInfo &FnInfo1 = Types.getFunctionInfo(ResultType, ActualArgs,
+ CC_Default, false);
llvm::Value *Callee = CGF.Builder.CreateStructGEP(Arg1, 0);
Callee = CGF.Builder.CreateLoad(Callee);
const llvm::FunctionType *FTy = Types.GetFunctionType(FnInfo1, true);
Modified: cfe/trunk/lib/CodeGen/CodeGenFunction.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/CodeGenFunction.cpp?rev=95436&r1=95435&r2=95436&view=diff
==============================================================================
--- cfe/trunk/lib/CodeGen/CodeGenFunction.cpp (original)
+++ cfe/trunk/lib/CodeGen/CodeGenFunction.cpp Fri Feb 5 15:31:56 2010
@@ -196,7 +196,9 @@
}
// FIXME: Leaked.
- CurFnInfo = &CGM.getTypes().getFunctionInfo(FnRetTy, Args);
+ // CC info is ignored, hopefully?
+ CurFnInfo = &CGM.getTypes().getFunctionInfo(FnRetTy, Args,
+ CC_Default, false);
if (RetTy->isVoidType()) {
// Void type; nothing to return.
Modified: cfe/trunk/lib/CodeGen/CodeGenTypes.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/CodeGenTypes.h?rev=95436&r1=95435&r2=95436&view=diff
==============================================================================
--- cfe/trunk/lib/CodeGen/CodeGenTypes.h (original)
+++ cfe/trunk/lib/CodeGen/CodeGenTypes.h Fri Feb 5 15:31:56 2010
@@ -198,6 +198,12 @@
const CGFunctionInfo &getFunctionInfo(const CXXDestructorDecl *D,
CXXDtorType Type);
+ const CGFunctionInfo &getFunctionInfo(const CallArgList &Args,
+ const FunctionType *Ty) {
+ return getFunctionInfo(Ty->getResultType(), Args,
+ Ty->getCallConv(), Ty->getNoReturnAttr());
+ }
+
// getFunctionInfo - Get the function info for a member function.
const CGFunctionInfo &getFunctionInfo(const CXXRecordDecl *RD,
const FunctionProtoType *FTP);
@@ -207,13 +213,16 @@
/// specified, the "C" calling convention will be used.
const CGFunctionInfo &getFunctionInfo(QualType ResTy,
const CallArgList &Args,
- unsigned CallingConvention = 0);
+ CallingConv CC,
+ bool NoReturn);
const CGFunctionInfo &getFunctionInfo(QualType ResTy,
const FunctionArgList &Args,
- unsigned CallingConvention = 0);
+ CallingConv CC,
+ bool NoReturn);
const CGFunctionInfo &getFunctionInfo(QualType RetTy,
const llvm::SmallVector<QualType, 16> &ArgTys,
- unsigned CallingConvention = 0);
+ CallingConv CC,
+ bool NoReturn);
public: // These are internal details of CGT that shouldn't be used externally.
/// addFieldInfo - Assign field number to field FD.
Modified: cfe/trunk/lib/Sema/Sema.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/Sema.h?rev=95436&r1=95435&r2=95436&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/Sema.h (original)
+++ cfe/trunk/lib/Sema/Sema.h Fri Feb 5 15:31:56 2010
@@ -559,10 +559,8 @@
//===--------------------------------------------------------------------===//
// Type Analysis / Processing: SemaType.cpp.
//
+
QualType adjustParameterType(QualType T);
- void ProcessTypeAttributeList(QualType &Result, const AttributeList *AL,
- bool HandleCallConvAttributes = false,
- bool HandleOnlyCallConv = false);
QualType BuildPointerType(QualType T, unsigned Quals,
SourceLocation Loc, DeclarationName Entity);
QualType BuildReferenceType(QualType T, bool LValueRef, unsigned Quals,
Modified: cfe/trunk/lib/Sema/SemaChecking.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaChecking.cpp?rev=95436&r1=95435&r2=95436&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/SemaChecking.cpp (original)
+++ cfe/trunk/lib/Sema/SemaChecking.cpp Fri Feb 5 15:31:56 2010
@@ -2500,7 +2500,8 @@
return;
if (FD->getResultType()->isVoidType())
ReturnsVoid = true;
- if (FD->hasAttr<NoReturnAttr>())
+ if (FD->hasAttr<NoReturnAttr>() ||
+ FD->getType()->getAs<FunctionType>()->getNoReturnAttr())
HasNoReturn = true;
} else if (ObjCMethodDecl *MD = dyn_cast<ObjCMethodDecl>(D)) {
if (MD->getResultType()->isVoidType())
Modified: cfe/trunk/lib/Sema/SemaDecl.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaDecl.cpp?rev=95436&r1=95435&r2=95436&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/SemaDecl.cpp (original)
+++ cfe/trunk/lib/Sema/SemaDecl.cpp Fri Feb 5 15:31:56 2010
@@ -908,14 +908,6 @@
return Sema::CXXCopyAssignment;
}
-static const char* getCallConvName(CallingConv CC) {
- switch (CC) {
- default: return "cdecl";
- case CC_X86StdCall: return "stdcall";
- case CC_X86FastCall: return "fastcall";
- }
-}
-
/// MergeFunctionDecl - We just parsed a function 'New' from
/// declarator D which has the same name and scope as a previous
/// declaration 'Old'. Figure out how to resolve this situation,
@@ -992,14 +984,25 @@
NewQType = Context.getCallConvType(NewQType, OldType->getCallConv());
New->setType(NewQType);
NewQType = Context.getCanonicalType(NewQType);
- } else if (OldType->getCallConv() != NewType->getCallConv()) {
+ } else if (!Context.isSameCallConv(OldType->getCallConv(),
+ NewType->getCallConv())) {
// Calling conventions really aren't compatible, so complain.
- Diag(New->getLocation(), diag::err_attributes_are_not_compatible)
- << getCallConvName(NewType->getCallConv())
- << getCallConvName(OldType->getCallConv());
+ Diag(New->getLocation(), diag::err_cconv_change)
+ << FunctionType::getNameForCallConv(NewType->getCallConv())
+ << (OldType->getCallConv() == CC_Default)
+ << (OldType->getCallConv() == CC_Default ? "" :
+ FunctionType::getNameForCallConv(OldType->getCallConv()));
+ Diag(Old->getLocation(), diag::note_previous_declaration);
return true;
}
+ // FIXME: diagnose the other way around?
+ if (OldType->getNoReturnAttr() && !NewType->getNoReturnAttr()) {
+ NewQType = Context.getNoReturnType(NewQType);
+ New->setType(NewQType);
+ assert(NewQType.isCanonical());
+ }
+
if (getLangOptions().CPlusPlus) {
// (C++98 13.1p2):
// Certain function declarations cannot be overloaded:
@@ -4383,7 +4386,7 @@
}
if (Context.BuiltinInfo.isNoReturn(BuiltinID))
- FD->addAttr(::new (Context) NoReturnAttr());
+ FD->setType(Context.getNoReturnType(FD->getType()));
if (Context.BuiltinInfo.isNoThrow(BuiltinID))
FD->addAttr(::new (Context) NoThrowAttr());
if (Context.BuiltinInfo.isConst(BuiltinID))
Modified: cfe/trunk/lib/Sema/SemaDeclAttr.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaDeclAttr.cpp?rev=95436&r1=95435&r2=95436&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/SemaDeclAttr.cpp (original)
+++ cfe/trunk/lib/Sema/SemaDeclAttr.cpp Fri Feb 5 15:31:56 2010
@@ -391,6 +391,11 @@
}
static void HandleNoReturnAttr(Decl *d, const AttributeList &Attr, Sema &S) {
+ // Don't apply as a decl attribute to ValueDecl.
+ // FIXME: probably ought to diagnose this.
+ if (isa<ValueDecl>(d))
+ return;
+
if (HandleCommonNoReturnAttr(d, Attr, S))
d->addAttr(::new (S.Context) NoReturnAttr());
}
@@ -404,7 +409,7 @@
static void HandleDependencyAttr(Decl *d, const AttributeList &Attr, Sema &S) {
if (!isFunctionOrMethod(d) && !isa<ParmVarDecl>(d)) {
S.Diag(Attr.getLoc(), diag::err_attribute_wrong_decl_type)
- << Attr.getName() << 8; /*function, method, or parameter*/
+ << Attr.getName() << 8 /*function, method, or parameter*/;
return;
}
// FIXME: Actually store the attribute on the declaration
@@ -940,120 +945,6 @@
D->addAttr(::new (S.Context) SectionAttr(SE->getString()));
}
-static void HandleCDeclAttr(Decl *d, const AttributeList &Attr, Sema &S) {
- // Attribute has no arguments.
- if (Attr.getNumArgs() != 0) {
- S.Diag(Attr.getLoc(), diag::err_attribute_wrong_number_arguments) << 0;
- return;
- }
-
- // Attribute can be applied only to functions.
- // If we try to apply it to a function pointer, don't warn, but don't
- // do anything, either. All the function-pointer stuff is handled in
- // SemaType.cpp.
- ValueDecl *VD = dyn_cast<ValueDecl>(d);
- if (VD && VD->getType()->isFunctionPointerType())
- return;
- if (!isa<FunctionDecl>(d)) {
- S.Diag(Attr.getLoc(), diag::warn_attribute_wrong_decl_type)
- << Attr.getName() << 0 /*function*/;
- return;
- }
-
- // cdecl and fastcall attributes are mutually incompatible.
- if (d->getAttr<FastCallAttr>()) {
- S.Diag(Attr.getLoc(), diag::err_attributes_are_not_compatible)
- << "cdecl" << "fastcall";
- return;
- }
-
- // cdecl and stdcall attributes are mutually incompatible.
- if (d->getAttr<StdCallAttr>()) {
- S.Diag(Attr.getLoc(), diag::err_attributes_are_not_compatible)
- << "cdecl" << "stdcall";
- return;
- }
-
- d->addAttr(::new (S.Context) CDeclAttr());
-}
-
-
-static void HandleStdCallAttr(Decl *d, const AttributeList &Attr, Sema &S) {
- // Attribute has no arguments.
- if (Attr.getNumArgs() != 0) {
- S.Diag(Attr.getLoc(), diag::err_attribute_wrong_number_arguments) << 0;
- return;
- }
-
- // Attribute can be applied only to functions.
- // If we try to apply it to a function pointer, don't warn, but don't
- // do anything, either. All the function-pointer stuff is handled in
- // SemaType.cpp.
- ValueDecl *VD = dyn_cast<ValueDecl>(d);
- if (VD && VD->getType()->isFunctionPointerType())
- return;
- if (!isa<FunctionDecl>(d)) {
- S.Diag(Attr.getLoc(), diag::warn_attribute_wrong_decl_type)
- << Attr.getName() << 0 /*function*/;
- return;
- }
-
- // stdcall and fastcall attributes are mutually incompatible.
- if (d->getAttr<FastCallAttr>()) {
- S.Diag(Attr.getLoc(), diag::err_attributes_are_not_compatible)
- << "stdcall" << "fastcall";
- return;
- }
-
- d->addAttr(::new (S.Context) StdCallAttr());
-}
-
-/// Diagnose the use of a non-standard calling convention on the given
-/// function.
-static void DiagnoseCConv(FunctionDecl *D, const char *CConv,
- SourceLocation Loc, Sema &S) {
- if (!D->hasPrototype()) {
- S.Diag(Loc, diag::err_cconv_knr) << CConv;
- return;
- }
-
- const FunctionProtoType *T = D->getType()->getAs<FunctionProtoType>();
- if (T->isVariadic()) {
- S.Diag(Loc, diag::err_cconv_varargs) << CConv;
- return;
- }
-}
-
-static void HandleFastCallAttr(Decl *d, const AttributeList &Attr, Sema &S) {
- // Attribute has no arguments.
- if (Attr.getNumArgs() != 0) {
- S.Diag(Attr.getLoc(), diag::err_attribute_wrong_number_arguments) << 0;
- return;
- }
-
- // If we try to apply it to a function pointer, don't warn, but don't
- // do anything, either. All the function-pointer stuff is handled in
- // SemaType.cpp.
- ValueDecl *VD = dyn_cast<ValueDecl>(d);
- if (VD && VD->getType()->isFunctionPointerType())
- return;
- if (!isa<FunctionDecl>(d)) {
- S.Diag(Attr.getLoc(), diag::warn_attribute_wrong_decl_type)
- << Attr.getName() << 0 /*function*/;
- return;
- }
-
- DiagnoseCConv(cast<FunctionDecl>(d), "fastcall", Attr.getLoc(), S);
-
- // stdcall and fastcall attributes are mutually incompatible.
- if (d->getAttr<StdCallAttr>()) {
- S.Diag(Attr.getLoc(), diag::err_attributes_are_not_compatible)
- << "fastcall" << "stdcall";
- return;
- }
-
- d->addAttr(::new (S.Context) FastCallAttr());
-}
static void HandleNothrowAttr(Decl *d, const AttributeList &Attr, Sema &S) {
// check the attribute arguments.
@@ -1926,7 +1817,6 @@
case AttributeList::AT_base_check: HandleBaseCheckAttr (D, Attr, S); break;
case AttributeList::AT_carries_dependency:
HandleDependencyAttr (D, Attr, S); break;
- case AttributeList::AT_cdecl: HandleCDeclAttr (D, Attr, S); break;
case AttributeList::AT_constructor: HandleConstructorAttr (D, Attr, S); break;
case AttributeList::AT_deprecated: HandleDeprecatedAttr (D, Attr, S); break;
case AttributeList::AT_destructor: HandleDestructorAttr (D, Attr, S); break;
@@ -1935,7 +1825,6 @@
case AttributeList::AT_ext_vector_type:
HandleExtVectorTypeAttr(scope, D, Attr, S);
break;
- case AttributeList::AT_fastcall: HandleFastCallAttr (D, Attr, S); break;
case AttributeList::AT_final: HandleFinalAttr (D, Attr, S); break;
case AttributeList::AT_format: HandleFormatAttr (D, Attr, S); break;
case AttributeList::AT_format_arg: HandleFormatArgAttr (D, Attr, S); break;
@@ -1958,7 +1847,6 @@
case AttributeList::AT_packed: HandlePackedAttr (D, Attr, S); break;
case AttributeList::AT_section: HandleSectionAttr (D, Attr, S); break;
- case AttributeList::AT_stdcall: HandleStdCallAttr (D, Attr, S); break;
case AttributeList::AT_unavailable: HandleUnavailableAttr (D, Attr, S); break;
case AttributeList::AT_unused: HandleUnusedAttr (D, Attr, S); break;
case AttributeList::AT_used: HandleUsedAttr (D, Attr, S); break;
@@ -1987,6 +1875,11 @@
case AttributeList::AT_no_instrument_function: // Interacts with -pg.
// Just ignore
break;
+ case AttributeList::AT_stdcall:
+ case AttributeList::AT_cdecl:
+ case AttributeList::AT_fastcall:
+ // These are all treated as type attributes.
+ break;
default:
// Ask target about the attribute.
const TargetAttributesSema &TargetAttrs = S.getTargetAttributesSema();
Modified: cfe/trunk/lib/Sema/SemaStmt.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaStmt.cpp?rev=95436&r1=95435&r2=95436&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/SemaStmt.cpp (original)
+++ cfe/trunk/lib/Sema/SemaStmt.cpp Fri Feb 5 15:31:56 2010
@@ -1043,7 +1043,8 @@
QualType FnRetType;
if (const FunctionDecl *FD = getCurFunctionDecl()) {
FnRetType = FD->getResultType();
- if (FD->hasAttr<NoReturnAttr>())
+ if (FD->hasAttr<NoReturnAttr>() ||
+ FD->getType()->getAs<FunctionType>()->getNoReturnAttr())
Diag(ReturnLoc, diag::warn_noreturn_function_has_return_expr)
<< getCurFunctionOrMethodDecl()->getDeclName();
} else if (ObjCMethodDecl *MD = getCurMethodDecl())
Modified: cfe/trunk/lib/Sema/SemaType.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaType.cpp?rev=95436&r1=95435&r2=95436&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/SemaType.cpp (original)
+++ cfe/trunk/lib/Sema/SemaType.cpp Fri Feb 5 15:31:56 2010
@@ -68,12 +68,41 @@
return false;
}
+typedef std::pair<const AttributeList*,QualType> DelayedAttribute;
+typedef llvm::SmallVectorImpl<DelayedAttribute> DelayedAttributeSet;
+
+static void ProcessTypeAttributeList(Sema &S, QualType &Type,
+ const AttributeList *Attrs,
+ DelayedAttributeSet &DelayedFnAttrs);
+static bool ProcessFnAttr(Sema &S, QualType &Type, const AttributeList &Attr);
+
+static void ProcessDelayedFnAttrs(Sema &S, QualType &Type,
+ DelayedAttributeSet &Attrs) {
+ for (DelayedAttributeSet::iterator I = Attrs.begin(),
+ E = Attrs.end(); I != E; ++I)
+ if (ProcessFnAttr(S, Type, *I->first))
+ S.Diag(I->first->getLoc(), diag::warn_function_attribute_wrong_type)
+ << I->first->getName() << I->second;
+ Attrs.clear();
+}
+
+static void DiagnoseDelayedFnAttrs(Sema &S, DelayedAttributeSet &Attrs) {
+ for (DelayedAttributeSet::iterator I = Attrs.begin(),
+ E = Attrs.end(); I != E; ++I) {
+ S.Diag(I->first->getLoc(), diag::warn_function_attribute_wrong_type)
+ << I->first->getName() << I->second;
+ }
+ Attrs.clear();
+}
+
/// \brief Convert the specified declspec to the appropriate type
/// object.
/// \param D the declarator containing the declaration specifier.
/// \returns The type described by the declaration specifiers. This function
/// never returns null.
-static QualType ConvertDeclSpecToType(Declarator &TheDeclarator, Sema &TheSema){
+static QualType ConvertDeclSpecToType(Sema &TheSema,
+ Declarator &TheDeclarator,
+ DelayedAttributeSet &Delayed) {
// FIXME: Should move the logic from DeclSpec::Finish to here for validity
// checking.
const DeclSpec &DS = TheDeclarator.getDeclSpec();
@@ -356,7 +385,7 @@
// See if there are any attributes on the declspec that apply to the type (as
// opposed to the decl).
if (const AttributeList *AL = DS.getAttributes())
- TheSema.ProcessTypeAttributeList(Result, AL);
+ ProcessTypeAttributeList(TheSema, Result, AL, Delayed);
// Apply const/volatile/restrict qualifiers to T.
if (unsigned TypeQuals = DS.getTypeQualifiers()) {
@@ -890,12 +919,14 @@
// have a type.
QualType T;
+ llvm::SmallVector<DelayedAttribute,4> FnAttrsFromDeclSpec;
+
switch (D.getName().getKind()) {
case UnqualifiedId::IK_Identifier:
case UnqualifiedId::IK_OperatorFunctionId:
case UnqualifiedId::IK_LiteralOperatorId:
case UnqualifiedId::IK_TemplateId:
- T = ConvertDeclSpecToType(D, *this);
+ T = ConvertDeclSpecToType(*this, D, FnAttrsFromDeclSpec);
if (!D.isInvalidType() && OwnedDecl && D.getDeclSpec().isTypeSpecOwned())
*OwnedDecl = cast<TagDecl>((Decl *)D.getDeclSpec().getTypeRep());
@@ -967,6 +998,8 @@
if (D.getIdentifier())
Name = D.getIdentifier();
+ llvm::SmallVector<DelayedAttribute,4> FnAttrsFromPreviousChunk;
+
// Walk the DeclTypeInfo, building the recursive type as we go.
// DeclTypeInfos are ordered from the identifier out, which is
// opposite of what we want :).
@@ -1186,6 +1219,13 @@
FTI.hasAnyExceptionSpec,
Exceptions.size(), Exceptions.data());
}
+
+ // For GCC compatibility, we allow attributes that apply only to
+ // function types to be placed on a function's return type
+ // instead (as long as that type doesn't happen to be function
+ // or function-pointer itself).
+ ProcessDelayedFnAttrs(*this, T, FnAttrsFromPreviousChunk);
+
break;
}
case DeclaratorChunk::MemberPointer:
@@ -1244,9 +1284,11 @@
T = Context.IntTy;
}
+ DiagnoseDelayedFnAttrs(*this, FnAttrsFromPreviousChunk);
+
// See if there are any attributes on this declarator chunk.
if (const AttributeList *AL = DeclType.getAttrs())
- ProcessTypeAttributeList(T, AL, true);
+ ProcessTypeAttributeList(*this, T, AL, FnAttrsFromPreviousChunk);
}
if (getLangOptions().CPlusPlus && T->isFunctionType()) {
@@ -1276,13 +1318,18 @@
}
}
- // If there were any type attributes applied to the decl itself (not the
- // type, apply the type attribute to the type!)
- if (const AttributeList *Attrs = D.getAttributes())
- ProcessTypeAttributeList(T, Attrs, true);
- // Also look in the decl spec.
- if (const AttributeList *Attrs = D.getDeclSpec().getAttributes())
- ProcessTypeAttributeList(T, Attrs, true, true);
+ // Process any function attributes we might have delayed from the
+ // declaration-specifiers.
+ ProcessDelayedFnAttrs(*this, T, FnAttrsFromDeclSpec);
+
+ // If there were any type attributes applied to the decl itself, not
+ // the type, apply them to the result type. But don't do this for
+ // block-literal expressions, which are parsed wierdly.
+ if (D.getContext() != Declarator::BlockLiteralContext)
+ if (const AttributeList *Attrs = D.getAttributes())
+ ProcessTypeAttributeList(*this, T, Attrs, FnAttrsFromPreviousChunk);
+
+ DiagnoseDelayedFnAttrs(*this, FnAttrsFromPreviousChunk);
if (TInfo) {
if (D.isInvalidType())
@@ -1620,36 +1667,6 @@
Type = S.Context.getAddrSpaceQualType(Type, ASIdx);
}
-/// HandleCDeclTypeAttribute - Process the cdecl attribute on the
-/// specified type. The attribute contains 0 arguments.
-static void HandleCDeclTypeAttribute(QualType &Type,
- const AttributeList &Attr, Sema &S) {
- if (Attr.getNumArgs() != 0)
- return;
-
- // We only apply this to a pointer to function.
- if (!Type->isFunctionPointerType()
- && !Type->isFunctionType())
- return;
-
- Type = S.Context.getCallConvType(Type, CC_C);
-}
-
-/// HandleFastCallTypeAttribute - Process the fastcall attribute on the
-/// specified type. The attribute contains 0 arguments.
-static void HandleFastCallTypeAttribute(QualType &Type,
- const AttributeList &Attr, Sema &S) {
- if (Attr.getNumArgs() != 0)
- return;
-
- // We only apply this to a pointer to function.
- if (!Type->isFunctionPointerType()
- && !Type->isFunctionType())
- return;
-
- Type = S.Context.getCallConvType(Type, CC_X86FastCall);
-}
-
/// HandleObjCGCTypeAttribute - Process an objc's gc attribute on the
/// specified type. The attribute contains 1 argument, weak or strong.
static void HandleObjCGCTypeAttribute(QualType &Type,
@@ -1683,35 +1700,79 @@
Type = S.Context.getObjCGCQualType(Type, GCAttr);
}
-/// HandleNoReturnTypeAttribute - Process the noreturn attribute on the
-/// specified type. The attribute contains 0 arguments.
-static void HandleNoReturnTypeAttribute(QualType &Type,
- const AttributeList &Attr, Sema &S) {
- if (Attr.getNumArgs() != 0)
- return;
+/// Process an individual function attribute. Returns true if the
+/// attribute does not make sense to apply to this type.
+bool ProcessFnAttr(Sema &S, QualType &Type, const AttributeList &Attr) {
+ if (Attr.getKind() == AttributeList::AT_noreturn) {
+ // Complain immediately if the arg count is wrong.
+ if (Attr.getNumArgs() != 0) {
+ S.Diag(Attr.getLoc(), diag::err_attribute_wrong_number_arguments) << 0;
+ return false;
+ }
+
+ // Delay if this is not a function or pointer to block.
+ if (!Type->isFunctionPointerType()
+ && !Type->isBlockPointerType()
+ && !Type->isFunctionType())
+ return true;
- // We only apply this to a pointer to function or a pointer to block.
- if (!Type->isFunctionPointerType()
- && !Type->isBlockPointerType()
- && !Type->isFunctionType())
- return;
+ // Otherwise we can process right away.
+ Type = S.Context.getNoReturnType(Type);
+ return false;
+ }
- Type = S.Context.getNoReturnType(Type);
-}
+ // Otherwise, a calling convention.
+ if (Attr.getNumArgs() != 0) {
+ S.Diag(Attr.getLoc(), diag::err_attribute_wrong_number_arguments) << 0;
+ return false;
+ }
-/// HandleStdCallTypeAttribute - Process the stdcall attribute on the
-/// specified type. The attribute contains 0 arguments.
-static void HandleStdCallTypeAttribute(QualType &Type,
- const AttributeList &Attr, Sema &S) {
- if (Attr.getNumArgs() != 0)
- return;
+ QualType T = Type;
+ if (const PointerType *PT = Type->getAs<PointerType>())
+ T = PT->getPointeeType();
+ const FunctionType *Fn = T->getAs<FunctionType>();
+
+ // Delay if the type didn't work out to a function.
+ if (!Fn) return true;
+
+ // TODO: diagnose uses of these conventions on the wrong target.
+ CallingConv CC;
+ switch (Attr.getKind()) {
+ case AttributeList::AT_cdecl: CC = CC_C; break;
+ case AttributeList::AT_fastcall: CC = CC_X86FastCall; break;
+ case AttributeList::AT_stdcall: CC = CC_X86StdCall; break;
+ default: llvm_unreachable("unexpected attribute kind"); return false;
+ }
+
+ CallingConv CCOld = Fn->getCallConv();
+ if (CC == CCOld) return false;
+
+ if (CCOld != CC_Default) {
+ // Should we diagnose reapplications of the same convention?
+ S.Diag(Attr.getLoc(), diag::err_attributes_are_not_compatible)
+ << FunctionType::getNameForCallConv(CC)
+ << FunctionType::getNameForCallConv(CCOld);
+ return false;
+ }
- // We only apply this to a pointer to function.
- if (!Type->isFunctionPointerType()
- && !Type->isFunctionType())
- return;
+ // Diagnose the use of X86 fastcall on varargs or unprototyped functions.
+ if (CC == CC_X86FastCall) {
+ if (isa<FunctionNoProtoType>(Fn)) {
+ S.Diag(Attr.getLoc(), diag::err_cconv_knr)
+ << FunctionType::getNameForCallConv(CC);
+ return false;
+ }
+
+ const FunctionProtoType *FnP = cast<FunctionProtoType>(Fn);
+ if (FnP->isVariadic()) {
+ S.Diag(Attr.getLoc(), diag::err_cconv_varargs)
+ << FunctionType::getNameForCallConv(CC);
+ return false;
+ }
+ }
- Type = S.Context.getCallConvType(Type, CC_X86StdCall);
+ Type = S.Context.getCallConvType(Type, CC);
+ return false;
}
/// HandleVectorSizeAttribute - this attribute is only applicable to integral
@@ -1761,12 +1822,9 @@
CurType = S.Context.getVectorType(CurType, vectorSize/typeSize, false, false);
}
-void Sema::ProcessTypeAttributeList(QualType &Result, const AttributeList *AL,
- bool HandleCallConvAttributes,
- bool HandleOnlyCallConv) {
- if(HandleOnlyCallConv)
- assert(HandleCallConvAttributes && "Can't not handle call-conv attributes"
- " while only handling them!");
+void ProcessTypeAttributeList(Sema &S, QualType &Result,
+ const AttributeList *AL,
+ DelayedAttributeSet &FnAttrs) {
// Scan through and apply attributes to this type where it makes sense. Some
// attributes (such as __address_space__, __vector_size__, etc) apply to the
// type, but others can be present in the type specifiers even though they
@@ -1776,33 +1834,23 @@
// the LeftOverAttrs list for rechaining.
switch (AL->getKind()) {
default: break;
+
case AttributeList::AT_address_space:
- if (!HandleOnlyCallConv)
- HandleAddressSpaceTypeAttribute(Result, *AL, *this);
- break;
- case AttributeList::AT_cdecl:
- if (HandleCallConvAttributes)
- HandleCDeclTypeAttribute(Result, *AL, *this);
- break;
- case AttributeList::AT_fastcall:
- if (HandleCallConvAttributes)
- HandleFastCallTypeAttribute(Result, *AL, *this);
+ HandleAddressSpaceTypeAttribute(Result, *AL, S);
break;
case AttributeList::AT_objc_gc:
- if (!HandleOnlyCallConv)
- HandleObjCGCTypeAttribute(Result, *AL, *this);
+ HandleObjCGCTypeAttribute(Result, *AL, S);
break;
- case AttributeList::AT_noreturn:
- if (!HandleOnlyCallConv)
- HandleNoReturnTypeAttribute(Result, *AL, *this);
+ case AttributeList::AT_vector_size:
+ HandleVectorSizeAttr(Result, *AL, S);
break;
+
+ case AttributeList::AT_noreturn:
+ case AttributeList::AT_cdecl:
+ case AttributeList::AT_fastcall:
case AttributeList::AT_stdcall:
- if (HandleCallConvAttributes)
- HandleStdCallTypeAttribute(Result, *AL, *this);
- break;
- case AttributeList::AT_vector_size:
- if (!HandleOnlyCallConv)
- HandleVectorSizeAttr(Result, *AL, *this);
+ if (ProcessFnAttr(S, Result, *AL))
+ FnAttrs.push_back(DelayedAttribute(AL, Result));
break;
}
}
Modified: cfe/trunk/test/CodeGen/attributes.c
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CodeGen/attributes.c?rev=95436&r1=95435&r2=95436&view=diff
==============================================================================
--- cfe/trunk/test/CodeGen/attributes.c (original)
+++ cfe/trunk/test/CodeGen/attributes.c Fri Feb 5 15:31:56 2010
@@ -74,3 +74,10 @@
void t20(void) {
__builtin_abort();
}
+
+void (__attribute__((fastcall)) *fptr)(int);
+void t21(void) {
+ fptr(10);
+}
+// CHECK: [[FPTRVAR:%[a-z0-9]+]] = load void (i32)** @fptr
+// CHECK-NEXT: call x86_fastcallcc void [[FPTRVAR]](i32 10)
Modified: cfe/trunk/test/CodeGen/stdcall-fastcall.c
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CodeGen/stdcall-fastcall.c?rev=95436&r1=95435&r2=95436&view=diff
==============================================================================
--- cfe/trunk/test/CodeGen/stdcall-fastcall.c (original)
+++ cfe/trunk/test/CodeGen/stdcall-fastcall.c Fri Feb 5 15:31:56 2010
@@ -24,10 +24,10 @@
// CHECK: call x86_fastcallcc void @f3()
// CHECK: call x86_stdcallcc void @f4()
pf1(); pf2(); pf3(); pf4();
- // CHECK: call x86_fastcallcc void %tmp()
- // CHECK: call x86_stdcallcc void %tmp1()
- // CHECK: call x86_fastcallcc void %tmp2()
- // CHECK: call x86_stdcallcc void %tmp3()
+ // CHECK: call x86_fastcallcc void %{{.*}}()
+ // CHECK: call x86_stdcallcc void %{{.*}}()
+ // CHECK: call x86_fastcallcc void %{{.*}}()
+ // CHECK: call x86_stdcallcc void %{{.*}}()
return 0;
}
Modified: cfe/trunk/test/Sema/attr-noreturn.c
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Sema/attr-noreturn.c?rev=95436&r1=95435&r2=95436&view=diff
==============================================================================
--- cfe/trunk/test/Sema/attr-noreturn.c (original)
+++ cfe/trunk/test/Sema/attr-noreturn.c Fri Feb 5 15:31:56 2010
@@ -11,7 +11,7 @@
// On K&R
int f1() __attribute__((noreturn));
-int g0 __attribute__((noreturn)); // expected-warning {{'noreturn' attribute only applies to function types}}
+int g0 __attribute__((noreturn)); // expected-warning {{'noreturn' only applies to function types; type here is 'int'}}
int f2() __attribute__((noreturn(1, 2))); // expected-error {{attribute requires 0 argument(s)}}
Modified: cfe/trunk/test/Sema/callingconv.c
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Sema/callingconv.c?rev=95436&r1=95435&r2=95436&view=diff
==============================================================================
--- cfe/trunk/test/Sema/callingconv.c (original)
+++ cfe/trunk/test/Sema/callingconv.c Fri Feb 5 15:31:56 2010
@@ -9,13 +9,13 @@
void __attribute__((fastcall(1))) baz(float *a) { // expected-error {{attribute requires 0 argument(s)}}
}
-void __attribute__((fastcall)) test0() { // expected-error {{function with no prototype cannot use 'fastcall' calling convention}}
+void __attribute__((fastcall)) test0() { // expected-error {{function with no prototype cannot use fastcall calling convention}}
}
void __attribute__((fastcall)) test1(void) {
}
-void __attribute__((fastcall)) test2(int a, ...) { // expected-error {{variadic function cannot use 'fastcall' calling convention}}
+void __attribute__((fastcall)) test2(int a, ...) { // expected-error {{variadic function cannot use fastcall calling convention}}
}
void __attribute__((cdecl)) ctest0() {}
@@ -33,3 +33,6 @@
void ctest2() {}
void (__attribute__((cdecl)) *pctest2)() = ctest2;
+typedef void (__attribute__((fastcall)) *Handler) (float *);
+Handler H = foo;
+
Modified: cfe/trunk/test/Sema/stdcall-fastcall.c
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Sema/stdcall-fastcall.c?rev=95436&r1=95435&r2=95436&view=diff
==============================================================================
--- cfe/trunk/test/Sema/stdcall-fastcall.c (original)
+++ cfe/trunk/test/Sema/stdcall-fastcall.c Fri Feb 5 15:31:56 2010
@@ -1,10 +1,10 @@
// RUN: %clang_cc1 -fsyntax-only -verify %s
// CC qualifier can be applied only to functions
-int __attribute__((stdcall)) var1; // expected-warning{{'stdcall' attribute only applies to function types}}
-int __attribute__((fastcall)) var2; // expected-warning{{'fastcall' attribute only applies to function types}}
+int __attribute__((stdcall)) var1; // expected-warning{{'stdcall' only applies to function types; type here is 'int'}}
+int __attribute__((fastcall)) var2; // expected-warning{{'fastcall' only applies to function types; type here is 'int'}}
// Different CC qualifiers are not compatible
void __attribute__((stdcall, fastcall)) foo3(void); // expected-error{{stdcall and fastcall attributes are not compatible}}
-void __attribute__((stdcall)) foo4();
-void __attribute__((fastcall)) foo4(void); // expected-error{{fastcall and stdcall attributes are not compatible}}
+void __attribute__((stdcall)) foo4(); // expected-note{{previous declaration is here}}
+void __attribute__((fastcall)) foo4(void); // expected-error{{function declared 'fastcall' here was previously declared 'stdcall'}}
More information about the cfe-commits
mailing list