diff mbox

Enable lightweight checks with _GLIBCXX_ASSERTIONS.

Message ID 20150907182755.GP2631@redhat.com
State New
Headers show

Commit Message

Jonathan Wakely Sept. 7, 2015, 6:27 p.m. UTC
This patch adds the "debug mode lite" we've been talking about, by
changing __glibcxx_assert to be activated by _GLIBCXX_ASSERTIONS
instead of _GLIBCXX_DEBUG (and making the latter imply the former).

_GLIBCXX_ASSERTIONS is already used in Parallel Mode for enabling
optional assertions (although some of them are O(n) and so we might
want to change them to use another macro like _GLIBCXX_DEBUG or
_GLIBCXX_PARALLEL_ASSERTIONS instead).

With the change to define __glibcxx_assert() without Debug Mode we can
change most uses of _GLIBCXX_DEBUG_ASSERT to simply __glibcxx_assert,
so that the assertion is done when _GLIBCXX_ASSERTIONS is defined (not
only in Debug Mode).

I haven't added any new assertions yet, this just converts the
lightweight Debug Mode checks, but the next step will be to add
additional assertions to the (normal mode) containers. The google
branches contain several good examples of checks to add.

François, what do you think of this approach?

Comments

Daniel Krügler Sept. 7, 2015, 7:04 p.m. UTC | #1
2015-09-07 20:27 GMT+02:00 Jonathan Wakely <jwakely@redhat.com>:
> This patch adds the "debug mode lite" we've been talking about, by
> changing __glibcxx_assert to be activated by _GLIBCXX_ASSERTIONS
> instead of _GLIBCXX_DEBUG (and making the latter imply the former).
>
> _GLIBCXX_ASSERTIONS is already used in Parallel Mode for enabling
> optional assertions (although some of them are O(n) and so we might
> want to change them to use another macro like _GLIBCXX_DEBUG or
> _GLIBCXX_PARALLEL_ASSERTIONS instead).
>
> With the change to define __glibcxx_assert() without Debug Mode we can
> change most uses of _GLIBCXX_DEBUG_ASSERT to simply __glibcxx_assert,
> so that the assertion is done when _GLIBCXX_ASSERTIONS is defined (not
> only in Debug Mode).
>
> I haven't added any new assertions yet, this just converts the
> lightweight Debug Mode checks, but the next step will be to add
> additional assertions to the (normal mode) containers. The google
> branches contain several good examples of checks to add.

In the suggested doc changes:

+        When defined, <code>_GLIBCXX_ASSERTIONS</code> is defined
+        automatically, so all the assertions that enables are also enabled
+        in debug mode.

there seems to be a typo, presumably it should be

+        When defined, <code>_GLIBCXX_ASSERTIONS</code> is defined
+        automatically, so all the assertions that <ins>it</ins>
enables are also enabled
+        in debug mode.

instead?

- Daniel
Florian Weimer Sept. 7, 2015, 7:31 p.m. UTC | #2
* Jonathan Wakely:

> This patch adds the "debug mode lite" we've been talking about, by
> changing __glibcxx_assert to be activated by _GLIBCXX_ASSERTIONS
> instead of _GLIBCXX_DEBUG (and making the latter imply the former).

Interesting.  Is this mode ABI-compatible with the default mode?
Should _FORTIFY_SOURCE imply _GLIBCXX_ASSERTIONS?
Jonathan Wakely Sept. 7, 2015, 7:53 p.m. UTC | #3
On 07/09/15 21:04 +0200, Daniel Krügler wrote:
>2015-09-07 20:27 GMT+02:00 Jonathan Wakely <jwakely@redhat.com>:
>> This patch adds the "debug mode lite" we've been talking about, by
>> changing __glibcxx_assert to be activated by _GLIBCXX_ASSERTIONS
>> instead of _GLIBCXX_DEBUG (and making the latter imply the former).
>>
>> _GLIBCXX_ASSERTIONS is already used in Parallel Mode for enabling
>> optional assertions (although some of them are O(n) and so we might
>> want to change them to use another macro like _GLIBCXX_DEBUG or
>> _GLIBCXX_PARALLEL_ASSERTIONS instead).
>>
>> With the change to define __glibcxx_assert() without Debug Mode we can
>> change most uses of _GLIBCXX_DEBUG_ASSERT to simply __glibcxx_assert,
>> so that the assertion is done when _GLIBCXX_ASSERTIONS is defined (not
>> only in Debug Mode).
>>
>> I haven't added any new assertions yet, this just converts the
>> lightweight Debug Mode checks, but the next step will be to add
>> additional assertions to the (normal mode) containers. The google
>> branches contain several good examples of checks to add.
>
>In the suggested doc changes:
>
>+        When defined, <code>_GLIBCXX_ASSERTIONS</code> is defined
>+        automatically, so all the assertions that enables are also enabled
>+        in debug mode.
>
>there seems to be a typo, presumably it should be
>
>+        When defined, <code>_GLIBCXX_ASSERTIONS</code> is defined
>+        automatically, so all the assertions that <ins>it</ins>
>enables are also enabled
>+        in debug mode.
>
>instead?

It's correct as I wrote it, but your version is clearer so I'll change
it.

My original can be read as "so all the assertions that that enables"
where the first "that" can be removed without changing the meaning.
Stoopid English ;-)
Jonathan Wakely Sept. 7, 2015, 7:59 p.m. UTC | #4
On 07/09/15 21:31 +0200, Florian Weimer wrote:
>* Jonathan Wakely:
>
>> This patch adds the "debug mode lite" we've been talking about, by
>> changing __glibcxx_assert to be activated by _GLIBCXX_ASSERTIONS
>> instead of _GLIBCXX_DEBUG (and making the latter imply the former).
>
>Interesting.  Is this mode ABI-compatible with the default mode?

Yes, that's the main reason I want to make this change.

>Should _FORTIFY_SOURCE imply _GLIBCXX_ASSERTIONS?

Yes, I think it should.

You can read my notes on these "debug mode lite" checks at
https://gcc.gnu.org/wiki/LibstdcxxDebugMode (including "This should be
discussed with Glibc and security teams" and I specifically had you in
mind when I wrote that :-)

Your thoughts would be much appreciated, especially regarding
_FORTIFY_SOURCE and which kind of new checks you think would be
appropriate to add.
Jonathan Wakely Sept. 7, 2015, 8:10 p.m. UTC | #5
On 07/09/15 20:53 +0100, Jonathan Wakely wrote:
>On 07/09/15 21:04 +0200, Daniel Krügler wrote:
>>2015-09-07 20:27 GMT+02:00 Jonathan Wakely <jwakely@redhat.com>:
>>>This patch adds the "debug mode lite" we've been talking about, by
>>>changing __glibcxx_assert to be activated by _GLIBCXX_ASSERTIONS
>>>instead of _GLIBCXX_DEBUG (and making the latter imply the former).
>>>
>>>_GLIBCXX_ASSERTIONS is already used in Parallel Mode for enabling
>>>optional assertions (although some of them are O(n) and so we might
>>>want to change them to use another macro like _GLIBCXX_DEBUG or
>>>_GLIBCXX_PARALLEL_ASSERTIONS instead).
>>>
>>>With the change to define __glibcxx_assert() without Debug Mode we can
>>>change most uses of _GLIBCXX_DEBUG_ASSERT to simply __glibcxx_assert,
>>>so that the assertion is done when _GLIBCXX_ASSERTIONS is defined (not
>>>only in Debug Mode).
>>>
>>>I haven't added any new assertions yet, this just converts the
>>>lightweight Debug Mode checks, but the next step will be to add
>>>additional assertions to the (normal mode) containers. The google
>>>branches contain several good examples of checks to add.
>>
>>In the suggested doc changes:
>>
>>+        When defined, <code>_GLIBCXX_ASSERTIONS</code> is defined
>>+        automatically, so all the assertions that enables are also enabled
>>+        in debug mode.
>>
>>there seems to be a typo, presumably it should be
>>
>>+        When defined, <code>_GLIBCXX_ASSERTIONS</code> is defined
>>+        automatically, so all the assertions that <ins>it</ins>
>>enables are also enabled
>>+        in debug mode.
>>
>>instead?
>
>It's correct as I wrote it, but your version is clearer so I'll change
>it.
>
>My original can be read as "so all the assertions that that enables"
>where the first "that" can be removed without changing the meaning.
>Stoopid English ;-)

I think this is even better:

  When defined, <code>_GLIBCXX_ASSERTIONS</code> is defined
  automatically, so all the assertions enabled by that macro are
  also enabled in debug mode.

Is that clear?
Daniel Krügler Sept. 7, 2015, 8:12 p.m. UTC | #6
2015-09-07 22:10 GMT+02:00 Jonathan Wakely <jwakely@redhat.com>:
> On 07/09/15 20:53 +0100, Jonathan Wakely wrote:
>> On 07/09/15 21:04 +0200, Daniel Krügler wrote:
>>> In the suggested doc changes:
>>>
>>> +        When defined, <code>_GLIBCXX_ASSERTIONS</code> is defined
>>> +        automatically, so all the assertions that enables are also
>>> enabled
>>> +        in debug mode.
>>>
>>> there seems to be a typo, presumably it should be
>>>
>>> +        When defined, <code>_GLIBCXX_ASSERTIONS</code> is defined
>>> +        automatically, so all the assertions that <ins>it</ins>
>>> enables are also enabled
>>> +        in debug mode.
>>>
>>> instead?
>>
>>
>> It's correct as I wrote it, but your version is clearer so I'll change
>> it.
>>
>> My original can be read as "so all the assertions that that enables"
>> where the first "that" can be removed without changing the meaning.
>> Stoopid English ;-)
>
>
> I think this is even better:
>
>  When defined, <code>_GLIBCXX_ASSERTIONS</code> is defined
>  automatically, so all the assertions enabled by that macro are
>  also enabled in debug mode.
>
> Is that clear?

It's perfect!

Thanks,

- Daniel
Michael Matz Sept. 8, 2015, 1:14 p.m. UTC | #7
Hi,

On Mon, 7 Sep 2015, Jonathan Wakely wrote:

> > Interesting.  Is this mode ABI-compatible with the default mode?
> 
> Yes, that's the main reason I want to make this change.
> 
> > Should _FORTIFY_SOURCE imply _GLIBCXX_ASSERTIONS?
> 
> Yes, I think it should.

Then at least those assertions that lie in a different big-O complexity 
class have to be moved away from _GLIBCXX_ASSERTIONS (as hinted in your 
initial mail).  Some distros build packages with _FORTIFY_SOURCE, and 
while additional asserts seem acceptable, going from constant to linear 
(or the like) seems not.


