https://gcc.gnu.org/bugzilla/show_bug.cgi?id=87494
Bug ID: 87494
Summary: hidden visibility constexpr variables left unevaluated
Product: gcc
Version: unknown
Status: UNCONFIRMED
Severity: normal
Priority: P3
Component: c++
Assignee: unassigned at gcc dot gnu.org
Reporter: froydnj at gcc dot gnu.org
Target Milestone: ---
The following testcase, reduced from Firefox:
#pragma GCC visibility push(hidden)
typedef int size_t;
class A;
class B {
A *m_fn1() const;
bool mBaseVal;
};
class A {};
class nsStaticAtom : public A {};
namespace mozilla {
namespace detail {
struct GkAtoms {
enum { F, T, AtomsCount };
nsStaticAtom mAtoms[AtomsCount];
} extern gGkAtoms;
}
}
class nsGkAtoms {
public:
static constexpr nsStaticAtom *_false =
&mozilla::detail::gGkAtoms.mAtoms[size_t(mozilla::detail::GkAtoms::F)];
static constexpr nsStaticAtom *_true =
&mozilla::detail::gGkAtoms.mAtoms[size_t(mozilla::detail::GkAtoms::T)];
};
A *B::m_fn1() const { return mBaseVal ? nsGkAtoms::_true : nsGkAtoms::_false; }
when compiled with x86-64 GCC version 8.2, gives:
cmpb $0, (%rdi)
movq _ZN9nsGkAtoms6_falseE(%rip), %rax
je .L1
movq _ZN9nsGkAtoms5_trueE(%rip), %rax
.L1:
ret
which leads to link failures, because neither symbol is defined.
Removing the #pragma gives correct output:
cmpb $0, (%rdi)
movq _ZN7mozilla6detail8gGkAtomsE@GOTPCREL(%rip), %rax
jne .L3
ret
.L3:
addq $1, %rax
ret
Very curiously, so does changing B::m_fn1() to:
A *B::m_fn1() const { return mBaseVal ? (nsStaticAtom*)nsGkAtoms::_true :
nsGkAtoms::_false; }
which gives slightly different, but still correct, assembly:
leaq 1+_ZN7mozilla6detail8gGkAtomsE(%rip), %rax
cmpb $0, (%rdi)
leaq -1(%rax), %rdx
cmove %rdx, %rax
ret