Clarify the semantics of init methods, and point out a few places

where mismatched semantics can cause undefined behavior.

llvm-svn: 133341
This commit is contained in:
John McCall 2011-06-18 08:15:19 +00:00
parent f8d4799267
commit 9cc574d538
1 changed files with 64 additions and 35 deletions

View File

@ -424,20 +424,29 @@ rolled into the initialization of the parameter.</p></div>
<p>The implicit <tt>self</tt> parameter of a method may be marked as <p>The implicit <tt>self</tt> parameter of a method may be marked as
consumed by adding <tt>__attribute__((ns_consumes_self))</tt> to the consumed by adding <tt>__attribute__((ns_consumes_self))</tt> to the
method declaration. Methods in method declaration. Methods in the <tt>init</tt>
the <tt>init</tt> <a href="#family">family</a> are implicitly <a href="#family">family</a> are treated as if they were implicitly
marked <tt>__attribute__((ns_consumes_self))</tt>.</p> marked with this attribute.</p>
<p>It is undefined behavior if an Objective-C message send of a method <p>It is undefined behavior if an Objective-C message send to a method
with <tt>ns_consumed</tt> parameters (other than self) is made to a with <tt>ns_consumed</tt> parameters (other than self) is made with a
null pointer.</p> null receiver. It is undefined behavior if the method to which an
Objective-C message send statically resolves to has a different set
of <tt>ns_consumed</tt> parameters than the method it dynamically
resolves to. It is undefined behavior if a block or function call is
made through a static type with a different set of <tt>ns_consumed</tt>
parameters than the implementation of the called block or function.</p>
<div class="rationale"><p>Rationale: in fact, it's probably a <div class="rationale"><p>Rationale: consumed parameters with null
guaranteed leak.</p></div> receiver are a guaranteed leak. Mismatches with consumed parameters
will cause over-retains or over-releases, depending on the direction.
The rule about function calls is really just an application of the
existing C/C++ rule about calling functions through an incompatible
function type, but it's useful to state it explicitly.</p></div>
</div> </div>
<div id="objects.operands.retained-returns"> <div id="objects.operands.retained_returns">
<h1>Retained return values</h1> <h1>Retained return values</h1>
<p>A function or method which returns a retainable object pointer type <p>A function or method which returns a retainable object pointer type
@ -474,6 +483,20 @@ by explicitly marking the
method <tt>__attribute__((ns_returns_not_retained))</tt>.</p> method <tt>__attribute__((ns_returns_not_retained))</tt>.</p>
</div> </div>
<p>It is undefined behavior if the method to which an Objective-C
message send statically resolves has different retain semantics on its
result from the method it dynamically resolves to. It is undefined
behavior if a block or function call is made through a static type
with different retain semantics on its result from the implementation
of the called block or function.</p>
<div class="rationale"><p>Rationale: Mismatches with returned results
will cause over-retains or over-releases, depending on the direction.
Again, the rule about function calls is really just an application of
the existing C/C++ rule about calling functions through an
incompatible function type.</p></div>
<div id="objects.operands.other-returns"> <div id="objects.operands.other-returns">
<h1>Unretained return values</h1> <h1>Unretained return values</h1>
@ -1038,9 +1061,9 @@ but <tt>performing:with</tt> would not.</p>
Objective-C pointer type. Additionally, a program is ill-formed if it Objective-C pointer type. Additionally, a program is ill-formed if it
declares or contains a call to an <tt>init</tt> method whose return declares or contains a call to an <tt>init</tt> method whose return
type is neither <tt>id</tt> nor a pointer to a super-class or type is neither <tt>id</tt> nor a pointer to a super-class or
sub-class of either the declaring class, if the method was declared on sub-class of the declaring class (if the method was declared on
a class, or the static receiver type of the call, if it was declared a class) or the static receiver type of the call (if it was declared
on a protocol.</p> on a protocol).</p>
<div class="rationale"><p>Rationale: there are a fair number of existing <div class="rationale"><p>Rationale: there are a fair number of existing
methods with <tt>init</tt>-like selectors which nonetheless don't methods with <tt>init</tt>-like selectors which nonetheless don't
@ -1051,10 +1074,14 @@ of <tt>init</tt> methods, it's very important not to treat these
methods as <tt>init</tt> methods if they aren't meant to be. It was methods as <tt>init</tt> methods if they aren't meant to be. It was
felt that implicitly defining these methods out of the family based on felt that implicitly defining these methods out of the family based on
the exact relationship between the return type and the declaring class the exact relationship between the return type and the declaring class
would much too subtle and fragile. Therefore we identify a small would be much too subtle and fragile. Therefore we identify a small
number of legitimate-seeming return types and call everything else an number of legitimate-seeming return types and call everything else an
error. This serves the secondary purpose of encouraging programmers error. This serves the secondary purpose of encouraging programmers
not to accidentally give methods names in the <tt>init</tt> family.</p></div> not to accidentally give methods names in the <tt>init</tt> family.</p>
<p>Note that a method with an <tt>init</tt>-family selector which
returns a non-Objective-C type (e.g. <tt>void</tt>) is perfectly
well-formed; it simply isn't in the <tt>init</tt> family.</p></div>
</li> </li>
</ul> </ul>
@ -1105,22 +1132,22 @@ semantics for its parameters and return type.</p>
<p>Methods in the <tt>alloc</tt>, <tt>copy</tt>, <tt>mutableCopy</tt>, <p>Methods in the <tt>alloc</tt>, <tt>copy</tt>, <tt>mutableCopy</tt>,
and <tt>new</tt> families &mdash; that is, methods in all the and <tt>new</tt> families &mdash; that is, methods in all the
currently-defined families except <tt>init</tt> &mdash; transfer currently-defined families except <tt>init</tt> &mdash; implicitly
ownership of a +1 retain count on their return value to the calling <a href="#objects.operands.retained_returns">return a retained
function, as if they were implicitly annotated with object</a> as if they were annotated with
the <tt>ns_returns_retained</tt> attribute. However, this is not true the <tt>ns_returns_retained</tt> attribute. This can be overridden by
if the method has either of the <tt>ns_returns_autoreleased</tt> or annotating the method with either of
the <tt>ns_returns_autoreleased</tt> or
<tt>ns_returns_not_retained</tt> attributes.</p> <tt>ns_returns_not_retained</tt> attributes.</p>
<div id="family.semantics.init"> <div id="family.semantics.init">
<h1>Semantics of <tt>init</tt></h1> <h1>Semantics of <tt>init</tt></h1>
<p>Methods in the <tt>init</tt> family must be transferred ownership <p>Methods in the <tt>init</tt> family implicitly
of a +1 retain count on their <tt>self</tt> parameter, exactly as if <a href="#objects.operands.consumed">consume</a> their <tt>self</tt>
the method had the <tt>ns_consumes_self</tt> attribute, and must parameter and <a href="#objects.operands.retained_returns">return a
transfer ownership of a +1 retain count on their return value, exactly retained object</a>. Neither of these properties can be altered
as if they method had the <tt>ns_returns_retained</tt> attribute. through attributes.</p>
Neither of these may be altered through attributes.</p>
<p>A call to an <tt>init</tt> method with a receiver that is either <p>A call to an <tt>init</tt> method with a receiver that is either
<tt>self</tt> (possibly parenthesized or casted) or <tt>super</tt> is <tt>self</tt> (possibly parenthesized or casted) or <tt>super</tt> is
@ -1128,17 +1155,19 @@ called a <span class="term">delegate init call</span>. It is an error
for a delegate init call to be made except from an <tt>init</tt> for a delegate init call to be made except from an <tt>init</tt>
method, and excluding blocks within such methods.</p> method, and excluding blocks within such methods.</p>
<p>The variable <tt>self</tt> is mutable in an <tt>init</tt> method <p>As an exception to the <a href="misc.self">usual rule</a>, the
and is implicitly qualified as <tt>__strong</tt>. However, a program variable <tt>self</tt> is mutable in an <tt>init</tt> method and has
is ill-formed, no diagnostic required, if it alters <tt>self</tt> the usual semantics for a <tt>__strong</tt> variable. However, it is
except to assign it the immediate result of a delegate init call. It undefined behavior and the program is ill-formed, no diagnostic
is an error to use the previous value of <tt>self</tt> after the required, if an <tt>init</tt> method attempts to use the previous
completion of a delegate init call.</p> value of <tt>self</tt> after the completion of a delegate init call.
It is conventional, but not required, for an <tt>init</tt> method to
return <tt>self</tt>.</p>
<p>A program is ill-formed, no diagnostic required, if it causes two <p>It is undefined behavior for a program to cause two or more calls
or more calls to <tt>init</tt> methods on the same object, except that to <tt>init</tt> methods on the same object, except that
each <tt>init</tt> method invocation may perform at most one each <tt>init</tt> method invocation may perform at most one delegate
delegate init call.</p> init call.</p>
</div> <!-- family.semantics.init --> </div> <!-- family.semantics.init -->