From e82247a71a1a76e78f3b979b64d5f6412ab40266 Mon Sep 17 00:00:00 2001 From: John McCall Date: Sat, 1 Oct 2011 05:17:03 +0000 Subject: [PATCH] Hey, maybe we shouldn't silently ignore decl attributes on declarators written as types. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@140931 91177308-0d34-0410-b5e6-96231b3b80d8 --- include/clang/Basic/DiagnosticSemaKinds.td | 2 ++ include/clang/Sema/AttributeList.h | 13 +++++++--- include/clang/Sema/Sema.h | 2 ++ lib/Sema/SemaDeclAttr.cpp | 28 ++++++++++++++++++++++ lib/Sema/SemaExpr.cpp | 2 ++ lib/Sema/SemaType.cpp | 12 ++++++++++ test/Parser/MicrosoftExtensions.c | 4 ++-- test/Sema/types.c | 4 ++++ 8 files changed, 62 insertions(+), 5 deletions(-) diff --git a/include/clang/Basic/DiagnosticSemaKinds.td b/include/clang/Basic/DiagnosticSemaKinds.td index 017e4e68b4..14b36e4598 100644 --- a/include/clang/Basic/DiagnosticSemaKinds.td +++ b/include/clang/Basic/DiagnosticSemaKinds.td @@ -1435,6 +1435,8 @@ def warn_label_attribute_not_unused : Warning< def err_invalid_pcs : Error<"Invalid PCS type">; def err_attribute_can_be_applied_only_to_value_decl : Error< "%0 attribute can only be applied to value declarations">; +def warn_attribute_not_on_decl : Error< + "%0 attribute ignored when parsing type">; // Availability attribute diff --git a/include/clang/Sema/AttributeList.h b/include/clang/Sema/AttributeList.h index c02d89dd11..46fcabc8e8 100644 --- a/include/clang/Sema/AttributeList.h +++ b/include/clang/Sema/AttributeList.h @@ -73,6 +73,9 @@ private: /// True if already diagnosed as invalid. mutable unsigned Invalid : 1; + /// True if this attribute was used as a type attribute. + mutable unsigned UsedAsTypeAttr : 1; + /// True if this has the extra information associated with an /// availability attribute. unsigned IsAvailability : 1; @@ -123,7 +126,8 @@ private: AttrRange(attrRange), ScopeLoc(scopeLoc), ParmLoc(parmLoc), NumArgs(numArgs), DeclspecAttribute(declspec), CXX0XAttribute(cxx0x), Invalid(false), - IsAvailability(false), NextInPosition(0), NextInPool(0) { + UsedAsTypeAttr(false), IsAvailability(false), + NextInPosition(0), NextInPool(0) { if (numArgs) memcpy(getArgsBuffer(), args, numArgs * sizeof(Expr*)); AttrKind = getKind(getName()); } @@ -139,8 +143,8 @@ private: : AttrName(attrName), ScopeName(scopeName), ParmName(parmName), AttrRange(attrRange), ScopeLoc(scopeLoc), ParmLoc(parmLoc), NumArgs(0), DeclspecAttribute(declspec), CXX0XAttribute(cxx0x), - Invalid(false), IsAvailability(true), UnavailableLoc(unavailable), - NextInPosition(0), NextInPool(0) { + Invalid(false), UsedAsTypeAttr(false), IsAvailability(true), + UnavailableLoc(unavailable), NextInPosition(0), NextInPool(0) { new (&getAvailabilitySlot(IntroducedSlot)) AvailabilityChange(introduced); new (&getAvailabilitySlot(DeprecatedSlot)) AvailabilityChange(deprecated); new (&getAvailabilitySlot(ObsoletedSlot)) AvailabilityChange(obsoleted); @@ -287,6 +291,9 @@ public: bool isInvalid() const { return Invalid; } void setInvalid(bool b = true) const { Invalid = b; } + bool isUsedAsTypeAttr() const { return UsedAsTypeAttr; } + void setUsedAsTypeAttr() { UsedAsTypeAttr = true; } + Kind getKind() const { return Kind(AttrKind); } static Kind getKind(const IdentifierInfo *Name); diff --git a/include/clang/Sema/Sema.h b/include/clang/Sema/Sema.h index cf3219042f..684bfc969b 100644 --- a/include/clang/Sema/Sema.h +++ b/include/clang/Sema/Sema.h @@ -1829,6 +1829,8 @@ public: void ProcessDeclAttributeList(Scope *S, Decl *D, const AttributeList *AL, bool NonInheritable = true, bool Inheritable = true); + void checkUnusedDeclAttributes(Declarator &D); + bool CheckRegparmAttr(const AttributeList &attr, unsigned &value); bool CheckCallingConvAttr(const AttributeList &attr, CallingConv &CC); bool CheckNoReturnAttr(const AttributeList &attr); diff --git a/lib/Sema/SemaDeclAttr.cpp b/lib/Sema/SemaDeclAttr.cpp index 5802aaad96..d9e4df058d 100644 --- a/lib/Sema/SemaDeclAttr.cpp +++ b/lib/Sema/SemaDeclAttr.cpp @@ -3719,6 +3719,34 @@ void Sema::ProcessDeclAttributeList(Scope *S, Decl *D, } } +/// checkUnusedDeclAttributes - Check a list of attributes to see if it +/// contains any decl attributes that we should warn about. +static void checkUnusedDeclAttributes(Sema &S, const AttributeList *A) { + for ( ; A; A = A->getNext()) { + // Only warn if the attribute is an unignored, non-type attribute. + if (A->isUsedAsTypeAttr()) continue; + if (A->getKind() == AttributeList::IgnoredAttribute) continue; + + if (A->getKind() == AttributeList::UnknownAttribute) { + S.Diag(A->getLoc(), diag::warn_unknown_attribute_ignored) + << A->getName() << A->getRange(); + } else { + S.Diag(A->getLoc(), diag::warn_attribute_not_on_decl) + << A->getName() << A->getRange(); + } + } +} + +/// checkUnusedDeclAttributes - Given a declarator which is not being +/// used to build a declaration, complain about any decl attributes +/// which might be lying around on it. +void Sema::checkUnusedDeclAttributes(Declarator &D) { + ::checkUnusedDeclAttributes(*this, D.getDeclSpec().getAttributes().getList()); + ::checkUnusedDeclAttributes(*this, D.getAttributes()); + for (unsigned i = 0, e = D.getNumTypeObjects(); i != e; ++i) + ::checkUnusedDeclAttributes(*this, D.getTypeObject(i).getAttrs()); +} + /// DeclClonePragmaWeak - clone existing decl (maybe definition), /// #pragma weak needs a non-definition decl and source may not have one NamedDecl * Sema::DeclClonePragmaWeak(NamedDecl *ND, IdentifierInfo *II, diff --git a/lib/Sema/SemaExpr.cpp b/lib/Sema/SemaExpr.cpp index 0fea54b77d..d0a3f6b5ec 100644 --- a/lib/Sema/SemaExpr.cpp +++ b/lib/Sema/SemaExpr.cpp @@ -4291,6 +4291,8 @@ Sema::ActOnCastExpr(Scope *S, SourceLocation LParenLoc, CheckExtraCXXDefaultArguments(D); } + checkUnusedDeclAttributes(D); + QualType castType = castTInfo->getType(); Ty = CreateParsedType(castType, castTInfo); diff --git a/lib/Sema/SemaType.cpp b/lib/Sema/SemaType.cpp index 25ec0b1477..9707804cf0 100644 --- a/lib/Sema/SemaType.cpp +++ b/lib/Sema/SemaType.cpp @@ -3064,6 +3064,9 @@ TypeResult Sema::ActOnTypeName(Scope *S, Declarator &D) { if (D.isInvalidType()) return true; + // Make sure there are no unused decl attributes on the declarator. + checkUnusedDeclAttributes(D); + if (getLangOptions().CPlusPlus) { // Check that there are no default arguments (C++ only). CheckExtraCXXDefaultArguments(D); @@ -3758,30 +3761,37 @@ static void processTypeAttrs(TypeProcessingState &state, QualType &type, case AttributeList::AT_address_space: HandleAddressSpaceTypeAttribute(type, attr, state.getSema()); + attr.setUsedAsTypeAttr(); break; OBJC_POINTER_TYPE_ATTRS_CASELIST: if (!handleObjCPointerTypeAttr(state, attr, type)) distributeObjCPointerTypeAttr(state, attr, type); + attr.setUsedAsTypeAttr(); break; case AttributeList::AT_vector_size: HandleVectorSizeAttr(type, attr, state.getSema()); + attr.setUsedAsTypeAttr(); break; case AttributeList::AT_ext_vector_type: if (state.getDeclarator().getDeclSpec().getStorageClassSpec() != DeclSpec::SCS_typedef) HandleExtVectorTypeAttr(type, attr, state.getSema()); + attr.setUsedAsTypeAttr(); break; case AttributeList::AT_neon_vector_type: HandleNeonVectorTypeAttr(type, attr, state.getSema(), VectorType::NeonVector, "neon_vector_type"); + attr.setUsedAsTypeAttr(); break; case AttributeList::AT_neon_polyvector_type: HandleNeonVectorTypeAttr(type, attr, state.getSema(), VectorType::NeonPolyVector, "neon_polyvector_type"); + attr.setUsedAsTypeAttr(); break; case AttributeList::AT_opencl_image_access: HandleOpenCLImageAccessAttribute(type, attr, state.getSema()); + attr.setUsedAsTypeAttr(); break; case AttributeList::AT_ns_returns_retained: @@ -3790,6 +3800,8 @@ static void processTypeAttrs(TypeProcessingState &state, QualType &type, // fallthrough into the function attrs FUNCTION_TYPE_ATTRS_CASELIST: + attr.setUsedAsTypeAttr(); + // Never process function type attributes as part of the // declaration-specifiers. if (isDeclSpec) diff --git a/test/Parser/MicrosoftExtensions.c b/test/Parser/MicrosoftExtensions.c index d03ada84b9..a0f15e9d86 100644 --- a/test/Parser/MicrosoftExtensions.c +++ b/test/Parser/MicrosoftExtensions.c @@ -11,11 +11,11 @@ typedef __w64 unsigned long ULONG_PTR, *PULONG_PTR; void * __ptr64 PtrToPtr64(const void *p) { - return((void * __ptr64) (unsigned __int64) (ULONG_PTR)p ); + return((void * __ptr64) (unsigned __int64) (ULONG_PTR)p ); // expected-warning {{unknown attribute '__ptr64' ignored}} } void * __ptr32 PtrToPtr32(const void *p) { - return((void * __ptr32) (unsigned __int32) (ULONG_PTR)p ); + return((void * __ptr32) (unsigned __int32) (ULONG_PTR)p ); // expected-warning {{unknown attribute '__ptr32' ignored}} } void __forceinline InterlockedBitTestAndSet (long *Base, long Bit) diff --git a/test/Sema/types.c b/test/Sema/types.c index f3244f7799..33305abe02 100644 --- a/test/Sema/types.c +++ b/test/Sema/types.c @@ -37,3 +37,7 @@ _Decimal32 x; // expected-error {{GNU decimal type extension not supported}} // rdar://6880951 int __attribute__ ((vector_size (8), vector_size (8))) v; // expected-error {{invalid vector element type}} + +void test(int i) { + char c = (char __attribute__((align(8)))) i; // expected-error {{'align' attribute ignored when parsing type}} +} -- 2.50.1