Should we use clang-only features? (and drop support for MSVC)

45 views
Skip to first unread message

Gabriel Charette

unread,
Feb 1, 2018, 6:48:26 AM2/1/18
to cxx, Daniel Cheng, Robert Liao, Francois Pierre Doray
Hello folks,

I have this internal debate with myself and would like your take.

Should we use clang-only features that are slightly better versions of the actual C++ spec?

e.g. :

clang doesn't generate static initializers for globals whose type is constexpr-default-constructible.
MSVC does -- we just found out.

With clang we have -Wglobal-constructors (now active in //base) that would throw if the compiler generated a static initializer.
I was also hoping to experiment with the [[clang::require_constant_initialization]] attribute (requires constant initialization without requiring constexpr -- useful for constexpr default constructible globals that then don't want to remain const).

Using these would allow us to get rid of much usage of LazyInstance, replacing it by compile-time initialization. Since we know LazyInstance initialization is somewhat costly (and sometimes problematic), reducing its usage would be great!

We have everything it takes to put this in place, but we need to use clang specific features to go beyond the C++ spec. Such features are apparently not supported by MSVC (should we even care?!).

Thanks!
Gab

Daniel Bratell

unread,
Feb 1, 2018, 8:22:31 AM2/1/18
to cxx, Gabriel Charette, Daniel Cheng, Robert Liao, Francois Pierre Doray
It is dangerous both to assume certain (unspecified) behaviour from the compiler and to require a certain toolchain that can't be replicated by other tools.

I've been around too long to trust any language designer's claim that the compiler will solve inefficiencies. What is and what isn't optimized and in exactly in what way varies both with toolchains and over time. Even if the one-and-only clang toolchain in this particular moment in time with the current set of compiler flags solves the problem adequately, there is really no guarantees that we are not painting ourself into a corner that will later limit ourselves or harm the project.

Considering that the problem is globals, may I suggest an alternative idea: get rid of the globals. Introduce an automatically generated class "Globals" where the members are the current globals and where everything from order to what code will be executed will be as well defined as in any other C++ class. It is not a novel idea in any way but I haven't seen it mentioned in this project.

For Opera, I think we won't be using VS for the next Windows release (assuming that order files can be used to compensate enough for the loss of PGO) and in that case we will be only using clang. That doesn't mean that I'm comfortable with the idea of shutting the door on all other toolchains by moving beyond specs.

/Daniel
--
You received this message because you are subscribed to the Google Groups "cxx" group.
To unsubscribe from this group and stop receiving emails from it, send an email to cxx+uns...@chromium.org.
To post to this group, send email to c...@chromium.org.
To view this discussion on the web visit https://groups.google.com/a/chromium.org/d/msgid/cxx/CAJTZ7L%2BpxUZnouwo%3DOLzLNqaN4z_gp13Z5Xao9LPk6YuNE%2BUpQ%40mail.gmail.com.



--
/* Opera Software, Linköping, Sweden: CET (UTC+1) */

Nico Weber

unread,
Feb 1, 2018, 8:34:18 AM2/1/18
to Gabriel Charette, cxx, Daniel Cheng, Robert Liao, Francois Pierre Doray
"It depends". Chromium is written in C++, so we should broadly aim to write in C++-as-spec'd. Several things we rely on heavily aren't covered by the language spec though (e.g. the whole _EXPORT macro business), and it's ok to use "progressively enhancing" features via a macro that is defined to nothing for other compilers (e.g. WARN_UNUSED_RESULT or the other stuff in base/compiler_specific.h; ASan; etc).

Number of static initializers for compile-time-evaluatable things are a quality-of-implementation thing. There are two problems in general with static initializers: 1. they have undefined order they run in 2. they can slow down startup. For compile-time evaluatable initializers, 1 is probably not an issue, so this is only a perf thing. For perf, we should only care about the configuration we ship (e.g. we wouldn't mind about debug builds).

Now, we currently still ship an MSVC build clang to some users, so for now I think the answer is we can't rely on this specific thing just yet. But once we ship only clang-built chromes to Windows users, I think it's fine to rely on this specific thing, for the reasons mentioned above.

--

Alex Clarke

unread,
Feb 1, 2018, 11:07:19 AM2/1/18
to Nico Weber, Gabriel Charette, cxx, Daniel Cheng, Robert Liao, Francois Pierre Doray
On 1 February 2018 at 13:34, Nico Weber <tha...@chromium.org> wrote:
"It depends". Chromium is written in C++, so we should broadly aim to write in C++-as-spec'd. Several things we rely on heavily aren't covered by the language spec though (e.g. the whole _EXPORT macro business), and it's ok to use "progressively enhancing" features via a macro that is defined to nothing for other compilers (e.g. WARN_UNUSED_RESULT or the other stuff in base/compiler_specific.h; ASan; etc).

Number of static initializers for compile-time-evaluatable things are a quality-of-implementation thing. There are two problems in general with static initializers: 1. they have undefined order they run in 2. they can slow down startup. For compile-time evaluatable initializers, 1 is probably not an issue, so this is only a perf thing. For perf, we should only care about the configuration we ship (e.g. we wouldn't mind about debug builds).

Now, we currently still ship an MSVC build clang to some users, so for now I think the answer is we can't rely on this specific thing just yet. But once we ship only clang-built chromes to Windows users, I think it's fine to rely on this specific thing, for the reasons mentioned above.

How's that effort going btw, is there a timeline?
 

On Thu, Feb 1, 2018 at 6:48 AM, Gabriel Charette <g...@chromium.org> wrote:
Hello folks,

I have this internal debate with myself and would like your take.

Should we use clang-only features that are slightly better versions of the actual C++ spec?

e.g. :

clang doesn't generate static initializers for globals whose type is constexpr-default-constructible.
MSVC does -- we just found out.

With clang we have -Wglobal-constructors (now active in //base) that would throw if the compiler generated a static initializer.
I was also hoping to experiment with the [[clang::require_constant_initialization]] attribute (requires constant initialization without requiring constexpr -- useful for constexpr default constructible globals that then don't want to remain const).

Using these would allow us to get rid of much usage of LazyInstance, replacing it by compile-time initialization. Since we know LazyInstance initialization is somewhat costly (and sometimes problematic), reducing its usage would be great!

We have everything it takes to put this in place, but we need to use clang specific features to go beyond the C++ spec. Such features are apparently not supported by MSVC (should we even care?!).

Thanks!
Gab

--
You received this message because you are subscribed to the Google Groups "cxx" group.
To unsubscribe from this group and stop receiving emails from it, send an email to cxx+uns...@chromium.org.
To post to this group, send email to c...@chromium.org.
To view this discussion on the web visit https://groups.google.com/a/chromium.org/d/msgid/cxx/CAJTZ7L%2BpxUZnouwo%3DOLzLNqaN4z_gp13Z5Xao9LPk6YuNE%2BUpQ%40mail.gmail.com.

--
You received this message because you are subscribed to the Google Groups "cxx" group.
To unsubscribe from this group and stop receiving emails from it, send an email to cxx+uns...@chromium.org.
To post to this group, send email to c...@chromium.org.

Nico Weber

unread,
Feb 1, 2018, 11:36:41 AM2/1/18
to Alex Clarke, Gabriel Charette, cxx, Daniel Cheng, Robert Liao, Francois Pierre Doray
On Thu, Feb 1, 2018 at 11:07 AM, Alex Clarke <alexc...@google.com> wrote:
On 1 February 2018 at 13:34, Nico Weber <tha...@chromium.org> wrote:
"It depends". Chromium is written in C++, so we should broadly aim to write in C++-as-spec'd. Several things we rely on heavily aren't covered by the language spec though (e.g. the whole _EXPORT macro business), and it's ok to use "progressively enhancing" features via a macro that is defined to nothing for other compilers (e.g. WARN_UNUSED_RESULT or the other stuff in base/compiler_specific.h; ASan; etc).

Number of static initializers for compile-time-evaluatable things are a quality-of-implementation thing. There are two problems in general with static initializers: 1. they have undefined order they run in 2. they can slow down startup. For compile-time evaluatable initializers, 1 is probably not an issue, so this is only a perf thing. For perf, we should only care about the configuration we ship (e.g. we wouldn't mind about debug builds).

Now, we currently still ship an MSVC build clang to some users, so for now I think the answer is we can't rely on this specific thing just yet. But once we ship only clang-built chromes to Windows users, I think it's fine to rely on this specific thing, for the reasons mentioned above.

How's that effort going btw, is there a timeline?

We have nothing to announce today :-)

Peter Kasting

unread,
Feb 1, 2018, 8:23:03 PM2/1/18
to Nico Weber, Gabriel Charette, cxx, Daniel Cheng, Robert Liao, Francois Pierre Doray
On Thu, Feb 1, 2018 at 5:34 AM, Nico Weber <tha...@chromium.org> wrote:
Number of static initializers for compile-time-evaluatable things are a quality-of-implementation thing. There are two problems in general with static initializers: 1. they have undefined order they run in 2. they can slow down startup. For compile-time evaluatable initializers, 1 is probably not an issue, so this is only a perf thing. For perf, we should only care about the configuration we ship (e.g. we wouldn't mind about debug builds).

Now, we currently still ship an MSVC build clang to some users, so for now I think the answer is we can't rely on this specific thing just yet. But once we ship only clang-built chromes to Windows users, I think it's fine to rely on this specific thing, for the reasons mentioned above.

My takeaway from https://bugs.chromium.org/p/chromium/issues/detail?id=807491 was that MSVC's behavior here caused DCHECK failures when we tried to rely on the clang behavior.  That seems worse than a perf issue.  We have code that does not work correctly unless the compiler does something not required by the standard.

I have previously expressed my discomfort with relying on this behavior.  This reinforces that for me.

PK

g...@chromium.org

unread,
Feb 12, 2018, 9:33:13 AM2/12/18
to cxx, tha...@chromium.org, g...@chromium.org, dch...@chromium.org, rob...@chromium.org, fdo...@chromium.org
Today I realized that this is already the case for at least two other types which have instances in over 25 files.

The scariest one being AtomicSequenceNumber (e.g. we could in practice get the same number twice if this is initialized twice -- this can probably have unexpected results in some systems).

Filed crbug.com/811266 to discuss next steps.
Reply all
Reply to author
Forward
0 new messages