From d277d790e0f6f23043397ba919619b5c3e157ff3 Mon Sep 17 00:00:00 2001 From: Anders Carlsson Date: Sat, 31 Jan 2009 01:16:18 +0000 Subject: [PATCH] Add sema support for the cleanup attribute. llvm-svn: 63462 --- clang/include/clang/AST/Attr.h | 19 +++++++- .../clang/Basic/DiagnosticSemaKinds.def | 8 +++- clang/include/clang/Parse/AttributeList.h | 1 + clang/lib/Parse/AttributeList.cpp | 1 + clang/lib/Sema/SemaDeclAttr.cpp | 46 +++++++++++++++++++ 5 files changed, 73 insertions(+), 2 deletions(-) diff --git a/clang/include/clang/AST/Attr.h b/clang/include/clang/AST/Attr.h index 726d35007226..38e2b9ecb181 100644 --- a/clang/include/clang/AST/Attr.h +++ b/clang/include/clang/AST/Attr.h @@ -52,7 +52,8 @@ public: Weak, Blocks, Const, - Pure + Pure, + Cleanup }; private: @@ -446,6 +447,22 @@ public: 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 #endif diff --git a/clang/include/clang/Basic/DiagnosticSemaKinds.def b/clang/include/clang/Basic/DiagnosticSemaKinds.def index 89577dfd3922..7f1ca49b66f1 100644 --- a/clang/include/clang/Basic/DiagnosticSemaKinds.def +++ b/clang/include/clang/Basic/DiagnosticSemaKinds.def @@ -377,7 +377,13 @@ DIAG(err_attribute_sentinel_less_than_zero, ERROR, "'sentinel' parameter 1 less than zero") DIAG(err_attribute_sentinel_not_zero_or_one, ERROR, "'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 DIAG(err_attribute_iboutlet_non_ivar, ERROR, "'iboutlet' attribute can only be applied to instance variables") diff --git a/clang/include/clang/Parse/AttributeList.h b/clang/include/clang/Parse/AttributeList.h index 9c8c70945e11..bca12a3e60a1 100644 --- a/clang/include/clang/Parse/AttributeList.h +++ b/clang/include/clang/Parse/AttributeList.h @@ -77,6 +77,7 @@ public: AT_sentinel, AT_const, AT_nsobject, + AT_cleanup, UnknownAttribute }; diff --git a/clang/lib/Parse/AttributeList.cpp b/clang/lib/Parse/AttributeList.cpp index 6c1583a0feb9..477d6e363d18 100644 --- a/clang/lib/Parse/AttributeList.cpp +++ b/clang/lib/Parse/AttributeList.cpp @@ -73,6 +73,7 @@ AttributeList::Kind AttributeList::getKind(const IdentifierInfo *Name) { if (!memcmp(Str, "nonnull", 7)) return AT_nonnull; if (!memcmp(Str, "objc_gc", 7)) return AT_objc_gc; if (!memcmp(Str, "stdcall", 7)) return AT_stdcall; + if (!memcmp(Str, "cleanup", 7)) return AT_cleanup; break; case 8: if (!memcmp(Str, "annotate", 8)) return AT_annotate; diff --git a/clang/lib/Sema/SemaDeclAttr.cpp b/clang/lib/Sema/SemaDeclAttr.cpp index bf4549d05bca..33985ee1a33f 100644 --- a/clang/lib/Sema/SemaDeclAttr.cpp +++ b/clang/lib/Sema/SemaDeclAttr.cpp @@ -846,6 +846,51 @@ static void HandlePureAttr(Decl *d, const AttributeList &Attr, Sema &S) { 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(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(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 /// based on http://gcc.gnu.org/onlinedocs/gcc/Function-Attributes.html 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_const: HandleConstAttr (D, Attr, S); break; case AttributeList::AT_pure: HandlePureAttr (D, Attr, S); break; + case AttributeList::AT_cleanup: HandleCleanupAttr (D, Attr, S); break; default: #if 0 // TODO: when we have the full set of attributes, warn about unknown ones.