diff options
Diffstat (limited to 'clang/lib/Sema')
| -rw-r--r-- | clang/lib/Sema/Sema.h | 4 | ||||
| -rw-r--r-- | clang/lib/Sema/SemaChecking.cpp | 3 | ||||
| -rw-r--r-- | clang/lib/Sema/SemaDecl.cpp | 29 | ||||
| -rw-r--r-- | clang/lib/Sema/SemaDeclAttr.cpp | 129 | ||||
| -rw-r--r-- | clang/lib/Sema/SemaStmt.cpp | 3 | ||||
| -rw-r--r-- | clang/lib/Sema/SemaType.cpp | 232 |
6 files changed, 172 insertions, 228 deletions
diff --git a/clang/lib/Sema/Sema.h b/clang/lib/Sema/Sema.h index 6a7590997cd..dfd8f3461eb 100644 --- a/clang/lib/Sema/Sema.h +++ b/clang/lib/Sema/Sema.h @@ -559,10 +559,8 @@ public: //===--------------------------------------------------------------------===// // 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, diff --git a/clang/lib/Sema/SemaChecking.cpp b/clang/lib/Sema/SemaChecking.cpp index cba3c606618..76ff8dc7cb9 100644 --- a/clang/lib/Sema/SemaChecking.cpp +++ b/clang/lib/Sema/SemaChecking.cpp @@ -2500,7 +2500,8 @@ void Sema::CheckFallThroughForFunctionDef(Decl *D, Stmt *Body, 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()) diff --git a/clang/lib/Sema/SemaDecl.cpp b/clang/lib/Sema/SemaDecl.cpp index 1415f73f644..52fc9b74e0c 100644 --- a/clang/lib/Sema/SemaDecl.cpp +++ b/clang/lib/Sema/SemaDecl.cpp @@ -908,14 +908,6 @@ 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, @@ -992,14 +984,25 @@ bool Sema::MergeFunctionDecl(FunctionDecl *New, Decl *OldD) { 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 @@ void Sema::AddKnownFunctionAttributes(FunctionDecl *FD) { } 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)) diff --git a/clang/lib/Sema/SemaDeclAttr.cpp b/clang/lib/Sema/SemaDeclAttr.cpp index 681a3b7813a..01e8fda2ebf 100644 --- a/clang/lib/Sema/SemaDeclAttr.cpp +++ b/clang/lib/Sema/SemaDeclAttr.cpp @@ -391,6 +391,11 @@ static bool HandleCommonNoReturnAttr(Decl *d, const AttributeList &Attr, } 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 HandleAnalyzerNoReturnAttr(Decl *d, const AttributeList &Attr, 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 @@ static void HandleSectionAttr(Decl *D, const AttributeList &Attr, Sema &S) { 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 @@ static void ProcessDeclAttribute(Scope *scope, Decl *D, 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 @@ static void ProcessDeclAttribute(Scope *scope, Decl *D, 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 @@ static void ProcessDeclAttribute(Scope *scope, Decl *D, 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 @@ static void ProcessDeclAttribute(Scope *scope, Decl *D, 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(); diff --git a/clang/lib/Sema/SemaStmt.cpp b/clang/lib/Sema/SemaStmt.cpp index a1aefee78bd..ad296eb3638 100644 --- a/clang/lib/Sema/SemaStmt.cpp +++ b/clang/lib/Sema/SemaStmt.cpp @@ -1043,7 +1043,8 @@ Sema::ActOnReturnStmt(SourceLocation ReturnLoc, ExprArg rex) { 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()) diff --git a/clang/lib/Sema/SemaType.cpp b/clang/lib/Sema/SemaType.cpp index 60f3b19060f..3ef13a2abaa 100644 --- a/clang/lib/Sema/SemaType.cpp +++ b/clang/lib/Sema/SemaType.cpp @@ -68,12 +68,41 @@ static bool isOmittedBlockReturnType(const Declarator &D) { 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 @@ static QualType ConvertDeclSpecToType(Declarator &TheDeclarator, Sema &TheSema){ // 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 @@ QualType Sema::GetTypeForDeclarator(Declarator &D, Scope *S, // 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 @@ QualType Sema::GetTypeForDeclarator(Declarator &D, Scope *S, 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 @@ QualType Sema::GetTypeForDeclarator(Declarator &D, Scope *S, 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 @@ QualType Sema::GetTypeForDeclarator(Declarator &D, Scope *S, 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 @@ 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, 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 @@ 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, @@ -1683,35 +1700,79 @@ static void HandleObjCGCTypeAttribute(QualType &Type, 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; + } - // We only apply this to a pointer to function or a pointer to block. - if (!Type->isFunctionPointerType() - && !Type->isBlockPointerType() - && !Type->isFunctionType()) - return; + // Delay if this is not a function or pointer to block. + if (!Type->isFunctionPointerType() + && !Type->isBlockPointerType() + && !Type->isFunctionType()) + return true; - Type = S.Context.getNoReturnType(Type); -} + // Otherwise we can process right away. + Type = S.Context.getNoReturnType(Type); + 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; + // Otherwise, a calling convention. + if (Attr.getNumArgs() != 0) { + S.Diag(Attr.getLoc(), diag::err_attribute_wrong_number_arguments) << 0; + return false; + } - // We only apply this to a pointer to function. - if (!Type->isFunctionPointerType() - && !Type->isFunctionType()) - 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; + } + + // 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 @@ static void HandleVectorSizeAttr(QualType& CurType, const AttributeList &Attr, S 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 @@ void Sema::ProcessTypeAttributeList(QualType &Result, const AttributeList *AL, // 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; } } |