Ciao,
Michael.
Jonathan Wakely Sept. 8, 2015, 2:34 p.m. UTC | #8
On 08/09/15 15:14 +0200, Michael Matz wrote:
>Hi,
>
>On Mon, 7 Sep 2015, Jonathan Wakely wrote:
>
>> > Interesting.  Is this mode ABI-compatible with the default mode?
>>
>> Yes, that's the main reason I want to make this change.
>>
>> > Should _FORTIFY_SOURCE imply _GLIBCXX_ASSERTIONS?
>>
>> Yes, I think it should.
>
>Then at least those assertions that lie in a different big-O complexity
>class have to be moved away from _GLIBCXX_ASSERTIONS (as hinted in your
>initial mail).  Some distros build packages with _FORTIFY_SOURCE, and
>while additional asserts seem acceptable, going from constant to linear
>(or the like) seems not.

Agreed.

AFAIK no distros have anything that depends on the libstdc++ Parallel
Mode (which enables O(n) checks under _GLIBCXX_ASSERTIONS), but as I
suggested I think those should be moved to another macro anyway.

Anything currently enabled by _GLIBCXX_DEBUG that changes the big-O
complexity is not touched by my patch, so wouldn't be enabled by
_GLIBCXX_ASSERTIONS. That's by design.

The existing _GLIBCXX_DEBUG Debug Mode is very important, and far more
powerful than the checks enabled by _GLIBCXX_ASSERTIONS will ever be,
but the ABI impact and the violations of the standard's complexity
guarantees mean that there are places it can't be used. For
_GLIBCXX_ASSERTIONS to be worthwhile it has to be usable in almost any
situations. In particular it should be reasonable to build entire
distros with those checks enabled.
Florian Weimer Sept. 8, 2015, 3 p.m. UTC | #9
On 09/07/2015 09:59 PM, Jonathan Wakely wrote:
> On 07/09/15 21:31 +0200, Florian Weimer wrote:
>> * Jonathan Wakely:
>>
>>> This patch adds the "debug mode lite" we've been talking about, by
>>> changing __glibcxx_assert to be activated by _GLIBCXX_ASSERTIONS
>>> instead of _GLIBCXX_DEBUG (and making the latter imply the former).
>>
>> Interesting.  Is this mode ABI-compatible with the default mode?
> 
> Yes, that's the main reason I want to make this change.

Good.  Past discussions of similar proposals indicated that these
#ifdefs are still ODR violations.

>> Should _FORTIFY_SOURCE imply _GLIBCXX_ASSERTIONS?
> 
> Yes, I think it should.
> 
> You can read my notes on these "debug mode lite" checks at
> https://gcc.gnu.org/wiki/LibstdcxxDebugMode (including "This should be
> discussed with Glibc and security teams" and I specifically had you in
> mind when I wrote that :-)

I doubt we can achieve the complexity goals in all cases.  I expect that

  for (int i = 0; i < 10000; ++i) {
    vector[i];
  }

is optimized away in default mode, but with _GLIBCXX_ASSERTIONS, it is not.

The last time I looked at this, GCC was unable to move bounds checks out
of loops.
Jonathan Wakely Sept. 8, 2015, 3:45 p.m. UTC | #10
On 08/09/15 17:00 +0200, Florian Weimer wrote:
>On 09/07/2015 09:59 PM, Jonathan Wakely wrote:
>> On 07/09/15 21:31 +0200, Florian Weimer wrote:
>>> * Jonathan Wakely:
>>>
>>>> This patch adds the "debug mode lite" we've been talking about, by
>>>> changing __glibcxx_assert to be activated by _GLIBCXX_ASSERTIONS
>>>> instead of _GLIBCXX_DEBUG (and making the latter imply the former).
>>>
>>> Interesting.  Is this mode ABI-compatible with the default mode?
>>
>> Yes, that's the main reason I want to make this change.
>
>Good.  Past discussions of similar proposals indicated that these
>#ifdefs are still ODR violations.

Well technically even using assert() in an inline function or template
is an ODR violation unless every file including the function uses the
same value of NDEBUG.

I tend to ignore that technicality :-)

>>> Should _FORTIFY_SOURCE imply _GLIBCXX_ASSERTIONS?
>>
>> Yes, I think it should.
>>
>> You can read my notes on these "debug mode lite" checks at
>> https://gcc.gnu.org/wiki/LibstdcxxDebugMode (including "This should be
>> discussed with Glibc and security teams" and I specifically had you in
>> mind when I wrote that :-)
>
>I doubt we can achieve the complexity goals in all cases.  I expect that
>
>  for (int i = 0; i < 10000; ++i) {
>    vector[i];
>  }
>
>is optimized away in default mode, but with _GLIBCXX_ASSERTIONS, it is not.
>
>The last time I looked at this, GCC was unable to move bounds checks out
>of loops.

Maybe we don't want to make _FORTIFY_SOURCE imply _GLIBCXX_ASSERTIONS
then, so they can be enabled independently. We don't have to make that
decision right away.
François Dumont Sept. 8, 2015, 7:52 p.m. UTC | #11
On 07/09/2015 20:27, Jonathan Wakely wrote:
> This patch adds the "debug mode lite" we've been talking about, by
> changing __glibcxx_assert to be activated by _GLIBCXX_ASSERTIONS
> instead of _GLIBCXX_DEBUG (and making the latter imply the former).
>
> _GLIBCXX_ASSERTIONS is already used in Parallel Mode for enabling
> optional assertions (although some of them are O(n) and so we might
> want to change them to use another macro like _GLIBCXX_DEBUG or
> _GLIBCXX_PARALLEL_ASSERTIONS instead).
>
> With the change to define __glibcxx_assert() without Debug Mode we can
> change most uses of _GLIBCXX_DEBUG_ASSERT to simply __glibcxx_assert,
> so that the assertion is done when _GLIBCXX_ASSERTIONS is defined (not
> only in Debug Mode).
>
> I haven't added any new assertions yet, this just converts the
> lightweight Debug Mode checks, but the next step will be to add
> additional assertions to the (normal mode) containers. The google
> branches contain several good examples of checks to add.
>
> François, what do you think of this approach?
>
>
Very good approach, I will start moving light checks from _GLIBCXX_DEBUG
implementation to normal one then.

Thanks

François
Jonathan Wakely Sept. 9, 2015, 1:54 p.m. UTC | #12
On 08/09/15 21:52 +0200, François Dumont wrote:
>Very good approach, I will start moving light checks from _GLIBCXX_DEBUG
>implementation to normal one then.

Great, thanks. I *think* my patch got most of the lightweight checks
already.

We could maybe include the irreflexivity checks, although it does
change the number of calls to the comparison function, which is not
allowed for some algorithms.

I'll commit my patch today.
Florian Weimer Sept. 9, 2015, 3:58 p.m. UTC | #13
On 09/08/2015 05:45 PM, Jonathan Wakely wrote:

>> I doubt we can achieve the complexity goals in all cases.  I expect that
>>
>>  for (int i = 0; i < 10000; ++i) {
>>    vector[i];
>>  }
>>
>> is optimized away in default mode, but with _GLIBCXX_ASSERTIONS, it is
>> not.
>>
>> The last time I looked at this, GCC was unable to move bounds checks out
>> of loops.
> 
> Maybe we don't want to make _FORTIFY_SOURCE imply _GLIBCXX_ASSERTIONS
> then, so they can be enabled independently. We don't have to make that
> decision right away.

I think we should try with _FORTIFY_SOURCE first.  The above case looks
rather artificial.  If there is a visible performance impact, maybe we
can get the compiler to eliminate the vector bounds checks in many cases.
Jonathan Wakely Sept. 9, 2015, 5:22 p.m. UTC | #14
On 09/09/15 14:54 +0100, Jonathan Wakely wrote:
>On 08/09/15 21:52 +0200, François Dumont wrote:
>>Very good approach, I will start moving light checks from _GLIBCXX_DEBUG
>>implementation to normal one then.
>
>Great, thanks. I *think* my patch got most of the lightweight checks
>already.
>
>We could maybe include the irreflexivity checks, although it does
>change the number of calls to the comparison function, which is not
>allowed for some algorithms.
>
>I'll commit my patch today.

I've committed the attached patch to trunk. It's the same as the
original one except for the tweaks to the docs in response to Daniel's
comment, and some whitespace changes in <valarray>.

I haven't made _FORTIFY_SOURCE enable these yet.

Tested powerpc64le-linux.

Here are some patches we should consider merging from the google
branches:

https://gcc.gnu.org/ml/gcc-patches/2015-08/msg00008.html
https://gcc.gnu.org/ml/gcc-patches/2014-01/msg00215.html
https://gcc.gnu.org/ml/gcc-patches/2013-09/msg01837.html
https://gcc.gnu.org/ml/gcc-patches/2013-05/msg01817.html
https://gcc.gnu.org/ml/gcc-patches/2013-01/msg01074.html
https://gcc.gnu.org/ml/gcc-patches/2013-01/msg01186.html

(The last two probably only work for unoptimized builds, but that may
still be useful).

Those are just ones I had in my mailbox, we should search for
__google_stl to find them all. Each should be considered individually,
I know I disliked some of the early patches when I first looked at
them years ago.

Discussion about enabling these checks automatically:
https://gcc.gnu.org/ml/gcc-paetches/2013-05/msg01386.html
https://gcc.gnu.org/ml/gcc-patches/2013-06/msg00211.html

I'd forgotten about Oleg's suggestion of _GLIBCXX_DEBUG_LEVEL_N:
https://gcc.gnu.org/ml/libstdc++/2014-06/msg00107.html
ANother option would be to support different checks depending on the
value of _GLIBCXX_ASSERTIONS=N, but I think for now we should keep it
simple and not complicate things like that. If these checks are light
enough then I think we only need two levels: cheap assertions and full
debug mode.
Martin Sebor Sept. 10, 2015, 4:30 p.m. UTC | #15
On 09/09/2015 09:58 AM, Florian Weimer wrote:
> On 09/08/2015 05:45 PM, Jonathan Wakely wrote:
>
>>> I doubt we can achieve the complexity goals in all cases.  I expect that
>>>
>>>   for (int i = 0; i < 10000; ++i) {
>>>     vector[i];
>>>   }
>>>
>>> is optimized away in default mode, but with _GLIBCXX_ASSERTIONS, it is
>>> not.
>>>
>>> The last time I looked at this, GCC was unable to move bounds checks out
>>> of loops.
>>
>> Maybe we don't want to make _FORTIFY_SOURCE imply _GLIBCXX_ASSERTIONS
>> then, so they can be enabled independently. We don't have to make that
>> decision right away.
>
> I think we should try with _FORTIFY_SOURCE first.  The above case looks
> rather artificial.  If there is a visible performance impact, maybe we
> can get the compiler to eliminate the vector bounds checks in many cases.

There is quite a bit of documentation of _FORTIFY_SOURCE that explains
its effect on user code. People who have read the documentation and
used the macro to achieve the effect might find the secondary effects
on libstdc++ surprising and unwelcome.

