[PATCH] D11297: PR17829: Functions declared extern "C" with a name matching a mangled C++ function are allowed

Andrey Bokhanko via cfe-commits cfe-commits at lists.llvm.org
Tue Aug 11 05:56:43 PDT 2015


andreybokhanko added a comment.

John,
(Others are welcome to chime in as well)

I started to implement your suggestion, but faced with problems.

Consider the following test case:

  1: struct T {
  2:   ~T() {}
  3: };
  4: 
  5: extern "C" void _ZN1TD1Ev();
  6: 
  7: int main() {
  8:   _ZN1TD1Ev();
  9:   T t;
  10: }

First time we visit "GetOrCreateLLVMFunction" for "_ZN1TD1Ev" mangled name is when we are dealing with the call at line 8. No global values are associated with "_ZN1TD1Ev" name yet, so we simply create a new llvm::Function and add it to the list of module's functions (ParentModule->getFunctionList().push_back(this); at Function.cpp:264).

Next time we visit "GetOrCreateLLVMFunction" for the same "_ZN1TD1Ev" name is when we are dealing with the implicit t's destructor call at the end of "main" routine (say, at line 10). We already have a global value associated with "_ZN1TD1Ev" name *and* we have a function with this name in module's function list. We can't create a new llvm::Function and add it to the functions list -- since module's machinery asserts that there is only one function with a given mangled name in the list; we can't remove old Function either -- since it is referred to in the call at line 8. The best we can do is to bit cast old llvm::Function (from line 8) to destructor's type and return it. But this generates destructor call for a wrong llvm::Function which means problems and further asserts down the road.

Any hints how to resolve this?

Yours,
Andrey

P.S.: I honestly believe this code is incorrect (despite no definition for "ZN1TD1Ev" function), so in my opinion the way to go would be to issue a warning inside "GetOrCreateLLVMFunction". This is different from my initial patch and still compiles fine the following code -- which, as I believe, you meant as a correct use of explicitly mangled names:

  struct T {
    ~T() {}
  };
  
  extern "C" void _ZN1TD1Ev(T *this_p);
  
  int main() {
    _ZN1TD1Ev(0);
    T t;
  }

(My initial patch warned even on this code, which is probably too strict indeed.)


http://reviews.llvm.org/D11297





More information about the cfe-commits mailing list