https://bugs.llvm.org/show_bug.cgi?id=34128

            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: unassignedclangb...@nondot.org
          Reporter: ryan.prich...@gmail.com
                CC: llvm-bugs@lists.llvm.org

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

    Base
     ^
     |
  +------+
  |Shared|
  +------+
   ^    ^
   |    |
   |    |
Left    Right
   ^    ^
   |    |
   |    |
    Root

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
would.)

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
    name=[4Root]
    info->flags=2:
      __diamond_shaped_mask
    info->base_count=2

    $ clang++ test.cc && ./a.out
    name=[4Root]
    info->flags=3:
      __non_diamond_repeat_mask
      __diamond_shaped_mask
    info->base_count=2

-- 
You are receiving this mail because:
You are on the CC list for the bug.
_______________________________________________
llvm-bugs mailing list
llvm-bugs@lists.llvm.org
http://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-bugs

Reply via email to