Martin
Florian Weimer Sept. 10, 2015, 4:38 p.m. UTC | #16
On 09/10/2015 06:30 PM, Martin Sebor wrote:
> On 09/09/2015 09:58 AM, Florian Weimer wrote:
>> On 09/08/2015 05:45 PM, Jonathan Wakely wrote:
>>
>>>> I doubt we can achieve the complexity goals in all cases.  I expect
>>>> that
>>>>
>>>>   for (int i = 0; i < 10000; ++i) {
>>>>     vector[i];
>>>>   }
>>>>
>>>> is optimized away in default mode, but with _GLIBCXX_ASSERTIONS, it is
>>>> not.
>>>>
>>>> The last time I looked at this, GCC was unable to move bounds checks
>>>> out
>>>> of loops.
>>>
>>> Maybe we don't want to make _FORTIFY_SOURCE imply _GLIBCXX_ASSERTIONS
>>> then, so they can be enabled independently. We don't have to make that
>>> decision right away.
>>
>> I think we should try with _FORTIFY_SOURCE first.  The above case looks
>> rather artificial.  If there is a visible performance impact, maybe we
>> can get the compiler to eliminate the vector bounds checks in many cases.
> 
> There is quite a bit of documentation of _FORTIFY_SOURCE that explains
> its effect on user code.

I think there are only random blog articles discussing aspects of it,
most of them slightly incorrect or outdated.

> People who have read the documentation and
> used the macro to achieve the effect might find the secondary effects
> on libstdc++ surprising and unwelcome.

I think we should ask Fedora, Debian and others if they want to enable
the new libstdc++ checks as part of their standard hardening features.
If the answer is yes, we should tack it onto _FORTIFY_SOURCE, so that
they do not have to audit all their package build processes to include
the additional preprocessor #define.

This discussion comes up every time we make *any* change to
_FORTIFY_SOURCE.  I'm not sure if it is that helpful because I haven't
seen much use of _FORTIFY_SOURCE outside distribution defaults.  If
distributions are indeed the target audience for _FORTIFY_SOURCE, and
they want the additional hardening, I don't think it's necessary to
split it off (but it certainly makes sense to have a way to turn it off
separately, if only to show that a particularly performance issue is not
caused by the new hardening feature).
Martin Sebor Sept. 10, 2015, 4:57 p.m. UTC | #17
On 09/10/2015 10:38 AM, Florian Weimer wrote:
> On 09/10/2015 06:30 PM, Martin Sebor wrote:
>> On 09/09/2015 09:58 AM, Florian Weimer wrote:
>>> On 09/08/2015 05:45 PM, Jonathan Wakely wrote:
>>>
>>>>> I doubt we can achieve the complexity goals in all cases.  I expect
>>>>> that
>>>>>
>>>>>    for (int i = 0; i < 10000; ++i) {
>>>>>      vector[i];
>>>>>    }
>>>>>
>>>>> is optimized away in default mode, but with _GLIBCXX_ASSERTIONS, it is
>>>>> not.
>>>>>
>>>>> The last time I looked at this, GCC was unable to move bounds checks
>>>>> out
>>>>> of loops.
>>>>
>>>> Maybe we don't want to make _FORTIFY_SOURCE imply _GLIBCXX_ASSERTIONS
>>>> then, so they can be enabled independently. We don't have to make that
>>>> decision right away.
>>>
>>> I think we should try with _FORTIFY_SOURCE first.  The above case looks
>>> rather artificial.  If there is a visible performance impact, maybe we
>>> can get the compiler to eliminate the vector bounds checks in many cases.
>>
>> There is quite a bit of documentation of _FORTIFY_SOURCE that explains
>> its effect on user code.
>
> I think there are only random blog articles discussing aspects of it,
> most of them slightly incorrect or outdated.

_FORTIFY_SOURCE is a GLIBC feature test macro. It's documented
in <features.h> and mentioned in some of its online manuals.
For example:

http://man7.org/linux/man-pages/man7/feature_test_macros.7.html

or here:

http://manpages.ubuntu.com/manpages/hardy/man7/feature_test_macros.7.html

Martin
Florian Weimer Sept. 14, 2015, 9:57 a.m. UTC | #18
On 09/10/2015 06:57 PM, Martin Sebor wrote:

>>> There is quite a bit of documentation of _FORTIFY_SOURCE that explains
>>> its effect on user code.
>>
>> I think there are only random blog articles discussing aspects of it,
>> most of them slightly incorrect or outdated.
> 
> _FORTIFY_SOURCE is a GLIBC feature test macro. It's documented
> in <features.h> and mentioned in some of its online manuals.
> For example:
> 
> http://man7.org/linux/man-pages/man7/feature_test_macros.7.html
> 
> or here:
> 
> http://manpages.ubuntu.com/manpages/hardy/man7/feature_test_macros.7.html

Oh, so there is an out-dated man-page as well. :-/

The fd_set checks added in glibc 2.15 are missing.  That caused some
backslash because some folks were actually abusing FD_SET and related
macros.  Nothing too severe, and in the end, we stood our ground.  I
expect the libstdc++ changes to be similar.

Again, my main argument is that the main users of _FORTIFY_SOURCE are
distributions, and they would inject whatever preprocessor macro enables
the new libstdc++ checks anyway, so saving them that work would be
preferable IMHO.
diff mbox

Patch

