-Wglobal-constructors warns on constexpr default constructor evaluated at compile-time?

classic Classic list List threaded Threaded
9 messages Options
Reply | Threaded
Open this post in threaded view
|

-Wglobal-constructors warns on constexpr default constructor evaluated at compile-time?

Richard Smith via cfe-dev
Hello Clang experts,

it seems that -Wglobal-constructors throws a warning on a global using a constexpr default constructor on classes that don't strictly have POD members only. Given constexpr + no params implies all members are either POD or constexpr default constructible themselves, shouldn't Clang be able to avoid the global constructor in all cases?

e.g.:

struct Foo {
 public:
  constexpr Foo() = default;

  std::unique_ptr<int> my_int_; --> std::unique_ptr's default constructor is constexpr
};

Foo f;  --> error: declaration requires a global destructor [-Werror,-Wglobal-constructors]

void Init() {
  printf("%d", *f.my_int_);
}

Is this expected?

Thanks,
Gab

_______________________________________________
cfe-dev mailing list
[hidden email]
http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-dev
Reply | Threaded
Open this post in threaded view
|

Re: -Wglobal-constructors warns on constexpr default constructor evaluated at compile-time?

Richard Smith via cfe-dev
Just in case somebody missed that, note that despite the switch name the error message is about the **de**structor.
Which makes sense for a unique_ptr which can be constexpr constructible but is clearly not trivially destructible. I just would have expected that to show up in -Wexit-time-destructors not in -Wglobal-constructors.

By glancing at the code in Sema::FinalizeVarWithDestructor it seems the logic for finalizers is:
- always warn on -Wexit-time-destructors for any sort of non trivial dtor
- warn also on -Wglobal-constructors but only for non-static-local cases.

I can't see a case that would generate a warn_exit_time_destructor without a warn_global_destructor.
What is the intended semantic of -Wglobal-constructors? Would it be possible to make it only warn about constructors and leave destructors only to -Wexit-time-destructors?

On Tue, Jan 16, 2018 at 10:10 AM Gabriel Charette <[hidden email]> wrote:
Hello Clang experts,

it seems that -Wglobal-constructors throws a warning on a global using a constexpr default constructor on classes that don't strictly have POD members only. Given constexpr + no params implies all members are either POD or constexpr default constructible themselves, shouldn't Clang be able to avoid the global constructor in all cases?

e.g.:

struct Foo {
 public:
  constexpr Foo() = default;

  std::unique_ptr<int> my_int_; --> std::unique_ptr's default constructor is constexpr
};

Foo f;  --> error: declaration requires a global destructor [-Werror,-Wglobal-constructors]

void Init() {
  printf("%d", *f.my_int_);
}

Is this expected?

Thanks,
Gab

_______________________________________________
cfe-dev mailing list
[hidden email]
http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-dev
Reply | Threaded
Open this post in threaded view
|

Re: -Wglobal-constructors warns on constexpr default constructor evaluated at compile-time?

Richard Smith via cfe-dev
In reply to this post by Richard Smith via cfe-dev
On 16 January 2018 at 10:10, Gabriel Charette via cfe-dev
<[hidden email]> wrote:

> it seems that -Wglobal-constructors throws a warning on a global using a
> constexpr default constructor on classes that don't strictly have POD
> members only. Given constexpr + no params implies all members are either POD
> or constexpr default constructible themselves, shouldn't Clang be able to
> avoid the global constructor in all cases?

The warning is about the *de*structor:

> Foo f;  --> error: declaration requires a global destructor
> [-Werror,-Wglobal-constructors]

--
Malcolm Parsons
_______________________________________________
cfe-dev mailing list
[hidden email]
http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-dev
Reply | Threaded
Open this post in threaded view
|

Re: -Wglobal-constructors warns on constexpr default constructor evaluated at compile-time?

Richard Smith via cfe-dev
Aaaaah! I had definitely missed that this was about the *de*destructor..!

I would indeed expect, like Primiano, that -Wglobal-constructors would only warn about *con*structors (one can decide to mitigate global *de*structors another way, e.g. by invoking _exit() before end of main()).

On Tue, Jan 16, 2018 at 1:03 PM Malcolm Parsons <[hidden email]> wrote:
On 16 January 2018 at 10:10, Gabriel Charette via cfe-dev
<[hidden email]> wrote:

> it seems that -Wglobal-constructors throws a warning on a global using a
> constexpr default constructor on classes that don't strictly have POD
> members only. Given constexpr + no params implies all members are either POD
> or constexpr default constructible themselves, shouldn't Clang be able to
> avoid the global constructor in all cases?

The warning is about the *de*structor:

> Foo f;  --> error: declaration requires a global destructor
> [-Werror,-Wglobal-constructors]

--
Malcolm Parsons

_______________________________________________
cfe-dev mailing list
[hidden email]
http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-dev
Reply | Threaded
Open this post in threaded view
|

Re: -Wglobal-constructors warns on constexpr default constructor evaluated at compile-time?

