xref: /openbsd-src/gnu/llvm/clang/docs/ObjectiveCLiterals.rst (revision e5dd70708596ae51455a0ffa086a00c5b29f8583)
1*e5dd7070Spatrick====================
2*e5dd7070SpatrickObjective-C Literals
3*e5dd7070Spatrick====================
4*e5dd7070Spatrick
5*e5dd7070SpatrickIntroduction
6*e5dd7070Spatrick============
7*e5dd7070Spatrick
8*e5dd7070SpatrickThree new features were introduced into clang at the same time:
9*e5dd7070Spatrick*NSNumber Literals* provide a syntax for creating ``NSNumber`` from
10*e5dd7070Spatrickscalar literal expressions; *Collection Literals* provide a short-hand
11*e5dd7070Spatrickfor creating arrays and dictionaries; *Object Subscripting* provides a
12*e5dd7070Spatrickway to use subscripting with Objective-C objects. Users of Apple
13*e5dd7070Spatrickcompiler releases can use these features starting with the Apple LLVM
14*e5dd7070SpatrickCompiler 4.0. Users of open-source LLVM.org compiler releases can use
15*e5dd7070Spatrickthese features starting with clang v3.1.
16*e5dd7070Spatrick
17*e5dd7070SpatrickThese language additions simplify common Objective-C programming
18*e5dd7070Spatrickpatterns, make programs more concise, and improve the safety of
19*e5dd7070Spatrickcontainer creation.
20*e5dd7070Spatrick
21*e5dd7070SpatrickThis document describes how the features are implemented in clang, and
22*e5dd7070Spatrickhow to use them in your own programs.
23*e5dd7070Spatrick
24*e5dd7070SpatrickNSNumber Literals
25*e5dd7070Spatrick=================
26*e5dd7070Spatrick
27*e5dd7070SpatrickThe framework class ``NSNumber`` is used to wrap scalar values inside
28*e5dd7070Spatrickobjects: signed and unsigned integers (``char``, ``short``, ``int``,
29*e5dd7070Spatrick``long``, ``long long``), floating point numbers (``float``,
30*e5dd7070Spatrick``double``), and boolean values (``BOOL``, C++ ``bool``). Scalar values
31*e5dd7070Spatrickwrapped in objects are also known as *boxed* values.
32*e5dd7070Spatrick
33*e5dd7070SpatrickIn Objective-C, any character, numeric or boolean literal prefixed with
34*e5dd7070Spatrickthe ``'@'`` character will evaluate to a pointer to an ``NSNumber``
35*e5dd7070Spatrickobject initialized with that value. C's type suffixes may be used to
36*e5dd7070Spatrickcontrol the size of numeric literals.
37*e5dd7070Spatrick
38*e5dd7070SpatrickExamples
39*e5dd7070Spatrick--------
40*e5dd7070Spatrick
41*e5dd7070SpatrickThe following program illustrates the rules for ``NSNumber`` literals:
42*e5dd7070Spatrick
43*e5dd7070Spatrick.. code-block:: objc
44*e5dd7070Spatrick
45*e5dd7070Spatrick    void main(int argc, const char *argv[]) {
46*e5dd7070Spatrick      // character literals.
47*e5dd7070Spatrick      NSNumber *theLetterZ = @'Z';          // equivalent to [NSNumber numberWithChar:'Z']
48*e5dd7070Spatrick
49*e5dd7070Spatrick      // integral literals.
50*e5dd7070Spatrick      NSNumber *fortyTwo = @42;             // equivalent to [NSNumber numberWithInt:42]
51*e5dd7070Spatrick      NSNumber *fortyTwoUnsigned = @42U;    // equivalent to [NSNumber numberWithUnsignedInt:42U]
52*e5dd7070Spatrick      NSNumber *fortyTwoLong = @42L;        // equivalent to [NSNumber numberWithLong:42L]
53*e5dd7070Spatrick      NSNumber *fortyTwoLongLong = @42LL;   // equivalent to [NSNumber numberWithLongLong:42LL]
54*e5dd7070Spatrick
55*e5dd7070Spatrick      // floating point literals.
56*e5dd7070Spatrick      NSNumber *piFloat = @3.141592654F;    // equivalent to [NSNumber numberWithFloat:3.141592654F]
57*e5dd7070Spatrick      NSNumber *piDouble = @3.1415926535;   // equivalent to [NSNumber numberWithDouble:3.1415926535]
58*e5dd7070Spatrick
59*e5dd7070Spatrick      // BOOL literals.
60*e5dd7070Spatrick      NSNumber *yesNumber = @YES;           // equivalent to [NSNumber numberWithBool:YES]
61*e5dd7070Spatrick      NSNumber *noNumber = @NO;             // equivalent to [NSNumber numberWithBool:NO]
62*e5dd7070Spatrick
63*e5dd7070Spatrick    #ifdef __cplusplus
64*e5dd7070Spatrick      NSNumber *trueNumber = @true;         // equivalent to [NSNumber numberWithBool:(BOOL)true]
65*e5dd7070Spatrick      NSNumber *falseNumber = @false;       // equivalent to [NSNumber numberWithBool:(BOOL)false]
66*e5dd7070Spatrick    #endif
67*e5dd7070Spatrick    }
68*e5dd7070Spatrick
69*e5dd7070SpatrickDiscussion
70*e5dd7070Spatrick----------
71*e5dd7070Spatrick
72*e5dd7070SpatrickNSNumber literals only support literal scalar values after the ``'@'``.
73*e5dd7070SpatrickConsequently, ``@INT_MAX`` works, but ``@INT_MIN`` does not, because
74*e5dd7070Spatrickthey are defined like this:
75*e5dd7070Spatrick
76*e5dd7070Spatrick.. code-block:: objc
77*e5dd7070Spatrick
78*e5dd7070Spatrick    #define INT_MAX   2147483647  /* max value for an int */
79*e5dd7070Spatrick    #define INT_MIN   (-2147483647-1) /* min value for an int */
80*e5dd7070Spatrick
81*e5dd7070SpatrickThe definition of ``INT_MIN`` is not a simple literal, but a
82*e5dd7070Spatrickparenthesized expression. Parenthesized expressions are supported using
83*e5dd7070Spatrickthe `boxed expression <#objc_boxed_expressions>`_ syntax, which is
84*e5dd7070Spatrickdescribed in the next section.
85*e5dd7070Spatrick
86*e5dd7070SpatrickBecause ``NSNumber`` does not currently support wrapping ``long double``
87*e5dd7070Spatrickvalues, the use of a ``long double NSNumber`` literal (e.g.
88*e5dd7070Spatrick``@123.23L``) will be rejected by the compiler.
89*e5dd7070Spatrick
90*e5dd7070SpatrickPreviously, the ``BOOL`` type was simply a typedef for ``signed char``,
91*e5dd7070Spatrickand ``YES`` and ``NO`` were macros that expand to ``(BOOL)1`` and
92*e5dd7070Spatrick``(BOOL)0`` respectively. To support ``@YES`` and ``@NO`` expressions,
93*e5dd7070Spatrickthese macros are now defined using new language keywords in
94*e5dd7070Spatrick``<objc/objc.h>``:
95*e5dd7070Spatrick
96*e5dd7070Spatrick.. code-block:: objc
97*e5dd7070Spatrick
98*e5dd7070Spatrick    #if __has_feature(objc_bool)
99*e5dd7070Spatrick    #define YES             __objc_yes
100*e5dd7070Spatrick    #define NO              __objc_no
101*e5dd7070Spatrick    #else
102*e5dd7070Spatrick    #define YES             ((BOOL)1)
103*e5dd7070Spatrick    #define NO              ((BOOL)0)
104*e5dd7070Spatrick    #endif
105*e5dd7070Spatrick
106*e5dd7070SpatrickThe compiler implicitly converts ``__objc_yes`` and ``__objc_no`` to
107*e5dd7070Spatrick``(BOOL)1`` and ``(BOOL)0``. The keywords are used to disambiguate
108*e5dd7070Spatrick``BOOL`` and integer literals.
109*e5dd7070Spatrick
110*e5dd7070SpatrickObjective-C++ also supports ``@true`` and ``@false`` expressions, which
111*e5dd7070Spatrickare equivalent to ``@YES`` and ``@NO``.
112*e5dd7070Spatrick
113*e5dd7070SpatrickBoxed Expressions
114*e5dd7070Spatrick=================
115*e5dd7070Spatrick
116*e5dd7070SpatrickObjective-C provides a new syntax for boxing C expressions:
117*e5dd7070Spatrick
118*e5dd7070Spatrick.. code-block:: objc
119*e5dd7070Spatrick
120*e5dd7070Spatrick    @( <expression> )
121*e5dd7070Spatrick
122*e5dd7070SpatrickExpressions of scalar (numeric, enumerated, BOOL), C string pointer
123*e5dd7070Spatrickand some C structures (via NSValue) are supported:
124*e5dd7070Spatrick
125*e5dd7070Spatrick.. code-block:: objc
126*e5dd7070Spatrick
127*e5dd7070Spatrick    // numbers.
128*e5dd7070Spatrick    NSNumber *smallestInt = @(-INT_MAX - 1);  // [NSNumber numberWithInt:(-INT_MAX - 1)]
129*e5dd7070Spatrick    NSNumber *piOverTwo = @(M_PI / 2);        // [NSNumber numberWithDouble:(M_PI / 2)]
130*e5dd7070Spatrick
131*e5dd7070Spatrick    // enumerated types.
132*e5dd7070Spatrick    typedef enum { Red, Green, Blue } Color;
133*e5dd7070Spatrick    NSNumber *favoriteColor = @(Green);       // [NSNumber numberWithInt:((int)Green)]
134*e5dd7070Spatrick
135*e5dd7070Spatrick    // strings.
136*e5dd7070Spatrick    NSString *path = @(getenv("PATH"));       // [NSString stringWithUTF8String:(getenv("PATH"))]
137*e5dd7070Spatrick    NSArray *pathComponents = [path componentsSeparatedByString:@":"];
138*e5dd7070Spatrick
139*e5dd7070Spatrick    // structs.
140*e5dd7070Spatrick    NSValue *center = @(view.center);         // Point p = view.center;
141*e5dd7070Spatrick                                              // [NSValue valueWithBytes:&p objCType:@encode(Point)];
142*e5dd7070Spatrick    NSValue *frame = @(view.frame);           // Rect r = view.frame;
143*e5dd7070Spatrick                                              // [NSValue valueWithBytes:&r objCType:@encode(Rect)];
144*e5dd7070Spatrick
145*e5dd7070SpatrickBoxed Enums
146*e5dd7070Spatrick-----------
147*e5dd7070Spatrick
148*e5dd7070SpatrickCocoa frameworks frequently define constant values using *enums.*
149*e5dd7070SpatrickAlthough enum values are integral, they may not be used directly as
150*e5dd7070Spatrickboxed literals (this avoids conflicts with future ``'@'``-prefixed
151*e5dd7070SpatrickObjective-C keywords). Instead, an enum value must be placed inside a
152*e5dd7070Spatrickboxed expression. The following example demonstrates configuring an
153*e5dd7070Spatrick``AVAudioRecorder`` using a dictionary that contains a boxed enumeration
154*e5dd7070Spatrickvalue:
155*e5dd7070Spatrick
156*e5dd7070Spatrick.. code-block:: objc
157*e5dd7070Spatrick
158*e5dd7070Spatrick    enum {
159*e5dd7070Spatrick      AVAudioQualityMin = 0,
160*e5dd7070Spatrick      AVAudioQualityLow = 0x20,
161*e5dd7070Spatrick      AVAudioQualityMedium = 0x40,
162*e5dd7070Spatrick      AVAudioQualityHigh = 0x60,
163*e5dd7070Spatrick      AVAudioQualityMax = 0x7F
164*e5dd7070Spatrick    };
165*e5dd7070Spatrick
166*e5dd7070Spatrick    - (AVAudioRecorder *)recordToFile:(NSURL *)fileURL {
167*e5dd7070Spatrick      NSDictionary *settings = @{ AVEncoderAudioQualityKey : @(AVAudioQualityMax) };
168*e5dd7070Spatrick      return [[AVAudioRecorder alloc] initWithURL:fileURL settings:settings error:NULL];
169*e5dd7070Spatrick    }
170*e5dd7070Spatrick
171*e5dd7070SpatrickThe expression ``@(AVAudioQualityMax)`` converts ``AVAudioQualityMax``
172*e5dd7070Spatrickto an integer type, and boxes the value accordingly. If the enum has a
173*e5dd7070Spatrick:ref:`fixed underlying type <objc-fixed-enum>` as in:
174*e5dd7070Spatrick
175*e5dd7070Spatrick.. code-block:: objc
176*e5dd7070Spatrick
177*e5dd7070Spatrick    typedef enum : unsigned char { Red, Green, Blue } Color;
178*e5dd7070Spatrick    NSNumber *red = @(Red), *green = @(Green), *blue = @(Blue); // => [NSNumber numberWithUnsignedChar:]
179*e5dd7070Spatrick
180*e5dd7070Spatrickthen the fixed underlying type will be used to select the correct
181*e5dd7070Spatrick``NSNumber`` creation method.
182*e5dd7070Spatrick
183*e5dd7070SpatrickBoxing a value of enum type will result in a ``NSNumber`` pointer with a
184*e5dd7070Spatrickcreation method according to the underlying type of the enum, which can
185*e5dd7070Spatrickbe a :ref:`fixed underlying type <objc-fixed-enum>`
186*e5dd7070Spatrickor a compiler-defined integer type capable of representing the values of
187*e5dd7070Spatrickall the members of the enumeration:
188*e5dd7070Spatrick
189*e5dd7070Spatrick.. code-block:: objc
190*e5dd7070Spatrick
191*e5dd7070Spatrick    typedef enum : unsigned char { Red, Green, Blue } Color;
192*e5dd7070Spatrick    Color col = Red;
193*e5dd7070Spatrick    NSNumber *nsCol = @(col); // => [NSNumber numberWithUnsignedChar:]
194*e5dd7070Spatrick
195*e5dd7070SpatrickBoxed C Strings
196*e5dd7070Spatrick---------------
197*e5dd7070Spatrick
198*e5dd7070SpatrickA C string literal prefixed by the ``'@'`` token denotes an ``NSString``
199*e5dd7070Spatrickliteral in the same way a numeric literal prefixed by the ``'@'`` token
200*e5dd7070Spatrickdenotes an ``NSNumber`` literal. When the type of the parenthesized
201*e5dd7070Spatrickexpression is ``(char *)`` or ``(const char *)``, the result of the
202*e5dd7070Spatrickboxed expression is a pointer to an ``NSString`` object containing
203*e5dd7070Spatrickequivalent character data, which is assumed to be '\\0'-terminated and
204*e5dd7070SpatrickUTF-8 encoded. The following example converts C-style command line
205*e5dd7070Spatrickarguments into ``NSString`` objects.
206*e5dd7070Spatrick
207*e5dd7070Spatrick.. code-block:: objc
208*e5dd7070Spatrick
209*e5dd7070Spatrick    // Partition command line arguments into positional and option arguments.
210*e5dd7070Spatrick    NSMutableArray *args = [NSMutableArray new];
211*e5dd7070Spatrick    NSMutableDictionary *options = [NSMutableDictionary new];
212*e5dd7070Spatrick    while (--argc) {
213*e5dd7070Spatrick        const char *arg = *++argv;
214*e5dd7070Spatrick        if (strncmp(arg, "--", 2) == 0) {
215*e5dd7070Spatrick            options[@(arg + 2)] = @(*++argv);   // --key value
216*e5dd7070Spatrick        } else {
217*e5dd7070Spatrick            [args addObject:@(arg)];            // positional argument
218*e5dd7070Spatrick        }
219*e5dd7070Spatrick    }
220*e5dd7070Spatrick
221*e5dd7070SpatrickAs with all C pointers, character pointer expressions can involve
222*e5dd7070Spatrickarbitrary pointer arithmetic, therefore programmers must ensure that the
223*e5dd7070Spatrickcharacter data is valid. Passing ``NULL`` as the character pointer will
224*e5dd7070Spatrickraise an exception at runtime. When possible, the compiler will reject
225*e5dd7070Spatrick``NULL`` character pointers used in boxed expressions.
226*e5dd7070Spatrick
227*e5dd7070SpatrickBoxed C Structures
228*e5dd7070Spatrick------------------
229*e5dd7070Spatrick
230*e5dd7070SpatrickBoxed expressions support construction of NSValue objects.
231*e5dd7070SpatrickIt said that C structures can be used, the only requirement is:
232*e5dd7070Spatrickstructure should be marked with ``objc_boxable`` attribute.
233*e5dd7070SpatrickTo support older version of frameworks and/or third-party libraries
234*e5dd7070Spatrickyou may need to add the attribute via ``typedef``.
235*e5dd7070Spatrick
236*e5dd7070Spatrick.. code-block:: objc
237*e5dd7070Spatrick
238*e5dd7070Spatrick    struct __attribute__((objc_boxable)) Point {
239*e5dd7070Spatrick        // ...
240*e5dd7070Spatrick    };
241*e5dd7070Spatrick
242*e5dd7070Spatrick    typedef struct __attribute__((objc_boxable)) _Size {
243*e5dd7070Spatrick        // ...
244*e5dd7070Spatrick    } Size;
245*e5dd7070Spatrick
246*e5dd7070Spatrick    typedef struct _Rect {
247*e5dd7070Spatrick        // ...
248*e5dd7070Spatrick    } Rect;
249*e5dd7070Spatrick
250*e5dd7070Spatrick    struct Point p;
251*e5dd7070Spatrick    NSValue *point = @(p);          // ok
252*e5dd7070Spatrick    Size s;
253*e5dd7070Spatrick    NSValue *size = @(s);           // ok
254*e5dd7070Spatrick
255*e5dd7070Spatrick    Rect r;
256*e5dd7070Spatrick    NSValue *bad_rect = @(r);       // error
257*e5dd7070Spatrick
258*e5dd7070Spatrick    typedef struct __attribute__((objc_boxable)) _Rect Rect;
259*e5dd7070Spatrick
260*e5dd7070Spatrick    NSValue *good_rect = @(r);      // ok
261*e5dd7070Spatrick
262*e5dd7070Spatrick
263*e5dd7070SpatrickContainer Literals
264*e5dd7070Spatrick==================
265*e5dd7070Spatrick
266*e5dd7070SpatrickObjective-C now supports a new expression syntax for creating immutable
267*e5dd7070Spatrickarray and dictionary container objects.
268*e5dd7070Spatrick
269*e5dd7070SpatrickExamples
270*e5dd7070Spatrick--------
271*e5dd7070Spatrick
272*e5dd7070SpatrickImmutable array expression:
273*e5dd7070Spatrick
274*e5dd7070Spatrick.. code-block:: objc
275*e5dd7070Spatrick
276*e5dd7070Spatrick    NSArray *array = @[ @"Hello", NSApp, [NSNumber numberWithInt:42] ];
277*e5dd7070Spatrick
278*e5dd7070SpatrickThis creates an ``NSArray`` with 3 elements. The comma-separated
279*e5dd7070Spatricksub-expressions of an array literal can be any Objective-C object
280*e5dd7070Spatrickpointer typed expression.
281*e5dd7070Spatrick
282*e5dd7070SpatrickImmutable dictionary expression:
283*e5dd7070Spatrick
284*e5dd7070Spatrick.. code-block:: objc
285*e5dd7070Spatrick
286*e5dd7070Spatrick    NSDictionary *dictionary = @{
287*e5dd7070Spatrick        @"name" : NSUserName(),
288*e5dd7070Spatrick        @"date" : [NSDate date],
289*e5dd7070Spatrick        @"processInfo" : [NSProcessInfo processInfo]
290*e5dd7070Spatrick    };
291*e5dd7070Spatrick
292*e5dd7070SpatrickThis creates an ``NSDictionary`` with 3 key/value pairs. Value
293*e5dd7070Spatricksub-expressions of a dictionary literal must be Objective-C object
294*e5dd7070Spatrickpointer typed, as in array literals. Key sub-expressions must be of an
295*e5dd7070SpatrickObjective-C object pointer type that implements the
296*e5dd7070Spatrick``<NSCopying>`` protocol.
297*e5dd7070Spatrick
298*e5dd7070SpatrickDiscussion
299*e5dd7070Spatrick----------
300*e5dd7070Spatrick
301*e5dd7070SpatrickNeither keys nor values can have the value ``nil`` in containers. If the
302*e5dd7070Spatrickcompiler can prove that a key or value is ``nil`` at compile time, then
303*e5dd7070Spatricka warning will be emitted. Otherwise, a runtime error will occur.
304*e5dd7070Spatrick
305*e5dd7070SpatrickUsing array and dictionary literals is safer than the variadic creation
306*e5dd7070Spatrickforms commonly in use today. Array literal expressions expand to calls
307*e5dd7070Spatrickto ``+[NSArray arrayWithObjects:count:]``, which validates that all
308*e5dd7070Spatrickobjects are non-``nil``. The variadic form,
309*e5dd7070Spatrick``+[NSArray arrayWithObjects:]`` uses ``nil`` as an argument list
310*e5dd7070Spatrickterminator, which can lead to malformed array objects. Dictionary
311*e5dd7070Spatrickliterals are similarly created with
312*e5dd7070Spatrick``+[NSDictionary dictionaryWithObjects:forKeys:count:]`` which validates
313*e5dd7070Spatrickall objects and keys, unlike
314*e5dd7070Spatrick``+[NSDictionary dictionaryWithObjectsAndKeys:]`` which also uses a
315*e5dd7070Spatrick``nil`` parameter as an argument list terminator.
316*e5dd7070Spatrick
317*e5dd7070SpatrickObject Subscripting
318*e5dd7070Spatrick===================
319*e5dd7070Spatrick
320*e5dd7070SpatrickObjective-C object pointer values can now be used with C's subscripting
321*e5dd7070Spatrickoperator.
322*e5dd7070Spatrick
323*e5dd7070SpatrickExamples
324*e5dd7070Spatrick--------
325*e5dd7070Spatrick
326*e5dd7070SpatrickThe following code demonstrates the use of object subscripting syntax
327*e5dd7070Spatrickwith ``NSMutableArray`` and ``NSMutableDictionary`` objects:
328*e5dd7070Spatrick
329*e5dd7070Spatrick.. code-block:: objc
330*e5dd7070Spatrick
331*e5dd7070Spatrick    NSMutableArray *array = ...;
332*e5dd7070Spatrick    NSUInteger idx = ...;
333*e5dd7070Spatrick    id newObject = ...;
334*e5dd7070Spatrick    id oldObject = array[idx];
335*e5dd7070Spatrick    array[idx] = newObject;         // replace oldObject with newObject
336*e5dd7070Spatrick
337*e5dd7070Spatrick    NSMutableDictionary *dictionary = ...;
338*e5dd7070Spatrick    NSString *key = ...;
339*e5dd7070Spatrick    oldObject = dictionary[key];
340*e5dd7070Spatrick    dictionary[key] = newObject;    // replace oldObject with newObject
341*e5dd7070Spatrick
342*e5dd7070SpatrickThe next section explains how subscripting expressions map to accessor
343*e5dd7070Spatrickmethods.
344*e5dd7070Spatrick
345*e5dd7070SpatrickSubscripting Methods
346*e5dd7070Spatrick--------------------
347*e5dd7070Spatrick
348*e5dd7070SpatrickObjective-C supports two kinds of subscript expressions: *array-style*
349*e5dd7070Spatricksubscript expressions use integer typed subscripts; *dictionary-style*
350*e5dd7070Spatricksubscript expressions use Objective-C object pointer typed subscripts.
351*e5dd7070SpatrickEach type of subscript expression is mapped to a message send using a
352*e5dd7070Spatrickpredefined selector. The advantage of this design is flexibility: class
353*e5dd7070Spatrickdesigners are free to introduce subscripting by declaring methods or by
354*e5dd7070Spatrickadopting protocols. Moreover, because the method names are selected by
355*e5dd7070Spatrickthe type of the subscript, an object can be subscripted using both array
356*e5dd7070Spatrickand dictionary styles.
357*e5dd7070Spatrick
358*e5dd7070SpatrickArray-Style Subscripting
359*e5dd7070Spatrick^^^^^^^^^^^^^^^^^^^^^^^^
360*e5dd7070Spatrick
361*e5dd7070SpatrickWhen the subscript operand has an integral type, the expression is
362*e5dd7070Spatrickrewritten to use one of two different selectors, depending on whether
363*e5dd7070Spatrickthe element is being read or written. When an expression reads an
364*e5dd7070Spatrickelement using an integral index, as in the following example:
365*e5dd7070Spatrick
366*e5dd7070Spatrick.. code-block:: objc
367*e5dd7070Spatrick
368*e5dd7070Spatrick    NSUInteger idx = ...;
369*e5dd7070Spatrick    id value = object[idx];
370*e5dd7070Spatrick
371*e5dd7070Spatrickit is translated into a call to ``objectAtIndexedSubscript:``
372*e5dd7070Spatrick
373*e5dd7070Spatrick.. code-block:: objc
374*e5dd7070Spatrick
375*e5dd7070Spatrick    id value = [object objectAtIndexedSubscript:idx];
376*e5dd7070Spatrick
377*e5dd7070SpatrickWhen an expression writes an element using an integral index:
378*e5dd7070Spatrick
379*e5dd7070Spatrick.. code-block:: objc
380*e5dd7070Spatrick
381*e5dd7070Spatrick    object[idx] = newValue;
382*e5dd7070Spatrick
383*e5dd7070Spatrickit is translated to a call to ``setObject:atIndexedSubscript:``
384*e5dd7070Spatrick
385*e5dd7070Spatrick.. code-block:: objc
386*e5dd7070Spatrick
387*e5dd7070Spatrick    [object setObject:newValue atIndexedSubscript:idx];
388*e5dd7070Spatrick
389*e5dd7070SpatrickThese message sends are then type-checked and performed just like
390*e5dd7070Spatrickexplicit message sends. The method used for objectAtIndexedSubscript:
391*e5dd7070Spatrickmust be declared with an argument of integral type and a return value of
392*e5dd7070Spatricksome Objective-C object pointer type. The method used for
393*e5dd7070SpatricksetObject:atIndexedSubscript: must be declared with its first argument
394*e5dd7070Spatrickhaving some Objective-C pointer type and its second argument having
395*e5dd7070Spatrickintegral type.
396*e5dd7070Spatrick
397*e5dd7070SpatrickThe meaning of indexes is left up to the declaring class. The compiler
398*e5dd7070Spatrickwill coerce the index to the appropriate argument type of the method it
399*e5dd7070Spatrickuses for type-checking. For an instance of ``NSArray``, reading an
400*e5dd7070Spatrickelement using an index outside the range ``[0, array.count)`` will raise
401*e5dd7070Spatrickan exception. For an instance of ``NSMutableArray``, assigning to an
402*e5dd7070Spatrickelement using an index within this range will replace that element, but
403*e5dd7070Spatrickassigning to an element using an index outside this range will raise an
404*e5dd7070Spatrickexception; no syntax is provided for inserting, appending, or removing
405*e5dd7070Spatrickelements for mutable arrays.
406*e5dd7070Spatrick
407*e5dd7070SpatrickA class need not declare both methods in order to take advantage of this
408*e5dd7070Spatricklanguage feature. For example, the class ``NSArray`` declares only
409*e5dd7070Spatrick``objectAtIndexedSubscript:``, so that assignments to elements will fail
410*e5dd7070Spatrickto type-check; moreover, its subclass ``NSMutableArray`` declares
411*e5dd7070Spatrick``setObject:atIndexedSubscript:``.
412*e5dd7070Spatrick
413*e5dd7070SpatrickDictionary-Style Subscripting
414*e5dd7070Spatrick^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
415*e5dd7070Spatrick
416*e5dd7070SpatrickWhen the subscript operand has an Objective-C object pointer type, the
417*e5dd7070Spatrickexpression is rewritten to use one of two different selectors, depending
418*e5dd7070Spatrickon whether the element is being read from or written to. When an
419*e5dd7070Spatrickexpression reads an element using an Objective-C object pointer
420*e5dd7070Spatricksubscript operand, as in the following example:
421*e5dd7070Spatrick
422*e5dd7070Spatrick.. code-block:: objc
423*e5dd7070Spatrick
424*e5dd7070Spatrick    id key = ...;
425*e5dd7070Spatrick    id value = object[key];
426*e5dd7070Spatrick
427*e5dd7070Spatrickit is translated into a call to the ``objectForKeyedSubscript:`` method:
428*e5dd7070Spatrick
429*e5dd7070Spatrick.. code-block:: objc
430*e5dd7070Spatrick
431*e5dd7070Spatrick    id value = [object objectForKeyedSubscript:key];
432*e5dd7070Spatrick
433*e5dd7070SpatrickWhen an expression writes an element using an Objective-C object pointer
434*e5dd7070Spatricksubscript:
435*e5dd7070Spatrick
436*e5dd7070Spatrick.. code-block:: objc
437*e5dd7070Spatrick
438*e5dd7070Spatrick    object[key] = newValue;
439*e5dd7070Spatrick
440*e5dd7070Spatrickit is translated to a call to ``setObject:forKeyedSubscript:``
441*e5dd7070Spatrick
442*e5dd7070Spatrick.. code-block:: objc
443*e5dd7070Spatrick
444*e5dd7070Spatrick    [object setObject:newValue forKeyedSubscript:key];
445*e5dd7070Spatrick
446*e5dd7070SpatrickThe behavior of ``setObject:forKeyedSubscript:`` is class-specific; but
447*e5dd7070Spatrickin general it should replace an existing value if one is already
448*e5dd7070Spatrickassociated with a key, otherwise it should add a new value for the key.
449*e5dd7070SpatrickNo syntax is provided for removing elements from mutable dictionaries.
450*e5dd7070Spatrick
451*e5dd7070SpatrickDiscussion
452*e5dd7070Spatrick----------
453*e5dd7070Spatrick
454*e5dd7070SpatrickAn Objective-C subscript expression occurs when the base operand of the
455*e5dd7070SpatrickC subscript operator has an Objective-C object pointer type. Since this
456*e5dd7070Spatrickpotentially collides with pointer arithmetic on the value, these
457*e5dd7070Spatrickexpressions are only supported under the modern Objective-C runtime,
458*e5dd7070Spatrickwhich categorically forbids such arithmetic.
459*e5dd7070Spatrick
460*e5dd7070SpatrickCurrently, only subscripts of integral or Objective-C object pointer
461*e5dd7070Spatricktype are supported. In C++, a class type can be used if it has a single
462*e5dd7070Spatrickconversion function to an integral or Objective-C pointer type, in which
463*e5dd7070Spatrickcase that conversion is applied and analysis continues as appropriate.
464*e5dd7070SpatrickOtherwise, the expression is ill-formed.
465*e5dd7070Spatrick
466*e5dd7070SpatrickAn Objective-C object subscript expression is always an l-value. If the
467*e5dd7070Spatrickexpression appears on the left-hand side of a simple assignment operator
468*e5dd7070Spatrick(=), the element is written as described below. If the expression
469*e5dd7070Spatrickappears on the left-hand side of a compound assignment operator (e.g.
470*e5dd7070Spatrick+=), the program is ill-formed, because the result of reading an element
471*e5dd7070Spatrickis always an Objective-C object pointer and no binary operators are
472*e5dd7070Spatricklegal on such pointers. If the expression appears in any other position,
473*e5dd7070Spatrickthe element is read as described below. It is an error to take the
474*e5dd7070Spatrickaddress of a subscript expression, or (in C++) to bind a reference to
475*e5dd7070Spatrickit.
476*e5dd7070Spatrick
477*e5dd7070SpatrickPrograms can use object subscripting with Objective-C object pointers of
478*e5dd7070Spatricktype ``id``. Normal dynamic message send rules apply; the compiler must
479*e5dd7070Spatricksee *some* declaration of the subscripting methods, and will pick the
480*e5dd7070Spatrickdeclaration seen first.
481*e5dd7070Spatrick
482*e5dd7070SpatrickCaveats
483*e5dd7070Spatrick=======
484*e5dd7070Spatrick
485*e5dd7070SpatrickObjects created using the literal or boxed expression syntax are not
486*e5dd7070Spatrickguaranteed to be uniqued by the runtime, but nor are they guaranteed to
487*e5dd7070Spatrickbe newly-allocated. As such, the result of performing direct comparisons
488*e5dd7070Spatrickagainst the location of an object literal (using ``==``, ``!=``, ``<``,
489*e5dd7070Spatrick``<=``, ``>``, or ``>=``) is not well-defined. This is usually a simple
490*e5dd7070Spatrickmistake in code that intended to call the ``isEqual:`` method (or the
491*e5dd7070Spatrick``compare:`` method).
492*e5dd7070Spatrick
493*e5dd7070SpatrickThis caveat applies to compile-time string literals as well.
494*e5dd7070SpatrickHistorically, string literals (using the ``@"..."`` syntax) have been
495*e5dd7070Spatrickuniqued across translation units during linking. This is an
496*e5dd7070Spatrickimplementation detail of the compiler and should not be relied upon. If
497*e5dd7070Spatrickyou are using such code, please use global string constants instead
498*e5dd7070Spatrick(``NSString * const MyConst = @"..."``) or use ``isEqual:``.
499*e5dd7070Spatrick
500*e5dd7070SpatrickGrammar Additions
501*e5dd7070Spatrick=================
502*e5dd7070Spatrick
503*e5dd7070SpatrickTo support the new syntax described above, the Objective-C
504*e5dd7070Spatrick``@``-expression grammar has the following new productions:
505*e5dd7070Spatrick
506*e5dd7070Spatrick::
507*e5dd7070Spatrick
508*e5dd7070Spatrick    objc-at-expression : '@' (string-literal | encode-literal | selector-literal | protocol-literal | object-literal)
509*e5dd7070Spatrick                       ;
510*e5dd7070Spatrick
511*e5dd7070Spatrick    object-literal : ('+' | '-')? numeric-constant
512*e5dd7070Spatrick                   | character-constant
513*e5dd7070Spatrick                   | boolean-constant
514*e5dd7070Spatrick                   | array-literal
515*e5dd7070Spatrick                   | dictionary-literal
516*e5dd7070Spatrick                   ;
517*e5dd7070Spatrick
518*e5dd7070Spatrick    boolean-constant : '__objc_yes' | '__objc_no' | 'true' | 'false'  /* boolean keywords. */
519*e5dd7070Spatrick                     ;
520*e5dd7070Spatrick
521*e5dd7070Spatrick    array-literal : '[' assignment-expression-list ']'
522*e5dd7070Spatrick                  ;
523*e5dd7070Spatrick
524*e5dd7070Spatrick    assignment-expression-list : assignment-expression (',' assignment-expression-list)?
525*e5dd7070Spatrick                               | /* empty */
526*e5dd7070Spatrick                               ;
527*e5dd7070Spatrick
528*e5dd7070Spatrick    dictionary-literal : '{' key-value-list '}'
529*e5dd7070Spatrick                       ;
530*e5dd7070Spatrick
531*e5dd7070Spatrick    key-value-list : key-value-pair (',' key-value-list)?
532*e5dd7070Spatrick                   | /* empty */
533*e5dd7070Spatrick                   ;
534*e5dd7070Spatrick
535*e5dd7070Spatrick    key-value-pair : assignment-expression ':' assignment-expression
536*e5dd7070Spatrick                   ;
537*e5dd7070Spatrick
538*e5dd7070SpatrickNote: ``@true`` and ``@false`` are only supported in Objective-C++.
539*e5dd7070Spatrick
540*e5dd7070SpatrickAvailability Checks
541*e5dd7070Spatrick===================
542*e5dd7070Spatrick
543*e5dd7070SpatrickPrograms test for the new features by using clang's \_\_has\_feature
544*e5dd7070Spatrickchecks. Here are examples of their use:
545*e5dd7070Spatrick
546*e5dd7070Spatrick.. code-block:: objc
547*e5dd7070Spatrick
548*e5dd7070Spatrick    #if __has_feature(objc_array_literals)
549*e5dd7070Spatrick        // new way.
550*e5dd7070Spatrick        NSArray *elements = @[ @"H", @"He", @"O", @"C" ];
551*e5dd7070Spatrick    #else
552*e5dd7070Spatrick        // old way (equivalent).
553*e5dd7070Spatrick        id objects[] = { @"H", @"He", @"O", @"C" };
554*e5dd7070Spatrick        NSArray *elements = [NSArray arrayWithObjects:objects count:4];
555*e5dd7070Spatrick    #endif
556*e5dd7070Spatrick
557*e5dd7070Spatrick    #if __has_feature(objc_dictionary_literals)
558*e5dd7070Spatrick        // new way.
559*e5dd7070Spatrick        NSDictionary *masses = @{ @"H" : @1.0078,  @"He" : @4.0026, @"O" : @15.9990, @"C" : @12.0096 };
560*e5dd7070Spatrick    #else
561*e5dd7070Spatrick        // old way (equivalent).
562*e5dd7070Spatrick        id keys[] = { @"H", @"He", @"O", @"C" };
563*e5dd7070Spatrick        id values[] = { [NSNumber numberWithDouble:1.0078], [NSNumber numberWithDouble:4.0026],
564*e5dd7070Spatrick                        [NSNumber numberWithDouble:15.9990], [NSNumber numberWithDouble:12.0096] };
565*e5dd7070Spatrick        NSDictionary *masses = [NSDictionary dictionaryWithObjects:objects forKeys:keys count:4];
566*e5dd7070Spatrick    #endif
567*e5dd7070Spatrick
568*e5dd7070Spatrick    #if __has_feature(objc_subscripting)
569*e5dd7070Spatrick        NSUInteger i, count = elements.count;
570*e5dd7070Spatrick        for (i = 0; i < count; ++i) {
571*e5dd7070Spatrick            NSString *element = elements[i];
572*e5dd7070Spatrick            NSNumber *mass = masses[element];
573*e5dd7070Spatrick            NSLog(@"the mass of %@ is %@", element, mass);
574*e5dd7070Spatrick        }
575*e5dd7070Spatrick    #else
576*e5dd7070Spatrick        NSUInteger i, count = [elements count];
577*e5dd7070Spatrick        for (i = 0; i < count; ++i) {
578*e5dd7070Spatrick            NSString *element = [elements objectAtIndex:i];
579*e5dd7070Spatrick            NSNumber *mass = [masses objectForKey:element];
580*e5dd7070Spatrick            NSLog(@"the mass of %@ is %@", element, mass);
581*e5dd7070Spatrick        }
582*e5dd7070Spatrick    #endif
583*e5dd7070Spatrick
584*e5dd7070Spatrick    #if __has_attribute(objc_boxable)
585*e5dd7070Spatrick        typedef struct __attribute__((objc_boxable)) _Rect Rect;
586*e5dd7070Spatrick    #endif
587*e5dd7070Spatrick
588*e5dd7070Spatrick    #if __has_feature(objc_boxed_nsvalue_expressions)
589*e5dd7070Spatrick        CABasicAnimation animation = [CABasicAnimation animationWithKeyPath:@"position"];
590*e5dd7070Spatrick        animation.fromValue = @(layer.position);
591*e5dd7070Spatrick        animation.toValue = @(newPosition);
592*e5dd7070Spatrick        [layer addAnimation:animation forKey:@"move"];
593*e5dd7070Spatrick    #else
594*e5dd7070Spatrick        CABasicAnimation animation = [CABasicAnimation animationWithKeyPath:@"position"];
595*e5dd7070Spatrick        animation.fromValue = [NSValue valueWithCGPoint:layer.position];
596*e5dd7070Spatrick        animation.toValue = [NSValue valueWithCGPoint:newPosition];
597*e5dd7070Spatrick        [layer addAnimation:animation forKey:@"move"];
598*e5dd7070Spatrick    #endif
599*e5dd7070Spatrick
600*e5dd7070SpatrickCode can use also ``__has_feature(objc_bool)`` to check for the
601*e5dd7070Spatrickavailability of numeric literals support. This checks for the new
602*e5dd7070Spatrick``__objc_yes / __objc_no`` keywords, which enable the use of
603*e5dd7070Spatrick``@YES / @NO`` literals.
604*e5dd7070Spatrick
605*e5dd7070SpatrickTo check whether boxed expressions are supported, use
606*e5dd7070Spatrick``__has_feature(objc_boxed_expressions)`` feature macro.
607