[cfe-dev] Clang emits unreachable `internal linkage` constructor

Mehdi Amini via cfe-dev cfe-dev at lists.llvm.org
Thu Oct 13 22:46:04 PDT 2016


Hi,

This fairly simple (and valid) code does not link (on MacOS):


#include <iostream>
#include <string>
namespace {
	struct VA {
	};
	struct A : virtual public VA {
		A() {
			static bool b = false;
			std::string str;
		}
	};
}
int main(int argc, char* argv[]) {
	A::A a;
}



The issue is that clang emits two constructors (the complete one and the base one) for struct A because it has a virtual base class.

Because struct A is declared in an anonymous namespace, these constructors are internal linkage. Only one of them is actually called, the other is unreachable.

The “always-inliner” does not visit unreachable internal function. However this constructor is calling into a function from libc++ that are marked “available_externally” and “always inline”: the basic_string constructor.

The problem is that the linkage “available_externally" is a “lie”: there is an external template instantiation in the header, but it is marked “visibility hidden”. So the function cannot be linked to in the libc++ dylib. (I think it’d work with a static libc++).

I see multiple ways to address such cases, possibly many of them can be implemented:

- Don’t emit unreferenced internal_linkage function. (We should try to do this anyway right?)
- Have the CGSCC run on the unreachable part of the call-graph.
- Run global-DCE at O0 (might be a good idea anyway if it speeds-up the build)
- We should have the “available_externally” compatible with “hidden visibility”. Maybe we need a way to have to mark some method excluded from one  `external template` instantiation so that it would be ODR.
- We could make the basic_string constructor and other method in the same situation internal linkage instead.


Thoughts?

— 
Mehdi


More information about the cfe-dev mailing list