commit 10af11a95e3a7341f6371801e37ff140e197e634
Author: Jonathan Wakely <jwakely@redhat.com>
Date:   Mon Sep 7 14:05:23 2015 +0100

    Enable lightweight checks with _GLIBCXX_ASSERTIONS.
    
    	* doc/xml/manual/using.xml (_GLIBCXX_ASSERTIONS): Document.
    	* doc/html/manual/using_macros.html: Regenerate.
    	* include/bits/c++config: Define _GLIBCXX_ASSERTIONS when
    	_GLIBCXX_DEBUG is defined. Disable std::string extern templates when
    	(_GLIBCXX_EXTERN_TEMPLATE, __glibcxx_assert): Depend on
    	_GLIBCXX_ASSERTIONS instead of _GLIBCXX_DEBUG.
    	* include/debug/debug.h [!_GLIBCXX_DEBUG]: Define
    	__glibcxx_requires_non_empty_range and __glibcxx_requires_nonempty.
    	* include/backward/auto_ptr.h (auto_ptr::operator*,
    	auto_ptr::operator->): Replace _GLIBCXX_DEBUG_ASSERT with
    	__glibcxx_assert.
    	* include/bits/basic_string.h (basic_string::operator[],
    	basic_string::front, basic_string::back, basic_string::pop_back):
    	Likewise.
    	* include/bits/random.h
    	(uniform_int_distribution::param_type::param_type,
    	uniform_real_distribution::param_type::param_type,
    	normal_distribution::param_type::param_type,
    	gamma_distribution::param_type::param_type,
    	bernoulli_distribution::param_type::param_type,
    	binomial_distribution::param_type::param_type,
    	geometric_distribution::param_type::param_type,
    	negative_binomial_distribution::param_type::param_type,
    	poisson_distribution::param_type::param_type,
    	exponential_distribution::param_type::param_type): Likewise.
    	* include/bits/regex.h (match_results::operator[],
    	match_results::prefix, match_results::suffix): Likewise.
    	* include/bits/regex.tcc (format, regex_iterator::operator++):
    	Likewise.
    	* include/bits/regex_automaton.tcc (_StateSeq::_M_clone): Likewise.
    	* include/bits/regex_compiler.tcc (_Compiler::_Compiler,
    	_Compiler::_M_insert_character_class_matcher): Likewise.
    	* include/bits/regex_executor.tcc (_Executor::_M_dfs): Likewise.
    	* include/bits/regex_scanner.tcc (_Scanner::_M_advance,
    	_Scanner::_M_scan_normal): Likewise.
    	* include/bits/shared_ptr_base.h (__shared_ptr::_M_reset,
    	__shared_ptr::operator*): Likewise.
    	* include/bits/stl_iterator_base_funcs.h (__advance): Likewise.
    	* include/bits/unique_ptr.h (unique_ptr::operator*,
    	unique_ptr::operator[]): Likewise.
    	* include/experimental/fs_path.h (path::path(string_type, _Type),
    	path::iterator::operator++, path::iterator::operator--,
    	path::iterator::operator*): Likewise.
    	* include/experimental/string_view (basic_string_view::operator[],
    	basic_string_view::front, basic_string_view::back,
    	basic_string_view::remove_prefix): Likewise.
    	* include/ext/random (beta_distribution::param_type::param_type,
    	normal_mv_distribution::param_type::param_type,
    	rice_distribution::param_type::param_type,
    	pareto_distribution::param_type::param_type,
    	k_distribution::param_type::param_type,
    	arcsine_distribution::param_type::param_type,
    	hoyt_distribution::param_type::param_type,
    	triangular_distribution::param_type::param_type,
    	von_mises_distribution::param_type::param_type,
    	hypergeometric_distribution::param_type::param_type,
    	logistic_distribution::param_type::param_type): Likewise.
    	* include/ext/vstring.h (__versa_string::operator[]): Likewise.
    	* include/std/complex (polar): Likewise.
    	* include/std/mutex [!_GTHREAD_USE_MUTEX_TIMEDLOCK]
    	(timed_mutex::~timed_mutex, timed_mutex::unlock,
    	(recursive_timed_mutex::~timed_mutex, recursive_timed_mutex::unlock):
    	Likewise.
    	* include/std/shared_mutex [!PTHREAD_RWLOCK_INITIALIZER]
    	(__shared_mutex_pthread::__shared_mutex_pthread,
    	__shared_mutex_pthread::~__shared_mutex_pthread): Likewise.
    	(__shared_mutex_pthread::lock, __shared_mutex_pthread::try_lock,
    	__shared_mutex_pthread::unlock, __shared_mutex_pthread::lock_shared,
    	__shared_mutex_pthread::try_lock_shared): Likewise.
    	(__shared_mutex_cv::~__shared_mutex_cv, __shared_mutex_cv::unlock,
    	__shared_mutex_cv::unlock_shared): Likewise.
    	(shared_timed_mutex::try_lock_until,
    	shared_timed_mutex::try_lock_shared_until): Likewise.
    	* include/std/valarray (valarray::valarray(const _Tp*, size_t),
    	valarray::operator=, valarray::sum, valarray::min, valarray::max,
    	_DEFINE_VALARRAY_AUGMENTED_ASSIGNMENT, _DEFINE_BINARY_OPERATOR):
    	Likewise.

diff --git a/libstdc++-v3/doc/xml/manual/using.xml b/libstdc++-v3/doc/xml/manual/using.xml
index 34b4883..a6447d4 100644
--- a/libstdc++-v3/doc/xml/manual/using.xml
+++ b/libstdc++-v3/doc/xml/manual/using.xml
@@ -903,11 +903,22 @@  g++ -Winvalid-pch -I. -include stdc++.h -H -g -O2 hello.cc -o test.exe
       </para>
     </listitem></varlistentry>
 
+    <varlistentry><term><code>_GLIBCXX_ASSERTIONS</code></term>
+    <listitem>
+      <para>
+	Undefined by default. When defined, enables extra error checking in
+        the form of precondition assertions, such as bounds checking in
+        strings and null pointer checks when dereferencing smart pointers.
+      </para>
+    </listitem></varlistentry>
     <varlistentry><term><code>_GLIBCXX_DEBUG</code></term>
     <listitem>
       <para>
 	Undefined by default. When defined, compiles user code using
 	the <link linkend="manual.ext.debug_mode">debug mode</link>.
+        When defined, <code>_GLIBCXX_ASSERTIONS</code> is defined
+        automatically, so all the assertions that enables are also enabled
+        in debug mode.
       </para>
     </listitem></varlistentry>
     <varlistentry><term><code>_GLIBCXX_DEBUG_PEDANTIC</code></term>
diff --git a/libstdc++-v3/include/backward/auto_ptr.h b/libstdc++-v3/include/backward/auto_ptr.h
index a6aa2eb..c2bd1aa 100644
--- a/libstdc++-v3/include/backward/auto_ptr.h
+++ b/libstdc++-v3/include/backward/auto_ptr.h
@@ -180,7 +180,7 @@  _GLIBCXX_BEGIN_NAMESPACE_VERSION
       element_type&
       operator*() const throw() 
       {
-	_GLIBCXX_DEBUG_ASSERT(_M_ptr != 0);
+	__glibcxx_assert(_M_ptr != 0);
 	return *_M_ptr; 
       }
       
@@ -193,7 +193,7 @@  _GLIBCXX_BEGIN_NAMESPACE_VERSION
       element_type*
       operator->() const throw() 
       {
-	_GLIBCXX_DEBUG_ASSERT(_M_ptr != 0);
+	__glibcxx_assert(_M_ptr != 0);
 	return _M_ptr; 
       }
       
diff --git a/libstdc++-v3/include/bits/basic_string.h b/libstdc++-v3/include/bits/basic_string.h
index 3ba6fc8..3226617 100644
--- a/libstdc++-v3/include/bits/basic_string.h
+++ b/libstdc++-v3/include/bits/basic_string.h
@@ -830,7 +830,7 @@  _GLIBCXX_BEGIN_NAMESPACE_CXX11
       const_reference
       operator[] (size_type __pos) const _GLIBCXX_NOEXCEPT
       {
-	_GLIBCXX_DEBUG_ASSERT(__pos <= size());
+	__glibcxx_assert(__pos <= size());
 	return _M_data()[__pos];
       }
 
@@ -849,7 +849,7 @@  _GLIBCXX_BEGIN_NAMESPACE_CXX11
       {
         // Allow pos == size() both in C++98 mode, as v3 extension,
 	// and in C++11 mode.
-	_GLIBCXX_DEBUG_ASSERT(__pos <= size());
+	__glibcxx_assert(__pos <= size());
         // In pedantic mode be strict in C++98 mode.
 	_GLIBCXX_DEBUG_PEDASSERT(__cplusplus >= 201103L || __pos < size());
 	return _M_data()[__pos];
@@ -905,7 +905,7 @@  _GLIBCXX_BEGIN_NAMESPACE_CXX11
       reference
       front() noexcept
       {
-	_GLIBCXX_DEBUG_ASSERT(!empty());
+	__glibcxx_assert(!empty());
 	return operator[](0);
       }
 
@@ -916,7 +916,7 @@  _GLIBCXX_BEGIN_NAMESPACE_CXX11
       const_reference
       front() const noexcept
       {
-	_GLIBCXX_DEBUG_ASSERT(!empty());
+	__glibcxx_assert(!empty());
 	return operator[](0);
       }
 
@@ -927,7 +927,7 @@  _GLIBCXX_BEGIN_NAMESPACE_CXX11
       reference
       back() noexcept
       {
-	_GLIBCXX_DEBUG_ASSERT(!empty());
+	__glibcxx_assert(!empty());
 	return operator[](this->size() - 1);
       }
 
@@ -938,7 +938,7 @@  _GLIBCXX_BEGIN_NAMESPACE_CXX11
       const_reference
       back() const noexcept
       {
-	_GLIBCXX_DEBUG_ASSERT(!empty());
+	__glibcxx_assert(!empty());
 	return operator[](this->size() - 1);
       }
 #endif
@@ -1520,7 +1520,7 @@  _GLIBCXX_BEGIN_NAMESPACE_CXX11
       void
       pop_back() noexcept
       {
-	_GLIBCXX_DEBUG_ASSERT(!empty());
+	__glibcxx_assert(!empty());
 	_M_erase(size() - 1, 1);
       }
 #endif // C++11
@@ -3276,7 +3276,7 @@  _GLIBCXX_END_NAMESPACE_CXX11
       const_reference
       operator[] (size_type __pos) const _GLIBCXX_NOEXCEPT
       {
-	_GLIBCXX_DEBUG_ASSERT(__pos <= size());
+	__glibcxx_assert(__pos <= size());
 	return _M_data()[__pos];
       }
 
@@ -3295,7 +3295,7 @@  _GLIBCXX_END_NAMESPACE_CXX11
       {
         // Allow pos == size() both in C++98 mode, as v3 extension,
 	// and in C++11 mode.
-	_GLIBCXX_DEBUG_ASSERT(__pos <= size());
+	__glibcxx_assert(__pos <= size());
         // In pedantic mode be strict in C++98 mode.
 	_GLIBCXX_DEBUG_PEDASSERT(__cplusplus >= 201103L || __pos < size());
 	_M_leak();
@@ -3354,7 +3354,7 @@  _GLIBCXX_END_NAMESPACE_CXX11
       reference
       front()
       {
-	_GLIBCXX_DEBUG_ASSERT(!empty());
+	__glibcxx_assert(!empty());
 	return operator[](0);
       }
 
@@ -3365,7 +3365,7 @@  _GLIBCXX_END_NAMESPACE_CXX11
       const_reference
       front() const _GLIBCXX_NOEXCEPT
       {
-	_GLIBCXX_DEBUG_ASSERT(!empty());
+	__glibcxx_assert(!empty());
 	return operator[](0);
       }
 
@@ -3376,7 +3376,7 @@  _GLIBCXX_END_NAMESPACE_CXX11
       reference
       back()
       {
-	_GLIBCXX_DEBUG_ASSERT(!empty());
+	__glibcxx_assert(!empty());
 	return operator[](this->size() - 1);
       }
 
@@ -3387,7 +3387,7 @@  _GLIBCXX_END_NAMESPACE_CXX11
       const_reference
       back() const _GLIBCXX_NOEXCEPT
       {
-	_GLIBCXX_DEBUG_ASSERT(!empty());
+	__glibcxx_assert(!empty());
 	return operator[](this->size() - 1);
       }
 #endif
@@ -3877,7 +3877,7 @@  _GLIBCXX_END_NAMESPACE_CXX11
       void
       pop_back() // FIXME C++11: should be noexcept.
       {
-	_GLIBCXX_DEBUG_ASSERT(!empty());
+	__glibcxx_assert(!empty());
 	erase(size() - 1, 1);
       }
 #endif // C++11
diff --git a/libstdc++-v3/include/bits/c++config b/libstdc++-v3/include/bits/c++config
index d450f61..924f13e 100644
--- a/libstdc++-v3/include/bits/c++config
+++ b/libstdc++-v3/include/bits/c++config
@@ -138,7 +138,7 @@ 
 # endif
 #endif
 
-// Macro for extern template, ie controling template linkage via use
+// Macro for extern template, ie controlling template linkage via use
 // of extern keyword on template declaration. As documented in the g++
 // manual, it inhibits all implicit instantiations and is used
 // throughout the library to avoid multiple weak definitions for
@@ -350,8 +350,6 @@  namespace std
 	 namespace _GLIBCXX_STD_C { _GLIBCXX_BEGIN_NAMESPACE_VERSION
 # define _GLIBCXX_END_NAMESPACE_CONTAINER \
 	 _GLIBCXX_END_NAMESPACE_VERSION }
-# undef _GLIBCXX_EXTERN_TEMPLATE
-# define _GLIBCXX_EXTERN_TEMPLATE -1
 #endif
 
 #ifdef _GLIBCXX_PARALLEL
@@ -414,8 +412,19 @@  namespace std
 # define _GLIBCXX_END_NAMESPACE_LDBL_OR_CXX11 _GLIBCXX_END_NAMESPACE_LDBL
 #endif
 
+// Debug Mode implies checking assertions.
+#ifdef _GLIBCXX_DEBUG
+# define _GLIBCXX_ASSERTIONS
+#endif
+
+// Disable std::string explicit instantiation declarations in order to assert.
+#ifdef _GLIBCXX_ASSERTIONS
+# undef _GLIBCXX_EXTERN_TEMPLATE
+# define _GLIBCXX_EXTERN_TEMPLATE -1
+#endif
+
 // Assert.
-#if !defined(_GLIBCXX_DEBUG) && !defined(_GLIBCXX_PARALLEL)
+#if !defined(_GLIBCXX_ASSERTIONS) && !defined(_GLIBCXX_PARALLEL)
 # define __glibcxx_assert(_Condition)
 #else
 namespace std
diff --git a/libstdc++-v3/include/bits/random.h b/libstdc++-v3/include/bits/random.h
index 5905e60..b29df30 100644
--- a/libstdc++-v3/include/bits/random.h
+++ b/libstdc++-v3/include/bits/random.h
@@ -1680,7 +1680,7 @@  _GLIBCXX_BEGIN_NAMESPACE_VERSION
 		   _IntType __b = std::numeric_limits<_IntType>::max())
 	: _M_a(__a), _M_b(__b)
 	{
-	  _GLIBCXX_DEBUG_ASSERT(_M_a <= _M_b);
+	  __glibcxx_assert(_M_a <= _M_b);
 	}
 
 	result_type
@@ -1881,7 +1881,7 @@  _GLIBCXX_BEGIN_NAMESPACE_VERSION
 		   _RealType __b = _RealType(1))
 	: _M_a(__a), _M_b(__b)
 	{
-	  _GLIBCXX_DEBUG_ASSERT(_M_a <= _M_b);
+	  __glibcxx_assert(_M_a <= _M_b);
 	}
 
 	result_type
@@ -2099,7 +2099,7 @@  _GLIBCXX_BEGIN_NAMESPACE_VERSION
 		   _RealType __stddev = _RealType(1))
 	: _M_mean(__mean), _M_stddev(__stddev)
 	{
-	  _GLIBCXX_DEBUG_ASSERT(_M_stddev > _RealType(0));
+	  __glibcxx_assert(_M_stddev > _RealType(0));
 	}
 
 	_RealType
@@ -2517,7 +2517,7 @@  _GLIBCXX_BEGIN_NAMESPACE_VERSION
 		   _RealType __beta_val = _RealType(1))
 	: _M_alpha(__alpha_val), _M_beta(__beta_val)
 	{
-	  _GLIBCXX_DEBUG_ASSERT(_M_alpha > _RealType(0));
+	  __glibcxx_assert(_M_alpha > _RealType(0));
 	  _M_initialize();
 	}
 
@@ -3582,7 +3582,7 @@  _GLIBCXX_BEGIN_NAMESPACE_VERSION
       param_type(double __p = 0.5)
       : _M_p(__p)
       {
-	_GLIBCXX_DEBUG_ASSERT((_M_p >= 0.0) && (_M_p <= 1.0));
+	__glibcxx_assert((_M_p >= 0.0) && (_M_p <= 1.0));
       }
 
       double
