Moving from using Intel compiler & VC to Apple clang 12.0.
In my code there are functions that are never called for a certain project (but needed when included in other projects). Clang insists on compiling the uncalled functions and detects errors, where Intel and VC simply skipped compilation.
These are errors that are tricky to fix for that certain project.
Is there a Clang flag that means "Don't compile if not called"?
EDIT: example:
template <class T> class A
{
public:
void foo() { garbage }; // <--- syntax error
};
int main() {
A<int> my_obj;
//my_obj.foo(); // <--- when unremarked, will fail all compilers
}
Compiler Explorer demo: Intel vs. Clang
Intel and VC compilers are relaxed until the call to foo() enters the scene.
Clang has a mode in which is tries to behave as if it's MSVC. This was introduced as part clang-cl, the driver for clang that accepts a lot of the same arguments as MSVC. You can find some information about it on the user manual and the MSVC compatibility pages.
Long story short, there is an option -fdelayed-template-parsing in clang that takes over the faulty behavior of the templates. As far as I'm aware, this ain't a 100% match, however, it is good enough.
If we add this to the example of Artyer, it compiles the code, see compiler-explorer.
From my experience of adding clang as 2nd compiler next to MSVC (it was still both on Windows using clang-cl, I didn't have to deal with the complexity of multiple OS and/or STL), I want to recommend to you to take this option as a temporary thing to get things working. Take your time removing this, as it will help making your code more maintainable.
EDIT: If you want to know more about why the compilation error is the right thing to do, you can lookup the term 2 phase lookup. You can find the announcement of it's introduction in the MSVC compiler here: https://devblogs.microsoft.com/cppblog/two-phase-name-lookup-support-comes-to-msvc/
From what I can see online, the intel compiler ain't doing 2 phase lookup either, or at least not the reporting of the errors.
Related
Consider this simple code:
#include <stdio.h>
extern "C"
{
void p4nenc256v32();
void p4ndec256v32();
}
void bigFunctionTest()
{
p4nenc256v32();
p4ndec256v32();
}
int main()
{
printf("hello\n");
}
Code size of those p4nenc256v32/p4ndec256v32 functions is significant, roughly 1.5MB. This binary size when compiled with latest VS2022 with optimizations enabled is 1.5MB. If I comment out that unused bigFunctionTest function then resulting binary is smaller by 1.4MB. Any ideas why would this clearly unused function wouldn't be eliminated by compiler and/or linker in release builds? By default, VS2022 in release uses /Gy and /OPT:REF.
I also tried mingw64 (gcc 12.2) with -fdata-sections -ffunction-sections -Wl,--gc-sections and results were much worse: when compiled with that dummy function exe grew by 5.2MB. Seem like ms and gcc compilers agree that for some reason these functions cannot be removed.
I created a working sample project that shows the issue: https://github.com/pps83/TestLinker.git (make sure to pull submodules as well) and filled an issue with VS issue tracker: Linker doesn't eliminate correctly dead code, however, I think I might get better explanation from SO users explaining what might be the reason for the problem.
When compiling this
#include <vector>
#include <stdio.h>
int main()
{
std::vector<int> foo;
foo.push_back( 1 );
printf( "%zu\n", foo.size() );
}
with clang++ foo.cpp -stdlib=libc++ -g, when running a.out in gdb and trying to show the result of foo.size(), gdb says "Cannot evaluate function -- may be inlined".
Is there a way to avoid the compiler's inlining in debug mode? I could use libstdc++, but it is quite painful when it is needed to go inside the templates (many many subcalls plus indentation is sometimes space-based and sometimes tab-based).
I am running with Debian 9 (stretch) using libc++-dev v3.5 with clang 3.8 (tried with clang 5.0 too, same result) and gdb 7.12.
libstdc++ implements so called Python xmethods, see documentation:
Xmethods are additional methods or replacements for existing methods
of a C++ class. This feature is useful for those cases where a method
defined in C++ source code could be inlined or optimized out by the
compiler, making it unavailable to GDB. For such cases, one can define
an xmethod to serve as a replacement for the method defined in the C++
source code. GDB will then invoke the xmethod, instead of the C++
method, to evaluate expressions. One can also use xmethods when
debugging with core files. Moreover, when debugging live programs,
invoking an xmethod need not involve running the inferior (which can
potentially perturb its state). Hence, even if the C++ method is
available, it is better to use its replacement xmethod if one is
defined.
That's why you can call mock foo.size() even if the real foo.size() was inlined by compiler when using libstdc++. As far as I know there is no alike xmethod implementation for libc++.
I have an existing application, which uses several static libraries (all of which I am compiling). I am compiling on the command line, with make and clang, not using the IDE. Previous to Xcode 7.3, all compiled and executed as I expect. With Xcode 7.3, in my release build (which adds -O2) I am getting strange behaviour with virtual inline functions - sometimes they return completely garbage values. This seems to happen in classes which have only virtual inline methods, eg:
class MyClass
{
public:
virtual ~MyClass() { }
virtual int foo() { return 1; }
};
In my investigation of the issue (trying several related compile flags), it appears adding -fno-inlines and/or -fvisibility-inlines-hidden works around the issue, and the program executes as expected. However, from my understanding, these are simply hints on how to optimize, and should not affect program execution (specifically, the second should only affect DSOs, which I am not using). This leads me to several questions:
Searching Apple support forums, I could not find any reference to similar errors. Is this an known issue?
Is this code somehow malformed? If so, is there some way I can get feedback from the compiler (eg. via a diagnostic) about the problem?
Why do the compiler flags I mentioned fix the issue? Am I misinterpreting their meaning?
A project need to compile in both gcc4.1.2(company's server) and gcc 4.7.3+(desktop linux system), and have some problems:
1. gcc 4.1.2 does not have Wno-unused-result and Wno-unused-but-set-variable. I tried to substitute the latter two with Wno-unused, but still generate an ignoring return value of a build-in function error.
2. There's also no Wno-narrowing in gcc 4.1.2, is there anything else I can use?
What should I do to make both of them happy?
I'd suggest you deal with the differences between the two versions in the makefile. You can detect the GCC version and pramatically include the extra warning options if the GCC version supports them. This will help when the company finally moves forward.
Fixing the code is worth doing, but don't then not use the warnings. They're the thing telling you there's a problem in the first place (otherwise you wouldn't have enabled them right?)
Anyway, you can get round the unused warnings to system functions by casting the result to void which the compiler is happy you should ignore:
(void)builtin( ... );
The following code crashes for me using GCC to build for ARM:
#include <vector>
using namespace std;
void foo(vector<bool>& bools) {
bools.push_back(true);
}
int main(int argc, char** argv) {
vector<bool> bools;
bool b = false;
bools.push_back(b);
}
My compiler is: arm_v5t_le-gcc (GCC) 3.4.3 (MontaVista 3.4.3-25.0.30.0501131 2005-07-23). The crash doesn't occur when building for debug, but occurs with optimizations set to -O2.
Yes, the foo function is necessary to reproduce the issue. This was very confusing at first, but I've discovered that the crash only happens when the push_back call isn't inlined. If GCC notices that the push_back method is called more than once, it won't inline it in each location. For example, I can also reproduce the crash by calling push_back twice inside of main. If you make foo static, then gcc can tell it is never called and will optimize it out, resulting in push_back getting inlined into main, resulting in the crash not occurring.
I've tried this on x86 with gcc 4.3.3, and it appears the issue is fixed for that version.
So, my questions are:
Has anyone else run into this? Perhaps there are some compiler flags I can pass in to prevent it.
Is this a bug with gcc's code generation, or is it a bug in the stl implementation (bits/stl_bvector.h)? (I plan on testing this out myself when I get the time)
If it is a problem with the compiler, is upgrading to 4.3.3 what fixes it, or is it switching to x86 from arm?
Incidentally, most other vector<bool> methods seem to work. And yes, I know that using vector<bool> isn't the best option in the world.
Can you build your own toolchain with gcc 3.4.6 and Montavista's patches? 3.4.6 is the last release of the 3.x line.
I can append some instructions for how to build an ARM cross-compiler from GCC sources if you want. I have to do it all the time, since nobody does prebuilt toolchains for Mac OS X.
I'd be really surprised if this is broken for ARM in gcc 4.x. But the only way to test is if you or someone else can try this out on an ARM-targeting gcc 4.x.
Upgrading to GCC 4 is a safe bet. Its code generation backend replaces the old RTL (Register Transfer Language) representation with SSA (Static Single Assignment). This change allowed a significant rewrite of the optimizer.