Richard Smith via cfe-dev
On 1/16/2018 4:14 AM, Gabriel Charette via cfe-dev wrote:
> I would indeed expect, like Primiano, that -Wglobal-constructors would
> only warn about *con*structors (one can decide to mitigate global
> *de*structors another way, e.g. by invoking _exit() before end of main()).
The point of -Wglobal-constructors is to avoid code which runs at
process startup.  Due to the way the C++ ABI works, a global destructor
involves emitting a call to __cxa_atexit which runs at startup, so we warn.

-Eli

--
Employee of Qualcomm Innovation Center, Inc.
Qualcomm Innovation Center, Inc. is a member of Code Aurora Forum, a Linux Foundation Collaborative Project

_______________________________________________
cfe-dev mailing list
[hidden email]
http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-dev
Reply | Threaded
Open this post in threaded view
|

Re: -Wglobal-constructors warns on constexpr default constructor evaluated at compile-time?

Richard Smith via cfe-dev
On 16 January 2018 at 10:43, Friedman, Eli via cfe-dev <[hidden email]> wrote:
On 1/16/2018 4:14 AM, Gabriel Charette via cfe-dev wrote:
I would indeed expect, like Primiano, that -Wglobal-constructors would only warn about *con*structors (one can decide to mitigate global *de*structors another way, e.g. by invoking _exit() before end of main()).
The point of -Wglobal-constructors is to avoid code which runs at process startup.  Due to the way the C++ ABI works, a global destructor involves emitting a call to __cxa_atexit which runs at startup, so we warn.

Well, there are (at least) four distinct problems here:

 1) Code running at process startup (a performance problem)
 2) Code running at process termination (a performance problem)
 3) Global variables with non-constant initialization resulting in buggy program startup (called the "initialization order fiasco" by some)
 4) Global variables with non-trivial destruction resulting in buggy program shutdown, particularly in multithreaded code (if you have non-trivial global dtors, multiple threads, and you call exit, you typically have a bug)

It makes sense to request warnings about #3 without requesting the more general warnings about #1; as such, ignoring destructors in the -Wglobal-constructors warning would seem reasonable to me. (That allows all four problems to be detected by some combination of the two warning flags.)

_______________________________________________
cfe-dev mailing list
[hidden email]
http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-dev
Reply | Threaded
Open this post in threaded view
|

Re: -Wglobal-constructors warns on constexpr default constructor evaluated at compile-time?

Richard Smith via cfe-dev


On Tue, Jan 16, 2018 at 8:00 PM Richard Smith <[hidden email]> wrote:
On 16 January 2018 at 10:43, Friedman, Eli via cfe-dev <[hidden email]> wrote:
On 1/16/2018 4:14 AM, Gabriel Charette via cfe-dev wrote:
I would indeed expect, like Primiano, that -Wglobal-constructors would only warn about *con*structors (one can decide to mitigate global *de*structors another way, e.g. by invoking _exit() before end of main()).
The point of -Wglobal-constructors is to avoid code which runs at process startup.  Due to the way the C++ ABI works, a global destructor involves emitting a call to __cxa_atexit which runs at startup, so we warn.

Well, there are (at least) four distinct problems here:

 1) Code running at process startup (a performance problem)
 2) Code running at process termination (a performance problem)
 3) Global variables with non-constant initialization resulting in buggy program startup (called the "initialization order fiasco" by some)
 4) Global variables with non-trivial destruction resulting in buggy program shutdown, particularly in multithreaded code (if you have non-trivial global dtors, multiple threads, and you call exit, you typically have a bug)

It makes sense to request warnings about #3 without requesting the more general warnings about #1; as such, ignoring destructors in the -Wglobal-constructors warning would seem reasonable to me. (That allows all four problems to be detected by some combination of the two warning flags.)

Yes, precisely.

A program can decide to mitigate against 2/4 by atomically exiting with _exit() before the end of main() and hence truly only want to be warned by 1/3.


_______________________________________________
cfe-dev mailing list
[hidden email]
http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-dev
Reply | Threaded
Open this post in threaded view
|

Re: -Wglobal-constructors warns on constexpr default constructor evaluated at compile-time?

Richard Smith via cfe-dev
On 1/16/2018 11:26 AM, Gabriel Charette wrote:


On Tue, Jan 16, 2018 at 8:00 PM Richard Smith <[hidden email]> wrote:
On 16 January 2018 at 10:43, Friedman, Eli via cfe-dev <[hidden email]> wrote:
On 1/16/2018 4:14 AM, Gabriel Charette via cfe-dev wrote:
I would indeed expect, like Primiano, that -Wglobal-constructors would only warn about *con*structors (one can decide to mitigate global *de*structors another way, e.g. by invoking _exit() before end of main()).
The point of -Wglobal-constructors is to avoid code which runs at process startup.  Due to the way the C++ ABI works, a global destructor involves emitting a call to __cxa_atexit which runs at startup, so we warn.

