[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