[llvm-bugs] [Bug 34128] New: Clang sets ItaniumCXXABI's __non_diamond_repeat_mask flag more often than GCC/ICC

via llvm-bugs llvm-bugs at lists.llvm.org
Tue Aug 8 14:50:53 PDT 2017


            Bug ID: 34128
           Summary: Clang sets ItaniumCXXABI's __non_diamond_repeat_mask
                    flag more often than GCC/ICC
           Product: clang
           Version: trunk
          Hardware: PC
                OS: Linux
            Status: NEW
          Severity: enhancement
          Priority: P
         Component: LLVM Codegen
          Assignee: unassignedclangbugs at nondot.org
          Reporter: ryan.prichard at gmail.com
                CC: llvm-bugs at lists.llvm.org

Consider this class hierarchy (each name is a subobject -- Shared is a virtual
base class):

   ^    ^
   |    |
   |    |
Left    Right
   ^    ^
   |    |
   |    |

The Itanium ABI specifies a __vmi_class_type_info for the Root class because it
has two base classes. The __vmi_class_type_info object has two flags, declared
like so in the libcxxabi source:

    enum {
        __non_diamond_repeat_mask = 0x1, // has two or more distinct base class
                                         //    objects of the same type
        __diamond_shaped_mask = 0x2      // has base class object with two or
                                         //    more derived objects

For this class hierarchy, GCC leaves Root's __non_diamond_repeat_mask flag
clear, which matches the comment in the libcxxabi header, whereas Clang sets
the flag. From a reliability/interoperability standpoint, maybe it'd be nice if
the compilers were consistent. The IA64ABI document's definitions of the two
flags weren't clear to me, so I'm not sure that Clang's behavior is technically
wrong. I also checked ICC via godbolt, which AFAIK uses the EDG frontend's
independent implementation of the IA64ABI, and it also clears the flag.

In libcxxabi, I think the two flags are only used for dynamic_cast, and I don't
think incorrectly setting the flag would ever break dynamic_cast. (Clearing it

In general, incorrectly setting the flag makes dynamic_cast slower. I don't
know whether fixing this particular issue would help.

Here's a test case demonstrating the inconsistency:

    #include <typeinfo>
    #include <stdio.h>

    struct Base { virtual ~Base() {} };
    struct Shared : Base {};
    struct Left : virtual Shared {};
    struct Right : virtual Shared {};
    struct Root : Left, Right {};
    Root root;

    enum {
        non_diamond_repeat_mask = 0x1, // has two or more distinct base class
                                       //    objects of the same type
        diamond_shaped_mask = 0x2      // has base class object with two or
                                       //    more derived objects

    // type info for classes that
    //  - have two or more base classes, or
    //  - have at least 1 virtual base class.
    struct vmi_class_type_info {
        virtual ~vmi_class_type_info();
        const char *name;
        unsigned int flags;
        unsigned int base_count;

    int main() {
        const vmi_class_type_info &info =
            reinterpret_cast<const vmi_class_type_info&>(typeid(root));
        printf("info.name=[%s]\n", info.name);
        printf("info.flags=%d:\n", info.flags);
        if (info.flags & non_diamond_repeat_mask) {
            printf("  non_diamond_repeat_mask\n");
        if (info.flags & diamond_shaped_mask) {
            printf("  diamond_shaped_mask\n");
        printf("info.base_count=%d\n", info.base_count);
        return 0;

Output (tested on Ubuntu 16.04):

    $ g++ test.cc && ./a.out

    $ clang++ test.cc && ./a.out

You are receiving this mail because:
You are on the CC list for the bug.
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.llvm.org/pipermail/llvm-bugs/attachments/20170808/8a34fb11/attachment.html>

More information about the llvm-bugs mailing list