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

            Bug ID: 28930
           Summary: Two classes with same name cause a runtime error
           Product: clang
           Version: trunk
          Hardware: PC
                OS: Linux
            Status: NEW
          Severity: normal
          Priority: P
         Component: -New Bugs
          Assignee: [email protected]
          Reporter: [email protected]
                CC: [email protected]
    Classification: Unclassified

Created attachment 16933
  --> https://llvm.org/bugs/attachment.cgi?id=16933&action=edit
hello.cc

This issue is a minimized and somewhat modified case that we hit in the
official Chrome.

Consider two C++ files:

hello.cc:
==========================================

#include <stdio.h>

class Foo {
 public:
  virtual void Do() {
    printf("A: do\n");
  }
};

void* CreateA() {
  Foo* foo = new Foo();
  printf("CreateA: %p\n", foo);
  return foo;
}

void* CreateB();
void UseB(void* obj);

int main(void) {
  void *b = CreateB();
  UseB(b);

  void *a = CreateA();

====================================


b.cc
====================================

#include <stdio.h>

class Foo {
 public:
  virtual void Do() {
    printf("B: do\n");
  }

  virtual void Do2() {
    printf("B: do2\n");
  }
};

void* CreateB() {
  Foo* obj = new Foo();
  printf("CreateB: %p\n", obj);
  return obj;
}

void UseB(void *obj) {
  printf("UseB(%p), begin\n", obj);
  Foo* foo = reinterpret_cast<Foo*>(obj);
  foo->Do();
  foo->Do2();
  printf("UseB(%p), end\n", obj);
}

====================================


As we can see, class Foo is defined in two translation units, but the uses are
isolated. Still, there's a name collision in the global namespace, so a linker
is in its right to throw an error about that, or it could rename the types to
avoid the collision. Let's compile and run:

$ clang++ -o hello hello.cc b.cc && ./hello
CreateB: 0x143a010
UseB(0x143a010), begin
A: do
Segmentation fault (core dumped)

Nice! Instead of creating Foo defined in b.cc, CreateB instantiated the Foo
defined in hello.cc, and then UseB caused a segfault while trying to access the
second virtual method, because Foo defined in hello.cc has just one.

It's not good that we were able to compile a malformed program and the compiler
didn't object. At the same time, it's probably hard to blame Clang here, as it
does not see the whole program, and the linker does not know about LLVM.

Let's try with LTO:

$ clang++ -o hello hello.cc b.cc -flto -fuse-ld=lld && ./hello
CreateB: 0x1c4e010
UseB(0x1c4e010), begin
A: do
Segmentation fault (core dumped)

Same thing, but here we actually have an ability to detect a problem and
complain or rename the type and avoid the collision.

It does not feel okay to pretend that everything is fine with the program.

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

Reply via email to