@@ -3791,7 +3791,7 @@  _GLIBCXX_BEGIN_NAMESPACE_VERSION
 	param_type(_IntType __t = _IntType(1), double __p = 0.5)
 	: _M_t(__t), _M_p(__p)
 	{
-	  _GLIBCXX_DEBUG_ASSERT((_M_t >= _IntType(0))
+	  __glibcxx_assert((_M_t >= _IntType(0))
 				&& (_M_p >= 0.0)
 				&& (_M_p <= 1.0));
 	  _M_initialize();
@@ -4022,7 +4022,7 @@  _GLIBCXX_BEGIN_NAMESPACE_VERSION
 	param_type(double __p = 0.5)
 	: _M_p(__p)
 	{
-	  _GLIBCXX_DEBUG_ASSERT((_M_p > 0.0) && (_M_p < 1.0));
+	  __glibcxx_assert((_M_p > 0.0) && (_M_p < 1.0));
 	  _M_initialize();
 	}
 
@@ -4221,7 +4221,7 @@  _GLIBCXX_BEGIN_NAMESPACE_VERSION
 	param_type(_IntType __k = 1, double __p = 0.5)
 	: _M_k(__k), _M_p(__p)
 	{
-	  _GLIBCXX_DEBUG_ASSERT((_M_k > 0) && (_M_p > 0.0) && (_M_p <= 1.0));
+	  __glibcxx_assert((_M_k > 0) && (_M_p > 0.0) && (_M_p <= 1.0));
 	}
 
 	_IntType
@@ -4444,7 +4444,7 @@  _GLIBCXX_BEGIN_NAMESPACE_VERSION
 	param_type(double __mean = 1.0)
 	: _M_mean(__mean)
 	{
-	  _GLIBCXX_DEBUG_ASSERT(_M_mean > 0.0);
+	  __glibcxx_assert(_M_mean > 0.0);
 	  _M_initialize();
 	}
 
@@ -4659,7 +4659,7 @@  _GLIBCXX_BEGIN_NAMESPACE_VERSION
 	param_type(_RealType __lambda = _RealType(1))
 	: _M_lambda(__lambda)
 	{
-	  _GLIBCXX_DEBUG_ASSERT(_M_lambda > _RealType(0));
+	  __glibcxx_assert(_M_lambda > _RealType(0));
 	}
 
 	_RealType
diff --git a/libstdc++-v3/include/bits/regex.h b/libstdc++-v3/include/bits/regex.h
index a23c2c9..07fed56 100644
--- a/libstdc++-v3/include/bits/regex.h
+++ b/libstdc++-v3/include/bits/regex.h
@@ -1693,7 +1693,7 @@  _GLIBCXX_BEGIN_NAMESPACE_CXX11
       const_reference
       operator[](size_type __sub) const
       {
-	_GLIBCXX_DEBUG_ASSERT( ready() );
+	__glibcxx_assert( ready() );
 	return __sub < size()
 	       ? _Base_type::operator[](__sub)
 	       : _M_unmatched_sub();
@@ -1710,7 +1710,7 @@  _GLIBCXX_BEGIN_NAMESPACE_CXX11
       const_reference
       prefix() const
       {
-	_GLIBCXX_DEBUG_ASSERT( ready() );
+	__glibcxx_assert( ready() );
 	return !empty() ? _M_prefix() : _M_unmatched_sub();
       }
 
@@ -1725,7 +1725,7 @@  _GLIBCXX_BEGIN_NAMESPACE_CXX11
       const_reference
       suffix() const
       {
-	_GLIBCXX_DEBUG_ASSERT( ready() );
+	__glibcxx_assert( ready() );
 	return !empty() ? _M_suffix() : _M_unmatched_sub();
       }
 
diff --git a/libstdc++-v3/include/bits/regex.tcc b/libstdc++-v3/include/bits/regex.tcc
index fedc2b9..ec220fd 100644
--- a/libstdc++-v3/include/bits/regex.tcc
+++ b/libstdc++-v3/include/bits/regex.tcc
@@ -362,7 +362,7 @@  _GLIBCXX_BEGIN_NAMESPACE_VERSION
 	   const match_results<_Bi_iter, _Alloc>::char_type* __fmt_last,
 	   match_flag_type __flags) const
     {
-      _GLIBCXX_DEBUG_ASSERT( ready() );
+      __glibcxx_assert( ready() );
       regex_traits<char_type> __traits;
       typedef std::ctype<char_type> __ctype_type;
       const __ctype_type&
@@ -535,7 +535,7 @@  _GLIBCXX_BEGIN_NAMESPACE_VERSION
 				   | regex_constants::match_not_null
 				   | regex_constants::match_continuous))
 		    {
-		      _GLIBCXX_DEBUG_ASSERT(_M_match[0].matched);
+		      __glibcxx_assert(_M_match[0].matched);
 		      auto& __prefix = _M_match._M_prefix();
 		      __prefix.first = __prefix_first;
 		      __prefix.matched = __prefix.first != __prefix.second;
@@ -550,7 +550,7 @@  _GLIBCXX_BEGIN_NAMESPACE_VERSION
 	  _M_flags |= regex_constants::match_prev_avail;
 	  if (regex_search(__start, _M_end, _M_match, *_M_pregex, _M_flags))
 	    {
-	      _GLIBCXX_DEBUG_ASSERT(_M_match[0].matched);
+	      __glibcxx_assert(_M_match[0].matched);
 	      auto& __prefix = _M_match._M_prefix();
 	      __prefix.first = __prefix_first;
 	      __prefix.matched = __prefix.first != __prefix.second;
diff --git a/libstdc++-v3/include/bits/regex_automaton.tcc b/libstdc++-v3/include/bits/regex_automaton.tcc
index cecc407..f6f63a1 100644
--- a/libstdc++-v3/include/bits/regex_automaton.tcc
+++ b/libstdc++-v3/include/bits/regex_automaton.tcc
@@ -216,13 +216,13 @@  _GLIBCXX_BEGIN_NAMESPACE_VERSION
 	  auto& __ref = _M_nfa[__v];
 	  if (__ref._M_next != _S_invalid_state_id)
 	    {
-	      _GLIBCXX_DEBUG_ASSERT(__m.count(__ref._M_next) > 0);
+	      __glibcxx_assert(__m.count(__ref._M_next) > 0);
 	      __ref._M_next = __m[__ref._M_next];
 	    }
 	  if (__ref._M_has_alt())
 	    if (__ref._M_alt != _S_invalid_state_id)
 	      {
-		_GLIBCXX_DEBUG_ASSERT(__m.count(__ref._M_alt) > 0);
+		__glibcxx_assert(__m.count(__ref._M_alt) > 0);
 		__ref._M_alt = __m[__ref._M_alt];
 	      }
 	}
diff --git a/libstdc++-v3/include/bits/regex_compiler.tcc b/libstdc++-v3/include/bits/regex_compiler.tcc
index 9a62311..336a2e8 100644
--- a/libstdc++-v3/include/bits/regex_compiler.tcc
+++ b/libstdc++-v3/include/bits/regex_compiler.tcc
@@ -83,7 +83,7 @@  _GLIBCXX_BEGIN_NAMESPACE_VERSION
       if (!_M_match_token(_ScannerT::_S_token_eof))
 	__throw_regex_error(regex_constants::error_paren);
       __r._M_append(_M_pop());
-      _GLIBCXX_DEBUG_ASSERT(_M_stack.empty());
+      __glibcxx_assert(_M_stack.empty());
       __r._M_append(_M_nfa->_M_insert_subexpr_end());
       __r._M_append(_M_nfa->_M_insert_accept());
       _M_nfa->_M_eliminate_dummy();
@@ -399,7 +399,7 @@  _GLIBCXX_BEGIN_NAMESPACE_VERSION
     _Compiler<_TraitsT>::
     _M_insert_character_class_matcher()
     {
-      _GLIBCXX_DEBUG_ASSERT(_M_value.size() == 1);
+      __glibcxx_assert(_M_value.size() == 1);
       _BracketMatcher<_TraitsT, __icase, __collate> __matcher
 	(_M_ctype.is(_CtypeT::upper, _M_value[0]), _M_traits);
       __matcher._M_add_character_class(_M_value, false);
diff --git a/libstdc++-v3/include/bits/regex_executor.tcc b/libstdc++-v3/include/bits/regex_executor.tcc
index 3fd17f6..a13f0d5 100644
--- a/libstdc++-v3/include/bits/regex_executor.tcc
+++ b/libstdc++-v3/include/bits/regex_executor.tcc
@@ -305,7 +305,7 @@  _GLIBCXX_BEGIN_NAMESPACE_VERSION
 	// If matched, keep going; else just return and try another state.
 	case _S_opcode_backref:
 	  {
-	    _GLIBCXX_DEBUG_ASSERT(__dfs_mode);
+	    __glibcxx_assert(__dfs_mode);
 	    auto& __submatch = _M_cur_results[__state._M_backref_index];
 	    if (!__submatch.matched)
 	      break;
@@ -333,7 +333,7 @@  _GLIBCXX_BEGIN_NAMESPACE_VERSION
 	case _S_opcode_accept:
 	  if (__dfs_mode)
 	    {
-	      _GLIBCXX_DEBUG_ASSERT(!_M_has_sol);
+	      __glibcxx_assert(!_M_has_sol);
 	      if (__match_mode == _Match_mode::_Exact)
 		_M_has_sol = _M_current == _M_end;
 	      else
@@ -347,7 +347,7 @@  _GLIBCXX_BEGIN_NAMESPACE_VERSION
 		    _M_results = _M_cur_results;
 		  else // POSIX
 		    {
-		      _GLIBCXX_DEBUG_ASSERT(_M_states._M_get_sol_pos());
+		      __glibcxx_assert(_M_states._M_get_sol_pos());
 		      // Here's POSIX's logic: match the longest one. However
 		      // we never know which one (lhs or rhs of "|") is longer
 		      // unless we try both of them and compare the results.
@@ -400,7 +400,7 @@  _GLIBCXX_BEGIN_NAMESPACE_VERSION
 	    }
 	  break;
 	default:
-	  _GLIBCXX_DEBUG_ASSERT(false);
+	  __glibcxx_assert(false);
 	}
     }
 
diff --git a/libstdc++-v3/include/bits/regex_scanner.tcc b/libstdc++-v3/include/bits/regex_scanner.tcc
index 1555669..c158c65 100644
--- a/libstdc++-v3/include/bits/regex_scanner.tcc
+++ b/libstdc++-v3/include/bits/regex_scanner.tcc
@@ -84,7 +84,7 @@  _GLIBCXX_BEGIN_NAMESPACE_VERSION
 	_M_scan_in_brace();
       else
 	{
-	  _GLIBCXX_DEBUG_ASSERT(false);
+	  __glibcxx_assert(false);
 	}
     }
 
@@ -186,7 +186,7 @@  _GLIBCXX_BEGIN_NAMESPACE_VERSION
 		_M_token = __it->second;
 		return;
 	      }
-	  _GLIBCXX_DEBUG_ASSERT(false);
+	  __glibcxx_assert(false);
 	}
       else
 	{
diff --git a/libstdc++-v3/include/bits/shared_ptr_base.h b/libstdc++-v3/include/bits/shared_ptr_base.h
index 75f1a0d..1a96b4c 100644
--- a/libstdc++-v3/include/bits/shared_ptr_base.h
+++ b/libstdc++-v3/include/bits/shared_ptr_base.h
@@ -1029,7 +1029,7 @@  _GLIBCXX_BEGIN_NAMESPACE_VERSION
 	reset(_Tp1* __p) // _Tp1 must be complete.
 	{
 	  // Catch self-reset errors.
-	  _GLIBCXX_DEBUG_ASSERT(__p == 0 || __p != _M_ptr);
+	  __glibcxx_assert(__p == 0 || __p != _M_ptr);
 	  __shared_ptr(__p).swap(*this);
 	}
 
@@ -1047,7 +1047,7 @@  _GLIBCXX_BEGIN_NAMESPACE_VERSION
       typename std::add_lvalue_reference<_Tp>::type
       operator*() const noexcept
       {
-	_GLIBCXX_DEBUG_ASSERT(_M_ptr != 0);
+	__glibcxx_assert(_M_ptr != 0);
 	return *_M_ptr;
       }
 
diff --git a/libstdc++-v3/include/bits/stl_iterator_base_funcs.h b/libstdc++-v3/include/bits/stl_iterator_base_funcs.h
index 0f77329..5d6d028 100644
--- a/libstdc++-v3/include/bits/stl_iterator_base_funcs.h
+++ b/libstdc++-v3/include/bits/stl_iterator_base_funcs.h
@@ -145,7 +145,7 @@  _GLIBCXX_BEGIN_NAMESPACE_VERSION
     {
       // concept requirements
       __glibcxx_function_requires(_InputIteratorConcept<_InputIterator>)
-      _GLIBCXX_DEBUG_ASSERT(__n >= 0);
+      __glibcxx_assert(__n >= 0);
       while (__n--)
 	++__i;
     }
diff --git a/libstdc++-v3/include/bits/unique_ptr.h b/libstdc++-v3/include/bits/unique_ptr.h
index bb96951..6344923 100644
--- a/libstdc++-v3/include/bits/unique_ptr.h
+++ b/libstdc++-v3/include/bits/unique_ptr.h
@@ -287,7 +287,7 @@  _GLIBCXX_BEGIN_NAMESPACE_VERSION
       typename add_lvalue_reference<element_type>::type
       operator*() const
       {
-	_GLIBCXX_DEBUG_ASSERT(get() != pointer());
+	__glibcxx_assert(get() != pointer());
 	return *get();
       }
 
@@ -555,7 +555,7 @@  _GLIBCXX_BEGIN_NAMESPACE_VERSION
       typename std::add_lvalue_reference<element_type>::type
       operator[](size_t __i) const
       {
-	_GLIBCXX_DEBUG_ASSERT(get() != pointer());
+	__glibcxx_assert(get() != pointer());
 	return get()[__i];
       }
 
diff --git a/libstdc++-v3/include/debug/debug.h b/libstdc++-v3/include/debug/debug.h
index 6b52b0a..b5935fe 100644
--- a/libstdc++-v3/include/debug/debug.h
+++ b/libstdc++-v3/include/debug/debug.h
@@ -62,7 +62,6 @@  namespace __gnu_debug
 
 # define __glibcxx_requires_cond(_Cond,_Msg)
 # define __glibcxx_requires_valid_range(_First,_Last)
-# define __glibcxx_requires_non_empty_range(_First,_Last)
 # define __glibcxx_requires_sorted(_First,_Last)
 # define __glibcxx_requires_sorted_pred(_First,_Last,_Pred)
 # define __glibcxx_requires_sorted_set(_First1,_Last1,_First2)
@@ -73,7 +72,6 @@  namespace __gnu_debug
 # define __glibcxx_requires_partitioned_upper_pred(_First,_Last,_Value,_Pred)
 # define __glibcxx_requires_heap(_First,_Last)
 # define __glibcxx_requires_heap_pred(_First,_Last,_Pred)
-# define __glibcxx_requires_nonempty()
 # define __glibcxx_requires_string(_String)
 # define __glibcxx_requires_string_len(_String,_Len)
 # define __glibcxx_requires_subscript(_N)
@@ -82,6 +80,18 @@  namespace __gnu_debug
 # define __glibcxx_requires_irreflexive_pred(_First,_Last,_Pred)
 # define __glibcxx_requires_irreflexive_pred2(_First,_Last,_Pred)
 
+#ifdef _GLIBCXX_ASSERTIONS
+// Verify that [_First, _Last) forms a non-empty iterator range.
+# define __glibcxx_requires_non_empty_range(_First,_Last) \
+  __glibcxx_assert(_First != _Last)
+// Verify that the container is nonempty
+# define __glibcxx_requires_nonempty() \
+  __glibcxx_assert(! this->empty())
+#else
+# define __glibcxx_requires_non_empty_range(_First,_Last)
+# define __glibcxx_requires_nonempty()
+#endif
+
 #else
 
 # include <debug/macros.h>
diff --git a/libstdc++-v3/include/experimental/fs_path.h b/libstdc++-v3/include/experimental/fs_path.h
index d103312..5daef12 100644
--- a/libstdc++-v3/include/experimental/fs_path.h
+++ b/libstdc++-v3/include/experimental/fs_path.h
@@ -341,8 +341,8 @@  _GLIBCXX_BEGIN_NAMESPACE_CXX11
 
     path(string_type __str, _Type __type) : _M_pathname(__str), _M_type(__type)
     {
-      _GLIBCXX_DEBUG_ASSERT(!empty());
-      _GLIBCXX_DEBUG_ASSERT(_M_type != _Type::_Multi);
+      __glibcxx_assert(!empty());
+      __glibcxx_assert(_M_type != _Type::_Multi);
     }
 
     enum class _Split { _Stem, _Extension };
@@ -948,15 +948,15 @@  _GLIBCXX_BEGIN_NAMESPACE_CXX11
   inline path::iterator&
   path::iterator::operator++()
   {
-    _GLIBCXX_DEBUG_ASSERT(_M_path != nullptr);
+    __glibcxx_assert(_M_path != nullptr);
     if (_M_path->_M_type == _Type::_Multi)
       {
-	_GLIBCXX_DEBUG_ASSERT(_M_cur != _M_path->_M_cmpts.end());
+	__glibcxx_assert(_M_cur != _M_path->_M_cmpts.end());
 	++_M_cur;
       }
     else
       {
-	_GLIBCXX_DEBUG_ASSERT(!_M_at_end);
+	__glibcxx_assert(!_M_at_end);
 	_M_at_end = true;
       }
     return *this;
@@ -965,15 +965,15 @@  _GLIBCXX_BEGIN_NAMESPACE_CXX11
   inline path::iterator&
   path::iterator::operator--()
   {
-    _GLIBCXX_DEBUG_ASSERT(_M_path != nullptr);
+    __glibcxx_assert(_M_path != nullptr);
     if (_M_path->_M_type == _Type::_Multi)
       {
-	_GLIBCXX_DEBUG_ASSERT(_M_cur != _M_path->_M_cmpts.begin());
+	__glibcxx_assert(_M_cur != _M_path->_M_cmpts.begin());
 	--_M_cur;
       }
     else
       {
-	_GLIBCXX_DEBUG_ASSERT(_M_at_end);
+	__glibcxx_assert(_M_at_end);
 	_M_at_end = false;
       }
     return *this;
@@ -982,10 +982,10 @@  _GLIBCXX_BEGIN_NAMESPACE_CXX11
   inline path::iterator::reference
   path::iterator::operator*() const
   {
-    _GLIBCXX_DEBUG_ASSERT(_M_path != nullptr);
+    __glibcxx_assert(_M_path != nullptr);
     if (_M_path->_M_type == _Type::_Multi)
       {
-	_GLIBCXX_DEBUG_ASSERT(_M_cur != _M_path->_M_cmpts.end());
+	__glibcxx_assert(_M_cur != _M_path->_M_cmpts.end());
 	return *_M_cur;
       }
     return *_M_path;
diff --git a/libstdc++-v3/include/experimental/string_view b/libstdc++-v3/include/experimental/string_view
index 9c2b773..9dca400 100644
--- a/libstdc++-v3/include/experimental/string_view
+++ b/libstdc++-v3/include/experimental/string_view
@@ -180,7 +180,7 @@  _GLIBCXX_BEGIN_NAMESPACE_VERSION
       operator[](size_type __pos) const
       {
 	// TODO: Assert to restore in a way compatible with the constexpr.
-	// _GLIBCXX_DEBUG_ASSERT(__pos < this->_M_len);
+	// __glibcxx_assert(__pos < this->_M_len);
 	return *(this->_M_str + __pos);
       }
 
@@ -200,7 +200,7 @@  _GLIBCXX_BEGIN_NAMESPACE_VERSION
       front() const
       {
 	// TODO: Assert to restore in a way compatible with the constexpr.
-	// _GLIBCXX_DEBUG_ASSERT(this->_M_len > 0);
+	// __glibcxx_assert(this->_M_len > 0);
 	return *this->_M_str;
       }
 
@@ -208,7 +208,7 @@  _GLIBCXX_BEGIN_NAMESPACE_VERSION
       back() const
       {
 	// TODO: Assert to restore in a way compatible with the constexpr.
-	// _GLIBCXX_DEBUG_ASSERT(this->_M_len > 0);
+	// __glibcxx_assert(this->_M_len > 0);
 	return *(this->_M_str + this->_M_len - 1);
       }
 
@@ -221,7 +221,7 @@  _GLIBCXX_BEGIN_NAMESPACE_VERSION
       void
       remove_prefix(size_type __n)
       {
-	_GLIBCXX_DEBUG_ASSERT(this->_M_len >= __n);
+	__glibcxx_assert(this->_M_len >= __n);
 	this->_M_str += __n;
 	this->_M_len -= __n;
       }
diff --git a/libstdc++-v3/include/ext/random b/libstdc++-v3/include/ext/random
index 37bc732..be6db5d 100644
--- a/libstdc++-v3/include/ext/random
+++ b/libstdc++-v3/include/ext/random
@@ -415,8 +415,8 @@  _GLIBCXX_BEGIN_NAMESPACE_VERSION
 		   _RealType __beta_val = _RealType(1))
 	: _M_alpha(__alpha_val), _M_beta(__beta_val)
 	{
-	  _GLIBCXX_DEBUG_ASSERT(_M_alpha > _RealType(0));
-	  _GLIBCXX_DEBUG_ASSERT(_M_beta > _RealType(0));
+	  __glibcxx_assert(_M_alpha > _RealType(0));
+	  __glibcxx_assert(_M_beta > _RealType(0));
 	}
 
 	_RealType
@@ -669,8 +669,11 @@  _GLIBCXX_BEGIN_NAMESPACE_VERSION
 	  else if (__dist == _Dimen * (_Dimen + 1) / 2)
 	    _M_init_lower(__meanbegin, __meanend, __varcovbegin, __varcovend);
 	  else
-	    _M_init_diagonal(__meanbegin, __meanend,
-			     __varcovbegin, __varcovend);
+	    {
+	      __glibcxx_assert(__dist == _Dimen);
+	      _M_init_diagonal(__meanbegin, __meanend,
+			       __varcovbegin, __varcovend);
+	    }
 	}
 
 	param_type(std::initializer_list<_RealType> __mean,
@@ -688,8 +691,11 @@  _GLIBCXX_BEGIN_NAMESPACE_VERSION
 	    _M_init_lower(__mean.begin(), __mean.end(),
 			  __varcov.begin(), __varcov.end());
 	  else
-	    _M_init_diagonal(__mean.begin(), __mean.end(),
-			     __varcov.begin(), __varcov.end());
+	    {
+	      __glibcxx_assert(__varcov.size() == _Dimen);
+	      _M_init_diagonal(__mean.begin(), __mean.end(),
+			       __varcov.begin(), __varcov.end());
+	    }
 	}
 
 	std::array<_RealType, _Dimen>
@@ -945,8 +951,8 @@  _GLIBCXX_BEGIN_NAMESPACE_VERSION
 		   result_type __sigma_val = result_type(1))
 	: _M_nu(__nu_val), _M_sigma(__sigma_val)
 	{
-	  _GLIBCXX_DEBUG_ASSERT(_M_nu >= result_type(0));
-	  _GLIBCXX_DEBUG_ASSERT(_M_sigma > result_type(0));
+	  __glibcxx_assert(_M_nu >= result_type(0));
+	  __glibcxx_assert(_M_sigma > result_type(0));
 	}
 
 	result_type
@@ -1187,8 +1193,8 @@  _GLIBCXX_BEGIN_NAMESPACE_VERSION
 		   result_type __omega_val = result_type(1))
 	: _M_mu(__mu_val), _M_omega(__omega_val)
 	{
-	  _GLIBCXX_DEBUG_ASSERT(_M_mu >= result_type(0.5L));
-	  _GLIBCXX_DEBUG_ASSERT(_M_omega > result_type(0));
+	  __glibcxx_assert(_M_mu >= result_type(0.5L));
+	  __glibcxx_assert(_M_omega > result_type(0));
 	}
 
 	result_type
