C89 allowed a type specifier to be elided with the resulting type being int, aka implicit int behavior. This feature was subsequently removed in C99 without a deprecation period, so implementations continued to support the feature. Now, as with implicit function declarations, is a good time to reevaluate the need for this support. This patch allows -Wimplicit-int to issue warnings in C89 mode (off by default), defaults the warning to an error in C99 through C17, and disables support for the feature entirely in C2x. It also removes a warning about missing declaration specifiers that really was just an implicit int warning in disguise and other minor related cleanups.
342 lines
7.5 KiB
C
342 lines
7.5 KiB
C
// RUN: %clang_cc1 -triple x86_64-apple-darwin9 %s -fsyntax-only -Wignored-qualifiers -Wno-error=return-type -Wno-error=implicit-int -verify -fblocks -Wno-unreachable-code -Wno-unused-value -Wno-strict-prototypes
|
|
|
|
// clang emits the following warning by default.
|
|
// With GCC, -pedantic, -Wreturn-type or -Wall are required to produce the
|
|
// following warning.
|
|
int t14(void) {
|
|
return; // expected-warning {{non-void function 't14' should return a value}}
|
|
}
|
|
|
|
void t15(void) {
|
|
return 1; // expected-warning {{void function 't15' should not return a value}}
|
|
}
|
|
|
|
int unknown(void);
|
|
|
|
void test0(void) {
|
|
}
|
|
|
|
int test1(void) {
|
|
} // expected-warning {{non-void function does not return a value}}
|
|
|
|
int test2(void) {
|
|
a: goto a;
|
|
}
|
|
|
|
int test3(void) {
|
|
goto a;
|
|
a: ;
|
|
} // expected-warning {{non-void function does not return a value}}
|
|
|
|
|
|
void halt(void) {
|
|
a: goto a;
|
|
}
|
|
|
|
void halt2(void) __attribute__((noreturn));
|
|
|
|
int test4(void) {
|
|
halt2();
|
|
}
|
|
|
|
int test5(void) {
|
|
halt2(), (void)1;
|
|
}
|
|
|
|
int test6(void) {
|
|
1, halt2();
|
|
}
|
|
|
|
int j;
|
|
int unknown_nohalt(void) {
|
|
return j;
|
|
}
|
|
|
|
int test7(void) {
|
|
unknown();
|
|
} // expected-warning {{non-void function does not return a value}}
|
|
|
|
int test8(void) {
|
|
(void)(1 + unknown());
|
|
} // expected-warning {{non-void function does not return a value}}
|
|
|
|
int halt3(void) __attribute__((noreturn));
|
|
|
|
int test9(void) {
|
|
(void)(halt3() + unknown());
|
|
}
|
|
|
|
int test10(void) {
|
|
(void)(unknown() || halt3());
|
|
} // expected-warning {{non-void function does not return a value in all control paths}}
|
|
|
|
int test11(void) {
|
|
(void)(unknown() && halt3());
|
|
} // expected-warning {{non-void function does not return a value in all control paths}}
|
|
|
|
int test12(void) {
|
|
(void)(halt3() || unknown());
|
|
}
|
|
|
|
int test13(void) {
|
|
(void)(halt3() && unknown());
|
|
}
|
|
|
|
int test14(void) {
|
|
(void)(1 || unknown());
|
|
} // expected-warning {{non-void function does not return a value}}
|
|
|
|
int test15(void) {
|
|
(void)(0 || unknown());
|
|
} // expected-warning {{non-void function does not return a value}}
|
|
|
|
int test16(void) {
|
|
(void)(0 && unknown());
|
|
} // expected-warning {{non-void function does not return a value}}
|
|
|
|
int test17(void) {
|
|
(void)(1 && unknown());
|
|
} // expected-warning {{non-void function does not return a value}}
|
|
|
|
int test18(void) {
|
|
(void)(unknown_nohalt() && halt3());
|
|
} // expected-warning {{non-void function does not return a value in all control paths}}
|
|
|
|
int test19(void) {
|
|
(void)(unknown_nohalt() && unknown());
|
|
} // expected-warning {{non-void function does not return a value}}
|
|
|
|
int test20(void) {
|
|
int i;
|
|
if (i)
|
|
return 0;
|
|
else if (0)
|
|
return 2;
|
|
} // expected-warning {{non-void function does not return a value in all control paths}}
|
|
|
|
int test21(void) {
|
|
int i;
|
|
if (i)
|
|
return 0;
|
|
else if (1)
|
|
return 2;
|
|
}
|
|
|
|
int test22(void) {
|
|
int i;
|
|
switch (i) default: ;
|
|
} // expected-warning {{non-void function does not return a value}}
|
|
|
|
int test23(void) {
|
|
int i;
|
|
switch (i) {
|
|
case 0:
|
|
return 0;
|
|
case 2:
|
|
return 2;
|
|
}
|
|
} // expected-warning {{non-void function does not return a value in all control paths}}
|
|
|
|
int test24(void) {
|
|
int i;
|
|
switch (i) {
|
|
case 0:
|
|
return 0;
|
|
case 2:
|
|
return 2;
|
|
default:
|
|
return -1;
|
|
}
|
|
}
|
|
|
|
int test25(void) {
|
|
1 ? halt3() : unknown();
|
|
}
|
|
|
|
int test26(void) {
|
|
0 ? halt3() : unknown();
|
|
} // expected-warning {{non-void function does not return a value}}
|
|
|
|
int j;
|
|
void (*fptr)(void) __attribute__((noreturn));
|
|
int test27(void) {
|
|
switch (j) {
|
|
case 1:
|
|
do { } while (1);
|
|
break;
|
|
case 2:
|
|
for (;;) ;
|
|
break;
|
|
case 3:
|
|
for (;1;) ;
|
|
for (;0;) {
|
|
goto done;
|
|
}
|
|
return 1;
|
|
case 4:
|
|
while (0) { goto done; }
|
|
return 1;
|
|
case 5:
|
|
while (1) { return 1; }
|
|
break;
|
|
case 6:
|
|
fptr();
|
|
break;
|
|
default:
|
|
return 1;
|
|
}
|
|
done: ;
|
|
}
|
|
|
|
// PR4624
|
|
void test28() __attribute__((noreturn));
|
|
void test28(x) { while (1) { } } // expected-warning {{parameter 'x' was not declared, defaults to 'int'; ISO C99 and later do not support implicit int}}
|
|
|
|
void exit(int);
|
|
int test29(void) {
|
|
exit(1);
|
|
}
|
|
|
|
// Include these declarations here explicitly so we don't depend on system headers.
|
|
typedef struct __jmp_buf_tag{} jmp_buf[1];
|
|
|
|
extern void longjmp (struct __jmp_buf_tag __env[1], int __val) __attribute__ ((noreturn));
|
|
extern void _longjmp (struct __jmp_buf_tag __env[1], int __val) __attribute__ ((noreturn));
|
|
|
|
jmp_buf test30_j;
|
|
|
|
int test30(void) {
|
|
if (j)
|
|
longjmp(test30_j, 1);
|
|
else
|
|
#if defined(_WIN32) || defined(_WIN64) || defined(__CYGWIN__)
|
|
longjmp(test30_j, 2);
|
|
#else
|
|
_longjmp(test30_j, 1);
|
|
#endif
|
|
}
|
|
|
|
typedef void test31_t(int status);
|
|
void test31(test31_t *callback __attribute__((noreturn)));
|
|
|
|
void test32(void) {
|
|
^ (void) { while (1) { } }();
|
|
^ (void) { if (j) while (1) { } }();
|
|
while (1) { }
|
|
}
|
|
|
|
void test33(void) {
|
|
if (j) while (1) { }
|
|
}
|
|
|
|
// Test that 'static inline' functions are only analyzed for CFG-based warnings
|
|
// when they are used.
|
|
static inline int si_has_missing_return(void) {} // expected-warning{{non-void function does not return a value}}
|
|
static inline int si_has_missing_return_2(void) {}; // expected-warning{{non-void function does not return a value}}
|
|
static inline int si_forward(void);
|
|
static inline int si_has_missing_return_3(int x) {
|
|
if (x)
|
|
return si_has_missing_return_3(x+1);
|
|
} // expected-warning{{non-void function does not return a value in all control paths}}
|
|
|
|
int test_static_inline(int x) {
|
|
si_forward();
|
|
return x ? si_has_missing_return_2() : si_has_missing_return_3(x);
|
|
}
|
|
static inline int si_forward(void) {} // expected-warning{{non-void function does not return a value}}
|
|
|
|
// Test warnings on ignored qualifiers on return types.
|
|
const int ignored_c_quals(void); // expected-warning{{'const' type qualifier on return type has no effect}}
|
|
const volatile int ignored_cv_quals(void); // expected-warning{{'const volatile' type qualifiers on return type have no effect}}
|
|
char* const volatile restrict ignored_cvr_quals(void); // expected-warning{{'const volatile restrict' type qualifiers on return type have no effect}}
|
|
|
|
typedef const int CI;
|
|
CI ignored_quals_typedef(void);
|
|
|
|
const CI ignored_quals_typedef_2(void); // expected-warning{{'const' type qualifier}}
|
|
|
|
// Test that for switch(enum) that if the switch statement covers all the cases
|
|
// that we don't consider that for -Wreturn-type.
|
|
enum Cases { C1, C2, C3, C4 };
|
|
int test_enum_cases(enum Cases C) {
|
|
switch (C) {
|
|
case C1: return 1;
|
|
case C2: return 2;
|
|
case C4: return 3;
|
|
case C3: return 4;
|
|
}
|
|
} // no-warning
|
|
|
|
// PR12318 - Don't give a may reach end of non-void function warning.
|
|
int test34(int x) {
|
|
if (x == 1) {
|
|
return 3;
|
|
} else if ( x == 2 || 1) {
|
|
return 5;
|
|
}
|
|
}
|
|
|
|
// PR18999
|
|
int test35(void) {
|
|
lbl:
|
|
if (1)
|
|
goto lbl;
|
|
}
|
|
|
|
int test36a(int b) {
|
|
if (b)
|
|
return 43;
|
|
__builtin_unreachable();
|
|
}
|
|
|
|
int test36b(int b) {
|
|
if (b)
|
|
return 43;
|
|
__builtin_assume(0);
|
|
}
|
|
|
|
// PR19074.
|
|
void abort(void) __attribute__((noreturn));
|
|
#define av_assert0(cond) do {\
|
|
if (!(cond)) {\
|
|
abort();\
|
|
}\
|
|
} while (0)
|
|
|
|
int PR19074(int x) {
|
|
switch(x) {
|
|
case 0:
|
|
return 0;
|
|
default:
|
|
av_assert0(0);
|
|
} // no-warning
|
|
}
|
|
|
|
int PR19074_positive(int x) {
|
|
switch(x) {
|
|
case 0:
|
|
return 0;
|
|
default:
|
|
break;
|
|
}
|
|
} // expected-warning {{non-void function does not return a value in all control paths}}
|
|
|
|
// sizeof(long) test.
|
|
int sizeof_long(void) {
|
|
if (sizeof(long) == 4)
|
|
return 1;
|
|
if (sizeof(long) == 8)
|
|
return 2;
|
|
} // no-warning
|
|
|
|
int return_statement_expression(void) {
|
|
if (unknown())
|
|
return ({
|
|
while (0)
|
|
;
|
|
0;
|
|
});
|
|
else
|
|
return 0;
|
|
} // no-warning (used to be "non-void function does not return a value in all control paths")
|