I'm using a shared library that defines inline functions in its header.
Here is a reduced test case, as seen by the compilation unit linking to the library (for the version seen by the library, just replace dllimport by dllexport).
class __declspec(dllimport) MyClass {
public:
int myFunc2();
int myFunc1();
};
inline int MyClass::myFunc2(void) {
return myFunc1();
}
inline int MyClass::myFunc1(void) {
return 0;
}
Compiling this gives the warning:
warning: 'int MyClass::myFunc1()' redeclared without dllimport
attribute after being referenced with dll linkage [enabled by default]
Please note that the order in which the functions are defined is important, as putting the definition of myFunc1 before the definition of myFunc2 results in no warnings.
Note also that this code compiles without warnings under Visual C++. These warnings are specific at least to MinGW, maybe to GCC in general. Edit: it came to my mind that I may have to verify if the warning is not inhibited by one of the flags set by the project.
My questions are then:
Why this behavior ?
Declaring myFunc1 as inline inside the class declaration fixes the problem. Why is that ? It's also against the recommended way of doing things.
Is there another (better ?) way to fix this problem ?
The problem comes about because of some magic in the way that dllimport works which normally means you only need it on the first declaration.
Basically, when you declare a function as dllimport and then later redeclare the function with an identical declaration except for the dllimport, the second declaration implicitly gets the dllimport. If the redeclaration is NOT identical, it doesn't get the implicit dllimport.
So what happens here is you first declare the function as dllimport/non-inline, and then declare it as non-dllimport/inline. Adding an inline to the first declaration fixes the problem, as the second then becomes implicitly dllimport. Alternately, adding a __declspec(dllimport) to the second declaration should fix the problem.
Note that reordering the definitions gets rid of the warning, since the warning is about using it before redeclaring it. With a reorder, you're no longer using it before the redeclaration, so you get no warning, though it will be using the non-dllimport version (ie, it will never use the version of the function from the dll).
Note also, using inline dllimport is dangerous. Any program built against the dll might use the inline function in some places and the non-inline function (from the dll) in others. Even if the two functions are identical NOW, a future version of the dll might change and have a different implementation. At which point the old program might start misbehaving if run with the new version of the dll.
Further information to Chris Dodd's answer:
I tested with MSVC 2017 and MinGW-w64 7.2.0; in both cases, with optimization enabled, the call of myFunc1() from myFunc2 resolved to the inline version, despite the warning. Even if the body of myFunc1 were moved to below main().
So my tentative conclusion is that it is safe to ignore this warning.
In the interest of a clean compile, the only method that seems to work in MinGW-w64 is to mark the function declaration within the class definition as inline. The compiler does not allow applying __declspec(dllimport) to the out-of-class function definition.
I have been unable to determine if there is a warning flag for g++ which will specifically disable this warning.
Related
My version (5.4) of gcc warns about unused static functions, even in a header file when -Wall is used. It doesn't complain if the same functions are defined static inline or simply inline.
For example, the following function in a file unused.h:
static void foo() {}
... when included in a test.cpp file as follows:
#include "unused.h"
Generates the following compiler diagnostic when compiler with -Wall:
In file included from test.cpp:11:0:
unused.h: At global scope:
unused.h:9:13: warning: ‘void foo()’ defined but not used [-Wunused-function]
static void foo() {}
^
It is common practice, as far as I know, to include headers with many utility functions, only a handful of which might be used in any given source file. This behavior means that I get warnings for any functions I don't use which are declared only static.
As a practical matter I can simply change these to static inline to get rid of the warning (or turn off the specific warning entirely, but I do find it useful from time to time), but it seems that large utility functions which won't benefit from inlining1 are more logically declared static2.
As far as I know unused static functions (just like static inline) are simply dropped by gcc when the translation unit is compiled, so they pose no binary size or link-time overhead at all.
Am I missing something here? Is there a good reason that unused static functions are more problematic than static inline?
1 Yes, I'm aware it's a hint only but gcc actually takes the hint in many cases.
2 Or perhaps better, only declared in the header file and defined somewhere else in a .cpp file - but that inhibits header-only use which is sometimes convenient.
The warning is because an unused static function might indicate a logic error: why would you have written such a function if it was never called?
However, it is a common idiom to have static inline functions in a header file. Those functions might only be used by some translation units that include the header. It would be annoying if the compiler gave a warning for a translation unit that didn't happen to use one of the functions.
If you deliberately have an unused static non-inline function, you probably will want to either disable the warning entirely, or use a compiler-specific feature to suppress the warning for that function.
Someone asked, "why would you use static inline anyway?". Well, in new C++ you mostly wouldn't use it. However, in C it is a reasonable thing to do. (This is because static inline means the same thing in ISO C and GNU C; however inline without static behaves differently in ISO C than GNU C, so defaulting to static inline just avoids all those issues with no down-side).
People might use static inline in headers that are to be included from both .c and .cpp files; or perhaps they just carry over that habit from C to C++. In the latter case, IMHO it would be annoying for the compiler to warn about something that, although unnecessary, is not a mistake or a problem either.
For such functions you need to set attribute __attribute__((unused)).
After searching for an answer for a while, I am now even more confused than before...
I am wondering if I declare in the header file an inline function that is not implemented, but called in the main function, will this result in an linker or compiler error?
When I look at the error I get undefined reference to 'A::a()' it seems like a linker error.
However, in some discussions it says that the Compiler MUST see the function delcaration, therefore it would be an Compiler Error.
I hope you can tell me what I am getting wrong here :)
Header:
Main function:
It is a linker error in most compilers when you have a functon declaration, but the implementation (definition) of the function is not present.
Technically, the compiler MAY report that an inline function is not present in the source, but the compiler is not obliged to do so, and code exists that do not always define the function that is declared as inline. It is not, in most compilers, an error to declare a function inline, and define it in a separate compilation unit (different source file), so compilers do not give an error by default.
If the compiler doesn't find the definition for an inline function, the compiler will assume that it's an external function, and the linker is the only place were all of the code comes together, and thus "it's not there" is issued by the linker.
To clarify:
You may well have a situation where you want to declare as inline a function but put the implementation of a function in a source-file (perhaps because it's never called anywhere else, there is a single factory function to instantiate all instances of that class). Then it is perfectly legal to declare the function [such as a constructor] as inline in the header-file, and the place the implementation of the function in a source file, using the object in various other files without an implementation present.
In practice, compilers also allow the calling of inline functions, even when they are only declared in a source file, not the header. The compiler will not always inline those functions [in practice, only "link time optimization" or "whole program optimization" are likely to do that].
It depends on the compiler you are using but as far as I remember an inline declaration is by default a recommendation to the compiler. In your case, since the compiler didn't find the implementation of the function it will not implement it inline and will leave it to the linker to link.
If you are using GCC you can force the compiler to do inline, see more details in this blog:
Force inline functions in C++(GCC)
This seems like a trivial thing, but I'm not an expert in C++, and I haven't found a good solution to this online as of yet. I'm suspecting I'm missing some basic coding construct that might solve this issue. I have the following definition in one of my main header files:
static const Foo INVALID_FOO = {};
where Foo is a POD class (it doesn't have constructors, as it's used in a union in a C++03 project). This seems fine, except for sources which include the header but don't use INVALID_FOO, I'm getting the warning:
error: 'Foo::INVALID_FOO' defined but not used [-Werror=unused-variable]
I've tried removing the static but then I get duplicate definitions. I could make this a forward declaration, and define it in a .c file, but then the compiler would need to access it through a reference and would not be able to make any optimizations. I'd also like to not disable the -Wall compiler flag. I'm wondering if there's a good way to do this?
You can suppress the GCC warning like this:
static const Foo INVALID_FOO __attribute__ ((unused)) = {};
Note that unused is correct here, all it does is that it suppresses the warning (and it's still fine to reference the identifier). There is also a used attribute which suppresses the warning and tells GCC to emit the definition in the object file even if the compiler does not see a reference to it in the source code—in most cases, this results in unnecessary code bloat.
You can suppress the warning portably using static_cast<void>(INVALID_FOO); statement.
Also note that static const at global and namespace scope is a bit of tautology - const makes it static, so that static is superfluous.
I have the following function defined in a header file of a visual studio makefile project that eventually builds in c using msys-rtems:
static inline UInt32 timer_now() {
...
Where the type UInt32 is a typedef from a included header file:
typedef unsigned long UInt32;
I get the following problems with my intellisense because of that function:
Intellisense suggests inline is not a type name. >Error: Variable 'inline' is not a type name
Intellisense thinks that the definition of UInt32 is this function instead of the typedef unsigned long.
If i remove the inline keyword everything works fine (except that i dont want to because this is a function we want inlined).
I don't think it is fully to do with my typedef UInt32 because if i swap this out with unsigned long i still get the same problem.
There are a bunch of other functions below this one using static inline double which dont have any error unless they are moved to be the first function. Then they experience the same error.
I have tried restarting VS2015 and deleting the SQL database file. I have played with various intellisense options to no avail. Is this an intellisense bug?
As an additional note, a quick look over the remainder of the project makes it look like the first inline function in any h file has this problem.
Visual studio bug opened here.
As a more minimal example I reduced the header file to just:
#ifndef SERVOSCHED_H
#define SERVOSCHED_H
typedef unsigned long UInt32;
static inline UInt32 timer_now() {}
#endif
And i still get this:
Why I don't want to just turn off intellisense.
This isn't just affecting my intellisense, otherwise i wouldnt care. The real problem is that it thinks UInt32 is declared in this line:
static inline UInt32 timer_now() {
ie. When i go to definition on any UInt32 use it takes me to this line. But its worse, because of this ANYTHING that is declared as type UInt32 cannot be found as defined. As in if i have this anywhere in our massive code base:
UInt32 ii;
...
for (ii = 0; ii < 10; ++ii) {
Then -
VS thinks ii is undefined.
You cannot follow ii to its definition - which is crazy annoying.
We use UInt32 and Int32 literally everywhere and anything declared with these types cannot be easily found which is a huge problem.
Why i dont want to just change the inline
I know that the static inline keywords might not do anything on this particular code. Its not that i don't want to change it. It is that i cant change it. This code is compiled as c in GCC 3.4.5. The compiler is a cross compiler written for RTEMS under the Power PC 5200 board BSP. How do you think it will change the assembly code when you just remove the inline? Don't know? Neither do I. Given that this is running a real time system that can affect safety functionality. I don't just not want to change it. I cant change it until such time as we decide to upgrade the compiler as well.
Current Workaround
In order to fix this for now i have defined the following typedef:
typedef UInt32 inlineUInt32;
and have used this instead of UInt32 in the static inline function definitions. This fixes the described problem with UInt32, but i have made a change in running code (That is built with a makefile) to please Visual Studio which is stupid.
This is a bug in the Visual C++ IntelliSense service when processing C source files (or headers included by C source files). This bug was reported several months ago on Microsoft Connect: IntelliSense does not accept "inline" C99 functions. The bug has been fixed and the fix will appear in the next update to Visual Studio 2015.
A workaround (while you await the next update to Visual Studio 2015) would be to define a macro named inline that expands to nothing, and to guard that macro so that it is only defined when the Visual C++ IntelliSense service is parsing the file.
#if defined _MSC_VER && defined __EDG__ && !defined __cplusplus
#define inline
#endif
Ideally this macro definition would be placed in one common header that is included by everything in your project. If no such header exists, then you can place it into its own header then force-include it at the top of every file using the /FI compiler option. (This is generally inadvisable, but since you'd only be using this as a temporary workaround for this IntelliSense issue, it's probably okay.)
From the example given, it is clear that 'inline' is not needed there, and can be safely removed. Expalanation:
if timer_now() is defined inside the class, inline is not needed there, since definitions inside the class are always inline. Remove to reduce the clutter.
timer_now() CAN NOT be a definition of free-standing function in the header file, since in this case it would not be marked 'static'
If timer_now() is a definiton withing .cpp file, inline is not needed, since if the function can be inlined by the compiler, it will be inlined, and there is no requirement to mark it inline.
I'm using a shared library that defines inline functions in its header.
Here is a reduced test case, as seen by the compilation unit linking to the library (for the version seen by the library, just replace dllimport by dllexport).
class __declspec(dllimport) MyClass {
public:
int myFunc2();
int myFunc1();
};
inline int MyClass::myFunc2(void) {
return myFunc1();
}
inline int MyClass::myFunc1(void) {
return 0;
}
Compiling this gives the warning:
warning: 'int MyClass::myFunc1()' redeclared without dllimport
attribute after being referenced with dll linkage [enabled by default]
Please note that the order in which the functions are defined is important, as putting the definition of myFunc1 before the definition of myFunc2 results in no warnings.
Note also that this code compiles without warnings under Visual C++. These warnings are specific at least to MinGW, maybe to GCC in general. Edit: it came to my mind that I may have to verify if the warning is not inhibited by one of the flags set by the project.
My questions are then:
Why this behavior ?
Declaring myFunc1 as inline inside the class declaration fixes the problem. Why is that ? It's also against the recommended way of doing things.
Is there another (better ?) way to fix this problem ?
The problem comes about because of some magic in the way that dllimport works which normally means you only need it on the first declaration.
Basically, when you declare a function as dllimport and then later redeclare the function with an identical declaration except for the dllimport, the second declaration implicitly gets the dllimport. If the redeclaration is NOT identical, it doesn't get the implicit dllimport.
So what happens here is you first declare the function as dllimport/non-inline, and then declare it as non-dllimport/inline. Adding an inline to the first declaration fixes the problem, as the second then becomes implicitly dllimport. Alternately, adding a __declspec(dllimport) to the second declaration should fix the problem.
Note that reordering the definitions gets rid of the warning, since the warning is about using it before redeclaring it. With a reorder, you're no longer using it before the redeclaration, so you get no warning, though it will be using the non-dllimport version (ie, it will never use the version of the function from the dll).
Note also, using inline dllimport is dangerous. Any program built against the dll might use the inline function in some places and the non-inline function (from the dll) in others. Even if the two functions are identical NOW, a future version of the dll might change and have a different implementation. At which point the old program might start misbehaving if run with the new version of the dll.
Further information to Chris Dodd's answer:
I tested with MSVC 2017 and MinGW-w64 7.2.0; in both cases, with optimization enabled, the call of myFunc1() from myFunc2 resolved to the inline version, despite the warning. Even if the body of myFunc1 were moved to below main().
So my tentative conclusion is that it is safe to ignore this warning.
In the interest of a clean compile, the only method that seems to work in MinGW-w64 is to mark the function declaration within the class definition as inline. The compiler does not allow applying __declspec(dllimport) to the out-of-class function definition.
I have been unable to determine if there is a warning flag for g++ which will specifically disable this warning.