@@ -1420,8 +1426,8 @@  _GLIBCXX_BEGIN_NAMESPACE_VERSION
 		   result_type __mu_val = result_type(1))
 	: _M_alpha(__alpha_val), _M_mu(__mu_val)
 	{
-	  _GLIBCXX_DEBUG_ASSERT(_M_alpha > result_type(0));
-	  _GLIBCXX_DEBUG_ASSERT(_M_mu > result_type(0));
+	  __glibcxx_assert(_M_alpha > result_type(0));
+	  __glibcxx_assert(_M_mu > result_type(0));
 	}
 
 	result_type
@@ -1655,9 +1661,9 @@  _GLIBCXX_BEGIN_NAMESPACE_VERSION
 		   result_type __nu_val = result_type(1))
 	: _M_lambda(__lambda_val), _M_mu(__mu_val), _M_nu(__nu_val)
 	{
-	  _GLIBCXX_DEBUG_ASSERT(_M_lambda > result_type(0));
-	  _GLIBCXX_DEBUG_ASSERT(_M_mu > result_type(0));
-	  _GLIBCXX_DEBUG_ASSERT(_M_nu > result_type(0));
+	  __glibcxx_assert(_M_lambda > result_type(0));
+	  __glibcxx_assert(_M_mu > result_type(0));
+	  __glibcxx_assert(_M_nu > result_type(0));
 	}
 
 	result_type
