First of all, sorry in advance for submitting a bug with no way to reproduce it
but I unfortunately already spent several hours on this and I simply can't
manage to make this fail in a simple example. In spite of this it seems like
this could be a compiler problem and not something in my code so I'd like to
report it and let you decide whether it's worth looking into.

Anyhow, the problem is that the compiler seems to do something strange with the
code which looks like this:

class UTF8String {
private:
    // we use this cache to speed up some common operations on UTF-8 strings
    struct CacheElement {
      const UTF8String *str; // the key of the cache
      int posInChars, posInBytes, len;
    };
    struct Cache { CacheElement cached[8]; int lastUsed; };
    static Cache& GetCache() { static Cache s_cache; return s_cache; }

    // find or allocate one of GetCache().cached elements for this object
    CacheElement *GetCacheElement() const { ... }

public:
    size_t length() const {
       CacheElement * const c = GetCacheElement();
       if ( cache->len == npos )
           cache->len = ... compute ...;
       return cache->len;
    }
};

Everything works perfectly fine with -O0 and with -O2 in simple examples.
However as soon as the code becomes a bit more complicated, sometimes
GetCacheElement() in length() returns bogus values, i.e. pointers to the
elements which are not in cached array at all (according to its printout, using
a special function in the program as gdb seems to be very confused by __thread
variables). I suspected a bug in my GetCacheElement(), of course, but it's
pretty trivial (linear search in the array basically...) and seems to be
correct and, moreover, everything works fine as long as -O2 is not used _or_
the Cache variable is made class static and accessed directly instead of in the
above way.

The real code can be found at
http://svn.wxwidgets.org/viewvc/wx/wxWidgets/trunk/include/wx/string.h?revision=55501&view=markup
but needs to be modified by disabling workaround found near comment containing
"g++ 4.1.2" string to see the problem. Basically it's enough to do "configure
&& make && cd tests && make && ./test" to see that it works with -O0 (or with
the workaround) and fails in mysterious ways with -O2. Sorry once again for not
being able to provide a simpler test case.

And all this happens on an amd64 Debian stable machine with (Debian) g++ 4.1.2
in single threaded test code.


-- 
           Summary: Incorrect access to static  __thread variables inside
                    static member functions
           Product: gcc
           Version: 4.1.2
            Status: UNCONFIRMED
          Severity: normal
          Priority: P3
         Component: c++
        AssignedTo: unassigned at gcc dot gnu dot org
        ReportedBy: vz-gcc at zeitlins dot org
  GCC host triplet: x86_64-unknown-linux-gnu


http://gcc.gnu.org/bugzilla/show_bug.cgi?id=37402

Reply via email to