]> granicus.if.org Git - clang/commitdiff
Add sema support for the cleanup attribute.
authorAnders Carlsson <andersca@mac.com>
Sat, 31 Jan 2009 01:16:18 +0000 (01:16 +0000)
committerAnders Carlsson <andersca@mac.com>
Sat, 31 Jan 2009 01:16:18 +0000 (01:16 +0000)
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@63462 91177308-0d34-0410-b5e6-96231b3b80d8

include/clang/AST/Attr.h
include/clang/Basic/DiagnosticSemaKinds.def
include/clang/Parse/AttributeList.h
lib/Parse/AttributeList.cpp
lib/Sema/SemaDeclAttr.cpp

index 726d35007226105f9192a4810a11d04fdaff72f8..38e2b9ecb18162cc8d6d31faf5649296279b15ed 100644 (file)
@@ -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
index 89577dfd3922c827fa0d2120583e1380daac73f3..7f1ca49b66f1886e53c9e95e77f741de58d2d87a 100644 (file)
@@ -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")
index 9c8c70945e11bfc61890497a8f43f6d1e32ff797..bca12a3e60a19b733122117c9cead0e95d3fca99 100644 (file)
@@ -77,6 +77,7 @@ public:
     AT_sentinel,
     AT_const,
     AT_nsobject,
+    AT_cleanup,
     UnknownAttribute
   };
   
index 6c1583a0feb97ab81115a8784935b2f598eadd51..477d6e363d18f8f45208681deb82ca72a237c96b 100644 (file)
@@ -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;
index bf4549d05bca5984d3c06ccdab0c4b9b25a5092e..33985ee1a33f070cac3375e7ca7841f56515fa2e 100644 (file)
@@ -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<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
 /// 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.