From 686b7778767f1f94cf9f6d5c2acd401d76bb3d4a Mon Sep 17 00:00:00 2001 From: Marius Hillenbrand Date: Tue, 14 Apr 2020 16:00:36 +0200 Subject: [PATCH] Move Stroke::save() and load() into header The template member functions Stroke::save and Stroke::load get called via the serialize() function generated by boost's macro BOOST_SERIALIZATION_SPLIT_MEMBER() in gesture.h. Since the definitions of save()/load() are only available in gesture.cc, the compiler may produce two versions of Stroke::serialize() -- one with save()/load() inlined in gesture.o and one with calls to save()/load() in all other referencing translation units. Since the compiler inlined Stroke::save() and Stroke::load(), it will not export them in gesture.o (which is legitimate, since the code only requests an export of Stroke::serialize). As a result, some orders of object files can fail to link, when the linker picks the version of Stroke::serialize() that would call save()/load() (which are not available separately) instead of the version with these functions inlined. Avoid relying on this compiler- and optimization-level dependent behavior by moving the definition of template member functions Stroke::save() and Stroke::load() into gesture.h. As a side-effect, that change unifies code style, since all other classes have their ::save() and ::load() definitions in header files, too. These link failures surfaced when building on s390x with -march=zEC12 or later, and can be reproduced on x86_64 with gcc parameters --param max-inline-insns-auto=80 --param inline-min-speedup=2 Signed-off-by: Marius Hillenbrand --- gesture.cc | 36 ------------------------------------ gesture.h | 37 +++++++++++++++++++++++++++++++++++-- 2 files changed, 35 insertions(+), 38 deletions(-) diff --git a/gesture.cc b/gesture.cc index 8531c084..f97bce3a 100644 --- a/gesture.cc +++ b/gesture.cc @@ -14,7 +14,6 @@ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ #include "gesture.h" -#include "prefdb.h" #include #include @@ -35,41 +34,6 @@ RTriple create_triple(float x, float y, Time t) { return e; } -template void Stroke::save(Archive & ar, const unsigned int version) const { - std::vector ps; - for (unsigned int i = 0; i < size(); i++) - ps.push_back(points(i)); - ar & ps; - ar & button; - ar & trigger; - ar & timeout; - ar & modifiers; -} - -template void Stroke::load(Archive & ar, const unsigned int version) { - std::vector ps; - ar & ps; - if (ps.size()) { - stroke_t *s = stroke_alloc(ps.size()); - for (std::vector::iterator i = ps.begin(); i != ps.end(); ++i) - stroke_add_point(s, i->x, i->y); - stroke_finish(s); - stroke.reset(s, &stroke_free); - } - if (version == 0) return; - ar & button; - if (version >= 2) - ar & trigger; - if (version < 4 && (!button || trigger == (int)prefs.button.get().button)) - trigger = 0; - if (version < 3) - return; - ar & timeout; - if (version < 5) - return; - ar & modifiers; -} - Stroke::Stroke(PreStroke &ps, int trigger_, int button_, unsigned int modifiers_, bool timeout_) : trigger(trigger_), button(button_), modifiers(modifiers_), timeout(timeout_) { if (ps.valid()) { stroke_t *s = stroke_alloc(ps.size()); diff --git a/gesture.h b/gesture.h index accecdfe..1c318872 100644 --- a/gesture.h +++ b/gesture.h @@ -16,6 +16,7 @@ #ifndef __GESTURE_H__ #define __GESTURE_H__ +#include "prefdb.h" #include "stroke.h" #include #include @@ -83,8 +84,40 @@ class Stroke { static Glib::RefPtr pbEmpty; BOOST_SERIALIZATION_SPLIT_MEMBER() - template void load(Archive & ar, const unsigned int version); - template void save(Archive & ar, const unsigned int version) const; + template void load(Archive & ar, const unsigned int version) { + std::vector ps; + ar & ps; + if (ps.size()) { + stroke_t *s = stroke_alloc(ps.size()); + for (std::vector::iterator i = ps.begin(); i != ps.end(); ++i) + stroke_add_point(s, i->x, i->y); + stroke_finish(s); + stroke.reset(s, &stroke_free); + } + if (version == 0) return; + ar & button; + if (version >= 2) + ar & trigger; + if (version < 4 && (!button || trigger == (int)prefs.button.get().button)) + trigger = 0; + if (version < 3) + return; + ar & timeout; + if (version < 5) + return; + ar & modifiers; + + } + template void save(Archive & ar, const unsigned int version) const { + std::vector ps; + for (unsigned int i = 0; i < size(); i++) + ps.push_back(points(i)); + ar & ps; + ar & button; + ar & trigger; + ar & timeout; + ar & modifiers; + } public: int trigger; int button;