зеркало из https://github.com/microsoft/clang-1.git
Add sema support for the cleanup attribute.
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@63462 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
Родитель
dd0db2a60b
Коммит
f6e35d0b9f
|
@ -52,7 +52,8 @@ public:
|
||||||
Weak,
|
Weak,
|
||||||
Blocks,
|
Blocks,
|
||||||
Const,
|
Const,
|
||||||
Pure
|
Pure,
|
||||||
|
Cleanup
|
||||||
};
|
};
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
@ -446,6 +447,22 @@ public:
|
||||||
static bool classof(const BlocksAttr *A) { return true; }
|
static bool classof(const BlocksAttr *A) { return true; }
|
||||||
};
|
};
|
||||||
|
|
||||||
|
class FunctionDecl;
|
||||||
|
|
||||||
|
class CleanupAttr : public Attr {
|
||||||
|
FunctionDecl *FD;
|
||||||
|
|
||||||
|
public:
|
||||||
|
CleanupAttr(FunctionDecl *fd) : Attr(Cleanup), FD(fd) {}
|
||||||
|
|
||||||
|
const FunctionDecl *getFunctionDecl() const { return FD; }
|
||||||
|
|
||||||
|
// Implement isa/cast/dyncast/etc.
|
||||||
|
|
||||||
|
static bool classof(const Attr *A) { return A->getKind() == Cleanup; }
|
||||||
|
static bool classof(const CleanupAttr *A) { return true; }
|
||||||
|
};
|
||||||
|
|
||||||
} // end namespace clang
|
} // end namespace clang
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -377,7 +377,13 @@ DIAG(err_attribute_sentinel_less_than_zero, ERROR,
|
||||||
"'sentinel' parameter 1 less than zero")
|
"'sentinel' parameter 1 less than zero")
|
||||||
DIAG(err_attribute_sentinel_not_zero_or_one, ERROR,
|
DIAG(err_attribute_sentinel_not_zero_or_one, ERROR,
|
||||||
"'sentinel' parameter 2 not 0 or 1")
|
"'sentinel' parameter 2 not 0 or 1")
|
||||||
|
DIAG(err_attribute_cleanup_arg_not_found, ERROR,
|
||||||
|
"'cleanup' argument %0 not found")
|
||||||
|
DIAG(err_attribute_cleanup_arg_not_function, ERROR,
|
||||||
|
"'cleanup' argument %0 is not a function")
|
||||||
|
DIAG(err_attribute_cleanup_arg_must_take_one_arg, ERROR,
|
||||||
|
"'cleanup' function %0 must take 1 parameter")
|
||||||
|
|
||||||
// Clang-Specific Attributes
|
// Clang-Specific Attributes
|
||||||
DIAG(err_attribute_iboutlet_non_ivar, ERROR,
|
DIAG(err_attribute_iboutlet_non_ivar, ERROR,
|
||||||
"'iboutlet' attribute can only be applied to instance variables")
|
"'iboutlet' attribute can only be applied to instance variables")
|
||||||
|
|
|
@ -77,6 +77,7 @@ public:
|
||||||
AT_sentinel,
|
AT_sentinel,
|
||||||
AT_const,
|
AT_const,
|
||||||
AT_nsobject,
|
AT_nsobject,
|
||||||
|
AT_cleanup,
|
||||||
UnknownAttribute
|
UnknownAttribute
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -73,6 +73,7 @@ AttributeList::Kind AttributeList::getKind(const IdentifierInfo *Name) {
|
||||||
if (!memcmp(Str, "nonnull", 7)) return AT_nonnull;
|
if (!memcmp(Str, "nonnull", 7)) return AT_nonnull;
|
||||||
if (!memcmp(Str, "objc_gc", 7)) return AT_objc_gc;
|
if (!memcmp(Str, "objc_gc", 7)) return AT_objc_gc;
|
||||||
if (!memcmp(Str, "stdcall", 7)) return AT_stdcall;
|
if (!memcmp(Str, "stdcall", 7)) return AT_stdcall;
|
||||||
|
if (!memcmp(Str, "cleanup", 7)) return AT_cleanup;
|
||||||
break;
|
break;
|
||||||
case 8:
|
case 8:
|
||||||
if (!memcmp(Str, "annotate", 8)) return AT_annotate;
|
if (!memcmp(Str, "annotate", 8)) return AT_annotate;
|
||||||
|
|
|
@ -846,6 +846,51 @@ static void HandlePureAttr(Decl *d, const AttributeList &Attr, Sema &S) {
|
||||||
d->addAttr(new PureAttr());
|
d->addAttr(new PureAttr());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void HandleCleanupAttr(Decl *d, const AttributeList &Attr, Sema &S) {
|
||||||
|
if (!Attr.getParameterName()) {
|
||||||
|
S.Diag(Attr.getLoc(), diag::err_attribute_wrong_number_arguments) << 1;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (Attr.getNumArgs() != 0) {
|
||||||
|
S.Diag(Attr.getLoc(), diag::err_attribute_wrong_number_arguments) << 1;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
VarDecl *VD = dyn_cast<VarDecl>(d);
|
||||||
|
|
||||||
|
if (!VD || !VD->hasLocalStorage()) {
|
||||||
|
S.Diag(Attr.getLoc(), diag::warn_attribute_ignored) << "cleanup";
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Look up the function
|
||||||
|
Decl *CleanupDecl = S.LookupName(S.TUScope, Attr.getParameterName(),
|
||||||
|
Sema::LookupOrdinaryName);
|
||||||
|
if (!CleanupDecl) {
|
||||||
|
S.Diag(Attr.getLoc(), diag::err_attribute_cleanup_arg_not_found) <<
|
||||||
|
Attr.getParameterName();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
FunctionDecl *FD = dyn_cast<FunctionDecl>(CleanupDecl);
|
||||||
|
if (!FD) {
|
||||||
|
S.Diag(Attr.getLoc(), diag::err_attribute_cleanup_arg_not_function) <<
|
||||||
|
Attr.getParameterName();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// FIXME: This needs to work with C++ overloading.
|
||||||
|
// FIXME: This should verify that the function type is compatible
|
||||||
|
if (FD->getNumParams() != 1) {
|
||||||
|
S.Diag(Attr.getLoc(), diag::err_attribute_cleanup_arg_must_take_one_arg)<<
|
||||||
|
Attr.getParameterName();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
d->addAttr(new CleanupAttr(FD));
|
||||||
|
}
|
||||||
|
|
||||||
/// Handle __attribute__((format(type,idx,firstarg))) attributes
|
/// Handle __attribute__((format(type,idx,firstarg))) attributes
|
||||||
/// based on http://gcc.gnu.org/onlinedocs/gcc/Function-Attributes.html
|
/// based on http://gcc.gnu.org/onlinedocs/gcc/Function-Attributes.html
|
||||||
static void HandleFormatAttr(Decl *d, const AttributeList &Attr, Sema &S) {
|
static void HandleFormatAttr(Decl *d, const AttributeList &Attr, Sema &S) {
|
||||||
|
@ -1248,6 +1293,7 @@ static void ProcessDeclAttribute(Decl *D, const AttributeList &Attr, Sema &S) {
|
||||||
case AttributeList::AT_sentinel: HandleSentinelAttr (D, Attr, S); break;
|
case AttributeList::AT_sentinel: HandleSentinelAttr (D, Attr, S); break;
|
||||||
case AttributeList::AT_const: HandleConstAttr (D, Attr, S); break;
|
case AttributeList::AT_const: HandleConstAttr (D, Attr, S); break;
|
||||||
case AttributeList::AT_pure: HandlePureAttr (D, Attr, S); break;
|
case AttributeList::AT_pure: HandlePureAttr (D, Attr, S); break;
|
||||||
|
case AttributeList::AT_cleanup: HandleCleanupAttr (D, Attr, S); break;
|
||||||
default:
|
default:
|
||||||
#if 0
|
#if 0
|
||||||
// TODO: when we have the full set of attributes, warn about unknown ones.
|
// TODO: when we have the full set of attributes, warn about unknown ones.
|
||||||
|
|
Загрузка…
Ссылка в новой задаче