[cfe-commits] r79040 - in /cfe/trunk: lib/Sema/SemaDeclAttr.cpp test/SemaObjC/attr-malloc.m

Ted Kremenek kremenek at apple.com
Fri Aug 14 13:49:41 PDT 2009


Author: kremenek
Date: Fri Aug 14 15:49:40 2009
New Revision: 79040

URL: http://llvm.org/viewvc/llvm-project?rev=79040&view=rev
Log:
Improve Sema's handling of attribute 'malloc' to reject the attribute when
attaching to Objective-C methods (which mirrors GCC's behavior) and to allow the
return type of the function to be an Objective-C pointer or Block pointer (which
GCC also accepts).

Along the way, add 'const' to some of the pointer arguments of various utility
functions...

Added:
    cfe/trunk/test/SemaObjC/attr-malloc.m
Modified:
    cfe/trunk/lib/Sema/SemaDeclAttr.cpp

Modified: cfe/trunk/lib/Sema/SemaDeclAttr.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaDeclAttr.cpp?rev=79040&r1=79039&r2=79040&view=diff

==============================================================================
--- cfe/trunk/lib/Sema/SemaDeclAttr.cpp (original)
+++ cfe/trunk/lib/Sema/SemaDeclAttr.cpp Fri Aug 14 15:49:40 2009
@@ -24,13 +24,14 @@
 //  Helper functions
 //===----------------------------------------------------------------------===//
 
-static const FunctionType *getFunctionType(Decl *d, bool blocksToo = true) {
+static const FunctionType *getFunctionType(const Decl *d,
+                                           bool blocksToo = true) {
   QualType Ty;
-  if (ValueDecl *decl = dyn_cast<ValueDecl>(d))
+  if (const ValueDecl *decl = dyn_cast<ValueDecl>(d))
     Ty = decl->getType();
-  else if (FieldDecl *decl = dyn_cast<FieldDecl>(d))
+  else if (const FieldDecl *decl = dyn_cast<FieldDecl>(d))
     Ty = decl->getType();
-  else if (TypedefDecl* decl = dyn_cast<TypedefDecl>(d))
+  else if (const TypedefDecl* decl = dyn_cast<TypedefDecl>(d))
     Ty = decl->getUnderlyingType();
   else
     return 0;
@@ -47,16 +48,22 @@
 // to provide the following bits of information.
 
 /// isFunctionOrMethod - Return true if the given decl has function
+/// type (function or function-typed variable).
+static bool isFunction(const Decl *d) {
+  return getFunctionType(d, false) != NULL;
+}
+
+/// isFunctionOrMethod - Return true if the given decl has function
 /// type (function or function-typed variable) or an Objective-C
 /// method.
-static bool isFunctionOrMethod(Decl *d) {
-  return getFunctionType(d, false) || isa<ObjCMethodDecl>(d);
+static bool isFunctionOrMethod(const Decl *d) {
+  return isFunction(d)|| isa<ObjCMethodDecl>(d);
 }
 
 /// isFunctionOrMethodOrBlock - Return true if the given decl has function
 /// type (function or function-typed variable) or an Objective-C
 /// method or a block.
-static bool isFunctionOrMethodOrBlock(Decl *d) {
+static bool isFunctionOrMethodOrBlock(const Decl *d) {
   if (isFunctionOrMethod(d))
     return true;
   // check for block is more involved.
@@ -70,7 +77,7 @@
 /// hasFunctionProto - Return true if the given decl has a argument
 /// information. This decl should have already passed
 /// isFunctionOrMethod or isFunctionOrMethodOrBlock.
-static bool hasFunctionProto(Decl *d) {
+static bool hasFunctionProto(const Decl *d) {
   if (const FunctionType *FnTy = getFunctionType(d))
     return isa<FunctionProtoType>(FnTy);
   else {
@@ -82,7 +89,7 @@
 /// getFunctionOrMethodNumArgs - Return number of function or method
 /// arguments. It is an error to call this on a K&R function (use
 /// hasFunctionProto first).
-static unsigned getFunctionOrMethodNumArgs(Decl *d) {
+static unsigned getFunctionOrMethodNumArgs(const Decl *d) {
   if (const FunctionType *FnTy = getFunctionType(d))
     return cast<FunctionProtoType>(FnTy)->getNumArgs();
   if (const BlockDecl *BD = dyn_cast<BlockDecl>(d))
@@ -90,7 +97,7 @@
   return cast<ObjCMethodDecl>(d)->param_size();
 }
 
-static QualType getFunctionOrMethodArgType(Decl *d, unsigned Idx) {
+static QualType getFunctionOrMethodArgType(const Decl *d, unsigned Idx) {
   if (const FunctionType *FnTy = getFunctionType(d))
     return cast<FunctionProtoType>(FnTy)->getArgType(Idx);
   if (const BlockDecl *BD = dyn_cast<BlockDecl>(d))
@@ -99,13 +106,13 @@
   return cast<ObjCMethodDecl>(d)->param_begin()[Idx]->getType();
 }
 
-static QualType getFunctionOrMethodResultType(Decl *d) {
+static QualType getFunctionOrMethodResultType(const Decl *d) {
   if (const FunctionType *FnTy = getFunctionType(d))
     return cast<FunctionProtoType>(FnTy)->getResultType();
   return cast<ObjCMethodDecl>(d)->getResultType();
 }
 
-static bool isFunctionOrMethodVariadic(Decl *d) {
+static bool isFunctionOrMethodVariadic(const Decl *d) {
   if (const FunctionType *FnTy = getFunctionType(d)) {
     const FunctionProtoType *proto = cast<FunctionProtoType>(FnTy);
     return proto->isVariadic();
@@ -431,17 +438,18 @@
     return;
   }
 
-  if (!isFunctionOrMethod(d)) {
+  if (!isFunction(d)) {
     S.Diag(Attr.getLoc(), diag::warn_attribute_wrong_decl_type)
       << Attr.getName() << 0 /*function*/;
     return;
   }
 
-  if (FunctionDecl *FD = dyn_cast<FunctionDecl>(d)) {
-    if (!FD->getResultType()->isPointerType()) {
-      S.Diag(Attr.getLoc(), diag::warn_attribute_malloc_pointer_only);
-      return;
-    }
+  const FunctionDecl *FD = cast<FunctionDecl>(d);
+  QualType RetTy = FD->getResultType();
+  
+  if (!(RetTy->isAnyPointerType() || RetTy->isBlockPointerType())) {
+    S.Diag(Attr.getLoc(), diag::warn_attribute_malloc_pointer_only);
+    return;
   }
 
   d->addAttr(::new (S.Context) MallocAttr());

Added: cfe/trunk/test/SemaObjC/attr-malloc.m
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/SemaObjC/attr-malloc.m?rev=79040&view=auto

==============================================================================
--- cfe/trunk/test/SemaObjC/attr-malloc.m (added)
+++ cfe/trunk/test/SemaObjC/attr-malloc.m Fri Aug 14 15:49:40 2009
@@ -0,0 +1,14 @@
+// RUN: clang-cc -verify -fsyntax-only -fblocks %s
+
+#include <stdlib.h>
+
+ at interface TestAttrMallocOnMethods {}
+- (id) test1 __attribute((malloc)); // expected-warning{{'malloc' attribute only applies to function types}}
+- (int) test2 __attribute((malloc)); // expected-warning{{'malloc' attribute only applies to function types}}
+ at end
+
+id bar(void) __attribute((malloc)); // no-warning
+
+typedef void (^bptr)(void);
+bptr baz(void) __attribute((malloc)); // no-warning
+





More information about the cfe-commits mailing list