Unresolved reference to implicitly generated move constructor (MSVC) or `= default` methods (clang,gcc) when using explicit template instantiation (compiler bugs) |
|
Issue descriptionChrome Version : 53.0.2774.3 I tried making event_with_latency_info.h use extern templates and ran into a couple of compiler bugs. Found a decent workaround though. Context: https://codereview.chromium.org/2091213002/ Goal: Encapsulate definitions for `CanCoalesceWith` and `CoalesceWith` https://codereview.chromium.org/2091213002/#ps120001 should have worked, but the build fails on the component build in win_chromium_compile_dbg_ng with [18246/18288] LINK content_unittests.exe FAILED: content_unittests.exe E:/b/depot_tools/python276_bin/python.exe gyp-win-tool link-wrapper environment.x86 False link.exe /nologo /OUT:content_unittests.exe /PDB:content_unittests.exe.pdb @content_unittests.exe.rsp event_with_latency_info_unittest.obj :error LNK2019: unresolved external symbol "__declspec(dllimport) public: __thiscall content::EventWithLatencyInfo<class blink::WebGestureEvent>::EventWithLatencyInfo<class blink::WebGestureEvent>(class content::EventWithLatencyInfo<class blink::WebGestureEvent> &&)" (__imp_??0?$EventWithLatencyInfo@VWebGestureEvent@blink@@@content@@QAE@$$QAV01@@Z) referenced in function "protected: class content::EventWithLatencyInfo<class blink::WebGestureEvent> __thiscall content::`anonymous namespace'::EventWithLatencyInfoTest::CreateGestureEvent(enum blink::WebInputEvent::Type,double)" (?CreateGestureEvent@EventWithLatencyInfoTest@?A0x58bef626@content@@IAE?AV?$EventWithLatencyInfo@VWebGestureEvent@blink@@@3@W4Type@WebInputEvent@blink@@N@Z) event_with_latency_info_unittest.obj :error LNK2019: unresolved external symbol "__declspec(dllimport) public: __thiscall content::EventWithLatencyInfo<class blink::WebMouseWheelEvent>... event_with_latency_info_unittest.obj :error LNK2019: unresolved external symbol "__declspec(dllimport) public: __thiscall content::EventWithLatencyInfo<class blink::WebMouseEvent>... event_with_latency_info_unittest.obj :error LNK2019: unresolved external symbol "__declspec(dllimport) public: __thiscall content::EventWithLatencyInfo<class blink::WebTouchEvent>... content_unittests.exe : fatalerror LNK1120: 4 unresolved externals Note these are the *move* constructors. They're being used for NVRO in event_with_latency_info_unittest.cc which has code like MouseEventWithLatencyInfo CreateMouseEvent(WebInputEvent::Type type, double timestamp) { MouseEventWithLatencyInfo mouse; mouse.event.type = type; mouse.event.timeStampSeconds = timestamp; return mouse; } I seem to recall the standards committee deciding that there would be no implicitly generated move constructors, so it's probably a bug that NVRO there tries to use it. But, we can resolve this by just declaring a move constructor (and the rest so they aren't hidden by the move constructor): EventWithLatencyInfo(const EventWithLatencyInfo& other) = default; EventWithLatencyInfo(EventWithLatencyInfo&& other) = default; EventWithLatencyInfo& operator=(const EventWithLatencyInfo& other) = default; But! Although this fixed Windows, it caused other platforms to fail in https://codereview.chromium.org/2091213002/#ps220001 Errors like [5056/5365] LINK ./components_unittests FAILED: components_unittests TOOL_VERSION=1465060049 ../../build/toolchain/mac/linker_driver.py /b/build/slave/cache/cipd/goma/gomacc ../../third_party/llvm-build/Release+Asserts/bin/clang++ -stdlib=libc++ /* snip */ Undefined symbols for architecture x86_64: "content::EventWithLatencyInfo<blink::WebMouseEvent>::operator=(content::EventWithLatencyInfo<blink::WebMouseEvent> const&)", referenced from: content::InputRouterImpl::SendMouseEventImmediately(content::EventWithLatencyInfo<blink::WebMouseEvent> const&) in input_router_impl.o content::TouchpadTapSuppressionController::ShouldDeferMouseDown(content::EventWithLatencyInfo<blink::WebMouseEvent> const&) in touchpad_tap_suppression_controller.o "content::EventWithLatencyInfo<blink::WebTouchEvent>::operator=(content::EventWithLatencyInfo<blink::WebTouchEvent> const&)", referenced from: content::TouchEventQueue::ForwardNextEventToRenderer() in touch_event_queue.o content::TouchEventQueue::TouchTimeoutHandler::StartIfNecessary(content::EventWithLatencyInfo<blink::WebTouchEvent> const&) in touch_event_queue.o "content::EventWithLatencyInfo<blink::WebGestureEvent>::operator=(content::EventWithLatencyInfo<blink::WebGestureEvent> const&)", referenced from: content::GestureEventQueue::QueueScrollOrPinchAndForwardIfNecessary(content::EventWithLatencyInfo<blink::WebGestureEvent> const&) in gesture_event_queue.o content::GestureEventQueue::ProcessGestureAck(content::InputEventAckState, blink::WebInputEvent::Type, ui::LatencyInfo const&) in gesture_event_queue.o std::__1::/* snip */ The bug here seems to be that the explicit instantiation of an extern template doesn't generate any code for `= default` methods. There's a gcc bug filed already here - https://gcc.gnu.org/bugzilla/show_bug.cgi?id=51629 . Couldn't find a clang bug for it. But since only Windows needs the `= default` thing they can just be put behind guards. A basic test case goes like: $ head -n100 e.h e.cc extern_default.cc build.sh ==> e.h <== class I { public: I() {} I& operator=(const I&); }; template <class T> class E { public: T t; E() : t() {} E& operator=(const E&) = default; }; extern template class E<I>; ==> e.cc <== #include "e.h" I& I::operator=(const I& i) { return *this; } template class E<I>; ==> extern_default.cc <== #include "e.h" int main() { E<I> e1, e2; e1 = e2; } ==> build.sh <== g++ extern_default.cc e.cc -Wall -std=c++11 $ bash build.sh Undefined symbols for architecture x86_64: "E<I>::operator=(E<I> const&)", referenced from: _main in extern_default-66fb4a.o ld: symbol(s) not found for architecture x86_64 clang: error: linker command failed with exit code 1 (use -v to see invocation) $ nm e.o | c++filt 0000000000000060 S E<I>::E() 0000000000000020 S E<I>::E() 0000000000000040 S I::I() 0000000000000080 S I::I() 0000000000000000 T I::operator=(I const&) Filing this to track, and cc some people who might care about it (or see an alternative diagnosis). Still need to hunt down (or file) a clang version of https://gcc.gnu.org/bugzilla/show_bug.cgi?id=51629, and put together a test case for MSVC.
,
Nov 3 2016
(to close the loop here, to satisfy the original goal we went with https://codereview.chromium.org/2111593003 - basically just use function overrides - forward declare (and export) them in the header so that the template definition can stay in the header as well.) |
|
►
Sign in to add a comment |
|
Comment 1 by thakis@chromium.org
, Jun 28 2016