@@ -1893,7 +1899,7 @@  _GLIBCXX_BEGIN_NAMESPACE_VERSION
 		   result_type __b = result_type(1))
 	: _M_a(__a), _M_b(__b)
 	{
-	  _GLIBCXX_DEBUG_ASSERT(_M_a <= _M_b);
+	  __glibcxx_assert(_M_a <= _M_b);
 	}
 
 	result_type
@@ -2129,8 +2135,8 @@  _GLIBCXX_BEGIN_NAMESPACE_VERSION
 		   result_type __omega = result_type(1))
 	: _M_q(__q), _M_omega(__omega)
 	{
-	  _GLIBCXX_DEBUG_ASSERT(_M_q > result_type(0));
-	  _GLIBCXX_DEBUG_ASSERT(_M_q < result_type(1));
+	  __glibcxx_assert(_M_q > result_type(0));
+	  __glibcxx_assert(_M_q < result_type(1));
 	}
 
 	result_type
@@ -2364,9 +2370,9 @@  _GLIBCXX_BEGIN_NAMESPACE_VERSION
 		   _RealType __c = _RealType(1))
 	: _M_a(__a), _M_b(__b), _M_c(__c)
 	{
-	  _GLIBCXX_DEBUG_ASSERT(_M_a <= _M_b);
-	  _GLIBCXX_DEBUG_ASSERT(_M_b <= _M_c);
-	  _GLIBCXX_DEBUG_ASSERT(_M_a < _M_c);
+	  __glibcxx_assert(_M_a <= _M_b);
+	  __glibcxx_assert(_M_b <= _M_c);
+	  __glibcxx_assert(_M_a < _M_c);
 
 	  _M_r_ab = (_M_b - _M_a) / (_M_c - _M_a);
 	  _M_f_ab_ac = (_M_b - _M_a) * (_M_c - _M_a);
@@ -2620,8 +2626,8 @@  _GLIBCXX_BEGIN_NAMESPACE_VERSION
 	: _M_mu(__mu), _M_kappa(__kappa)
 	{
 	  const _RealType __pi = __gnu_cxx::__math_constants<_RealType>::__pi;
-	  _GLIBCXX_DEBUG_ASSERT(_M_mu >= -__pi && _M_mu <= __pi);
-	  _GLIBCXX_DEBUG_ASSERT(_M_kappa >= _RealType(0));
+	  __glibcxx_assert(_M_mu >= -__pi && _M_mu <= __pi);
+	  __glibcxx_assert(_M_kappa >= _RealType(0));
 
 	  auto __tau = std::sqrt(_RealType(4) * _M_kappa * _M_kappa
 				 + _RealType(1)) + _RealType(1);
@@ -2857,8 +2863,8 @@  _GLIBCXX_BEGIN_NAMESPACE_VERSION
 		   result_type __n = 1)
 	: _M_N{__N}, _M_K{__K}, _M_n{__n}
 	{
-	  _GLIBCXX_DEBUG_ASSERT(_M_N >= _M_K);
-	  _GLIBCXX_DEBUG_ASSERT(_M_N >= _M_n);
+	  __glibcxx_assert(_M_N >= _M_K);
+	  __glibcxx_assert(_M_N >= _M_n);
 	}
 
 	result_type
@@ -3114,7 +3120,7 @@  _GLIBCXX_BEGIN_NAMESPACE_VERSION
 		   result_type __b = result_type(1))
 	: _M_a(__a), _M_b(__b)
 	{
-	  _GLIBCXX_DEBUG_ASSERT(_M_b > result_type(0));
+	  __glibcxx_assert(_M_b > result_type(0));
 	}
 
 	result_type
diff --git a/libstdc++-v3/include/ext/vstring.h b/libstdc++-v3/include/ext/vstring.h
index 63349dd..94af25e 100644
--- a/libstdc++-v3/include/ext/vstring.h
+++ b/libstdc++-v3/include/ext/vstring.h
@@ -536,7 +536,7 @@  _GLIBCXX_BEGIN_NAMESPACE_VERSION
       const_reference
       operator[] (size_type __pos) const _GLIBCXX_NOEXCEPT
       {
-	_GLIBCXX_DEBUG_ASSERT(__pos <= this->size());
+	__glibcxx_assert(__pos <= this->size());
 	return this->_M_data()[__pos];
       }
 
@@ -555,7 +555,7 @@  _GLIBCXX_BEGIN_NAMESPACE_VERSION
       {
         // Allow pos == size() both in C++98 mode, as v3 extension,
 	// and in C++11 mode.
-	_GLIBCXX_DEBUG_ASSERT(__pos <= this->size());
+	__glibcxx_assert(__pos <= this->size());
         // In pedantic mode be strict in C++98 mode.
 	_GLIBCXX_DEBUG_PEDASSERT(__cplusplus >= 201103L
 				 || __pos < this->size());
diff --git a/libstdc++-v3/include/std/complex b/libstdc++-v3/include/std/complex
index f2a6cf9..5ed4fd5 100644
--- a/libstdc++-v3/include/std/complex
+++ b/libstdc++-v3/include/std/complex
@@ -668,7 +668,7 @@  _GLIBCXX_BEGIN_NAMESPACE_VERSION
     inline complex<_Tp>
     polar(const _Tp& __rho, const _Tp& __theta)
     {
-      _GLIBCXX_DEBUG_ASSERT( __rho >= 0 );
+      __glibcxx_assert( __rho >= 0 );
       return complex<_Tp>(__rho * cos(__theta), __rho * sin(__theta));
     }
 
diff --git a/libstdc++-v3/include/std/mutex b/libstdc++-v3/include/std/mutex
index 38950b6..5e5ced1 100644
--- a/libstdc++-v3/include/std/mutex
+++ b/libstdc++-v3/include/std/mutex
@@ -302,7 +302,7 @@  _GLIBCXX_BEGIN_NAMESPACE_VERSION
   public:
 
     timed_mutex() = default;
-    ~timed_mutex() { _GLIBCXX_DEBUG_ASSERT( !_M_locked ); }
+    ~timed_mutex() { __glibcxx_assert( !_M_locked ); }
 
     timed_mutex(const timed_mutex&) = delete;
     timed_mutex& operator=(const timed_mutex&) = delete;
@@ -351,7 +351,7 @@  _GLIBCXX_BEGIN_NAMESPACE_VERSION
     unlock()
     {
       lock_guard<mutex> __lk(_M_mut);
-      _GLIBCXX_DEBUG_ASSERT( _M_locked );
+      __glibcxx_assert( _M_locked );
       _M_locked = false;
       _M_cv.notify_one();
     }
@@ -380,7 +380,7 @@  _GLIBCXX_BEGIN_NAMESPACE_VERSION
   public:
 
     recursive_timed_mutex() = default;
-    ~recursive_timed_mutex() { _GLIBCXX_DEBUG_ASSERT( _M_count == 0 ); }
+    ~recursive_timed_mutex() { __glibcxx_assert( _M_count == 0 ); }
 
     recursive_timed_mutex(const recursive_timed_mutex&) = delete;
     recursive_timed_mutex& operator=(const recursive_timed_mutex&) = delete;
@@ -449,8 +449,8 @@  _GLIBCXX_BEGIN_NAMESPACE_VERSION
     unlock()
     {
       lock_guard<mutex> __lk(_M_mut);
-      _GLIBCXX_DEBUG_ASSERT( _M_owner == this_thread::get_id() );
-      _GLIBCXX_DEBUG_ASSERT( _M_count > 0 );
+      __glibcxx_assert( _M_owner == this_thread::get_id() );
+      __glibcxx_assert( _M_count > 0 );
       if (--_M_count == 0)
 	{
 	  _M_owner = {};
diff --git a/libstdc++-v3/include/std/shared_mutex b/libstdc++-v3/include/std/shared_mutex
index 69107cc..5ae492d 100644
--- a/libstdc++-v3/include/std/shared_mutex
+++ b/libstdc++-v3/include/std/shared_mutex
@@ -85,14 +85,14 @@  _GLIBCXX_BEGIN_NAMESPACE_VERSION
       else if (__ret == EPERM)
 	__throw_system_error(int(errc::operation_not_permitted));
       // Errors not handled: EBUSY, EINVAL
-      _GLIBCXX_DEBUG_ASSERT(__ret == 0);
+      __glibcxx_assert(__ret == 0);
     }
 
     ~__shared_mutex_pthread()
     {
       int __ret __attribute((__unused__)) = pthread_rwlock_destroy(&_M_rwlock);
       // Errors not handled: EBUSY, EINVAL
-      _GLIBCXX_DEBUG_ASSERT(__ret == 0);
+      __glibcxx_assert(__ret == 0);
     }
 #endif
 
@@ -106,7 +106,7 @@  _GLIBCXX_BEGIN_NAMESPACE_VERSION
       if (__ret == EDEADLK)
 	__throw_system_error(int(errc::resource_deadlock_would_occur));
       // Errors not handled: EINVAL
-      _GLIBCXX_DEBUG_ASSERT(__ret == 0);
+      __glibcxx_assert(__ret == 0);
     }
 
     bool
@@ -115,7 +115,7 @@  _GLIBCXX_BEGIN_NAMESPACE_VERSION
       int __ret = pthread_rwlock_trywrlock(&_M_rwlock);
       if (__ret == EBUSY) return false;
       // Errors not handled: EINVAL
-      _GLIBCXX_DEBUG_ASSERT(__ret == 0);
+      __glibcxx_assert(__ret == 0);
       return true;
     }
 
