[PATCH] Mangling of local names: anonymous unions, names in dead code

Evgeny Astigeevich evgeny.astigeevich at arm.com
Thu Nov 20 02:07:25 PST 2014


>>! In D6295#3, @rnk wrote:
> I don't think we should change our behavior w.r.t. static locals of non-inline functions. This behavior should stay the same:
>   void f() {
>     if (0) {
>       static int a = 0;
>     }
>     static int a = 0; // _ZZ1fvE1a
>   }
> 
>   inline void f() {
>     if (0) {
>       static int a = 0;
>     }
>     static int a = 0; // _ZZ1fvE1a_0
>   }
> 
> The reason is that in the non-inline case, we don't want to waste time during Sema building up tables on the ASTContext. The name is not ABI relevant, and either name is as good as the next.
> 
> I agree with your assessment of the static local union case, though. It's not clear to me how your fix works, but maybe -ast-dump isn't complete enough for me to see the IndirectFieldDecl that you're finding.

You mean that this will hurt performance, don't you?

The code that takes into account declarations in dead code was added in revision [[ http://llvm.org/viewvc/llvm-project?view=revision&revision=185986 | 185986 ]] by an engineer from Apple as a fix of the issue rdar://problem/14204721. I do not have access to Apple's bug tracking system to see what was the issue.

The current issue is that different enumeration schemas are used by getNextDiscriminator. And they produce different names depending on the function specifier 'inline'.
For example:

f.h
```
inline int f(int v) {
  static union {
    int a;
    int b;
  };

  static union {
    union {
      union {
        int c;                                                                                                                                                                                                                                
      };
      float d;
    };
  };

  int r = a+c;

  a = v;
  c = v+1;

  return r;
}
```

m_a.cpp
```
#include "f.h"                                                                                                                                                                                                                                

int f_a(int a) {
  return a+f(a);
}
```

m_b.cpp
```
#include "f.h"                                                                                                                                                                                                                                

int f_b(int b) {
  return b+f(b);
}
```

main.cpp

```
extern int f_a(int);
extern int f_b(int);

int main(int argc, const char* argv[]) {
  int r1 = f_a(argc);
  int r2 = f_b(argc+1);
  return r1 + r2;                                                                                                                                                                                                                             
}
```

According to the C++ standard [dcl.fct.spec]: A static local variable in an extern inline function always refers to the same object.
This works when everything is compile by one compiler but it does not work when m_a.cpp is compiled with clang and other files are compiled with g++:

```
$ /tools/collections/clang/3.5.0/3/linux_3.2-ubuntu_12.04-x86_64/bin/clang++ -c -O3 m_a.cpp
$ /tools/collections/clang/3.5.0/3/linux_3.2-ubuntu_12.04-x86_64/bin/clang++ -c -O3 m_b.cpp
$ /tools/collections/clang/3.5.0/3/linux_3.2-ubuntu_12.04-x86_64/bin/clang++ -O3 main.cpp m_a.o m_b.o
$ ./a.out 
$ echo $?
6

$ g++ -c -O3 m_a.cpp
$ g++ -c -O3 m_b.cpp
$ g++ -O3 main.cpp m_b.o m_a.o
$ ./a.out 
$ echo $?
6

$ /arm/devsys-tools/collections/clang/3.5.0/3/linux_3.2-ubuntu_12.04-x86_64/bin/clang++ -c -O3 m_a.cpp
$ g++ -O3 main.cpp m_b.o m_a.o
$ ./a.out 
$ echo $?
4
```

http://reviews.llvm.org/D6295






More information about the cfe-commits mailing list