From 3068ae0feb5d477477f45045f7ec9d0414fe57f3 Mon Sep 17 00:00:00 2001 From: Daniel Dunbar Date: Thu, 31 Jul 2008 22:40:48 +0000 Subject: [PATCH] Support __attribute__(({con,de}structor)) in Parse & Sema - Including possible priority argument - In other news, the attribute parsing code really needs a cleanup git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@54257 91177308-0d34-0410-b5e6-96231b3b80d8 --- include/clang/AST/Attr.h | 22 +++++++ include/clang/Parse/AttributeList.h | 2 + lib/Parse/AttributeList.cpp | 3 + lib/Sema/SemaDeclAttr.cpp | 94 ++++++++++++++++++++++++----- test/Sema/constructor-attribute.c | 15 +++++ 5 files changed, 121 insertions(+), 15 deletions(-) create mode 100644 test/Sema/constructor-attribute.c diff --git a/include/clang/AST/Attr.h b/include/clang/AST/Attr.h index 0ae0acb878..ac00422482 100644 --- a/include/clang/AST/Attr.h +++ b/include/clang/AST/Attr.h @@ -28,7 +28,9 @@ public: Alias, Aligned, Annotate, + Constructor, Deprecated, + Destructor, DLLImport, DLLExport, FastCall, @@ -125,7 +127,27 @@ public: static bool classof(const Attr *A) { return A->getKind() == Alias; } static bool classof(const AliasAttr *A) { return true; } }; + +class ConstructorAttr : public Attr { + int priority; +public: + ConstructorAttr(int p) : Attr(Constructor), priority(p) {} + + // Implement isa/cast/dyncast/etc. + static bool classof(const Attr *A) { return A->getKind() == Constructor; } + static bool classof(const ConstructorAttr *A) { return true; } +}; +class DestructorAttr : public Attr { + int priority; +public: + DestructorAttr(int p) : Attr(Destructor), priority(p) {} + + // Implement isa/cast/dyncast/etc. + static bool classof(const Attr *A) { return A->getKind() == Destructor; } + static bool classof(const DestructorAttr *A) { return true; } +}; + class IBOutletAttr : public Attr { public: IBOutletAttr() : Attr(IBOutletKind) {} diff --git a/include/clang/Parse/AttributeList.h b/include/clang/Parse/AttributeList.h index 202e499f06..0b27860699 100644 --- a/include/clang/Parse/AttributeList.h +++ b/include/clang/Parse/AttributeList.h @@ -46,7 +46,9 @@ public: AT_alias, AT_aligned, AT_annotate, + AT_constructor, AT_deprecated, + AT_destructor, AT_dllimport, AT_dllexport, AT_ext_vector_type, diff --git a/lib/Parse/AttributeList.cpp b/lib/Parse/AttributeList.cpp index 0eaba66514..b120f7eda8 100644 --- a/lib/Parse/AttributeList.cpp +++ b/lib/Parse/AttributeList.cpp @@ -50,6 +50,7 @@ AttributeList::Kind AttributeList::getKind(const IdentifierInfo *Name) { Len -= 4; } + // FIXME: Hand generating this is neither smart nor efficient. switch (Len) { case 4: if (!memcmp(Str, "weak", 4)) return AT_weak; @@ -85,9 +86,11 @@ AttributeList::Kind AttributeList::getKind(const IdentifierInfo *Name) { case 10: if (!memcmp(Str, "deprecated", 10)) return AT_deprecated; if (!memcmp(Str, "visibility", 10)) return AT_visibility; + if (!memcmp(Str, "destructor", 10)) return AT_destructor; break; case 11: if (!memcmp(Str, "vector_size", 11)) return AT_vector_size; + if (!memcmp(Str, "constructor", 11)) return AT_constructor; break; case 13: if (!memcmp(Str, "address_space", 13)) return AT_address_space; diff --git a/lib/Sema/SemaDeclAttr.cpp b/lib/Sema/SemaDeclAttr.cpp index e6a7ce654f..3f9da3bebe 100644 --- a/lib/Sema/SemaDeclAttr.cpp +++ b/lib/Sema/SemaDeclAttr.cpp @@ -61,6 +61,10 @@ static inline bool isNSStringType(QualType T, ASTContext &Ctx) { // Attribute Implementations //===----------------------------------------------------------------------===// +// FIXME: All this manual attribute parsing code is gross. At the +// least add some helper functions to check most argument patterns (# +// and types of args). + static void HandleExtVectorTypeAttr(Decl *d, const AttributeList &Attr, Sema &S) { TypedefDecl *tDecl = dyn_cast(d); @@ -353,6 +357,64 @@ static void HandleUnusedAttr(Decl *d, const AttributeList &Attr, Sema &S) { d->addAttr(new UnusedAttr()); } +static void HandleConstructorAttr(Decl *d, const AttributeList &Attr, Sema &S) { + // check the attribute arguments. + if (Attr.getNumArgs() != 0 && Attr.getNumArgs() != 1) { + S.Diag(Attr.getLoc(), diag::err_attribute_wrong_number_arguments, "0 or 1"); + return; + } + + int priority = 65535; // FIXME: Do not hardcode such constants. + if (Attr.getNumArgs() > 0) { + Expr *E = static_cast(Attr.getArg(0)); + llvm::APSInt Idx(32); + if (!E->isIntegerConstantExpr(Idx, S.Context)) { + S.Diag(Attr.getLoc(), diag::err_attribute_argument_n_not_int, + "constructor", "1", E->getSourceRange()); + return; + } + priority = Idx.getZExtValue(); + } + + FunctionDecl *Fn = dyn_cast(d); + if (!Fn) { + S.Diag(Attr.getLoc(), diag::warn_attribute_wrong_decl_type, + "constructor", "function"); + return; + } + + d->addAttr(new ConstructorAttr(priority)); +} + +static void HandleDestructorAttr(Decl *d, const AttributeList &Attr, Sema &S) { + // check the attribute arguments. + if (Attr.getNumArgs() != 0 && Attr.getNumArgs() != 1) { + S.Diag(Attr.getLoc(), diag::err_attribute_wrong_number_arguments, "0 or 1"); + return; + } + + int priority = 65535; // FIXME: Do not hardcode such constants. + if (Attr.getNumArgs() > 0) { + Expr *E = static_cast(Attr.getArg(0)); + llvm::APSInt Idx(32); + if (!E->isIntegerConstantExpr(Idx, S.Context)) { + S.Diag(Attr.getLoc(), diag::err_attribute_argument_n_not_int, + "destructor", "1", E->getSourceRange()); + return; + } + priority = Idx.getZExtValue(); + } + + FunctionDecl *Fn = dyn_cast(d); + if (!Fn) { + S.Diag(Attr.getLoc(), diag::warn_attribute_wrong_decl_type, + "destructor", "function"); + return; + } + + d->addAttr(new DestructorAttr(priority)); +} + static void HandleDeprecatedAttr(Decl *d, const AttributeList &Attr, Sema &S) { // check the attribute arguments. if (Attr.getNumArgs() != 0) { @@ -816,31 +878,33 @@ static void HandleModeAttr(Decl *D, const AttributeList &Attr, Sema &S) { /// silently ignore it. static void ProcessDeclAttribute(Decl *D, const AttributeList &Attr, Sema &S) { switch (Attr.getKind()) { + case AttributeList::AT_IBOutlet: HandleIBOutletAttr (D, Attr, S); break; case AttributeList::AT_address_space: // Ignore this, this is a type attribute, handled by ProcessTypeAttributes. break; - case AttributeList::AT_ext_vector_type: - HandleExtVectorTypeAttr(D, Attr, S); - break; - case AttributeList::AT_vector_size: HandleVectorSizeAttr(D, Attr, S); break; - case AttributeList::AT_mode: HandleModeAttr (D, Attr, S); break; case AttributeList::AT_alias: HandleAliasAttr (D, Attr, S); break; + case AttributeList::AT_aligned: HandleAlignedAttr (D, Attr, S); break; + case AttributeList::AT_annotate: HandleAnnotateAttr (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_visibility: HandleVisibilityAttr(D, Attr, S); break; - case AttributeList::AT_weak: HandleWeakAttr (D, Attr, S); break; - case AttributeList::AT_dllimport: HandleDLLImportAttr (D, Attr, S); break; + case AttributeList::AT_destructor: HandleDestructorAttr(D, Attr, S); break; case AttributeList::AT_dllexport: HandleDLLExportAttr (D, Attr, S); break; - case AttributeList::AT_nothrow: HandleNothrowAttr (D, Attr, S); break; - case AttributeList::AT_stdcall: HandleStdCallAttr (D, Attr, S); break; + case AttributeList::AT_dllimport: HandleDLLImportAttr (D, Attr, S); break; + case AttributeList::AT_ext_vector_type: + HandleExtVectorTypeAttr(D, Attr, S); + break; case AttributeList::AT_fastcall: HandleFastCallAttr (D, Attr, S); break; - case AttributeList::AT_aligned: HandleAlignedAttr (D, Attr, S); break; - case AttributeList::AT_packed: HandlePackedAttr (D, Attr, S); break; - case AttributeList::AT_annotate: HandleAnnotateAttr (D, Attr, S); break; - case AttributeList::AT_noreturn: HandleNoReturnAttr (D, Attr, S); break; case AttributeList::AT_format: HandleFormatAttr (D, Attr, S); break; - case AttributeList::AT_IBOutlet: HandleIBOutletAttr (D, Attr, S); break; + case AttributeList::AT_mode: HandleModeAttr (D, Attr, S); break; case AttributeList::AT_nonnull: HandleNonNullAttr (D, Attr, S); break; + case AttributeList::AT_noreturn: HandleNoReturnAttr (D, Attr, S); break; + case AttributeList::AT_nothrow: HandleNothrowAttr (D, Attr, S); break; + case AttributeList::AT_packed: HandlePackedAttr (D, Attr, S); break; + case AttributeList::AT_stdcall: HandleStdCallAttr (D, Attr, S); break; case AttributeList::AT_unused: HandleUnusedAttr (D, Attr, S); break; + case AttributeList::AT_vector_size: HandleVectorSizeAttr(D, Attr, S); break; + case AttributeList::AT_visibility: HandleVisibilityAttr(D, Attr, S); break; + case AttributeList::AT_weak: HandleWeakAttr (D, Attr, S); break; case AttributeList::AT_transparent_union: HandleTransparentUnionAttr(D, Attr, S); break; diff --git a/test/Sema/constructor-attribute.c b/test/Sema/constructor-attribute.c new file mode 100644 index 0000000000..3f240b02e5 --- /dev/null +++ b/test/Sema/constructor-attribute.c @@ -0,0 +1,15 @@ +// RUN: clang -fsyntax-only -verify %s + +int x __attribute__((constructor)); // expected-warning {{'constructor' attribute only applies to function types}} +int f() __attribute__((constructor)); +int f() __attribute__((constructor(1))); +int f() __attribute__((constructor(1,2))); // expected-error {{attribute requires 0 or 1 argument(s)}} +int f() __attribute__((constructor(1.0))); // expected-error {{'constructor' attribute requires parameter 1 to be an integer constant}} + +int x __attribute__((destructor)); // expected-warning {{'destructor' attribute only applies to function types}} +int f() __attribute__((destructor)); +int f() __attribute__((destructor(1))); +int f() __attribute__((destructor(1,2))); // expected-error {{attribute requires 0 or 1 argument(s)}} +int f() __attribute__((destructor(1.0))); // expected-error {{'destructor' attribute requires parameter 1 to be an integer constant}} + + -- 2.40.0