@@ -124,7 +124,7 @@  _GLIBCXX_BEGIN_NAMESPACE_VERSION
     {
       int __ret __attribute((__unused__)) = pthread_rwlock_unlock(&_M_rwlock);
       // Errors not handled: EPERM, EBUSY, EINVAL
-      _GLIBCXX_DEBUG_ASSERT(__ret == 0);
+      __glibcxx_assert(__ret == 0);
     }
 
     // Shared ownership
@@ -143,7 +143,7 @@  _GLIBCXX_BEGIN_NAMESPACE_VERSION
       if (__ret == EDEADLK)
 	__throw_system_error(int(errc::resource_deadlock_would_occur));
       // Errors not handled: EINVAL
-      _GLIBCXX_DEBUG_ASSERT(__ret == 0);
+      __glibcxx_assert(__ret == 0);
     }
 
     bool
@@ -155,7 +155,7 @@  _GLIBCXX_BEGIN_NAMESPACE_VERSION
       // an exception.
       if (__ret == EBUSY || __ret == EAGAIN) return false;
       // Errors not handled: EINVAL
-      _GLIBCXX_DEBUG_ASSERT(__ret == 0);
+      __glibcxx_assert(__ret == 0);
       return true;
     }
 
@@ -224,7 +224,7 @@  _GLIBCXX_BEGIN_NAMESPACE_VERSION
 
     ~__shared_mutex_cv()
     {
-      _GLIBCXX_DEBUG_ASSERT( _M_state == 0 );
+      __glibcxx_assert( _M_state == 0 );
     }
 
     __shared_mutex_cv(const __shared_mutex_cv&) = delete;
@@ -259,7 +259,7 @@  _GLIBCXX_BEGIN_NAMESPACE_VERSION
     unlock()
     {
       lock_guard<mutex> __lk(_M_mut);
-      _GLIBCXX_DEBUG_ASSERT( _M_write_entered() );
+      __glibcxx_assert( _M_write_entered() );
       _M_state = 0;
       // call notify_all() while mutex is held so that another thread can't
       // lock and unlock the mutex then destroy *this before we make the call.
@@ -294,7 +294,7 @@  _GLIBCXX_BEGIN_NAMESPACE_VERSION
     unlock_shared()
     {
       lock_guard<mutex> __lk(_M_mut);
-      _GLIBCXX_DEBUG_ASSERT( _M_readers() > 0 );
+      __glibcxx_assert( _M_readers() > 0 );
       auto __prev = _M_state--;
       if (_M_write_entered())
 	{
@@ -422,7 +422,7 @@  _GLIBCXX_BEGIN_NAMESPACE_VERSION
 	if (__ret == ETIMEDOUT || __ret == EDEADLK)
 	  return false;
 	// Errors not handled: EINVAL
-	_GLIBCXX_DEBUG_ASSERT(__ret == 0);
+	__glibcxx_assert(__ret == 0);
 	return true;
       }
 
@@ -474,7 +474,7 @@  _GLIBCXX_BEGIN_NAMESPACE_VERSION
 	if (__ret == ETIMEDOUT)
 	  return false;
 	// Errors not handled: EINVAL
-	_GLIBCXX_DEBUG_ASSERT(__ret == 0);
+	__glibcxx_assert(__ret == 0);
 	return true;
       }
 
diff --git a/libstdc++-v3/include/std/valarray b/libstdc++-v3/include/std/valarray
index 8275249..f566e0a 100644
--- a/libstdc++-v3/include/std/valarray
+++ b/libstdc++-v3/include/std/valarray
@@ -621,7 +621,7 @@  _GLIBCXX_BEGIN_NAMESPACE_VERSION
     valarray<_Tp>::valarray(const _Tp* __restrict__ __p, size_t __n)
     : _M_size(__n), _M_data(__valarray_get_storage<_Tp>(__n))
     { 
-      _GLIBCXX_DEBUG_ASSERT(__p != 0 || __n == 0);
+      __glibcxx_assert(__p != 0 || __n == 0);
       std::__valarray_copy_construct(__p, __p + __n, _M_data); 
     }
 
@@ -779,7 +779,7 @@  _GLIBCXX_BEGIN_NAMESPACE_VERSION
     inline valarray<_Tp>&
     valarray<_Tp>::operator=(const slice_array<_Tp>& __sa)
     {
-      _GLIBCXX_DEBUG_ASSERT(_M_size == __sa._M_sz);
+      __glibcxx_assert(_M_size == __sa._M_sz);
       std::__valarray_copy(__sa._M_array, __sa._M_sz,
 			   __sa._M_stride, _Array<_Tp>(_M_data));
       return *this;
@@ -789,7 +789,7 @@  _GLIBCXX_BEGIN_NAMESPACE_VERSION
     inline valarray<_Tp>&
     valarray<_Tp>::operator=(const gslice_array<_Tp>& __ga)
     {
-      _GLIBCXX_DEBUG_ASSERT(_M_size == __ga._M_index.size());
+      __glibcxx_assert(_M_size == __ga._M_index.size());
       std::__valarray_copy(__ga._M_array, _Array<size_t>(__ga._M_index),
 			   _Array<_Tp>(_M_data), _M_size);
       return *this;
@@ -799,7 +799,7 @@  _GLIBCXX_BEGIN_NAMESPACE_VERSION
     inline valarray<_Tp>&
     valarray<_Tp>::operator=(const mask_array<_Tp>& __ma)
     {
-      _GLIBCXX_DEBUG_ASSERT(_M_size == __ma._M_sz);
+      __glibcxx_assert(_M_size == __ma._M_sz);
       std::__valarray_copy(__ma._M_array, __ma._M_mask,
 			   _Array<_Tp>(_M_data), _M_size);
       return *this;
@@ -809,7 +809,7 @@  _GLIBCXX_BEGIN_NAMESPACE_VERSION
     inline valarray<_Tp>&
     valarray<_Tp>::operator=(const indirect_array<_Tp>& __ia)
     {
-      _GLIBCXX_DEBUG_ASSERT(_M_size == __ia._M_sz);
+      __glibcxx_assert(_M_size == __ia._M_sz);
       std::__valarray_copy(__ia._M_array, __ia._M_index,
 			   _Array<_Tp>(_M_data), _M_size);
       return *this;
@@ -925,7 +925,7 @@  _GLIBCXX_BEGIN_NAMESPACE_VERSION
     inline _Tp
     valarray<_Tp>::sum() const
     {
-      _GLIBCXX_DEBUG_ASSERT(_M_size > 0);
+      __glibcxx_assert(_M_size > 0);
       return std::__valarray_sum(_M_data, _M_data + _M_size);
     }
 
@@ -1032,7 +1032,7 @@  _GLIBCXX_BEGIN_NAMESPACE_VERSION
     inline _Tp
     valarray<_Tp>::min() const
     {
-      _GLIBCXX_DEBUG_ASSERT(_M_size > 0);
+      __glibcxx_assert(_M_size > 0);
       return *std::min_element(_M_data, _M_data + _M_size);
     }
 
@@ -1040,7 +1040,7 @@  _GLIBCXX_BEGIN_NAMESPACE_VERSION
     inline _Tp
     valarray<_Tp>::max() const
     {
-      _GLIBCXX_DEBUG_ASSERT(_M_size > 0);
+      __glibcxx_assert(_M_size > 0);
       return *std::max_element(_M_data, _M_data + _M_size);
     }
   
@@ -1090,7 +1090,7 @@  _GLIBCXX_BEGIN_NAMESPACE_VERSION
     inline valarray<_Tp>&						\
     valarray<_Tp>::operator _Op##=(const valarray<_Tp> &__v)		\
     {									\
-      _GLIBCXX_DEBUG_ASSERT(_M_size == __v._M_size);                    \
+      __glibcxx_assert(_M_size == __v._M_size);                    \
       _Array_augmented_##_Name(_Array<_Tp>(_M_data), _M_size, 		\
 			       _Array<_Tp>(__v._M_data));		\
       return *this;							\
@@ -1138,7 +1138,7 @@  _DEFINE_VALARRAY_EXPR_AUGMENTED_ASSIGNMENT(>>, __shift_right)
                  typename __fun<_Name, _Tp>::result_type>               \
     operator _Op(const valarray<_Tp>& __v, const valarray<_Tp>& __w)	\
     {									\
-      _GLIBCXX_DEBUG_ASSERT(__v.size() == __w.size());                  \
+      __glibcxx_assert(__v.size() == __w.size());                  \
       typedef _BinClos<_Name, _ValArray, _ValArray, _Tp, _Tp> _Closure; \
       typedef typename __fun<_Name, _Tp>::result_type _Rt;              \
       return _Expr<_Closure, _Rt>(_Closure(__v, __w));                  \