Home | History | Annotate | Download | only in SemaObjC
      1 // RUN: %clang_cc1  -fsyntax-only -verify %s
      2 
      3 /*
      4   Conditions for warning:
      5   1. the property is atomic
      6   2. the current @implementation contains an @synthesize for the property
      7   3. the current @implementation contains a hand-written setter XOR getter
      8   4. the property is read-write
      9   
     10   Cases marked WARN should warn one the following:
     11   warning: Atomic property 'x' has a synthesized setter and a 
     12   manually-implemented getter, which may break atomicity.
     13   warning: Atomic property 'x' has a synthesized getter and a 
     14   manually-implemented setter, which may break atomicity.
     15   
     16   Cases not marked WARN only satisfy the indicated subset 
     17   of the conditions required to warn.
     18 
     19   There should be 8 warnings.
     20 */
     21 
     22 @interface Foo 
     23 {
     24     /* 12 4 */    int GetSet;
     25     /* WARN */    int Get;
     26     /* WARN */    int Set;
     27     /* 12 4 */    int None;
     28     /*  2 4 */    int GetSet_Nonatomic;
     29     /*  234 */    int Get_Nonatomic;
     30     /*  234 */    int Set_Nonatomic;
     31     /*  2 4 */    int None_Nonatomic;
     32 
     33     /* 12   */    int GetSet_ReadOnly;
     34     /* 123  */    int Get_ReadOnly;
     35     /* 123  */    int Set_ReadOnly;
     36     /* 12   */    int None_ReadOnly;
     37     /*  2   */    int GetSet_Nonatomic_ReadOnly;
     38     /*  23  */    int Get_Nonatomic_ReadOnly;
     39     /*  23  */    int Set_Nonatomic_ReadOnly;
     40     /*  2   */    int None_Nonatomic_ReadOnly;
     41 
     42     /* 12 4 */    int GetSet_ReadWriteInExt;
     43     /* WARN */    int Get_ReadWriteInExt;
     44     /* WARN */    int Set_ReadWriteInExt;
     45     /* 12 4 */    int None_ReadWriteInExt;
     46     /*  2 4 */    int GetSet_Nonatomic_ReadWriteInExt;
     47     /*  234 */    int Get_Nonatomic_ReadWriteInExt;
     48     /*  234 */    int Set_Nonatomic_ReadWriteInExt;
     49     /*  2 4 */    int None_Nonatomic_ReadWriteInExt;
     50 
     51 
     52     /* 12 4 */    int GetSet_LateSynthesize;
     53     /* WARN */    int Get_LateSynthesize;
     54     /* WARN */    int Set_LateSynthesize;
     55     /* 12 4 */    int None_LateSynthesize;
     56     /*  2 4 */    int GetSet_Nonatomic_LateSynthesize;
     57     /*  234 */    int Get_Nonatomic_LateSynthesize;
     58     /*  234 */    int Set_Nonatomic_LateSynthesize;
     59     /*  2 4 */    int None_Nonatomic_LateSynthesize;
     60 
     61     /* 12   */    int GetSet_ReadOnly_LateSynthesize;
     62     /* 123  */    int Get_ReadOnly_LateSynthesize;
     63     /* 123  */    int Set_ReadOnly_LateSynthesize;
     64     /* 12   */    int None_ReadOnly_LateSynthesize;
     65     /*  2   */    int GetSet_Nonatomic_ReadOnly_LateSynthesize;
     66     /*  23  */    int Get_Nonatomic_ReadOnly_LateSynthesize;
     67     /*  23  */    int Set_Nonatomic_ReadOnly_LateSynthesize;
     68     /*  2   */    int None_Nonatomic_ReadOnly_LateSynthesize;
     69 
     70     /* 12 4 */    int GetSet_ReadWriteInExt_LateSynthesize;
     71     /* WARN */    int Get_ReadWriteInExt_LateSynthesize;
     72     /* WARN */    int Set_ReadWriteInExt_LateSynthesize;
     73     /* 12 4 */    int None_ReadWriteInExt_LateSynthesize;
     74     /*  2 4 */    int GetSet_Nonatomic_ReadWriteInExt_LateSynthesize;
     75     /*  234 */    int Get_Nonatomic_ReadWriteInExt_LateSynthesize;
     76     /*  234 */    int Set_Nonatomic_ReadWriteInExt_LateSynthesize;
     77     /*  2 4 */    int None_Nonatomic_ReadWriteInExt_LateSynthesize;
     78 
     79 
     80     /* 1  4 */    int GetSet_NoSynthesize;
     81     /* 1 34 */    int Get_NoSynthesize;
     82     /* 1 34 */    int Set_NoSynthesize;
     83     /* 1  4 */    int None_NoSynthesize;
     84     /*    4 */    int GetSet_Nonatomic_NoSynthesize;
     85     /*   34 */    int Get_Nonatomic_NoSynthesize;
     86     /*   34 */    int Set_Nonatomic_NoSynthesize;
     87     /*    4 */    int None_Nonatomic_NoSynthesize;
     88 
     89     /* 1    */    int GetSet_ReadOnly_NoSynthesize;
     90     /* 1 3  */    int Get_ReadOnly_NoSynthesize;
     91     /* 1 3  */    int Set_ReadOnly_NoSynthesize;
     92     /* 1    */    int None_ReadOnly_NoSynthesize;
     93     /*      */    int GetSet_Nonatomic_ReadOnly_NoSynthesize;
     94     /*   3  */    int Get_Nonatomic_ReadOnly_NoSynthesize;
     95     /*   3  */    int Set_Nonatomic_ReadOnly_NoSynthesize;
     96     /*      */    int None_Nonatomic_ReadOnly_NoSynthesize;
     97 
     98     /* 1  4 */    int GetSet_ReadWriteInExt_NoSynthesize;
     99     /* 1 34 */    int Get_ReadWriteInExt_NoSynthesize;
    100     /* 1 34 */    int Set_ReadWriteInExt_NoSynthesize;
    101     /* 1  4 */    int None_ReadWriteInExt_NoSynthesize;
    102     /*    4 */    int GetSet_Nonatomic_ReadWriteInExt_NoSynthesize;
    103     /*   34 */    int Get_Nonatomic_ReadWriteInExt_NoSynthesize;
    104     /*   34 */    int Set_Nonatomic_ReadWriteInExt_NoSynthesize;
    105     /*    4 */    int None_Nonatomic_ReadWriteInExt_NoSynthesize;
    106 }
    107 
    108 // read-write - might warn
    109 @property int GetSet;
    110 @property int Get;	// expected-note {{property declared here}}
    111 @property int Set;	// expected-note {{property declared here}}
    112 @property int None;
    113 @property(nonatomic) int GetSet_Nonatomic;
    114 @property(nonatomic) int Get_Nonatomic;
    115 @property(nonatomic) int Set_Nonatomic;
    116 @property(nonatomic) int None_Nonatomic;
    117 
    118 // read-only - must not warn
    119 @property(readonly) int GetSet_ReadOnly;
    120 @property(readonly) int Get_ReadOnly;
    121 @property(readonly) int Set_ReadOnly;
    122 @property(readonly) int None_ReadOnly;
    123 @property(nonatomic,readonly) int GetSet_Nonatomic_ReadOnly;
    124 @property(nonatomic,readonly) int Get_Nonatomic_ReadOnly;
    125 @property(nonatomic,readonly) int Set_Nonatomic_ReadOnly;
    126 @property(nonatomic,readonly) int None_Nonatomic_ReadOnly;
    127 
    128 // read-only in class, read-write in class extension - might warn
    129 @property(readonly) int GetSet_ReadWriteInExt;
    130 @property(readonly) int Get_ReadWriteInExt;	// expected-note {{property declared here}}
    131 @property(readonly) int Set_ReadWriteInExt;	// expected-note {{property declared here}}
    132 @property(readonly) int None_ReadWriteInExt;
    133 @property(nonatomic,readonly) int GetSet_Nonatomic_ReadWriteInExt;
    134 @property(nonatomic,readonly) int Get_Nonatomic_ReadWriteInExt;
    135 @property(nonatomic,readonly) int Set_Nonatomic_ReadWriteInExt;
    136 @property(nonatomic,readonly) int None_Nonatomic_ReadWriteInExt;
    137 
    138 
    139 // same as above, but @synthesize follows the hand-written methods - might warn
    140 @property int GetSet_LateSynthesize;
    141 @property int Get_LateSynthesize;	// expected-note {{property declared here}}
    142 @property int Set_LateSynthesize;	// expected-note {{property declared here}}
    143 @property int None_LateSynthesize;
    144 @property(nonatomic) int GetSet_Nonatomic_LateSynthesize;
    145 @property(nonatomic) int Get_Nonatomic_LateSynthesize;
    146 @property(nonatomic) int Set_Nonatomic_LateSynthesize;
    147 @property(nonatomic) int None_Nonatomic_LateSynthesize;
    148 
    149 @property(readonly) int GetSet_ReadOnly_LateSynthesize;
    150 @property(readonly) int Get_ReadOnly_LateSynthesize;
    151 @property(readonly) int Set_ReadOnly_LateSynthesize;
    152 @property(readonly) int None_ReadOnly_LateSynthesize;
    153 @property(nonatomic,readonly) int GetSet_Nonatomic_ReadOnly_LateSynthesize;
    154 @property(nonatomic,readonly) int Get_Nonatomic_ReadOnly_LateSynthesize;
    155 @property(nonatomic,readonly) int Set_Nonatomic_ReadOnly_LateSynthesize;
    156 @property(nonatomic,readonly) int None_Nonatomic_ReadOnly_LateSynthesize;
    157 
    158 @property(readonly) int GetSet_ReadWriteInExt_LateSynthesize;
    159 @property(readonly) int Get_ReadWriteInExt_LateSynthesize;	// expected-note {{property declared here}}
    160 @property(readonly) int Set_ReadWriteInExt_LateSynthesize;	// expected-note {{property declared here}}
    161 @property(readonly) int None_ReadWriteInExt_LateSynthesize;
    162 @property(nonatomic,readonly) int GetSet_Nonatomic_ReadWriteInExt_LateSynthesize;
    163 @property(nonatomic,readonly) int Get_Nonatomic_ReadWriteInExt_LateSynthesize;
    164 @property(nonatomic,readonly) int Set_Nonatomic_ReadWriteInExt_LateSynthesize;
    165 @property(nonatomic,readonly) int None_Nonatomic_ReadWriteInExt_LateSynthesize;
    166 
    167 
    168 // same as above, but with no @synthesize - must not warn
    169 @property int GetSet_NoSynthesize;
    170 @property int Get_NoSynthesize;
    171 @property int Set_NoSynthesize;
    172 @property int None_NoSynthesize;
    173 @property(nonatomic) int GetSet_Nonatomic_NoSynthesize;
    174 @property(nonatomic) int Get_Nonatomic_NoSynthesize;
    175 @property(nonatomic) int Set_Nonatomic_NoSynthesize;
    176 @property(nonatomic) int None_Nonatomic_NoSynthesize;
    177 
    178 @property(readonly) int GetSet_ReadOnly_NoSynthesize;
    179 @property(readonly) int Get_ReadOnly_NoSynthesize;
    180 @property(readonly) int Set_ReadOnly_NoSynthesize;
    181 @property(readonly) int None_ReadOnly_NoSynthesize;
    182 @property(nonatomic,readonly) int GetSet_Nonatomic_ReadOnly_NoSynthesize;
    183 @property(nonatomic,readonly) int Get_Nonatomic_ReadOnly_NoSynthesize;
    184 @property(nonatomic,readonly) int Set_Nonatomic_ReadOnly_NoSynthesize;
    185 @property(nonatomic,readonly) int None_Nonatomic_ReadOnly_NoSynthesize;
    186 
    187 @property(readonly) int GetSet_ReadWriteInExt_NoSynthesize;
    188 @property(readonly) int Get_ReadWriteInExt_NoSynthesize;
    189 @property(readonly) int Set_ReadWriteInExt_NoSynthesize;
    190 @property(readonly) int None_ReadWriteInExt_NoSynthesize;
    191 @property(nonatomic,readonly) int GetSet_Nonatomic_ReadWriteInExt_NoSynthesize;
    192 @property(nonatomic,readonly) int Get_Nonatomic_ReadWriteInExt_NoSynthesize;
    193 @property(nonatomic,readonly) int Set_Nonatomic_ReadWriteInExt_NoSynthesize;
    194 @property(nonatomic,readonly) int None_Nonatomic_ReadWriteInExt_NoSynthesize;
    195 
    196 @end
    197 
    198 
    199 @interface Foo ()
    200 
    201 @property(readwrite) int GetSet_ReadWriteInExt;
    202 @property(readwrite) int Get_ReadWriteInExt;
    203 @property(readwrite) int Set_ReadWriteInExt;
    204 @property(readwrite) int None_ReadWriteInExt;
    205 @property(nonatomic,readwrite) int GetSet_Nonatomic_ReadWriteInExt;
    206 @property(nonatomic,readwrite) int Get_Nonatomic_ReadWriteInExt;
    207 @property(nonatomic,readwrite) int Set_Nonatomic_ReadWriteInExt;
    208 @property(nonatomic,readwrite) int None_Nonatomic_ReadWriteInExt;
    209 
    210 @property(readwrite) int GetSet_ReadWriteInExt_LateSynthesize;
    211 @property(readwrite) int Get_ReadWriteInExt_LateSynthesize;
    212 @property(readwrite) int Set_ReadWriteInExt_LateSynthesize;
    213 @property(readwrite) int None_ReadWriteInExt_LateSynthesize;
    214 @property(nonatomic,readwrite) int GetSet_Nonatomic_ReadWriteInExt_LateSynthesize;
    215 @property(nonatomic,readwrite) int Get_Nonatomic_ReadWriteInExt_LateSynthesize;
    216 @property(nonatomic,readwrite) int Set_Nonatomic_ReadWriteInExt_LateSynthesize;
    217 @property(nonatomic,readwrite) int None_Nonatomic_ReadWriteInExt_LateSynthesize;
    218 
    219 @property(readwrite) int GetSet_ReadWriteInExt_NoSynthesize;
    220 @property(readwrite) int Get_ReadWriteInExt_NoSynthesize;
    221 @property(readwrite) int Set_ReadWriteInExt_NoSynthesize;
    222 @property(readwrite) int None_ReadWriteInExt_NoSynthesize;
    223 @property(nonatomic,readwrite) int GetSet_Nonatomic_ReadWriteInExt_NoSynthesize;
    224 @property(nonatomic,readwrite) int Get_Nonatomic_ReadWriteInExt_NoSynthesize;
    225 @property(nonatomic,readwrite) int Set_Nonatomic_ReadWriteInExt_NoSynthesize;
    226 @property(nonatomic,readwrite) int None_Nonatomic_ReadWriteInExt_NoSynthesize;
    227 
    228 @end
    229 
    230 @implementation Foo
    231 
    232 @synthesize GetSet, Get, Set, None, GetSet_Nonatomic, Get_Nonatomic, Set_Nonatomic, None_Nonatomic;
    233 @synthesize GetSet_ReadOnly, Get_ReadOnly, Set_ReadOnly, None_ReadOnly, GetSet_Nonatomic_ReadOnly, Get_Nonatomic_ReadOnly, Set_Nonatomic_ReadOnly, None_Nonatomic_ReadOnly;
    234 @synthesize GetSet_ReadWriteInExt, Get_ReadWriteInExt, Set_ReadWriteInExt, None_ReadWriteInExt, GetSet_Nonatomic_ReadWriteInExt, Get_Nonatomic_ReadWriteInExt, Set_Nonatomic_ReadWriteInExt, None_Nonatomic_ReadWriteInExt;
    235 
    236 #define GET(x) \
    237     -(int) x { return self->x; }  
    238 #define SET(x) \
    239     -(void) set##x:(int)value { self->x = value; }  
    240 
    241 GET(GetSet)
    242 SET(GetSet)
    243 GET(Get) // expected-warning {{writable atomic property 'Get' cannot pair a synthesized setter/getter with a user defined setter/getter}}
    244 SET(Set) // expected-warning {{writable atomic property 'Set' cannot pair a synthesized setter/getter with a user defined setter/getter}}
    245 GET(GetSet_Nonatomic)
    246 SET(GetSet_Nonatomic)
    247 GET(Get_Nonatomic)
    248 SET(Set_Nonatomic)
    249 
    250 GET(GetSet_ReadOnly)
    251 SET(GetSet_ReadOnly)
    252 GET(Get_ReadOnly)
    253 SET(Set_ReadOnly)
    254 GET(GetSet_Nonatomic_ReadOnly)
    255 SET(GetSet_Nonatomic_ReadOnly)
    256 GET(Get_Nonatomic_ReadOnly)
    257 SET(Set_Nonatomic_ReadOnly)
    258 
    259 GET(GetSet_ReadWriteInExt)
    260 SET(GetSet_ReadWriteInExt)
    261 GET(Get_ReadWriteInExt) // expected-warning {{writable atomic property 'Get_ReadWriteInExt' cannot pair a synthesized setter/getter with a user defined setter/getter}}
    262 SET(Set_ReadWriteInExt) // expected-warning {{writable atomic property 'Set_ReadWriteInExt' cannot pair a synthesized setter/getter with a user defined setter/getter}}
    263 GET(GetSet_Nonatomic_ReadWriteInExt)
    264 SET(GetSet_Nonatomic_ReadWriteInExt)
    265 GET(Get_Nonatomic_ReadWriteInExt)
    266 SET(Set_Nonatomic_ReadWriteInExt)
    267 
    268 
    269 GET(GetSet_LateSynthesize)
    270 SET(GetSet_LateSynthesize)
    271 GET(Get_LateSynthesize) // expected-warning {{writable atomic property 'Get_LateSynthesize' cannot pair a synthesized setter/getter with a user defined setter/getter}}
    272 SET(Set_LateSynthesize) // expected-warning {{writable atomic property 'Set_LateSynthesize' cannot pair a synthesized setter/getter with a user defined setter/getter}}
    273 GET(GetSet_Nonatomic_LateSynthesize)
    274 SET(GetSet_Nonatomic_LateSynthesize)
    275 GET(Get_Nonatomic_LateSynthesize)
    276 SET(Set_Nonatomic_LateSynthesize)
    277 
    278 GET(GetSet_ReadOnly_LateSynthesize)
    279 SET(GetSet_ReadOnly_LateSynthesize)
    280 GET(Get_ReadOnly_LateSynthesize)
    281 SET(Set_ReadOnly_LateSynthesize)
    282 GET(GetSet_Nonatomic_ReadOnly_LateSynthesize)
    283 SET(GetSet_Nonatomic_ReadOnly_LateSynthesize)
    284 GET(Get_Nonatomic_ReadOnly_LateSynthesize)
    285 SET(Set_Nonatomic_ReadOnly_LateSynthesize)
    286 
    287 GET(GetSet_ReadWriteInExt_LateSynthesize)
    288 SET(GetSet_ReadWriteInExt_LateSynthesize)
    289 GET(Get_ReadWriteInExt_LateSynthesize) // expected-warning {{writable atomic property 'Get_ReadWriteInExt_LateSynthesize' cannot pair a synthesized setter/getter with a user defined setter/getter}}
    290 SET(Set_ReadWriteInExt_LateSynthesize) // expected-warning {{writable atomic property 'Set_ReadWriteInExt_LateSynthesize' cannot pair a synthesized setter/getter with a user defined setter/getter}}
    291 GET(GetSet_Nonatomic_ReadWriteInExt_LateSynthesize)
    292 SET(GetSet_Nonatomic_ReadWriteInExt_LateSynthesize)
    293 GET(Get_Nonatomic_ReadWriteInExt_LateSynthesize)
    294 SET(Set_Nonatomic_ReadWriteInExt_LateSynthesize)
    295 
    296 
    297 GET(GetSet_NoSynthesize)
    298 SET(GetSet_NoSynthesize)
    299 GET(Get_NoSynthesize)
    300 SET(Set_NoSynthesize)
    301 GET(GetSet_Nonatomic_NoSynthesize)
    302 SET(GetSet_Nonatomic_NoSynthesize)
    303 GET(Get_Nonatomic_NoSynthesize)
    304 SET(Set_Nonatomic_NoSynthesize)
    305 
    306 GET(GetSet_ReadOnly_NoSynthesize)
    307 SET(GetSet_ReadOnly_NoSynthesize)
    308 GET(Get_ReadOnly_NoSynthesize)
    309 SET(Set_ReadOnly_NoSynthesize)
    310 GET(GetSet_Nonatomic_ReadOnly_NoSynthesize)
    311 SET(GetSet_Nonatomic_ReadOnly_NoSynthesize)
    312 GET(Get_Nonatomic_ReadOnly_NoSynthesize)
    313 SET(Set_Nonatomic_ReadOnly_NoSynthesize)
    314 
    315 GET(GetSet_ReadWriteInExt_NoSynthesize)
    316 SET(GetSet_ReadWriteInExt_NoSynthesize)
    317 GET(Get_ReadWriteInExt_NoSynthesize)
    318 SET(Set_ReadWriteInExt_NoSynthesize)
    319 GET(GetSet_Nonatomic_ReadWriteInExt_NoSynthesize)
    320 SET(GetSet_Nonatomic_ReadWriteInExt_NoSynthesize)
    321 GET(Get_Nonatomic_ReadWriteInExt_NoSynthesize)
    322 SET(Set_Nonatomic_ReadWriteInExt_NoSynthesize)
    323 
    324 
    325 // late synthesize - follows getter/setter implementations
    326 
    327 @synthesize GetSet_LateSynthesize, Get_LateSynthesize, Set_LateSynthesize, None_LateSynthesize, GetSet_Nonatomic_LateSynthesize, Get_Nonatomic_LateSynthesize, Set_Nonatomic_LateSynthesize, None_Nonatomic_LateSynthesize;
    328 @synthesize GetSet_ReadOnly_LateSynthesize, Get_ReadOnly_LateSynthesize, Set_ReadOnly_LateSynthesize, None_ReadOnly_LateSynthesize, GetSet_Nonatomic_ReadOnly_LateSynthesize, Get_Nonatomic_ReadOnly_LateSynthesize, Set_Nonatomic_ReadOnly_LateSynthesize, None_Nonatomic_ReadOnly_LateSynthesize;
    329 @synthesize GetSet_ReadWriteInExt_LateSynthesize, Get_ReadWriteInExt_LateSynthesize, Set_ReadWriteInExt_LateSynthesize, None_ReadWriteInExt_LateSynthesize, GetSet_Nonatomic_ReadWriteInExt_LateSynthesize, Get_Nonatomic_ReadWriteInExt_LateSynthesize, Set_Nonatomic_ReadWriteInExt_LateSynthesize, None_Nonatomic_ReadWriteInExt_LateSynthesize;
    330 
    331 // no synthesize - use dynamic instead
    332 
    333 @dynamic GetSet_NoSynthesize, Get_NoSynthesize, Set_NoSynthesize, None_NoSynthesize, GetSet_Nonatomic_NoSynthesize, Get_Nonatomic_NoSynthesize, Set_Nonatomic_NoSynthesize, None_Nonatomic_NoSynthesize;
    334 @dynamic GetSet_ReadOnly_NoSynthesize, Get_ReadOnly_NoSynthesize, Set_ReadOnly_NoSynthesize, None_ReadOnly_NoSynthesize, GetSet_Nonatomic_ReadOnly_NoSynthesize, Get_Nonatomic_ReadOnly_NoSynthesize, Set_Nonatomic_ReadOnly_NoSynthesize, None_Nonatomic_ReadOnly_NoSynthesize;
    335 @dynamic GetSet_ReadWriteInExt_NoSynthesize, Get_ReadWriteInExt_NoSynthesize, Set_ReadWriteInExt_NoSynthesize, None_ReadWriteInExt_NoSynthesize, GetSet_Nonatomic_ReadWriteInExt_NoSynthesize, Get_Nonatomic_ReadWriteInExt_NoSynthesize, Set_Nonatomic_ReadWriteInExt_NoSynthesize, None_Nonatomic_ReadWriteInExt_NoSynthesize;
    336 
    337 @end
    338 
    339 /*
    340 // the following method should cause a warning along the lines of
    341 // :warning: Atomic property 'x' cannot pair a synthesized setter/getter with a manually implemented setter/getter
    342 - (void) setX: (int) aValue
    343 {
    344     x = aValue;
    345 }
    346 
    347 // no warning 'cause this is nonatomic
    348 - (void) setY: (int) aValue
    349 {
    350     y = aValue;
    351 }
    352 
    353 // the following method should cause a warning along the lines of
    354 // :warning: Atomic property 'x' cannot pair a synthesized setter/getter with a manually implemented setter/getter
    355 - (int) j
    356 {
    357     return j;
    358 }
    359 
    360 // no warning 'cause this is nonatomic
    361 - (int) k
    362 {
    363     return k;
    364 }
    365 @end
    366 */
    367 int main (int argc, const char * argv[]) {
    368     return 0;
    369 }
    370