<div dir="ltr"><div class="gmail_extra"><div class="gmail_quote">On Wed, Dec 2, 2015 at 4:11 PM, Richard Smith <span dir="ltr"><<a href="mailto:richard@metafoo.co.uk" target="_blank">richard@metafoo.co.uk</a>></span> wrote:<br><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left-width:1px;border-left-color:rgb(204,204,204);border-left-style:solid;padding-left:1ex"><div dir="ltr"><div class="gmail_extra"><div class="gmail_quote"><div><div class="h5">On Wed, Dec 2, 2015 at 1:41 AM, Weitian Leung via cfe-dev <span dir="ltr"><<a href="mailto:cfe-dev@lists.llvm.org" target="_blank">cfe-dev@lists.llvm.org</a>></span> wrote:<br><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left-width:1px;border-left-color:rgb(204,204,204);border-left-style:solid;padding-left:1ex"><div dir="ltr"><div>Hi all,<br></div><div><br>
    Consider the following code (full source code can be found in
    attachment)<br>
    <br>
    object.h<br>
    <blockquote type="cite">#define _DESTRUCTOR_IN_HEADER<br>
      <br>
      class Object<br>
      {<br>
      public:<br>
          Object();<br>
      #ifdef _DESTRUCTOR_IN_HEADER<br>
          ~Object()<br>
          {<br>
          }<br>
      #else<br>
          ~Object();<br>
      #endif<br>
      <br>
      private:<br>
          class Counter<br>
          {<br>
          public:<br>
              Counter()<br>
                  : _count(0)<br>
              {<br>
                  printf("Counter: %p %d\n", this, _count);<br>
              }<br>
      <br>
              ~Counter()<br>
              {<br>
                  printf("~Counter: %p %d\n", this, _count);<br>
              }<br>
      <br>
              void operator++()    { ++_count; }<br>
              void operator--()    { --_count; }<br>
      <br>
          private:<br>
              int _count;<br>
          };<br>
      <br>
          class Foo<br>
          {<br>
          public:<br>
              Foo() { ++counter(); }<br>
              ~Foo() { --counter(); }<br>
      <br>
          private:<br>
              Counter& counter()<br>
              {<br>
                  static Counter s_counter;<br>
                  return s_counter;<br>
              }<br></blockquote></div></div></blockquote><div><br></div></div></div><div>When you use -fvisibility-inlines-hidden, you give this function hidden visibility, so each DSO gets its own copy of the function. We also give each DSO its own copy of each inline function's static local variables. Thus the Object::Object() constructor in your shared library increments one counter, and the Object::~Object() destructor in your main binary decrements a different counter.</div><div><br></div><div>GCC appears to not make the static local variable hidden when it makes the surrounding function hidden. That makes sense, since -fvisibility-inlines-hidden is supposed to not change the semantics of the program unless you're comparing addresses of inline functions.</div></div></div></div></blockquote><div><br></div><div>It also looks like this may have changed since the flag was originally designed.</div><div><br></div><div><a href="https://gcc.gnu.org/wiki/Visibility">https://gcc.gnu.org/wiki/Visibility</a> says "However, -fvisibility-inlines-hidden can be used with no source alterations, unless you need to override it for inlines where address identity is important either for the function itself <b>or any function local static data.</b>" (Clearly this is somewhat bogus: if the addresses of function local statics are different, their contents may also be different.)</div><div><br></div><div><a href="https://gcc.gnu.org/onlinedocs/gcc/C_002b_002b-Dialect-Options.html">https://gcc.gnu.org/onlinedocs/gcc/C_002b_002b-Dialect-Options.html</a> says: "This switch declares that the user does not attempt to compare pointers to inline functions or methods where the addresses of the two functions are taken in different shared objects. [...] The behavior of this switch is not quite the same as marking the methods as hidden directly, because it <b>does not affect static variables local to the function</b> or cause the compiler to deduce that the function is defined in only one shared object."</div><div><br></div><div>In any case, this is a Clang bug.</div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left-width:1px;border-left-color:rgb(204,204,204);border-left-style:solid;padding-left:1ex"><div dir="ltr"><div class="gmail_extra"><div class="gmail_quote"><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left-width:1px;border-left-color:rgb(204,204,204);border-left-style:solid;padding-left:1ex"><div><div class="h5"><div dir="ltr"><div><blockquote type="cite">
          } foo;<br>
      };<br>
    </blockquote>
    object.cpp
    <blockquote type="cite">#include "object.h"<br>
      <br>
      Object::Object()<br>
      {<br>
      }<br>
      <br>
      #ifndef _DESTRUCTOR_IN_HEADER<br>
      Object::~Object()<br>
      {<br>
      <br>
      }<br>
      #endif</blockquote>
    <br>
    Build the source to a shared library (compile with
    -fvisibility-inlines-hidden flag),<br>
    uses in main (another module)<br>
    <blockquote type="cite">    Object *obj = new Object;<br>
          delete obj;</blockquote>
    you may see the strange output when running<br>
    <blockquote type="cite">Counter: 0x7f2ded933efc 0<br>
      Counter: 0x6012d4 0<br>
      ~Counter: 0x6012d4 -1<br>
      ~Counter: 0x7f2ded933efc 1</blockquote>
    <br>
    The Counter construct/destruct twice, the second one (Counter:
    0x6012d4 0) construct from<br>
     delete obj > Object::Foo::~Foo() > Object::Foo::counter()<br>
    <br>
    when comment out the line <b>#define _DESTRUCTOR_IN_HEADER </b>or
    remove the<b><br>
    </b><b>-fvisibility-inlines-hidden</b> flag, it works as expected<br>
    remove the compile flag<br>
    <blockquote type="cite">Counter: 0x6013a4 0<br>
      ~Counter: 0x6013a4 0</blockquote>
    comment out #define _DESTRUCTOR_IN_HEADER<br>
    <blockquote type="cite">Counter: 0x7f1eaa16629c 0<br>
      ~Counter: 0x7f1eaa16629c 0</blockquote>
    <br>
    A bit difference, as the address isn't the same (heap and stack)<br>
    <br>
    this code works with GCC (as least 5.2 as my test) with or without
    the -fvisibility-inlines-hidden<br>
    flag, of course it works with MSVC too.<br>
    <br>
    I don't known is this a bug with the flag or because the silly code
    makes it (as when constructor and<br>
    destructor defined in the same file, it works).<br><br></div><div>It seems that my last post failed, seems no body answers me, so I repost again, sorry.<br></div><div>If this is the wrong place, please let me know where to post, thanks.<br></div><div><br></div></div>
<br></div></div>_______________________________________________<br>
cfe-dev mailing list<br>
<a href="mailto:cfe-dev@lists.llvm.org" target="_blank">cfe-dev@lists.llvm.org</a><br>
<a href="http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-dev" rel="noreferrer" target="_blank">http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-dev</a><br>
<br></blockquote></div><br></div></div>
</blockquote></div><br></div></div>