r240186 - CF_RETURNS_[NOT_]RETAINED on a param makes the inner pointer __nullable.
Douglas Gregor
dgregor at apple.com
Fri Jun 19 16:17:51 PDT 2015
Author: dgregor
Date: Fri Jun 19 18:17:51 2015
New Revision: 240186
URL: http://llvm.org/viewvc/llvm-project?rev=240186&view=rev
Log:
CF_RETURNS_[NOT_]RETAINED on a param makes the inner pointer __nullable.
That is,
void cf2(CFTypeRef * __nullable p CF_RETURNS_NOT_RETAINED);
is equivalent to
void cf2(CFTypeRef __nullable * __nullable p CF_RETURNS_NOT_RETAINED);
More rdar://problem/18742441
Modified:
cfe/trunk/lib/Sema/SemaType.cpp
cfe/trunk/test/Analysis/retain-release.m
cfe/trunk/test/SemaObjCXX/Inputs/nullability-consistency-8.h
Modified: cfe/trunk/lib/Sema/SemaType.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaType.cpp?rev=240186&r1=240185&r2=240186&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/SemaType.cpp (original)
+++ cfe/trunk/lib/Sema/SemaType.cpp Fri Jun 19 18:17:51 2015
@@ -2614,6 +2614,8 @@ namespace {
SingleLevelPointer,
// Multi-level pointer (of any pointer kind).
MultiLevelPointer,
+ // CFFooRef*
+ MaybePointerToCFRef,
// CFErrorRef*
CFErrorRefPointer,
// NSError**
@@ -2754,6 +2756,9 @@ static PointerDeclaratorKind classifyPoi
case 1:
return PointerDeclaratorKind::SingleLevelPointer;
+ case 2:
+ return PointerDeclaratorKind::MaybePointerToCFRef;
+
default:
return PointerDeclaratorKind::MultiLevelPointer;
}
@@ -2894,6 +2899,8 @@ static TypeSourceInfo *GetFullTypeForDec
// Determine whether we should infer __nonnull on pointer types.
Optional<NullabilityKind> inferNullability;
bool inferNullabilityCS = false;
+ bool inferNullabilityInnerOnly = false;
+ bool inferNullabilityInnerOnlyComplete = false;
// Are we in an assume-nonnull region?
bool inAssumeNonNullRegion = false;
@@ -3007,6 +3014,31 @@ static TypeSourceInfo *GetFullTypeForDec
if (isFunctionOrMethod && inAssumeNonNullRegion)
inferNullability = NullabilityKind::Nullable;
break;
+
+ case PointerDeclaratorKind::MaybePointerToCFRef:
+ if (isFunctionOrMethod) {
+ // On pointer-to-pointer parameters marked cf_returns_retained or
+ // cf_returns_not_retained, if the outer pointer is explicit then
+ // infer the inner pointer as __nullable.
+ auto hasCFReturnsAttr = [](const AttributeList *NextAttr) -> bool {
+ while (NextAttr) {
+ if (NextAttr->getKind() == AttributeList::AT_CFReturnsRetained ||
+ NextAttr->getKind() == AttributeList::AT_CFReturnsNotRetained)
+ return true;
+ NextAttr = NextAttr->getNext();
+ }
+ return false;
+ };
+ if (const auto *InnermostChunk = D.getInnermostNonParenChunk()) {
+ if (hasCFReturnsAttr(D.getAttributes()) ||
+ hasCFReturnsAttr(InnermostChunk->getAttrs()) ||
+ hasCFReturnsAttr(D.getDeclSpec().getAttributes().getList())) {
+ inferNullability = NullabilityKind::Nullable;
+ inferNullabilityInnerOnly = true;
+ }
+ }
+ }
+ break;
}
break;
@@ -3047,9 +3079,10 @@ static TypeSourceInfo *GetFullTypeForDec
return nullptr;
// If we're supposed to infer nullability, do so now.
- if (inferNullability) {
- auto syntax = inferNullabilityCS ? AttributeList::AS_ContextSensitiveKeyword
- : AttributeList::AS_Keyword;
+ if (inferNullability && !inferNullabilityInnerOnlyComplete) {
+ AttributeList::Syntax syntax
+ = inferNullabilityCS ? AttributeList::AS_ContextSensitiveKeyword
+ : AttributeList::AS_Keyword;
AttributeList *nullabilityAttr = state.getDeclarator().getAttributePool()
.create(
S.getNullabilityKeyword(
@@ -3059,6 +3092,9 @@ static TypeSourceInfo *GetFullTypeForDec
nullptr, 0, syntax);
spliceAttrIntoList(*nullabilityAttr, attrs);
+
+ if (inferNullabilityInnerOnly)
+ inferNullabilityInnerOnlyComplete = true;
return nullabilityAttr;
}
Modified: cfe/trunk/test/Analysis/retain-release.m
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Analysis/retain-release.m?rev=240186&r1=240185&r2=240186&view=diff
==============================================================================
--- cfe/trunk/test/Analysis/retain-release.m (original)
+++ cfe/trunk/test/Analysis/retain-release.m Fri Jun 19 18:17:51 2015
@@ -2164,6 +2164,13 @@ void testCFReturnsNotRetained() {
CFRelease(obj); // // expected-warning {{Incorrect decrement of the reference count of an object that is not owned at this point by the caller}}
}
+void testCFReturnsNotRetainedAnnotated() {
+ extern void getViaParam2(CFTypeRef * __nonnull CF_RETURNS_NOT_RETAINED outObj);
+ CFTypeRef obj;
+ getViaParam2(&obj);
+ CFRelease(obj); // // expected-warning {{Incorrect decrement of the reference count of an object that is not owned at this point by the caller}}
+}
+
void testCFReturnsRetained() {
extern int copyViaParam(CFTypeRef * CF_RETURNS_RETAINED outObj);
CFTypeRef obj;
Modified: cfe/trunk/test/SemaObjCXX/Inputs/nullability-consistency-8.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/SemaObjCXX/Inputs/nullability-consistency-8.h?rev=240186&r1=240185&r2=240186&view=diff
==============================================================================
--- cfe/trunk/test/SemaObjCXX/Inputs/nullability-consistency-8.h (original)
+++ cfe/trunk/test/SemaObjCXX/Inputs/nullability-consistency-8.h Fri Jun 19 18:17:51 2015
@@ -9,3 +9,19 @@ void func2(mynonnull i);
void func3(int *); // expected-warning{{pointer is missing a nullability type specifier}}
+#define CF_RETURNS_NOT_RETAINED __attribute__((cf_returns_not_retained))
+typedef void *CFTypeRef;
+void cf1(CFTypeRef * p CF_RETURNS_NOT_RETAINED); // expected-warning {{pointer is missing a nullability type specifier}}
+
+void cf2(CFTypeRef * __nullable p CF_RETURNS_NOT_RETAINED);
+void cf3(CFTypeRef * __nonnull p CF_RETURNS_NOT_RETAINED);
+
+void cf4(CFTypeRef __nullable * __nullable p CF_RETURNS_NOT_RETAINED);
+void cf5(CFTypeRef __nonnull * __nullable p CF_RETURNS_NOT_RETAINED);
+
+void cf6(CFTypeRef * __nullable CF_RETURNS_NOT_RETAINED p);
+void cf7(CF_RETURNS_NOT_RETAINED CFTypeRef * __nonnull p);
+
+typedef CFTypeRef __nullable *CFTypeRefPtr;
+void cfp1(CFTypeRefPtr p CF_RETURNS_NOT_RETAINED); // expected-warning {{pointer is missing a nullability type specifier}}
+void cfp2(CFTypeRefPtr __nonnull p CF_RETURNS_NOT_RETAINED);
More information about the cfe-commits
mailing list