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

Jakub Jelinek <jakub at gcc dot gnu.org> changed:

           What    |Removed                     |Added
----------------------------------------------------------------------------
                 CC|                            |jakub at gcc dot gnu.org

--- Comment #21 from Jakub Jelinek <jakub at gcc dot gnu.org> ---
What is not satisfying?

struct QualifiedNameComponents {
    StringImpl* m_prefix;
    StringImpl* m_localName;
    StringImpl* m_namespace;
};
...
    template<typename T, UChar Converter(T)> static inline unsigned
computeHash(const T* data, unsigned length)
    {
        StringHasher hasher;
        bool rem = length & 1;
        length >>= 1;
        while (length--) {
            hasher.addCharacters(Converter(data[0]), Converter(data[1]));
            data += 2;
        }
        if (rem)
            hasher.addCharacter(Converter(*data));
        return hasher.hash();
    }
...
    template<size_t length> static inline unsigned hashMemory(const void* data)
    {
        typedef int dummylength_must_be_a_multible_of_four [(!(length % 4)) ? 1
: -1];
        return computeHash<UChar>(static_cast<const UChar*>(data), length /
sizeof(UChar));
    }
...
inline unsigned hashComponents(const QualifiedNameComponents& buf)
{
    return StringHasher::hashMemory<sizeof(QualifiedNameComponents)>(&buf);
}
struct QualifiedNameHash {
    static unsigned hash(const QualifiedName& name) { return hash(name.impl());
}
    static unsigned hash(const QualifiedName::QualifiedNameImpl* name)
    {
        QualifiedNameComponents c = { name->m_prefix.impl(),
name->m_localName.impl(), name->m_namespace.impl() };
        return hashComponents(c);
    }
    static bool equal(const QualifiedName& a, const QualifiedName& b) { return
a == b; }
    static bool equal(const QualifiedName::QualifiedNameImpl* a, const
QualifiedName::QualifiedNameImpl* b) { return a == b; }
    static const bool safeToCompareToEmptyOrDeleted = false;
};

is a clear aliasing violation and thus undefined behavior when called.
The `c' object has object type QualifiedNameComponents, whose subobjects have
type pointer to StringImpl.  In computeHash you are then reading the object
using the UChar (unsigned short) effective type, only char or unsigned char
types can be used for that, see e.g. [basic.types]/2, or read -fstrict-aliasing
documentation in info gcc.
For g++, you could read the object through say typedef UChar UCharMayAlias
__attribute__((__may_alias__));, or you can say std::memcpy the object into an
correspondigly sized array of UChar and hash that rather than the original
object, etc.

Reply via email to