[cfe-commits] r124174 - in /cfe/trunk: include/clang/Basic/Attr.td include/clang/Basic/DiagnosticSemaKinds.td include/clang/Sema/AttributeList.h lib/Sema/AttributeList.cpp lib/Sema/SemaDeclAttr.cpp test/Analysis/retain-release.m
John McCall
rjmccall at apple.com
Mon Jan 24 19:31:58 PST 2011
Author: rjmccall
Date: Mon Jan 24 21:31:58 2011
New Revision: 124174
URL: http://llvm.org/viewvc/llvm-project?rev=124174&view=rev
Log:
Add the ns_consumes_self, ns_consumed, cf_consumed, and ns_returns_autoreleased
attributes for the benefit of the static analyzer.
Modified:
cfe/trunk/include/clang/Basic/Attr.td
cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td
cfe/trunk/include/clang/Sema/AttributeList.h
cfe/trunk/lib/Sema/AttributeList.cpp
cfe/trunk/lib/Sema/SemaDeclAttr.cpp
cfe/trunk/test/Analysis/retain-release.m
Modified: cfe/trunk/include/clang/Basic/Attr.td
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Basic/Attr.td?rev=124174&r1=124173&r2=124174&view=diff
==============================================================================
--- cfe/trunk/include/clang/Basic/Attr.td (original)
+++ cfe/trunk/include/clang/Basic/Attr.td Mon Jan 24 21:31:58 2011
@@ -146,10 +146,17 @@
def CFReturnsRetained : InheritableAttr {
let Spellings = ["cf_returns_retained"];
+ let Subjects = [ObjCMethod, Function];
}
def CFReturnsNotRetained : InheritableAttr {
let Spellings = ["cf_returns_not_retained"];
+ let Subjects = [ObjCMethod, Function];
+}
+
+def CFConsumed : InheritableAttr {
+ let Spellings = ["cf_consumed"];
+ let Subjects = [ParmVar];
}
def Cleanup : InheritableAttr {
@@ -326,10 +333,27 @@
def NSReturnsRetained : InheritableAttr {
let Spellings = ["ns_returns_retained"];
+ let Subjects = [ObjCMethod, Function];
}
def NSReturnsNotRetained : InheritableAttr {
let Spellings = ["ns_returns_not_retained"];
+ let Subjects = [ObjCMethod, Function];
+}
+
+def NSReturnsAutoreleased : InheritableAttr {
+ let Spellings = ["ns_returns_autoreleased"];
+ let Subjects = [ObjCMethod, Function];
+}
+
+def NSConsumesSelf : InheritableAttr {
+ let Spellings = ["ns_consumes_self"];
+ let Subjects = [ObjCMethod];
+}
+
+def NSConsumed : InheritableAttr {
+ let Spellings = ["ns_consumed"];
+ let Subjects = [ParmVar];
}
def ObjCException : InheritableAttr {
@@ -337,7 +361,7 @@
}
def ObjCNSObject : InheritableAttr {
- let Spellings = ["NSOjbect"];
+ let Spellings = ["NSObject"];
}
def Overloadable : Attr {
Modified: cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td?rev=124174&r1=124173&r2=124174&view=diff
==============================================================================
--- cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td (original)
+++ cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td Mon Jan 24 21:31:58 2011
@@ -1040,15 +1040,15 @@
def warn_attribute_wrong_decl_type : Warning<
"%0 attribute only applies to %select{function|union|"
"variable and function|function or method|parameter|"
- "parameter or Objective-C method |function, method or block|"
+ "parameter or Objective-C method|function, method or block|"
"virtual method or class|function, method, or parameter|class|virtual method"
- "|member|variable}1 types">;
+ "|member|variable|method}1 types">;
def err_attribute_wrong_decl_type : Error<
"%0 attribute only applies to %select{function|union|"
"variable and function|function or method|parameter|"
- "parameter or Objective-C method |function, method or block|"
+ "parameter or Objective-C method|function, method or block|"
"virtual method or class|function, method, or parameter|class|virtual method"
- "|member|variable}1 types">;
+ "|member|variable|method}1 types">;
def warn_function_attribute_wrong_type : Warning<
"%0 only applies to function types; type here is %1">;
def warn_gnu_inline_attribute_requires_inline : Warning<
@@ -1179,8 +1179,11 @@
def err_attribute_overloadable_no_prototype : Error<
"'overloadable' function %0 must have a prototype">;
def warn_ns_attribute_wrong_return_type : Warning<
- "%0 attribute only applies to functions or methods that "
- "return a pointer or Objective-C object">;
+ "%0 attribute only applies to %select{functions|methods}1 that "
+ "return %select{an Objective-C object|a pointer}2">;
+def warn_ns_attribute_wrong_parameter_type : Warning<
+ "%0 attribute only applies to %select{Objective-C object|pointer}1 "
+ "parameters">;
// Function Parameter Semantic Analysis.
def err_param_with_void_type : Error<"argument may not have 'void' type">;
Modified: cfe/trunk/include/clang/Sema/AttributeList.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Sema/AttributeList.h?rev=124174&r1=124173&r2=124174&view=diff
==============================================================================
--- cfe/trunk/include/clang/Sema/AttributeList.h (original)
+++ cfe/trunk/include/clang/Sema/AttributeList.h Mon Jan 24 21:31:58 2011
@@ -129,6 +129,10 @@
AT_cf_returns_retained, // Clang-specific.
AT_ns_returns_not_retained, // Clang-specific.
AT_ns_returns_retained, // Clang-specific.
+ AT_ns_returns_autoreleased, // Clang-specific.
+ AT_cf_consumed, // Clang-specific.
+ AT_ns_consumed, // Clang-specific.
+ AT_ns_consumes_self, // Clang-specific.
AT_objc_gc,
AT_overloadable, // Clang-specific.
AT_ownership_holds, // Clang-specific.
Modified: cfe/trunk/lib/Sema/AttributeList.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/AttributeList.cpp?rev=124174&r1=124173&r2=124174&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/AttributeList.cpp (original)
+++ cfe/trunk/lib/Sema/AttributeList.cpp Mon Jan 24 21:31:58 2011
@@ -105,8 +105,12 @@
.Case("analyzer_noreturn", AT_analyzer_noreturn)
.Case("warn_unused_result", AT_warn_unused_result)
.Case("carries_dependency", AT_carries_dependency)
+ .Case("ns_consumed", AT_ns_consumed)
+ .Case("ns_consumes_self", AT_ns_consumes_self)
+ .Case("ns_returns_autoreleased", AT_ns_returns_autoreleased)
.Case("ns_returns_not_retained", AT_ns_returns_not_retained)
.Case("ns_returns_retained", AT_ns_returns_retained)
+ .Case("cf_consumed", AT_cf_consumed)
.Case("cf_returns_not_retained", AT_cf_returns_not_retained)
.Case("cf_returns_retained", AT_cf_returns_retained)
.Case("ownership_returns", AT_ownership_returns)
Modified: cfe/trunk/lib/Sema/SemaDeclAttr.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaDeclAttr.cpp?rev=124174&r1=124173&r2=124174&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/SemaDeclAttr.cpp (original)
+++ cfe/trunk/lib/Sema/SemaDeclAttr.cpp Mon Jan 24 21:31:58 2011
@@ -2441,48 +2441,116 @@
// Checker-specific attribute handlers.
//===----------------------------------------------------------------------===//
-static void HandleNSReturnsRetainedAttr(Decl *d, const AttributeList &Attr,
+static bool isValidSubjectOfNSAttribute(Sema &S, QualType type) {
+ return type->isObjCObjectPointerType() || S.Context.isObjCNSObjectType(type);
+}
+static bool isValidSubjectOfCFAttribute(Sema &S, QualType type) {
+ return type->isPointerType() || isValidSubjectOfNSAttribute(S, type);
+}
+
+static void HandleNSConsumedAttr(Decl *d, const AttributeList &attr, Sema &S) {
+ ParmVarDecl *param = dyn_cast<ParmVarDecl>(d);
+ if (!param) {
+ S.Diag(d->getLocStart(), diag::warn_attribute_wrong_decl_type)
+ << SourceRange(attr.getLoc()) << attr.getName() << 4 /*parameter*/;
+ return;
+ }
+
+ bool typeOK, cf;
+ if (attr.getKind() == AttributeList::AT_ns_consumed) {
+ typeOK = isValidSubjectOfNSAttribute(S, param->getType());
+ cf = false;
+ } else {
+ typeOK = isValidSubjectOfCFAttribute(S, param->getType());
+ cf = true;
+ }
+
+ if (!typeOK) {
+ S.Diag(d->getLocStart(), diag::warn_ns_attribute_wrong_parameter_type)
+ << SourceRange(attr.getLoc()) << attr.getName() << cf;
+ return;
+ }
+
+ if (cf)
+ param->addAttr(::new (S.Context) CFConsumedAttr(attr.getLoc(), S.Context));
+ else
+ param->addAttr(::new (S.Context) NSConsumedAttr(attr.getLoc(), S.Context));
+}
+
+static void HandleNSConsumesSelfAttr(Decl *d, const AttributeList &attr,
+ Sema &S) {
+ if (!isa<ObjCMethodDecl>(d)) {
+ S.Diag(d->getLocStart(), diag::warn_attribute_wrong_decl_type)
+ << SourceRange(attr.getLoc()) << attr.getName() << 13 /*method*/;
+ return;
+ }
+
+ d->addAttr(::new (S.Context) NSConsumesSelfAttr(attr.getLoc(), S.Context));
+}
+
+static void HandleNSReturnsRetainedAttr(Decl *d, const AttributeList &attr,
Sema &S) {
- QualType RetTy;
+ QualType returnType;
if (ObjCMethodDecl *MD = dyn_cast<ObjCMethodDecl>(d))
- RetTy = MD->getResultType();
+ returnType = MD->getResultType();
else if (FunctionDecl *FD = dyn_cast<FunctionDecl>(d))
- RetTy = FD->getResultType();
+ returnType = FD->getResultType();
else {
- SourceLocation L = Attr.getLoc();
S.Diag(d->getLocStart(), diag::warn_attribute_wrong_decl_type)
- << SourceRange(L, L) << Attr.getName() << 3 /* function or method */;
+ << SourceRange(attr.getLoc()) << attr.getName()
+ << 3 /* function or method */;
return;
}
- if (!(S.Context.isObjCNSObjectType(RetTy) || RetTy->getAs<PointerType>()
- || RetTy->getAs<ObjCObjectPointerType>())) {
- SourceLocation L = Attr.getLoc();
+ bool typeOK;
+ bool cf;
+ switch (attr.getKind()) {
+ default: llvm_unreachable("invalid ownership attribute"); return;
+ case AttributeList::AT_ns_returns_autoreleased:
+ case AttributeList::AT_ns_returns_retained:
+ case AttributeList::AT_ns_returns_not_retained:
+ typeOK = isValidSubjectOfNSAttribute(S, returnType);
+ cf = false;
+ break;
+
+ case AttributeList::AT_cf_returns_retained:
+ case AttributeList::AT_cf_returns_not_retained:
+ typeOK = isValidSubjectOfCFAttribute(S, returnType);
+ cf = true;
+ break;
+ }
+
+ if (!typeOK) {
S.Diag(d->getLocStart(), diag::warn_ns_attribute_wrong_return_type)
- << SourceRange(L, L) << Attr.getName();
+ << SourceRange(attr.getLoc())
+ << attr.getName() << isa<ObjCMethodDecl>(d) << cf;
return;
}
- switch (Attr.getKind()) {
+ switch (attr.getKind()) {
default:
assert(0 && "invalid ownership attribute");
return;
+ case AttributeList::AT_ns_returns_autoreleased:
+ d->addAttr(::new (S.Context) NSReturnsAutoreleasedAttr(attr.getLoc(),
+ S.Context));
+ return;
case AttributeList::AT_cf_returns_not_retained:
- d->addAttr(::new (S.Context) CFReturnsNotRetainedAttr(Attr.getLoc(),
+ d->addAttr(::new (S.Context) CFReturnsNotRetainedAttr(attr.getLoc(),
S.Context));
return;
case AttributeList::AT_ns_returns_not_retained:
- d->addAttr(::new (S.Context) NSReturnsNotRetainedAttr(Attr.getLoc(),
+ d->addAttr(::new (S.Context) NSReturnsNotRetainedAttr(attr.getLoc(),
S.Context));
return;
case AttributeList::AT_cf_returns_retained:
- d->addAttr(::new (S.Context) CFReturnsRetainedAttr(Attr.getLoc(),
+ d->addAttr(::new (S.Context) CFReturnsRetainedAttr(attr.getLoc(),
S.Context));
return;
case AttributeList::AT_ns_returns_retained:
- d->addAttr(::new (S.Context) NSReturnsRetainedAttr(Attr.getLoc(),
+ d->addAttr(::new (S.Context) NSReturnsRetainedAttr(attr.getLoc(),
S.Context));
return;
};
@@ -2629,6 +2697,12 @@
case AttributeList::AT_vecreturn: HandleVecReturnAttr (D, Attr, S); break;
// Checker-specific.
+ case AttributeList::AT_cf_consumed:
+ case AttributeList::AT_ns_consumed: HandleNSConsumedAttr (D, Attr, S); break;
+ case AttributeList::AT_ns_consumes_self:
+ HandleNSConsumesSelfAttr(D, Attr, S); break;
+
+ case AttributeList::AT_ns_returns_autoreleased:
case AttributeList::AT_ns_returns_not_retained:
case AttributeList::AT_cf_returns_not_retained:
case AttributeList::AT_ns_returns_retained:
Modified: cfe/trunk/test/Analysis/retain-release.m
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Analysis/retain-release.m?rev=124174&r1=124173&r2=124174&view=diff
==============================================================================
--- cfe/trunk/test/Analysis/retain-release.m (original)
+++ cfe/trunk/test/Analysis/retain-release.m Mon Jan 24 21:31:58 2011
@@ -1210,7 +1210,7 @@
- (MyStringTy) returnsAnOwnedTypedString NS_RETURNS_RETAINED; // no-warning
- (NSString*) newString NS_RETURNS_NOT_RETAINED; // no-warning
- (NSString*) newStringNoAttr;
-- (int) returnsAnOwnedInt NS_RETURNS_RETAINED; // expected-warning{{'ns_returns_retained' attribute only applies to functions or methods that return a pointer or Objective-C object}}
+- (int) returnsAnOwnedInt NS_RETURNS_RETAINED; // expected-warning{{'ns_returns_retained' attribute only applies to methods that return an Objective-C object}}
@end
static int ownership_attribute_doesnt_go_here NS_RETURNS_RETAINED; // expected-warning{{'ns_returns_retained' attribute only applies to function or method types}}
More information about the cfe-commits
mailing list