Enabling LTO silently breaks programs like so:
// A.hpp
extern "C" bool some_external_bool; // comes from dynamic linking
struct A {
const bool cond;
A() : cond{some_external_bool} {}
};
extern const A currentA;
// A.cpp
#include "A.hpp"
const A currentA {};
// B.hpp
#include "A.hpp"
struct BConstants {
unsigned int val;
B() { this->val = currentA::cond ? 0xDEAD : 0xBEEF; }
static const BConstants singleton;
};
// B.cpp
#include "B.hpp"
const BConstants BConstants::singleton {};
// main.cpp
#include "B.hpp"
#include <iostream>
int main() {
std::cout << "val is: " << BConstants::singleton.val << std::endl;
}
Note: Manually typed-out code, may need some adjustments to compile, hopefully not. I was ready to break my keyboard trying to understand why my macOS Kernel Extension was misbehaving, my patience is waning.
Yes, I tried with both Apple Clang and upstream LLVM Clang, it happened with both.
The output will always be 0xBEEF no matter the value of some_external_bool, because LTO is removing the code and replacing it with a constant 0xBEEF.