r175326 - Rework the visibility computation algorithm in preparation

Rafael EspĂ­ndola rafael.espindola at gmail.com
Tue Feb 19 13:07:57 PST 2013


> Rework the visibility computation algorithm in preparation
> for distinguishing type vs. value visibility.
>
> The changes to the visibility of explicit specializations
> are intentional.

Thanks. It is indeed much cleaner to ignore other sources when a
specialization explicitly says what visibility should be used. A
change that looks unintended is that in

  struct HIDDEN foo {
  };
  template <class P>
  struct bar {
    static DEFAULT void zed();
  };
  template <class P>
  void bar<P>::zed() {
  }

  //template class bar<foo>;

  void test() {
    bar<foo>::zed();
  }

We produce a hidden symbol for zed, but uncommenting the explicit
template instantiation causes us to produce a default symbol. The idea
was for explicit template instantiations to make a difference only if
they have an attribute, no?

>  The change to the "ugly" test case is
> a consequence of a sensible implementation, and I am happy
> to argue that this is better behavior.

This one I think we need back :-(

The problem is that in gcc it is really easy for a project to use
-fvisibility=hidden. They change the build system and then add default
visibility attributes to *definitions* that they need to show up in
the libraries. That is how we end up with things like:

  template<typename T>
  struct DEFAULT foo {
    void bar() {}
  };
  class zed;
  template class foo<zed>;
  class DEFAULT zed {
  };

It was originally found by clang being unable to build chrome in
"components mode". I did try making it an error, but that then
requires changing quiet a bit of code to forward declare types with
the correct visibility or avoid the forward declaration.

The bit I think we need back from the old implementation is that an
implicit visibility, like the one zed has up to its definition, should
not force foo<zed> to have a hidden visibility since foo has an
explicit visibility. This does mean we would produce a default symbol
for

  template<typename T>
  struct DEFAULT foo {
    void bar() {}
  };
  class zed;
  template class foo<zed>;
  class HIDDEN zed {
  };

but a hidden one for

  template<typename T>
  struct DEFAULT foo {
    void bar() {}
  };
  class zed;
  class HIDDEN zed {
  };
  template class foo<zed>;

Cheers,
Rafael



More information about the cfe-commits mailing list