From: Chris Lattner Date: Sun, 29 Jun 2008 00:16:31 +0000 (+0000) Subject: Make ProcessDeclAttributes walk the declarator structure pulling X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=e5c5ee1cff9ec084f176fa252774262677857ad2;p=clang Make ProcessDeclAttributes walk the declarator structure pulling decl attributes out of the various places they can hide. This makes us correctly reject things like this: t.c:2:22: error: mode attribute only supported for integer and floating-point types int **__attribute((mode(HI)))* i32; ^ because you can't make a pointer be HImode. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@52876 91177308-0d34-0410-b5e6-96231b3b80d8 --- diff --git a/include/clang/Parse/DeclSpec.h b/include/clang/Parse/DeclSpec.h index 2524d882da..dc769951fe 100644 --- a/include/clang/Parse/DeclSpec.h +++ b/include/clang/Parse/DeclSpec.h @@ -457,6 +457,19 @@ struct DeclaratorChunk { }; + /// getAttrs - If there are attributes applied to this declaratorchunk, return + /// them. + const AttributeList *getAttrs() const { + switch (Kind) { + default: assert(0 && "Unknown declarator kind!"); + case Pointer: return Ptr.AttrList; + case Reference: return Ref.AttrList; + case Array: return 0; + case Function: return 0; + } + } + + /// getPointer - Return a DeclaratorChunk for a pointer. /// static DeclaratorChunk getPointer(unsigned TypeQuals, SourceLocation Loc, diff --git a/lib/Sema/Sema.h b/lib/Sema/Sema.h index da1747aab1..23f0cb6e5d 100644 --- a/lib/Sema/Sema.h +++ b/lib/Sema/Sema.h @@ -301,7 +301,7 @@ private: ScopedDecl *ImplicitlyDefineFunction(SourceLocation Loc, IdentifierInfo &II, Scope *S); // Decl attributes - this routine is the top level dispatcher. - void ProcessDeclAttributes(Decl *D, Declarator &PD); + void ProcessDeclAttributes(Decl *D, const Declarator &PD); void ProcessDeclAttributeList(Decl *D, const AttributeList *AttrList); void ProcessDeclAttribute(Decl *D, const AttributeList &Attr); diff --git a/lib/Sema/SemaDeclAttr.cpp b/lib/Sema/SemaDeclAttr.cpp index cdb5485666..28905314ee 100644 --- a/lib/Sema/SemaDeclAttr.cpp +++ b/lib/Sema/SemaDeclAttr.cpp @@ -16,9 +16,12 @@ #include "clang/Basic/TargetInfo.h" using namespace clang; +//===----------------------------------------------------------------------===// +// Helper functions +//===----------------------------------------------------------------------===// + static const FunctionTypeProto *getFunctionProto(Decl *d) { QualType Ty; - if (ValueDecl *decl = dyn_cast(d)) Ty = decl->getType(); else if (FieldDecl *decl = dyn_cast(d)) @@ -54,27 +57,44 @@ static inline bool isNSStringType(QualType T, ASTContext &Ctx) { ClsName == &Ctx.Idents.get("NSMutableString"); } -void Sema::ProcessDeclAttributes(Decl *D, Declarator &PD) { - const AttributeList *DeclSpecAttrs = PD.getDeclSpec().getAttributes(); - const AttributeList *DeclaratorAttrs = PD.getAttributes(); - - if (DeclSpecAttrs == 0 && DeclaratorAttrs == 0) return; +//===----------------------------------------------------------------------===// +// Top Level Sema Entry Points +//===----------------------------------------------------------------------===// - ProcessDeclAttributeList(D, DeclSpecAttrs); - - // If there are any type attributes that were in the declarator, apply them to - // its top level type. - if (ValueDecl *VD = dyn_cast(D)) { - QualType DT = VD->getType(); - ProcessTypeAttributes(DT, DeclaratorAttrs); - VD->setType(DT); - } else if (TypedefDecl *TD = dyn_cast(D)) { - QualType DT = TD->getUnderlyingType(); - ProcessTypeAttributes(DT, DeclaratorAttrs); - TD->setUnderlyingType(DT); +/// ProcessDeclAttributes - Given a declarator (PD) with attributes indicated in +/// it, apply them to D. This is a bit tricky because PD can have attributes +/// specified in many different places, and we need to find and apply them all. +void Sema::ProcessDeclAttributes(Decl *D, const Declarator &PD) { + // Apply decl attributes from the DeclSpec if present. + if (const AttributeList *Attrs = PD.getDeclSpec().getAttributes()) + ProcessDeclAttributeList(D, Attrs); + + // Walk the declarator structure, applying decl attributes that were in a type + // position to the decl itself. This handles cases like: + // int *__attr__(x)** D; + // when X is a decl attribute. + for (unsigned i = 0, e = PD.getNumTypeObjects(); i != e; ++i) + if (const AttributeList *Attrs = PD.getTypeObject(i).getAttrs()) + ProcessDeclAttributeList(D, Attrs); + + // Finally, apply any attributes on the decl itself. + if (const AttributeList *Attrs = PD.getAttributes()) { + ProcessDeclAttributeList(D, Attrs); + + // If there are any type attributes that were in the declarator, apply them to + // its top-level type. + // FIXME: we shouldn't allow type attributes here. :( + if (ValueDecl *VD = dyn_cast(D)) { + QualType DT = VD->getType(); + ProcessTypeAttributes(DT, Attrs); + VD->setType(DT); + } else if (TypedefDecl *TD = dyn_cast(D)) { + QualType DT = TD->getUnderlyingType(); + ProcessTypeAttributes(DT, Attrs); + TD->setUnderlyingType(DT); + } + // FIXME: field decl? } - - ProcessDeclAttributeList(D, DeclaratorAttrs); } /// ProcessDeclAttributeList - Apply all the decl attributes in the specified @@ -126,6 +146,10 @@ void Sema::ProcessDeclAttribute(Decl *D, const AttributeList &Attr) { } } +//===----------------------------------------------------------------------===// +// Attribute Implementations +//===----------------------------------------------------------------------===// + void Sema::HandleExtVectorTypeAttribute(Decl *d, const AttributeList &Attr) { TypedefDecl *tDecl = dyn_cast(d); if (tDecl == 0) { diff --git a/test/Sema/attr-mode.c b/test/Sema/attr-mode.c index 4eb1399071..0f8d5da24a 100644 --- a/test/Sema/attr-mode.c +++ b/test/Sema/attr-mode.c @@ -13,3 +13,5 @@ typedef int invalid_2 __attribute((mode())); // expected-error{{attribute requir typedef int invalid_3 __attribute((mode(II))); // expected-error{{unknown machine mode}} typedef struct {int i,j,k;} invalid_4 __attribute((mode(SI))); // expected-error{{mode attribute only supported for integer and floating-point types}} typedef float invalid_5 __attribute((mode(SI))); // expected-error{{type of machine mode does not match type of base type}} + +int **__attribute((mode(QI)))* i32; // expected-error{{mode attribute}}