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