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 11EXTERN_C int printf(const char *,...); 12 13typedef 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 18void test(TestEnum input) { 19 printf("%hhd", input); // expected-warning{{format specifies type 'char' but the argument has type 'TestEnum'}} 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 type 'TestEnum'}} 30 printf("%lld", Constant); // expected-warning{{format specifies type 'long long'}} 31} 32 33 34typedef enum : unsigned long { LongConstant = ~0UL } LongEnum; 35 36void testLong(LongEnum input) { 37 printf("%u", input); // expected-warning{{format specifies type 'unsigned int' but the argument has type 'LongEnum'}} 38 printf("%u", LongConstant); // expected-warning{{format specifies type 'unsigned int'}} 39 40 printf("%lu", input); 41 printf("%lu", LongConstant); 42} 43 44 45typedef short short_t; 46typedef enum : short_t { ShortConstant = 0 } ShortEnum; 47 48void testUnderlyingTypedef(ShortEnum input) { 49 printf("%hhd", input); // expected-warning{{format specifies type 'char' but the argument has type 'ShortEnum'}} 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 type 'ShortEnum'}} 60 printf("%lld", ShortConstant); // expected-warning{{format specifies type 'long long'}} 61} 62 63 64typedef ShortEnum ShortEnum2; 65 66void testTypedefChain(ShortEnum2 input) { 67 printf("%hhd", input); // expected-warning{{format specifies type 'char' but the argument has type 'ShortEnum2' (aka 'ShortEnum')}} 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 type 'ShortEnum2' (aka 'ShortEnum')}} 71} 72 73 74typedef 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. 78void 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 type 'CharEnum'}} 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 type 'CharEnum'}} 91 printf("%lld", CharConstant); // expected-warning{{format specifies type 'long long'}} 92} 93