Home | History | Annotate | Download | only in Sema
      1 // RUN: %clang_cc1 -triple i386-apple-darwin9 -x c++ -std=c++11 -verify %s
      2 // RUN: %clang_cc1 -triple i386-apple-darwin9 -x objective-c -verify %s
      3 // RUN: %clang_cc1 -triple i386-apple-darwin9 -x objective-c++ -verify %s
      4 
      5 #ifdef __cplusplus
      6 # define EXTERN_C extern "C"
      7 #else
      8 # define EXTERN_C extern
      9 #endif
     10 
     11 EXTERN_C int printf(const char *,...);
     12 
     13 typedef enum : short { Constant = 0 } TestEnum;
     14 // Note that in C (and Objective-C), the type of 'Constant' is 'short'.
     15 // In C++ (and Objective-C++) it is 'TestEnum'.
     16 // This is why we don't check for that in the expected output.
     17 
     18 void test(TestEnum input) {
     19   printf("%hhd", input); // expected-warning{{format specifies type 'char' but the argument has underlying type 'short'}}
     20   printf("%hhd", Constant); // expected-warning{{format specifies type 'char'}}
     21 
     22   printf("%hd", input); // no-warning
     23   printf("%hd", Constant); // no-warning
     24 
     25   // While these are less correct, they are still safe.
     26   printf("%d", input); // no-warning
     27   printf("%d", Constant); // no-warning
     28 
     29   printf("%lld", input); // expected-warning{{format specifies type 'long long' but the argument has underlying type 'short'}}
     30   printf("%lld", Constant); // expected-warning{{format specifies type 'long long'}}
     31 }
     32 
     33 
     34 typedef enum : unsigned long { LongConstant = ~0UL } LongEnum;
     35 
     36 void testLong(LongEnum input) {
     37   printf("%u", input); // expected-warning{{format specifies type 'unsigned int' but the argument has underlying type 'unsigned long'}}
     38   printf("%u", LongConstant); // expected-warning{{format specifies type 'unsigned int'}}
     39 
     40   printf("%lu", input);
     41   printf("%lu", LongConstant);
     42 }
     43 
     44 
     45 typedef short short_t;
     46 typedef enum : short_t { ShortConstant = 0 } ShortEnum;
     47 
     48 void testUnderlyingTypedef(ShortEnum input) {
     49   printf("%hhd", input); // expected-warning{{format specifies type 'char' but the argument has underlying type 'short_t' (aka 'short')}}
     50   printf("%hhd", ShortConstant); // expected-warning{{format specifies type 'char'}}
     51 
     52   printf("%hd", input); // no-warning
     53   printf("%hd", ShortConstant); // no-warning
     54 
     55   // While these are less correct, they are still safe.
     56   printf("%d", input); // no-warning
     57   printf("%d", ShortConstant); // no-warning
     58 
     59   printf("%lld", input); // expected-warning{{format specifies type 'long long' but the argument has underlying type 'short_t' (aka 'short')}}
     60   printf("%lld", ShortConstant); // expected-warning{{format specifies type 'long long'}}
     61 }
     62 
     63 
     64 typedef ShortEnum ShortEnum2;
     65 
     66 void testTypedefChain(ShortEnum2 input) {
     67   printf("%hhd", input); // expected-warning{{format specifies type 'char' but the argument has underlying type 'short_t' (aka 'short')}}
     68   printf("%hd", input); // no-warning
     69   printf("%d", input); // no-warning
     70   printf("%lld", input); // expected-warning{{format specifies type 'long long' but the argument has underlying type 'short_t' (aka 'short')}}
     71 }
     72 
     73 
     74 typedef enum : char { CharConstant = 'a' } CharEnum;
     75 
     76 // %hhd is deliberately not required to be signed, because 'char' isn't either.
     77 // This is a separate code path in FormatString.cpp.
     78 void testChar(CharEnum input) {
     79   printf("%hhd", input); // no-warning
     80   printf("%hhd", CharConstant); // no-warning
     81 
     82   // This is not correct but it is safe. We warn because '%hd' shows intent.
     83   printf("%hd", input); // expected-warning{{format specifies type 'short' but the argument has underlying type 'char'}}
     84   printf("%hd", CharConstant); // expected-warning{{format specifies type 'short'}}
     85 
     86   // This is not correct but it matches the promotion rules (and is safe).
     87   printf("%d", input); // no-warning
     88   printf("%d", CharConstant); // no-warning
     89 
     90   printf("%lld", input); // expected-warning{{format specifies type 'long long' but the argument has underlying type 'char'}}
     91   printf("%lld", CharConstant); // expected-warning{{format specifies type 'long long'}}
     92 }
     93