From: Abramo Bagnara Date: Fri, 30 Apr 2010 13:10:51 +0000 (+0000) Subject: Add calling convention related attributes to related declaration. Mark attributes... X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=e215f7232dd4aa65ebf2a1ecd07cd95fe1ce3481;p=clang Add calling convention related attributes to related declaration. Mark attributes invalid on type related checking so to add them to declarations only when everything is ok. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@102710 91177308-0d34-0410-b5e6-96231b3b80d8 --- diff --git a/include/clang/Parse/AttributeList.h b/include/clang/Parse/AttributeList.h index 37acab9b01..12512f33c7 100644 --- a/include/clang/Parse/AttributeList.h +++ b/include/clang/Parse/AttributeList.h @@ -41,6 +41,7 @@ class AttributeList { unsigned NumArgs; AttributeList *Next; bool DeclspecAttribute, CXX0XAttribute; + mutable bool Invalid; /// True if already diagnosed as invalid. AttributeList(const AttributeList &); // DO NOT IMPLEMENT void operator=(const AttributeList &); // DO NOT IMPLEMENT public: @@ -128,6 +129,9 @@ public: bool isDeclspecAttribute() const { return DeclspecAttribute; } bool isCXX0XAttribute() const { return CXX0XAttribute; } + bool isInvalid() const { return Invalid; } + void setInvalid(bool b = true) const { Invalid = b; } + Kind getKind() const { return getKind(getName()); } static Kind getKind(const IdentifierInfo *Name); diff --git a/lib/Parse/AttributeList.cpp b/lib/Parse/AttributeList.cpp index 0ab67107fa..bae2a09a98 100644 --- a/lib/Parse/AttributeList.cpp +++ b/lib/Parse/AttributeList.cpp @@ -23,7 +23,7 @@ AttributeList::AttributeList(IdentifierInfo *aName, SourceLocation aLoc, AttributeList *n, bool declspec, bool cxx0x) : AttrName(aName), AttrLoc(aLoc), ScopeName(sName), ScopeLoc(sLoc), ParmName(pName), ParmLoc(pLoc), NumArgs(numArgs), Next(n), - DeclspecAttribute(declspec), CXX0XAttribute(cxx0x) { + DeclspecAttribute(declspec), CXX0XAttribute(cxx0x), Invalid(false) { if (numArgs == 0) Args = 0; diff --git a/lib/Sema/SemaDeclAttr.cpp b/lib/Sema/SemaDeclAttr.cpp index 52d9f58d37..90aa9c1c13 100644 --- a/lib/Sema/SemaDeclAttr.cpp +++ b/lib/Sema/SemaDeclAttr.cpp @@ -467,11 +467,10 @@ static void HandleMallocAttr(Decl *d, const AttributeList &Attr, Sema &S) { } static bool HandleCommonNoReturnAttr(Decl *d, const AttributeList &Attr, - Sema &S, bool EmitDiagnostics) { + Sema &S) { // check the attribute arguments. if (Attr.getNumArgs() != 0) { - if (EmitDiagnostics) - S.Diag(Attr.getLoc(), diag::err_attribute_wrong_number_arguments) << 0; + S.Diag(Attr.getLoc(), diag::err_attribute_wrong_number_arguments) << 0; return false; } @@ -479,11 +478,10 @@ static bool HandleCommonNoReturnAttr(Decl *d, const AttributeList &Attr, ValueDecl *VD = dyn_cast(d); if (VD == 0 || (!VD->getType()->isBlockPointerType() && !VD->getType()->isFunctionPointerType())) { - if (EmitDiagnostics) - S.Diag(Attr.getLoc(), - Attr.isCXX0XAttribute() ? diag::err_attribute_wrong_decl_type - : diag::warn_attribute_wrong_decl_type) - << Attr.getName() << 0 /*function*/; + S.Diag(Attr.getLoc(), + Attr.isCXX0XAttribute() ? diag::err_attribute_wrong_decl_type + : diag::warn_attribute_wrong_decl_type) + << Attr.getName() << 0 /*function*/; return false; } } @@ -492,17 +490,14 @@ static bool HandleCommonNoReturnAttr(Decl *d, const AttributeList &Attr, } static void HandleNoReturnAttr(Decl *d, const AttributeList &Attr, Sema &S) { - /* - Do check for well-formedness, but do not emit diagnostics: - it was already emitted by Sema::ProcessFnAttr(). - */ - if (HandleCommonNoReturnAttr(d, Attr, S, /*EmitDiagnostic=*/false)) - d->addAttr(::new (S.Context) NoReturnAttr()); + /* Diagnostics (if any) was emitted by Sema::ProcessFnAttr(). */ + assert(Attr.isInvalid() == false); + d->addAttr(::new (S.Context) NoReturnAttr()); } static void HandleAnalyzerNoReturnAttr(Decl *d, const AttributeList &Attr, Sema &S) { - if (HandleCommonNoReturnAttr(d, Attr, S, true)) + if (HandleCommonNoReturnAttr(d, Attr, S)) d->addAttr(::new (S.Context) AnalyzerNoReturnAttr()); } @@ -1647,6 +1642,27 @@ static void HandleGNUInlineAttr(Decl *d, const AttributeList &Attr, Sema &S) { d->addAttr(::new (S.Context) GNUInlineAttr()); } +static void HandleCallConvAttr(Decl *d, const AttributeList &Attr, Sema &S) { + // Diagnostic is emitted elsewhere: here we store the (valid) Attr + // in the Decl node for syntactic reasoning, e.g., pretty-printing. + assert(Attr.isInvalid() == false); + + switch (Attr.getKind()) { + case AttributeList::AT_fastcall: + d->addAttr(::new (S.Context) FastCallAttr()); + return; + case AttributeList::AT_stdcall: + d->addAttr(::new (S.Context) StdCallAttr()); + return; + case AttributeList::AT_cdecl: + d->addAttr(::new (S.Context) CDeclAttr()); + return; + default: + llvm_unreachable("unexpected attribute kind"); + return; + } +} + static void HandleRegparmAttr(Decl *d, const AttributeList &Attr, Sema &S) { // check the attribute arguments. if (Attr.getNumArgs() != 1) { @@ -1847,6 +1863,9 @@ static bool isKnownDeclSpecAttr(const AttributeList &Attr) { /// the wrong thing is illegal (C++0x [dcl.attr.grammar]/4). static void ProcessDeclAttribute(Scope *scope, Decl *D, const AttributeList &Attr, Sema &S) { + if (Attr.isInvalid()) + return; + if (Attr.isDeclspecAttribute() && !isKnownDeclSpecAttr(Attr)) // FIXME: Try to deal with other __declspec attributes! return; @@ -1931,7 +1950,7 @@ static void ProcessDeclAttribute(Scope *scope, Decl *D, case AttributeList::AT_stdcall: case AttributeList::AT_cdecl: case AttributeList::AT_fastcall: - // These are all treated as type attributes. + HandleCallConvAttr(D, Attr, S); break; default: // Ask target about the attribute. diff --git a/lib/Sema/SemaType.cpp b/lib/Sema/SemaType.cpp index dc78fd633f..d1a74beb53 100644 --- a/lib/Sema/SemaType.cpp +++ b/lib/Sema/SemaType.cpp @@ -81,9 +81,12 @@ 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)) + if (ProcessFnAttr(S, Type, *I->first)) { S.Diag(I->first->getLoc(), diag::warn_function_attribute_wrong_type) << I->first->getName() << I->second; + // Avoid any further processing of this attribute. + I->first->setInvalid(); + } Attrs.clear(); } @@ -92,6 +95,8 @@ static void DiagnoseDelayedFnAttrs(Sema &S, DelayedAttributeSet &Attrs) { E = Attrs.end(); I != E; ++I) { S.Diag(I->first->getLoc(), diag::warn_function_attribute_wrong_type) << I->first->getName() << I->second; + // Avoid any further processing of this attribute. + I->first->setInvalid(); } Attrs.clear(); } @@ -1687,12 +1692,14 @@ static void HandleAddressSpaceTypeAttribute(QualType &Type, // for two or more different address spaces." if (Type.getAddressSpace()) { S.Diag(Attr.getLoc(), diag::err_attribute_address_multiple_qualifiers); + Attr.setInvalid(); return; } // Check the attribute arguments. if (Attr.getNumArgs() != 1) { S.Diag(Attr.getLoc(), diag::err_attribute_wrong_number_arguments) << 1; + Attr.setInvalid(); return; } Expr *ASArgExpr = static_cast(Attr.getArg(0)); @@ -1700,6 +1707,7 @@ static void HandleAddressSpaceTypeAttribute(QualType &Type, if (!ASArgExpr->isIntegerConstantExpr(addrSpace, S.Context)) { S.Diag(Attr.getLoc(), diag::err_attribute_address_space_not_int) << ASArgExpr->getSourceRange(); + Attr.setInvalid(); return; } @@ -1708,6 +1716,7 @@ static void HandleAddressSpaceTypeAttribute(QualType &Type, if (addrSpace.isNegative()) { S.Diag(Attr.getLoc(), diag::err_attribute_address_space_negative) << ASArgExpr->getSourceRange(); + Attr.setInvalid(); return; } addrSpace.setIsSigned(false); @@ -1717,6 +1726,7 @@ static void HandleAddressSpaceTypeAttribute(QualType &Type, if (addrSpace > max) { S.Diag(Attr.getLoc(), diag::err_attribute_address_space_too_high) << Qualifiers::MaxAddressSpace << ASArgExpr->getSourceRange(); + Attr.setInvalid(); return; } @@ -1730,6 +1740,7 @@ static void HandleObjCGCTypeAttribute(QualType &Type, const AttributeList &Attr, Sema &S) { if (Type.getObjCGCAttr() != Qualifiers::GCNone) { S.Diag(Attr.getLoc(), diag::err_attribute_multiple_objc_gc); + Attr.setInvalid(); return; } @@ -1737,11 +1748,13 @@ static void HandleObjCGCTypeAttribute(QualType &Type, if (!Attr.getParameterName()) { S.Diag(Attr.getLoc(), diag::err_attribute_argument_n_not_string) << "objc_gc" << 1; + Attr.setInvalid(); return; } Qualifiers::GC GCAttr; if (Attr.getNumArgs() != 0) { S.Diag(Attr.getLoc(), diag::err_attribute_wrong_number_arguments) << 1; + Attr.setInvalid(); return; } if (Attr.getParameterName()->isStr("weak")) @@ -1751,6 +1764,7 @@ static void HandleObjCGCTypeAttribute(QualType &Type, else { S.Diag(Attr.getLoc(), diag::warn_attribute_type_not_supported) << "objc_gc" << Attr.getParameterName(); + Attr.setInvalid(); return; } @@ -1764,6 +1778,7 @@ bool ProcessFnAttr(Sema &S, QualType &Type, const AttributeList &Attr) { // Complain immediately if the arg count is wrong. if (Attr.getNumArgs() != 0) { S.Diag(Attr.getLoc(), diag::err_attribute_wrong_number_arguments) << 0; + Attr.setInvalid(); return false; } @@ -1805,6 +1820,7 @@ bool ProcessFnAttr(Sema &S, QualType &Type, const AttributeList &Attr) { // Otherwise, a calling convention. if (Attr.getNumArgs() != 0) { S.Diag(Attr.getLoc(), diag::err_attribute_wrong_number_arguments) << 0; + Attr.setInvalid(); return false; } @@ -1827,13 +1843,17 @@ bool ProcessFnAttr(Sema &S, QualType &Type, const AttributeList &Attr) { CallingConv CCOld = Fn->getCallConv(); if (S.Context.getCanonicalCallConv(CC) == - S.Context.getCanonicalCallConv(CCOld)) return false; + S.Context.getCanonicalCallConv(CCOld)) { + Attr.setInvalid(); + 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); + Attr.setInvalid(); return false; } @@ -1842,6 +1862,7 @@ bool ProcessFnAttr(Sema &S, QualType &Type, const AttributeList &Attr) { if (isa(Fn)) { S.Diag(Attr.getLoc(), diag::err_cconv_knr) << FunctionType::getNameForCallConv(CC); + Attr.setInvalid(); return false; } @@ -1849,6 +1870,7 @@ bool ProcessFnAttr(Sema &S, QualType &Type, const AttributeList &Attr) { if (FnP->isVariadic()) { S.Diag(Attr.getLoc(), diag::err_cconv_varargs) << FunctionType::getNameForCallConv(CC); + Attr.setInvalid(); return false; } } @@ -1868,6 +1890,7 @@ static void HandleVectorSizeAttr(QualType& CurType, const AttributeList &Attr, S // Check the attribute arugments. if (Attr.getNumArgs() != 1) { S.Diag(Attr.getLoc(), diag::err_attribute_wrong_number_arguments) << 1; + Attr.setInvalid(); return; } Expr *sizeExpr = static_cast(Attr.getArg(0)); @@ -1875,12 +1898,14 @@ static void HandleVectorSizeAttr(QualType& CurType, const AttributeList &Attr, S if (!sizeExpr->isIntegerConstantExpr(vecSize, S.Context)) { S.Diag(Attr.getLoc(), diag::err_attribute_argument_not_int) << "vector_size" << sizeExpr->getSourceRange(); + Attr.setInvalid(); return; } // the base type must be integer or float, and can't already be a vector. if (CurType->isVectorType() || (!CurType->isIntegerType() && !CurType->isRealFloatingType())) { S.Diag(Attr.getLoc(), diag::err_attribute_invalid_vector_type) << CurType; + Attr.setInvalid(); return; } unsigned typeSize = static_cast(S.Context.getTypeSize(CurType)); @@ -1891,11 +1916,13 @@ static void HandleVectorSizeAttr(QualType& CurType, const AttributeList &Attr, S if (vectorSize % typeSize) { S.Diag(Attr.getLoc(), diag::err_attribute_invalid_size) << sizeExpr->getSourceRange(); + Attr.setInvalid(); return; } if (vectorSize == 0) { S.Diag(Attr.getLoc(), diag::err_attribute_zero_size) << sizeExpr->getSourceRange(); + Attr.setInvalid(); return; } @@ -1912,6 +1939,10 @@ void ProcessTypeAttributeList(Sema &S, QualType &Result, // type, but others can be present in the type specifiers even though they // apply to the decl. Here we apply type attributes and ignore the rest. for (; AL; AL = AL->getNext()) { + // Skip attributes that were marked to be invalid. + if (AL->isInvalid()) + continue; + // If this is an attribute we can handle, do so now, // otherwise, add it to the FnAttrs list for rechaining. switch (AL->getKind()) {