r175326 - Rework the visibility computation algorithm in preparation

Nico Weber thakis at chromium.org
Tue Feb 26 14:06:20 PST 2013


Thank you for landing this in r176112. However, things are still
broken if one adds

class EXPORT MyFoo {  // happens without this EXPORT too
  void calculateDrawProperties(Layer *rootLayer);
};

between `class Layer;` and `class EXPORT Layer;` in the example above:


$ ~/src/llvm/Release+Asserts/bin/clang --version
clang version 3.3 (trunk 176115)
Target: x86_64-apple-darwin12.2.1
Thread model: posix
$ cat test.cc
#define EXPORT __attribute__((visibility("default")))

class Layer;

class EXPORT MyFoo {
  void calculateDrawProperties(Layer *rootLayer);
};

class EXPORT Layer;

template <typename LayerType>
struct EXPORT OcclusionTrackerBase {
  OcclusionTrackerBase();
};

template <typename LayerType>
OcclusionTrackerBase<LayerType>::OcclusionTrackerBase() {}

extern template struct OcclusionTrackerBase<Layer>;
template struct OcclusionTrackerBase<Layer>;
$  ~/src/llvm/Release+Asserts/bin/clang -c test.cc -fvisibility=hidden
&&  nm -m test.o
0000000000000070 (__TEXT,__eh_frame) non-external EH_frame0
0000000000000000 (__TEXT,__textcoal_nt) weak private external
__ZN20OcclusionTrackerBaseI5LayerEC1Ev
0000000000000088 (__TEXT,__eh_frame) weak private external
__ZN20OcclusionTrackerBaseI5LayerEC1Ev.eh
0000000000000020 (__TEXT,__textcoal_nt) weak private external
__ZN20OcclusionTrackerBaseI5LayerEC2Ev
00000000000000b0 (__TEXT,__eh_frame) weak private external
__ZN20OcclusionTrackerBaseI5LayerEC2Ev.eh



On Tue, Feb 26, 2013 at 6:31 PM, John McCall <rjmccall at apple.com> wrote:
> On Feb 26, 2013, at 8:39 AM, Rafael EspĂ­ndola <rafael.espindola at gmail.com> wrote:
>>> I found one more bug, with problem (1). It looks like the first
>>> declaration of a type must be marked visible, not just any declaration
>>> before an instantiation with that type:
>>
>> The problem comes from the template using the canonical (first) decl
>> for the arguments. Some extra examples:
>>
>> template <typename T>
>> struct __attribute__((visibility("default"))) barT {
>>  static void zed() {}
>> };
>> class foo;
>> class __attribute__((visibility("default"))) foo;
>> template struct barT<foo>;
>>
>> template <int* I>
>> struct __attribute__((visibility("default"))) barI {
>>  static void zed() {}
>> };
>> extern int I;
>> extern int I __attribute__((visibility("default")));
>> template struct barI<&I>;
>>
>> typedef void (*fType)(void);
>> template<fType F>
>> struct __attribute__((visibility("default"))) barF {
>>  static void zed() {}
>> };
>> void F();
>> void F() __attribute__((visibility("default")));;
>> template struct barF<F>;
>>
>> This is somewhat easy to hack in the visibility computation (see
>> attached patch), but what should we do for cases like:
>>
>>
>> template <typename T>
>> struct __attribute__((visibility("default"))) barT {
>>  static void zed() {}
>> };
>> class foo;
>> template struct barT<foo>;
>> class __attribute__((visibility("default"))) foo;
>>
>>
>> With this patch we print a hidden visibility. But for
>>
>> emplate <int* I>
>> struct __attribute__((visibility("default"))) barI {
>>  static void zed() {}
>> };
>> extern int I;
>> void use() {
>>  barI<&I>::zed();
>> }
>> extern int I __attribute__((visibility("default")));
>>
>> We produce a default one unless the last line is commented. Should the
>> template instantiation point to the last decl available when it is
>> created?
>
> In these cases, templates point to types, not declarations.
> But the declaration stored in the type is the first declaration until
> we see a definition, at which point it's always that.
>
> This patch seems fine.
>
> John.




More information about the cfe-commits mailing list