summaryrefslogtreecommitdiffstats
path: root/clang/lib/Sema/SemaDecl.cpp
diff options
context:
space:
mode:
authorJohn McCall <rjmccall@apple.com>2010-02-04 05:44:44 +0000
committerJohn McCall <rjmccall@apple.com>2010-02-04 05:44:44 +0000
commitcddbad000dcfb8e9cbdc9b95438b40c83357ed40 (patch)
treef7efff3f1ba3668a399b8f6d117b7afd856b4864 /clang/lib/Sema/SemaDecl.cpp
parent319deb83d2a52bf788d0e724c8cd463cf9c576fd (diff)
downloadbcm5719-llvm-cddbad000dcfb8e9cbdc9b95438b40c83357ed40.tar.gz
bcm5719-llvm-cddbad000dcfb8e9cbdc9b95438b40c83357ed40.zip
Allow calling convention attributes to apply to types. Patch by Chip Davis!
llvm-svn: 95291
Diffstat (limited to 'clang/lib/Sema/SemaDecl.cpp')
-rw-r--r--clang/lib/Sema/SemaDecl.cpp35
1 files changed, 35 insertions, 0 deletions
diff --git a/clang/lib/Sema/SemaDecl.cpp b/clang/lib/Sema/SemaDecl.cpp
index 80831f42c8c..2e3a4352f2a 100644
--- a/clang/lib/Sema/SemaDecl.cpp
+++ b/clang/lib/Sema/SemaDecl.cpp
@@ -901,6 +901,14 @@ static Sema::CXXSpecialMember getSpecialMember(ASTContext &Ctx,
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,
@@ -958,6 +966,33 @@ bool Sema::MergeFunctionDecl(FunctionDecl *New, Decl *OldD) {
return true;
}
+ // If a function is first declared with a calling convention, but is
+ // later declared or defined without one, the second decl assumes the
+ // calling convention of the first.
+ //
+ // For the new decl, we have to look at the NON-canonical type to tell the
+ // difference between a function that really doesn't have a calling
+ // convention and one that is declared cdecl. That's because in
+ // canonicalization (see ASTContext.cpp), cdecl is canonicalized away
+ // because it is the default calling convention.
+ //
+ // Note also that we DO NOT return at this point, because we still have
+ // other tests to run.
+ const FunctionType *OldType = OldQType->getAs<FunctionType>();
+ const FunctionType *NewType = New->getType()->getAs<FunctionType>();
+ if (OldType->getCallConv() != CC_Default &&
+ NewType->getCallConv() == CC_Default) {
+ NewQType = Context.getCallConvType(NewQType, OldType->getCallConv());
+ New->setType(NewQType);
+ NewQType = Context.getCanonicalType(NewQType);
+ } else if (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());
+ return true;
+ }
+
if (getLangOptions().CPlusPlus) {
// (C++98 13.1p2):
// Certain function declarations cannot be overloaded:
OpenPOWER on IntegriCloud