-
Notifications
You must be signed in to change notification settings - Fork 744
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
clang 3.9.1 Wundefined-var-template warnings #3705
Comments
It looks like we have to move the declarations of this (and some other objects) from the .cc into the header. Alternatively we can ignore the warning. Thoughts? |
Hm, this warning strikes me as wrong. To use a variable, all you need is a declaration. It is not generally necessary to see a definition. I also don't quite understand the "forward declaration" line -- it's just a regular declaration of a member variable in a templated class. I vote to just disable this warning. |
The compiler warns that it could not implicitly instantiate What about we simply disable the warning? Alternatively, we could cleanse relevant I have put together some references to the upstream discussion. References: |
I don't understand the rationale for the warning. I vote to disable. |
Took me a minute to come up with a minimal example:
|
This is perfectly valid C++ code except that linking might fail because a definition of
|
Whereas clang emits a warning that something might go wrong:
|
So I see the warning as a helper to diagnose problems in case you forget to instantiate a static member. I agree with disabling it. |
This warning leads to a lot of false positives. Simply disable the diagnostic. Fixes dealii#3705
This warning leads to a lot of false positives. Simply disable the diagnostic. Fixes dealii#3705
This clang warning issue is discussed here: dealii/dealii#3705 Apparently in some cases clang issues a warning for what might later cause a linker error for missing definitions of static template variables. In our case, definitions are in fact present and no linker error gets reported. Hence, I disabled clang from reporting these kinds of warnings.
I fully agree with dealii/dealii#3705 here.
I fully agree with dealii/dealii#3705 here.
I'm a former clang developer and I pushed for this warning to be enabled by default. I'm going to comment the rationale on this closed issue mainly because I see other repos referring to this bug's description of this warning and the problem it prevents, and are basing their decisions on it.
You might or you might not. Have you ever gotten into a situation where your template-using C++ code sometimes doesn't link for no good reason? Maybe it builds at -O0 but not at -O2 or vice-versa? Or you make a seemingly unrelated change like moving a method from a .cpp file to the .h file, or marking a const static or something innocuous and now you get a link error about a template? This warning helps catch those.
It does do that, though that's not all it achieves. In C and in C++ if you call a function "do_something();" and never have a declaration of that function, then you will get an error while compiling. The compiler doesn't simply assume that you will be providing "do_something" in another .o file, you must declare that you are. Not so for templates. If you have a declaration like In C++98 there did not exist any syntax to write an explicit instantiation declaration, and clang disables this warning by default when building in c++98 mode. Starting in C++11 there's a new syntax for declaring that you intend to explicitly instantiate your template in another .cpp file. Clang enables this warning by default when building in c++11 mode or newer. (The C++ standard did not make it an error for compatibility with old C++98 code that doesn't have any.) You should add explicit instantiation declarations to your header files that match the explicit instantiations in your .cpp files. If you need to support c++98 builds, wrap them in An explicit instantiation looks like:
while an explicit instantiation has
If your code was previously correct, this is a very easy fix, just copy the explicit instantiation lines from your .cpp files to the matching .h files which are already included by the .cpp files that need that template, prefix the lines with However, if your code looks like The solution is to declare the right thing before it's used. Thanks to this warning, you will be informed when you didn't. (The case where you need no additional declaration, As for why this causes link errors, an explicit specialization is assumed to be defined in every .cpp that uses it, which gives the compiler the freedom to eliminate dead functions/variables, inline the functions, and so on. Explicit instantiations are assumed to be defined in exactly one object file so the whole thing must be present (a "strong" definition), and other .cpp's using it don't emit the code to their object files. If these happen to line up and all the code from the specialization that the user needs is there in the object file, then we're good to go, but a seemingly innocuous change to either side can break that causing a very mysterious link error. (One thing the C++ community could have done is make the names mangle for specializations differently, which would have made it always be a link error. Regrettably they didn't, and it would break ABI to fix now.) |
@nlewycky Thanks a lot for the detailed information. We'll have a second look at the compiler warning and will discuss how to refactor our code appropriately. |
Fascinating. Would this mean that we need to include the .inst files in our headers? |
We can certainly automate creating explicit But I am not sure this is a feasible approach.
and our header files under
So adding all of the explicit instantiations to our header files will blow up our headers by a factor 3. I am currently running a build with clang and the warning reenabled. I don't think that the number of actual warnings we generate is actually that bad - two or three isolated issues that we could just fix. Correction: Removing all of the
So adding all explicit instantiations is roundabout a factor of 3.6. |
Reenabling the warning doesn't actually produce that much fallout: I think we can easily fix these warnings in the library. The bigger question will be how this will affect user projects (i.e., do we need an extern declaration for every possible use case?). Edit: Judging from compiling some of my projects the fallout is also rather small (it found two instances of this issue in my own code). |
I've found my way back to this PR in mysterious ways and the discussion at https://stackoverflow.com/questions/25056802/c11-explicit-instantiation-declaration-vs-explicit-instantiation-definition/25057121#25057121 . The conversation above raised the suggestion that we put |
I just installed clang 3.9.1 and I am getting a ton of warnings of the following kind:
I will investigate later today.
The text was updated successfully, but these errors were encountered: