// RUN: %clang_cc1 -fsyntax-only -verify %s #if defined(INCLUDE) // ------- // This section acts like a header file. // ------- // Check the use of static variables in non-static inline functions. static int staticVar; // expected-note + {{'staticVar' declared here}} static int staticFunction(); // expected-note + {{'staticFunction' declared here}} static struct { int x; } staticStruct; // expected-note + {{'staticStruct' declared here}} inline int useStatic () { // expected-note 3 {{use 'static' to give inline function 'useStatic' internal linkage}} staticFunction(); // expected-warning{{static function 'staticFunction' is used in an inline function with external linkage}} (void)staticStruct.x; // expected-warning{{static variable 'staticStruct' is used in an inline function with external linkage}} return staticVar; // expected-warning{{static variable 'staticVar' is used in an inline function with external linkage}} } extern inline int useStaticFromExtern () { // no suggestions staticFunction(); // expected-warning{{static function 'staticFunction' is used in an inline function with external linkage}} return staticVar; // expected-warning{{static variable 'staticVar' is used in an inline function with external linkage}} } static inline int useStaticFromStatic () { staticFunction(); // no-warning return staticVar; // no-warning } extern inline int useStaticInlineFromExtern () { // Heuristic: if the function we're using is also inline, don't warn. // This can still be wrong (in this case, we end up inlining calls to // staticFunction and staticVar) but this got very noisy even using // standard headers. return useStaticFromStatic(); // no-warning } static int constFunction() __attribute__((const)); inline int useConst () { return constFunction(); // no-warning } #else // ------- // This is the main source file. // ------- #define INCLUDE #include "inline.c" // Check that we don't allow illegal uses of inline inline int a; // expected-error{{'inline' can only appear on functions}} typedef inline int b; // expected-error{{'inline' can only appear on functions}} int d(inline int a); // expected-error{{'inline' can only appear on functions}} // Check that the warnings from the "header file" aren't on by default in // the main source file. inline int useStaticMainFile () { staticFunction(); // no-warning return staticVar; // no-warning } // Check that the warnings show up when explicitly requested. #pragma clang diagnostic push #pragma clang diagnostic warning "-Wstatic-in-inline" inline int useStaticAgain () { // expected-note 2 {{use 'static' to give inline function 'useStaticAgain' internal linkage}} staticFunction(); // expected-warning{{static function 'staticFunction' is used in an inline function with external linkage}} return staticVar; // expected-warning{{static variable 'staticVar' is used in an inline function with external linkage}} } #pragma clang diagnostic pop inline void defineStaticVar() { // expected-note {{use 'static' to give inline function 'defineStaticVar' internal linkage}} static const int x = 0; // ok static int y = 0; // expected-warning {{non-constant static local variable in inline function may be different in different files}} } extern inline void defineStaticVarInExtern() { static const int x = 0; // ok static int y = 0; // ok } // Check behavior of line markers. # 1 "XXX.h" 1 inline int useStaticMainFileInLineMarker() { // expected-note 2 {{use 'static' to give inline function 'useStaticMainFileInLineMarker' internal linkage}} staticFunction(); // expected-warning{{static function 'staticFunction' is used in an inline function with external linkage}} return staticVar; // expected-warning{{static variable 'staticVar' is used in an inline function with external linkage}} } # 100 "inline.c" 2 inline int useStaticMainFileAfterLineMarker() { staticFunction(); // no-warning return staticVar; // no-warning } #endif