Support __attribute__(({con,de}structor)) in Parse & Sema
- Including possible priority argument - In other news, the attribute parsing code really needs a cleanup llvm-svn: 54257
This commit is contained in:
parent
a7045d663d
commit
032db47f0f
|
@ -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) {}
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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<TypedefDecl>(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<Expr *>(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<FunctionDecl>(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<Expr *>(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<FunctionDecl>(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_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_destructor: HandleDestructorAttr(D, Attr, S); break;
|
||||
case AttributeList::AT_dllexport: HandleDLLExportAttr (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_vector_size: HandleVectorSizeAttr(D, Attr, S); break;
|
||||
case AttributeList::AT_fastcall: HandleFastCallAttr (D, Attr, S); break;
|
||||
case AttributeList::AT_format: HandleFormatAttr (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_deprecated: HandleDeprecatedAttr(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_dllimport: HandleDLLImportAttr (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_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_nonnull: HandleNonNullAttr (D, Attr, S); break;
|
||||
case AttributeList::AT_unused: HandleUnusedAttr (D, Attr, S); break;
|
||||
case AttributeList::AT_transparent_union:
|
||||
HandleTransparentUnionAttr(D, Attr, S);
|
||||
break;
|
||||
|
|
|
@ -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}}
|
||||
|
||||
|
Loading…
Reference in New Issue