diff options
author | John McCall <rjmccall@apple.com> | 2010-02-04 05:44:44 +0000 |
---|---|---|
committer | John McCall <rjmccall@apple.com> | 2010-02-04 05:44:44 +0000 |
commit | cddbad000dcfb8e9cbdc9b95438b40c83357ed40 (patch) | |
tree | f7efff3f1ba3668a399b8f6d117b7afd856b4864 /clang/lib/Sema/SemaDecl.cpp | |
parent | 319deb83d2a52bf788d0e724c8cd463cf9c576fd (diff) | |
download | bcm5719-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.cpp | 35 |
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: |