Opened 14 years ago

Closed 14 years ago

#1892 closed Bugs (fixed)

boost::spirit::static_ causes link error (using wave)

Reported by: anonymous Owned by: Joel de Guzman
Milestone: Boost 1.36.0 Component: spirit
Version: Boost 1.35.0 Severity: Regression
Keywords: Cc:

Description

When using wave, I encounter a link error when attempting to #include wave headers in more than one translation unit. Although this is via use of wave, I believe it is due to a breaking change in spirit. There is no error in 1.34. This effectively renders wave/spirit next to useless as it forces users to use one source file in their projects.

The link error text is (vs2005): 1>token_output.obj : error LNK2005: "public: thiscall public: __thiscall boost::spirit::static_<class boost::thread_specific_ptr<class boost::weak_ptr<struct boost::spirit::impl::grammar_helper<struct boost::spirit::grammar<class boost::wave::util::time_conversion::time_conversion_grammar,struct boost::spirit::parser_context<struct boost::spirit::nil_t> >,class boost::wave::util::time_conversion::time_conversion_grammar,class boost::spirit::scanner<char const *,struct boost::spirit::scanner_policies<struct boost::spirit::skipper_iteration_policy<struct boost::spirit::iteration_policy>,struct boost::spirit::match_policy,struct boost::spirit::action_policy> > > > >,class boost::spirit::impl::get_definition_static_data_tag>::static_<class boost::thread_specific_ptr<class boost::weak_ptr<struct boost::spirit::impl::grammar_helper<struct boost::spirit::grammar<class boost::wave::util::time_conversion::time_conversion_grammar,struct boost::spirit::parser_context<struct boost::spirit::nil_t> >,class boost::wave::util::time_conversion::time_conversion_grammar,class boost::spirit::scanner<char const *,struct boost::spirit::scanner_policies<struct boost::spirit::skipper_iteration_policy<struct boost::spirit::iteration_policy>,struct boost::spirit::match_policy,struct boost::spirit::action_policy> > > > >,class boost::spirit::impl::get_definition_static_data_tag>(class boost::spirit::impl::get_definition_static_data_tag)'::2'::destructor::~destructor(void)" (??1destructor@?1???0?$static_@V?$thread_specific_ptr@V?$weak_ptr@U?$grammar_helper@U?$grammar@Vtime_conversion_grammar@time_conversion@util@wave@boost@@U?$parser_context@Unil_t@spirit@boost@@@spirit@5@@spirit@boost@@Vtime_conversion_grammar@time_conversion@util@wave@3@V?$scanner@PBDU?$scanner_policies@U?$skipper_iteration_policy@Uiteration_policy@spirit@boost@@@spirit@boost@@Umatch_policy@23@Uaction_policy@23@@spirit@boost@@@23@@impl@spirit@boost@@@boost@@@boost@@Vget_definition_static_data_tag@impl@spirit@2@@spirit@boost@@QAE@Vget_definition_static_data_tag@impl@23@@Z@QAE@XZ) already defined in scramble.obj 1>token_output.obj : error LNK2005: "public: static void cdecl public: __thiscall boost::spirit::static_<class boost::thread_specific_ptr<class boost::weak_ptr<struct boost::spirit::impl::grammar_helper<struct boost::spirit::grammar<class boost::wave::util::time_conversion::time_conversion_grammar,struct boost::spirit::parser_context<struct boost::spirit::nil_t> >,class boost::wave::util::time_conversion::time_conversion_grammar,class boost::spirit::scanner<char const *,struct boost::spirit::scanner_policies<struct boost::spirit::skipper_iteration_policy<struct boost::spirit::iteration_policy>,struct boost::spirit::match_policy,struct boost::spirit::action_policy> > > > >,class boost::spirit::impl::get_definition_static_data_tag>::static_<class boost::thread_specific_ptr<class boost::weak_ptr<struct boost::spirit::impl::grammar_helper<struct boost::spirit::grammar<class boost::wave::util::time_conversion::time_conversion_grammar,struct boost::spirit::parser_context<struct boost::spirit::nil_t> >,class boost::wave::util::time_conversion::time_conversion_grammar,class boost::spirit::scanner<char const *,struct boost::spirit::scanner_policies<struct boost::spirit::skipper_iteration_policy<struct boost::spirit::iteration_policy>,struct boost::spirit::match_policy,struct boost::spirit::action_policy> > > > >,class boost::spirit::impl::get_definition_static_data_tag>(class boost::spirit::impl::get_definition_static_data_tag)'::3'::default_ctor::construct(void)" (?construct@default_ctor@?2???0?$static_@V?$thread_specific_ptr@V?$weak_ptr@U?$grammar_helper@U?$grammar@Vtime_conversion_grammar@time_conversion@util@wave@boost@@U?$parser_context@Unil_t@spirit@boost@@@spirit@5@@spirit@boost@@Vtime_conversion_grammar@time_conversion@util@wave@3@V?$scanner@PBDU?$scanner_policies@U?$skipper_iteration_policy@Uiteration_policy@spirit@boost@@@spirit@boost@@Umatch_policy@23@Uaction_policy@23@@spirit@boost@@@23@@impl@spirit@boost@@@boost@@@boost@@Vget_definition_static_data_tag@impl@spirit@2@@spirit@boost@@QAE@Vget_definition_static_data_tag@impl@34@@Z@SAXXZ) already defined in scramble.obj

Attachments (1)

reproduce1892.zip (1.1 KB ) - added by eric.malenfant@… 14 years ago.
Source files to reproduce the link errors

Download all attachments as: .zip

Change History (3)

by eric.malenfant@…, 14 years ago

Attachment: reproduce1892.zip added

Source files to reproduce the link errors

comment:1 by eric.malenfant@…, 14 years ago

Proposed fix:

Move the definitions of the "destructor" and "default_constructor" out of static_'s ctor body, and put them inside the class template definition instead.

A patch against Boost release 1.35 of /boost/spirit/core/non_terminal/impl/static.hpp gives:

@@ -40,20 +40,15 @@
     struct static_
         : boost::noncopyable
     {
-        typedef T value_type;
-        typedef typename boost::call_traits<T>::reference reference;
-        typedef typename boost::call_traits<T>::const_reference const_reference;
-
-        static_(Tag = Tag())
-        {
-            struct destructor
+    private:
+        struct destructor
             {
                 ~destructor()
                 {
                     static_::get_address()->~value_type();
                 }
             };
-
+                    
             struct default_ctor
             {
                 static void construct()
@@ -63,6 +58,13 @@
                 }
             };
 
+    public:
+        typedef T value_type;
+        typedef typename boost::call_traits<T>::reference reference;
+        typedef typename boost::call_traits<T>::const_reference const_reference;
+
+        static_(Tag = Tag())
+        {
             boost::call_once(&default_ctor::construct, constructed_);
         }

comment:2 by Joel de Guzman, 14 years ago

Resolution: fixed
Status: newclosed
Note: See TracTickets for help on using tickets.