Well, there are (at least) four distinct problems here:

 1) Code running at process startup (a performance problem)
 2) Code running at process termination (a performance problem)
 3) Global variables with non-constant initialization resulting in buggy program startup (called the "initialization order fiasco" by some)
 4) Global variables with non-trivial destruction resulting in buggy program shutdown, particularly in multithreaded code (if you have non-trivial global dtors, multiple threads, and you call exit, you typically have a bug)

It makes sense to request warnings about #3 without requesting the more general warnings about #1; as such, ignoring destructors in the -Wglobal-constructors warning would seem reasonable to me. (That allows all four problems to be detected by some combination of the two warning flags.)

Yes, precisely.

A program can decide to mitigate against 2/4 by atomically exiting with _exit() before the end of main() and hence truly only want to be warned by 1/3.

I'm not sure (3) is a problem this warning solves well; there are a lot of classes with constructors which aren't constexpr, but don't have relevant side-effects (for example, std::vector).  But I guess we could introduce a new warning flag.  (We probably don't want to change the meaning of the current warning flag for the sake of compatibility with existing build systems.)

On a side-note, it would be nice if the following worked to suppress global destructors:

struct A { ~A(); };
template<typename T> union NoDestroy {
  T t;
  constexpr NoDestroy():t{} {}
  constexpr ~NoDestroy() {}
};
NoDestroy<A> x;

-Eli

-- 
Employee of Qualcomm Innovation Center, Inc.
Qualcomm Innovation Center, Inc. is a member of Code Aurora Forum, a Linux Foundation Collaborative Project

_______________________________________________
cfe-dev mailing list
[hidden email]
http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-dev
Reply | Threaded
Open this post in threaded view
|

Re: -Wglobal-constructors warns on constexpr default constructor evaluated at compile-time?

Richard Smith via cfe-dev
On 16 January 2018 at 12:12, Friedman, Eli via cfe-dev <[hidden email]> wrote:
On 1/16/2018 11:26 AM, Gabriel Charette wrote:


On Tue, Jan 16, 2018 at 8:00 PM Richard Smith <[hidden email]> wrote:
On 16 January 2018 at 10:43, Friedman, Eli via cfe-dev <[hidden email]> wrote:
On 1/16/2018 4:14 AM, Gabriel Charette via cfe-dev wrote:
I would indeed expect, like Primiano, that -Wglobal-constructors would only warn about *con*structors (one can decide to mitigate global *de*structors another way, e.g. by invoking _exit() before end of main()).
The point of -Wglobal-constructors is to avoid code which runs at process startup.  Due to the way the C++ ABI works, a global destructor involves emitting a call to __cxa_atexit which runs at startup, so we warn.

Well, there are (at least) four distinct problems here:

 1) Code running at process startup (a performance problem)
 2) Code running at process termination (a performance problem)
 3) Global variables with non-constant initialization resulting in buggy program startup (called the "initialization order fiasco" by some)
 4) Global variables with non-trivial destruction resulting in buggy program shutdown, particularly in multithreaded code (if you have non-trivial global dtors, multiple threads, and you call exit, you typically have a bug)

It makes sense to request warnings about #3 without requesting the more general warnings about #1; as such, ignoring destructors in the -Wglobal-constructors warning would seem reasonable to me. (That allows all four problems to be detected by some combination of the two warning flags.)

Yes, precisely.

A program can decide to mitigate against 2/4 by atomically exiting with _exit() before the end of main() and hence truly only want to be warned by 1/3.

I'm not sure (3) is a problem this warning solves well; there are a lot of classes with constructors which aren't constexpr, but don't have relevant side-effects (for example, std::vector).

Yes, but it depends on how you try to solve (3). If you allow dynamically-initialized globals, but only if they don't reference other dynamically-initialized globals, you're right that this is pretty far from ideal. But that approach is fraught with peril, since even innocuous-seeming changes become wrong if you happen to be changing code that's reachable from a dynamically-initialized global. A more reliable (but obviously more restrictlve) approach is to avoid dynamically-initialized globals altogether, which this warning does help with :) Given the ongoing expansion of the powers of constexpr evaluation, the more restrictive approach is likely to become appropriate for more projects over time.

But I guess we could introduce a new warning flag.  (We probably don't want to change the meaning of the current warning flag for the sake of compatibility with existing build systems.)

On a side-note, it would be nice if the following worked to suppress global destructors:

struct A { ~A(); };
template<typename T> union NoDestroy {
  T t;
  constexpr NoDestroy():t{} {}
  constexpr ~NoDestroy() {}
};
NoDestroy<A> x;

This already suppresses the global dtor when compiled with optimization enabled (and the 'constexpr' on the destructor removed): we optimize out __cxa_atexit calls registering empty functions, IIRC. Support for constexpr destructors is working its way through the C++ committee right now, and that should behave as you expect on the above example (removing the global dtor).

_______________________________________________
cfe-dev mailing list
[hidden email]
http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-dev