2020-02-16 22:01:25 +08:00
// RUN: %clang_cc1 -Wno-int-to-pointer-cast -Wno-pointer-to-int-cast -pedantic -fsyntax-only %s -verify -fblocks
2008-09-17 06:25:10 +08:00
[C11/C2x] Change the behavior of the implicit function declaration warning
C89 had a questionable feature where the compiler would implicitly
declare a function that the user called but was never previously
declared. The resulting function would be globally declared as
extern int func(); -- a function without a prototype which accepts zero
or more arguments.
C99 removed support for this questionable feature due to severe
security concerns. However, there was no deprecation period; C89 had
the feature, C99 didn't. So Clang (and GCC) both supported the
functionality as an extension in C99 and later modes.
C2x no longer supports that function signature as it now requires all
functions to have a prototype, and given the known security issues with
the feature, continuing to support it as an extension is not tenable.
This patch changes the diagnostic behavior for the
-Wimplicit-function-declaration warning group depending on the language
mode in effect. We continue to warn by default in C89 mode (due to the
feature being dangerous to use). However, because this feature will not
be supported in C2x mode, we've diagnosed it as being invalid for so
long, the security concerns with the feature, and the trivial
workaround for users (declare the function), we now default the
extension warning to an error in C99-C17 mode. This still gives users
an easy workaround if they are extensively using the extension in those
modes (they can disable the warning or use -Wno-error to downgrade the
error), but the new diagnostic makes it more clear that this feature is
not supported and should be avoided. In C2x mode, we no longer allow an
implicit function to be defined and treat the situation the same as any
other lookup failure.
Differential Revision: https://reviews.llvm.org/D122983
2022-04-20 23:25:35 +08:00
extern int printf ( const char * , . . . ) ;
2008-09-17 06:25:10 +08:00
typedef void ( ^ CL ) ( void ) ;
2022-02-04 05:39:21 +08:00
CL foo ( void ) {
2009-02-05 06:31:32 +08:00
short y ;
2010-04-10 01:53:29 +08:00
short ( ^ add1 ) ( void ) = ^ { return y + 1 ; } ; // expected-error {{incompatible block pointer types initializing 'short (^)(void)' with an expression of type 'int (^)(void)'}}
2008-09-17 06:25:10 +08:00
2009-02-05 06:31:32 +08:00
CL X = ^ {
if ( 2 )
return ;
2011-12-04 07:53:56 +08:00
return 1 ; // expected-error {{return type 'int' must match previous return type 'void' when block literal has unspecified explicit return type}}
2008-09-17 06:25:10 +08:00
} ;
2009-02-05 06:31:32 +08:00
int ( ^ Y ) ( void ) = ^ {
2008-09-17 06:25:10 +08:00
if ( 3 )
return 1 ;
else
2011-12-04 07:53:56 +08:00
return ; // expected-error {{return type 'void' must match previous return type 'int' when block literal has unspecified explicit return type}}
2008-09-17 06:25:10 +08:00
} ;
2009-02-05 06:31:32 +08:00
char * ( ^ Z ) ( void ) = ^ {
2008-09-17 06:25:10 +08:00
if ( 3 )
return " " ;
else
return ( char * ) 0 ;
} ;
2010-04-10 01:53:29 +08:00
double ( ^ A ) ( void ) = ^ { // expected-error {{incompatible block pointer types initializing 'double (^)(void)' with an expression of type 'float (^)(void)'}}
2009-02-05 06:31:32 +08:00
if ( 1 )
return ( float ) 1.0 ;
2008-09-17 06:25:10 +08:00
else
if ( 2 )
2011-12-04 01:47:53 +08:00
return ( double ) 2.0 ; // expected-error {{return type 'double' must match previous return type 'float' when block literal has unspecified explicit return type}}
return 1 ; // expected-error {{return type 'int' must match previous return type 'float' when block literal has unspecified explicit return type}}
2008-09-17 06:25:10 +08:00
} ;
2009-02-05 06:31:32 +08:00
char * ( ^ B ) ( void ) = ^ {
2008-09-17 06:25:10 +08:00
if ( 3 )
return " " ;
else
2011-12-04 01:47:53 +08:00
return 2 ; // expected-error {{return type 'int' must match previous return type 'char *' when block literal has unspecified explicit return type}}
2008-09-17 06:25:10 +08:00
} ;
2009-02-05 06:31:32 +08:00
2010-04-09 08:35:39 +08:00
return ^ { return 1 ; } ; // expected-error {{incompatible block pointer types returning 'int (^)(void)' from a function with result type 'CL' (aka 'void (^)(void)')}}
2008-09-17 06:25:10 +08:00
}
typedef int ( ^ CL2 ) ( void ) ;
2022-02-04 05:39:21 +08:00
CL2 foo2 ( void ) {
2009-04-17 08:09:41 +08:00
return ^ { return 1 ; } ;
2008-09-17 06:25:10 +08:00
}
2008-09-25 06:26:48 +08:00
typedef unsigned int * uintptr_t ;
typedef char Boolean ;
typedef int CFBasicHash ;
# define INVOKE_CALLBACK2(P, A, B) (P)(A, B)
typedef struct {
Boolean ( ^ isEqual ) ( const CFBasicHash * , uintptr_t stack_value_or_key1 , uintptr_t stack_value_or_key2 , Boolean is_key ) ;
} CFBasicHashCallbacks ;
2022-02-04 05:39:21 +08:00
int foo3 ( void ) {
2008-09-25 06:26:48 +08:00
CFBasicHashCallbacks cb ;
[C11/C2x] Change the behavior of the implicit function declaration warning
C89 had a questionable feature where the compiler would implicitly
declare a function that the user called but was never previously
declared. The resulting function would be globally declared as
extern int func(); -- a function without a prototype which accepts zero
or more arguments.
C99 removed support for this questionable feature due to severe
security concerns. However, there was no deprecation period; C89 had
the feature, C99 didn't. So Clang (and GCC) both supported the
functionality as an extension in C99 and later modes.
C2x no longer supports that function signature as it now requires all
functions to have a prototype, and given the known security issues with
the feature, continuing to support it as an extension is not tenable.
This patch changes the diagnostic behavior for the
-Wimplicit-function-declaration warning group depending on the language
mode in effect. We continue to warn by default in C89 mode (due to the
feature being dangerous to use). However, because this feature will not
be supported in C2x mode, we've diagnosed it as being invalid for so
long, the security concerns with the feature, and the trivial
workaround for users (declare the function), we now default the
extension warning to an error in C99-C17 mode. This still gives users
an easy workaround if they are extensively using the extension in those
modes (they can disable the warning or use -Wno-error to downgrade the
error), but the new diagnostic makes it more clear that this feature is
not supported and should be avoided. In C2x mode, we no longer allow an
implicit function to be defined and treat the situation the same as any
other lookup failure.
Differential Revision: https://reviews.llvm.org/D122983
2022-04-20 23:25:35 +08:00
2008-09-25 06:26:48 +08:00
Boolean ( * value_equal ) ( uintptr_t , uintptr_t ) = 0 ;
[C11/C2x] Change the behavior of the implicit function declaration warning
C89 had a questionable feature where the compiler would implicitly
declare a function that the user called but was never previously
declared. The resulting function would be globally declared as
extern int func(); -- a function without a prototype which accepts zero
or more arguments.
C99 removed support for this questionable feature due to severe
security concerns. However, there was no deprecation period; C89 had
the feature, C99 didn't. So Clang (and GCC) both supported the
functionality as an extension in C99 and later modes.
C2x no longer supports that function signature as it now requires all
functions to have a prototype, and given the known security issues with
the feature, continuing to support it as an extension is not tenable.
This patch changes the diagnostic behavior for the
-Wimplicit-function-declaration warning group depending on the language
mode in effect. We continue to warn by default in C89 mode (due to the
feature being dangerous to use). However, because this feature will not
be supported in C2x mode, we've diagnosed it as being invalid for so
long, the security concerns with the feature, and the trivial
workaround for users (declare the function), we now default the
extension warning to an error in C99-C17 mode. This still gives users
an easy workaround if they are extensively using the extension in those
modes (they can disable the warning or use -Wno-error to downgrade the
error), but the new diagnostic makes it more clear that this feature is
not supported and should be avoided. In C2x mode, we no longer allow an
implicit function to be defined and treat the situation the same as any
other lookup failure.
Differential Revision: https://reviews.llvm.org/D122983
2022-04-20 23:25:35 +08:00
2008-09-25 06:26:48 +08:00
cb . isEqual = ^ ( const CFBasicHash * table , uintptr_t stack_value_or_key1 , uintptr_t stack_value_or_key2 , Boolean is_key ) {
2009-09-09 23:08:12 +08:00
return ( Boolean ) ( uintptr_t ) INVOKE_CALLBACK2 ( value_equal , ( uintptr_t ) stack_value_or_key1 , ( uintptr_t ) stack_value_or_key2 ) ;
2008-09-25 06:26:48 +08:00
} ;
}
2008-09-25 07:31:10 +08:00
static int funk ( char * s ) {
2008-09-28 09:11:11 +08:00
if ( ^ { } = = ( ( void * ) 0 ) )
return 1 ;
[C11/C2x] Change the behavior of the implicit function declaration warning
C89 had a questionable feature where the compiler would implicitly
declare a function that the user called but was never previously
declared. The resulting function would be globally declared as
extern int func(); -- a function without a prototype which accepts zero
or more arguments.
C99 removed support for this questionable feature due to severe
security concerns. However, there was no deprecation period; C89 had
the feature, C99 didn't. So Clang (and GCC) both supported the
functionality as an extension in C99 and later modes.
C2x no longer supports that function signature as it now requires all
functions to have a prototype, and given the known security issues with
the feature, continuing to support it as an extension is not tenable.
This patch changes the diagnostic behavior for the
-Wimplicit-function-declaration warning group depending on the language
mode in effect. We continue to warn by default in C89 mode (due to the
feature being dangerous to use). However, because this feature will not
be supported in C2x mode, we've diagnosed it as being invalid for so
long, the security concerns with the feature, and the trivial
workaround for users (declare the function), we now default the
extension warning to an error in C99-C17 mode. This still gives users
an easy workaround if they are extensively using the extension in those
modes (they can disable the warning or use -Wno-error to downgrade the
error), but the new diagnostic makes it more clear that this feature is
not supported and should be avoided. In C2x mode, we no longer allow an
implicit function to be defined and treat the situation the same as any
other lookup failure.
Differential Revision: https://reviews.llvm.org/D122983
2022-04-20 23:25:35 +08:00
else
2008-09-28 09:11:11 +08:00
return 0 ;
2008-09-25 07:31:10 +08:00
}
2022-02-04 05:39:21 +08:00
void next ( void ) ;
void foo4 ( void ) {
2010-09-05 08:04:01 +08:00
int ( ^ xx ) ( const char * s ) = ^ ( char * s ) { return 1 ; } ; // expected-error {{incompatible block pointer types initializing 'int (^)(const char *)' with an expression of type 'int (^)(char *)'}}
2022-08-11 01:52:33 +08:00
int ( * yy ) ( const char * s ) = funk ; // expected-error {{incompatible function pointer types initializing 'int (*)(const char *)' with an expression of type 'int (char *)'}}
[C11/C2x] Change the behavior of the implicit function declaration warning
C89 had a questionable feature where the compiler would implicitly
declare a function that the user called but was never previously
declared. The resulting function would be globally declared as
extern int func(); -- a function without a prototype which accepts zero
or more arguments.
C99 removed support for this questionable feature due to severe
security concerns. However, there was no deprecation period; C89 had
the feature, C99 didn't. So Clang (and GCC) both supported the
functionality as an extension in C99 and later modes.
C2x no longer supports that function signature as it now requires all
functions to have a prototype, and given the known security issues with
the feature, continuing to support it as an extension is not tenable.
This patch changes the diagnostic behavior for the
-Wimplicit-function-declaration warning group depending on the language
mode in effect. We continue to warn by default in C89 mode (due to the
feature being dangerous to use). However, because this feature will not
be supported in C2x mode, we've diagnosed it as being invalid for so
long, the security concerns with the feature, and the trivial
workaround for users (declare the function), we now default the
extension warning to an error in C99-C17 mode. This still gives users
an easy workaround if they are extensively using the extension in those
modes (they can disable the warning or use -Wno-error to downgrade the
error), but the new diagnostic makes it more clear that this feature is
not supported and should be avoided. In C2x mode, we no longer allow an
implicit function to be defined and treat the situation the same as any
other lookup failure.
Differential Revision: https://reviews.llvm.org/D122983
2022-04-20 23:25:35 +08:00
int ( ^ nested ) ( char * s ) = ^ ( char * str ) { void ( ^ nest ) ( void ) = ^ ( void ) { printf ( " %s \n " , str ) ; } ; next ( ) ; return 1 ; } ;
2008-09-25 07:31:10 +08:00
}
2009-04-17 08:09:41 +08:00
typedef void ( ^ bptr ) ( void ) ;
bptr foo5 ( int j ) {
__block int i ;
if ( j )
return ^ { ^ { i = 0 ; } ( ) ; } ; // expected-error {{returning block that lives on the local stack}}
return ^ { i = 0 ; } ; // expected-error {{returning block that lives on the local stack}}
2009-09-08 08:36:37 +08:00
return ( ^ { i = 0 ; } ) ; // expected-error {{returning block that lives on the local stack}}
return ( void * ) ( ^ { i = 0 ; } ) ; // expected-error {{returning block that lives on the local stack}}
2009-04-17 08:09:41 +08:00
}
2009-04-28 09:10:27 +08:00
int ( * funcptr3 [ 5 ] ) ( long ) ;
2022-07-23 03:24:54 +08:00
int sz8 = sizeof ( ^ int ( * [ 5 ] ) ( long ) { return funcptr3 ; } ) ; // expected-error {{block cannot return array type}} expected-error {{incompatible pointer to integer conversion}}
2011-01-26 09:26:44 +08:00
int sz9 = sizeof ( ^ int ( * ( ) ) ( ) [ 3 ] { } ) ; // expected-error {{function cannot return array type}}
2022-05-13 20:25:40 +08:00
// expected-warning@-1 {{a function declaration without a prototype is deprecated in all versions of C}}
2009-04-30 03:03:13 +08:00
2022-02-04 05:39:21 +08:00
void foo6 ( void ) {
2010-09-03 08:25:02 +08:00
int ( ^ b ) ( int ) __attribute__ ( ( noreturn ) ) ;
2009-04-30 03:03:13 +08:00
b = ^ ( int i ) __attribute__ ( ( noreturn ) ) { return 1 ; } ; // expected-error {{block declared 'noreturn' should not return}}
b ( 1 ) ;
2010-09-03 08:25:02 +08:00
int ( ^ c ) ( void ) __attribute__ ( ( noreturn ) ) = ^ __attribute__ ( ( noreturn ) ) { return 100 ; } ; // expected-error {{block declared 'noreturn' should not return}}
2009-04-30 03:03:13 +08:00
}
2009-06-20 07:37:08 +08:00
2022-02-04 05:39:21 +08:00
void foo7 ( void )
2009-06-20 07:37:08 +08:00
{
2011-02-12 02:46:17 +08:00
const int ( ^ BB ) ( void ) = ^ { const int i = 1 ; return i ; } ; // OK - initializing 'const int (^)(void)' with an expression of type 'int (^)(void)'
2010-07-13 16:18:22 +08:00
2010-07-14 14:36:18 +08:00
const int ( ^ CC ) ( void ) = ^ const int { const int i = 1 ; return i ; } ;
2010-07-13 16:18:22 +08:00
2009-06-20 07:37:08 +08:00
int i ;
int ( ^ FF ) ( void ) = ^ { return i ; } ; // OK
int ( ^ EE ) ( void ) = ^ { return i + 1 ; } ; // OK
__block int j ;
int ( ^ JJ ) ( void ) = ^ { return j ; } ; // OK
int ( ^ KK ) ( void ) = ^ { return j + 1 ; } ; // OK
__block const int k ;
const int cint = 100 ;
2010-02-03 08:27:59 +08:00
int ( ^ MM ) ( void ) = ^ { return k ; } ;
int ( ^ NN ) ( void ) = ^ { return cint ; } ;
2009-06-20 07:37:08 +08:00
}
2012-03-22 00:45:13 +08:00
// rdar://11069896
void ( ^ blk ) ( void ) = ^ {
2012-03-22 04:28:39 +08:00
return ( void ) 0 ; // expected-warning {{void block literal should not return void expression}}
2012-03-22 00:45:13 +08:00
} ;
2013-03-21 08:10:07 +08:00
// rdar://13463504
enum Test8 { T8_a , T8_b , T8_c } ;
void test8 ( void ) {
extern void test8_helper ( int ( ^ ) ( int ) ) ;
test8_helper ( ^ ( int flag ) { if ( flag ) return T8_a ; return T8_b ; } ) ;
}
void test8b ( void ) {
extern void test8_helper2 ( char ( ^ ) ( int ) ) ; // expected-note {{here}}
test8_helper2 ( ^ ( int flag ) { if ( flag ) return T8_a ; return T8_b ; } ) ; // expected-error {{passing 'enum Test8 (^)(int)' to parameter of type 'char (^)(int)'}}
}