diff options
Diffstat (limited to 'clang/lib/Sema')
| -rw-r--r-- | clang/lib/Sema/Sema.h | 4 | ||||
| -rw-r--r-- | clang/lib/Sema/SemaDecl.cpp | 35 | ||||
| -rw-r--r-- | clang/lib/Sema/SemaDeclAttr.cpp | 16 | ||||
| -rw-r--r-- | clang/lib/Sema/SemaType.cpp | 83 |
4 files changed, 130 insertions, 8 deletions
diff --git a/clang/lib/Sema/Sema.h b/clang/lib/Sema/Sema.h index 12ce174308a..19de095b2aa 100644 --- a/clang/lib/Sema/Sema.h +++ b/clang/lib/Sema/Sema.h @@ -560,7 +560,9 @@ public: // Type Analysis / Processing: SemaType.cpp. // QualType adjustParameterType(QualType T); - void ProcessTypeAttributeList(QualType &Result, const AttributeList *AL); + 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, 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: diff --git a/clang/lib/Sema/SemaDeclAttr.cpp b/clang/lib/Sema/SemaDeclAttr.cpp index a391a0eaed1..5e7788ef40f 100644 --- a/clang/lib/Sema/SemaDeclAttr.cpp +++ b/clang/lib/Sema/SemaDeclAttr.cpp @@ -948,6 +948,12 @@ static void HandleCDeclAttr(Decl *d, const AttributeList &Attr, Sema &S) { } // 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*/; @@ -980,6 +986,11 @@ static void HandleStdCallAttr(Decl *d, const AttributeList &Attr, Sema &S) { } // 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. + 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*/; @@ -1019,6 +1030,11 @@ static void HandleFastCallAttr(Decl *d, const AttributeList &Attr, Sema &S) { return; } + // If we try to apply it to a function pointer, don't warn, but don't + // do anything, either. + 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*/; diff --git a/clang/lib/Sema/SemaType.cpp b/clang/lib/Sema/SemaType.cpp index 906576115a5..8833792494e 100644 --- a/clang/lib/Sema/SemaType.cpp +++ b/clang/lib/Sema/SemaType.cpp @@ -1241,7 +1241,7 @@ QualType Sema::GetTypeForDeclarator(Declarator &D, Scope *S, // See if there are any attributes on this declarator chunk. if (const AttributeList *AL = DeclType.getAttrs()) - ProcessTypeAttributeList(T, AL); + ProcessTypeAttributeList(T, AL, true); } if (getLangOptions().CPlusPlus && T->isFunctionType()) { @@ -1274,7 +1274,10 @@ QualType Sema::GetTypeForDeclarator(Declarator &D, Scope *S, // 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); + ProcessTypeAttributeList(T, Attrs, true); + // Also look in the decl spec. + if (const AttributeList *Attrs = D.getDeclSpec().getAttributes()) + ProcessTypeAttributeList(T, Attrs, true, true); if (TInfo) { if (D.isInvalidType()) @@ -1612,6 +1615,36 @@ static void HandleAddressSpaceTypeAttribute(QualType &Type, 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, @@ -1661,6 +1694,21 @@ static void HandleNoReturnTypeAttribute(QualType &Type, Type = S.Context.getNoReturnType(Type); } +/// 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; + + // We only apply this to a pointer to function. + if (!Type->isFunctionPointerType() + && !Type->isFunctionType()) + return; + + Type = S.Context.getCallConvType(Type, CC_X86StdCall); +} + /// HandleVectorSizeAttribute - this attribute is only applicable to integral /// and float scalars, although arrays, pointers, and function return values are /// allowed in conjunction with this construct. Aggregates with this attribute @@ -1708,7 +1756,12 @@ static void HandleVectorSizeAttr(QualType& CurType, const AttributeList &Attr, S CurType = S.Context.getVectorType(CurType, vectorSize/typeSize); } -void Sema::ProcessTypeAttributeList(QualType &Result, const AttributeList *AL) { +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!"); // 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 @@ -1719,16 +1772,32 @@ void Sema::ProcessTypeAttributeList(QualType &Result, const AttributeList *AL) { switch (AL->getKind()) { default: break; case AttributeList::AT_address_space: - HandleAddressSpaceTypeAttribute(Result, *AL, *this); + 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); break; case AttributeList::AT_objc_gc: - HandleObjCGCTypeAttribute(Result, *AL, *this); + if (!HandleOnlyCallConv) + HandleObjCGCTypeAttribute(Result, *AL, *this); break; case AttributeList::AT_noreturn: - HandleNoReturnTypeAttribute(Result, *AL, *this); + if (!HandleOnlyCallConv) + HandleNoReturnTypeAttribute(Result, *AL, *this); + break; + case AttributeList::AT_stdcall: + if (HandleCallConvAttributes) + HandleStdCallTypeAttribute(Result, *AL, *this); break; case AttributeList::AT_vector_size: - HandleVectorSizeAttr(Result, *AL, *this); + if (!HandleOnlyCallConv) + HandleVectorSizeAttr(Result, *AL, *this); break; } } |

