[2/4] MSP430: Disable exception handling by default for C++
diff mbox series

Message ID 20191107213727.731656fe@jozef-kubuntu
State New
Headers show
Series
  • Tweaks to default configuration to reduce code size
Related show

Commit Message

Jozef Lawrynowicz Nov. 7, 2019, 9:37 p.m. UTC
The code size bloat added by building C++ programs using libraries containing
support for exceptions is significant. When using simple constructs such as
static variables, sometimes many kB from the libraries are unnecessarily
pulled in.

So this patch disable exceptions by default for MSP430 when compiling for C++,
by implicitly passing -fno-exceptions unless -fexceptions is passed.

Multilibs have been added for the -fexceptions configuration.
Since building double the multilibs does significantly increase build time,
the patch also adds a configure option --disable-exceptions. This disables the
fexceptions mulitlibs from being built.

There was a lot of fallout from the G++ testsuite caused by disabling exceptions
by default.

I've mitigated some of it by adding dg-prune strings which mark a test as
unsupported if the compiler reports exception handling is disabled. This doesn't
work for some execution tests or tests for warnings/errors/messages.

There's some further mitigation achieved by new functionality which
will pass -fexceptions as a default flag if exceptions are supported but not
enabled by default.
However, for tests with dg-options directives, this gets ignored. So
for these tests (of which there weren't *too* many, I've added -fexceptions to
the dg-options directives in the tests.

As a result of all the above there aren't any DejaGNU regressions.

Comments

Oleg Endo Nov. 8, 2019, 12:07 a.m. UTC | #1
On Thu, 2019-11-07 at 21:37 +0000, Jozef Lawrynowicz wrote:
> The code size bloat added by building C++ programs using libraries containing
> support for exceptions is significant. When using simple constructs such as
> static variables, sometimes many kB from the libraries are unnecessarily
> pulled in.
> 
> So this patch disable exceptions by default for MSP430 when compiling for C++,
> by implicitly passing -fno-exceptions unless -fexceptions is passed.

It is extremely annoying when GCC's default standard behavior differs
across different targets.  And as a consequence, you have to add a load
of workarounds and disable other things, like fiddling with the
testsuite.  It's the same thing as setting "double = float" to get more
"speed" by default.

I would strongly advice against making such non-standard behaviors the
default in the vanilla compiler.  C++ normally has exceptions enabled. 
If a user doesn't want them and is willing to deal with it all the
consequences, then we already have a mechanism to do that:
 --fno-exceptions

Perhaps it's generally more useful to add a global configure option for
GCC to disable exception handling by default.  Then you can provide a
turn-key toolchain to your customers as well -- just add an option to
the configure line.

Cheers,
Oleg
Jozef Lawrynowicz Nov. 8, 2019, 1:26 p.m. UTC | #2
On Fri, 08 Nov 2019 09:07:39 +0900
Oleg Endo <oleg.endo@t-online.de> wrote:

> On Thu, 2019-11-07 at 21:37 +0000, Jozef Lawrynowicz wrote:
> > The code size bloat added by building C++ programs using libraries containing
> > support for exceptions is significant. When using simple constructs such as
> > static variables, sometimes many kB from the libraries are unnecessarily
> > pulled in.
> > 
> > So this patch disable exceptions by default for MSP430 when compiling for C++,
> > by implicitly passing -fno-exceptions unless -fexceptions is passed.  
> 
> It is extremely annoying when GCC's default standard behavior differs
> across different targets.  And as a consequence, you have to add a load
> of workarounds and disable other things, like fiddling with the
> testsuite.  It's the same thing as setting "double = float" to get more
> "speed" by default.
> 
> I would strongly advice against making such non-standard behaviors the
> default in the vanilla compiler.  C++ normally has exceptions enabled. 
> If a user doesn't want them and is willing to deal with it all the
> consequences, then we already have a mechanism to do that:
>  --fno-exceptions
> 
> Perhaps it's generally more useful to add a global configure option for
> GCC to disable exception handling by default.  Then you can provide a
> turn-key toolchain to your customers as well -- just add an option to
> the configure line.
> 
> Cheers,
> Oleg
> 

Fair point, I probably should have realised whilst implementing all the
testsuite workarounds that this wasn't the best choice for upstream GCC and
integrating nicely with the testsuite.

So I've regtested and attached a revised patch to instead build -fno-exceptions
multilibs, so the reduced code size can still be achieved by passing with
-fno-exceptions.

And the --disable-no-exceptions multilib option is added to reduce build time
for developers.

Thanks for providing your input,
Jozef
Richard Sandiford Nov. 12, 2019, 9:08 p.m. UTC | #3
Jozef Lawrynowicz <jozef.l@mittosystems.com> writes:
> diff --git a/gcc/testsuite/lib/gcc-dg.exp b/gcc/testsuite/lib/gcc-dg.exp
> index 1df645e283c..1ce449cb935 100644
> --- a/gcc/testsuite/lib/gcc-dg.exp
> +++ b/gcc/testsuite/lib/gcc-dg.exp
> @@ -417,6 +417,16 @@ proc gcc-dg-prune { system text } {
>  	return "::unsupported::large return values"
>      }
>  
> +    # If exceptions are disabled, mark tests expecting exceptions to be enabled
> +    # as unsupported.
> +    if [regexp "(^|\n)\[^\n\]*: error: exception handling disabled" $text] {
> +	return "::unsupported::exception handling disabled"
> +    }

This is probably safe, but...

> +
> +    if [regexp "(^|\n)\[^\n\]*: error: #error .__cpp_exceptions." $text] {
> +	return "::unsupported::exception handling disabled"
> +    }

...it looks like this would disable g++.dg/cpp1y/feat-neg.C for all
targets.  I assume this was motivated by g++.dg/cpp2a/feat-cxx2a.C,
but the kind of effective-target tests you had in the original patch
are probably better there.  It might then be more robust to test that
[check_effective_target_...] for the "exception handling disabled" case
above as well, so that other targets aren't affected accidentally.

It'd be good to test a target/multilib that has exceptions enabled by
default to make sure there's no change in the number of unsupported
tests (rather than just no new fails).

Thanks,
Richard
Jozef Lawrynowicz Nov. 27, 2019, 1:17 p.m. UTC | #4
On Tue, 12 Nov 2019 21:08:48 +0000
Richard Sandiford <richard.sandiford@arm.com> wrote:

> Jozef Lawrynowicz <jozef.l@mittosystems.com> writes:
> > diff --git a/gcc/testsuite/lib/gcc-dg.exp b/gcc/testsuite/lib/gcc-dg.exp
> > index 1df645e283c..1ce449cb935 100644
> > --- a/gcc/testsuite/lib/gcc-dg.exp
> > +++ b/gcc/testsuite/lib/gcc-dg.exp
> > @@ -417,6 +417,16 @@ proc gcc-dg-prune { system text } {
> >  	return "::unsupported::large return values"
> >      }
> >  
> > +    # If exceptions are disabled, mark tests expecting exceptions to be enabled
> > +    # as unsupported.
> > +    if [regexp "(^|\n)\[^\n\]*: error: exception handling disabled" $text] {
> > +	return "::unsupported::exception handling disabled"
> > +    }  
> 
> This is probably safe, but...
> 
> > +
> > +    if [regexp "(^|\n)\[^\n\]*: error: #error .__cpp_exceptions." $text] {
> > +	return "::unsupported::exception handling disabled"
> > +    }  
> 
> ...it looks like this would disable g++.dg/cpp1y/feat-neg.C for all
> targets.  I assume this was motivated by g++.dg/cpp2a/feat-cxx2a.C,
> but the kind of effective-target tests you had in the original patch
> are probably better there.  It might then be more robust to test that
> [check_effective_target_...] for the "exception handling disabled" case
> above as well, so that other targets aren't affected accidentally.
> 
> It'd be good to test a target/multilib that has exceptions enabled by
> default to make sure there's no change in the number of unsupported
> tests (rather than just no new fails).

Apologies for the delayed response.

The messages caught in gcc-dg-prune will only be pruned if they haven't already
been caught by dg-warning/error/etc. So basically only if the regex being tested
would trigger an "excess errors" failure.

As a result, there was no change in passes/fails/unsupported on
x86_64-pc-linux-gnu.

Checking if exceptions are actually disabled before enabling those prunes is a
nice suggestion though, I'll add it to the revised patch.

Thanks,
Jozef

> 
> Thanks,
> Richard

Patch
diff mbox series

From 7844e05172d07443167c3e852cf0b695f043c0eb Mon Sep 17 00:00:00 2001
From: Jozef Lawrynowicz <jozef.l@mittosystems.com>
Date: Tue, 29 Oct 2019 15:32:07 +0000
Subject: [PATCH 2/4] MSP430: Disable exception handling by default for C++

ChangeLog:

2019-11-07  Jozef Lawrynowicz  <jozef.l@mittosystems.com>

	* config-ml.in: Support --disable-exceptions configure flag.

gcc/ChangeLog:

2019-11-07  Jozef Lawrynowicz  <jozef.l@mittosystems.com>

	* config/msp430/msp430.h (STARTFILE_SPEC) [!fexceptions]: Use
	crtbegin_no_eh.o.
	(ENDFILE_SPEC) [!fexceptions]: Use crtend_no_eh.o.
	(CC1PLUS_SPEC): Define.
	* config/msp430/t-msp430: Add -fexceptions multilibs.
	* doc/install.texi: Document --disable-exceptions configure option.
	* doc/invoke.texi: Document that exceptions are disabled by default for
	C++ for msp430-elf.

gcc/testsuite/ChangeLog:

2019-11-07  Jozef Lawrynowicz  <jozef.l@mittosystems.com>

	* g++.dg/cpp1y/sized-dealloc2.C: Add -fexceptions to dg-options.
	* g++.dg/cpp2a/explicit1.C: Likewise.
	* g++.dg/cpp2a/explicit2.C: Likewise.
	* g++.dg/cpp2a/explicit5.C: Likewise.
	* g++.dg/eh/array1.C: Likewise.
	* g++.dg/eh/spec11.C: Likewise.
	* g++.dg/eh/spec6.C: Likewise.
	* g++.dg/ext/vla4.C: Likewise.
	* g++.dg/ipa/pr64612.C: Likewise.
	* g++.dg/other/error32.C: Likewise.
	* g++.dg/torture/pr34850.C: Likewise.
	* g++.dg/tree-ssa/ivopts-3.C: Likewise.
	* g++.dg/tree-ssa/pr33615.C: Likewise.
	* g++.dg/warn/Wcatch-value-1.C: Likewise.
	* g++.dg/warn/Wcatch-value-2.C: Likewise.
	* g++.dg/warn/Wcatch-value-3.C: Likewise.
	* g++.dg/warn/Wstringop-truncation-2.C: Likewise.
	* g++.dg/warn/Wterminate1.C: Likewise.
	* g++.dg/warn/pr83054.C: Likewise.
	* g++.old-deja/g++.other/cond5.C: Likewise.
	* g++.dg/dg.exp: Pass -fexceptions as a default flag if exceptions
	aren't enabled by default.
	* g++.dg/torture/dg-torture.exp: Likewise.
	* g++.old-deja/old-deja.exp:
	* lib/gcc-dg.exp: Add dg-prune messages for when exception handling is
	disabled.
	* lib/target-supports.exp (check_effective_target_exceptions): Check if
	GCC was configured with --disable-exceptions.
	(check_effective_target_exceptions_enabled_by_default): New.

libgcc/ChangeLog:

2019-11-07  Jozef Lawrynowicz  <jozef.l@mittosystems.com>

	* config.host: Add crt{begin,end}_no_eh.o to "extra_parts".
	* config/msp430/t-msp430: Add rules to build crt{begin,end}_no_eh.o.
---
 config-ml.in                                  | 13 ++++++++++
 gcc/config/msp430/msp430.h                    | 11 +++++++--
 gcc/config/msp430/t-msp430                    |  9 +++----
 gcc/doc/install.texi                          |  3 +++
 gcc/doc/invoke.texi                           |  6 +++--
 gcc/testsuite/g++.dg/cpp1y/sized-dealloc2.C   |  2 +-
 gcc/testsuite/g++.dg/cpp2a/explicit1.C        |  2 +-
 gcc/testsuite/g++.dg/cpp2a/explicit2.C        |  2 +-
 gcc/testsuite/g++.dg/cpp2a/explicit5.C        |  2 +-
 gcc/testsuite/g++.dg/dg.exp                   |  9 ++++++-
 gcc/testsuite/g++.dg/eh/array1.C              |  2 +-
 gcc/testsuite/g++.dg/eh/spec11.C              |  2 +-
 gcc/testsuite/g++.dg/eh/spec6.C               |  2 +-
 gcc/testsuite/g++.dg/ext/vla4.C               |  2 +-
 gcc/testsuite/g++.dg/ipa/pr64612.C            |  2 +-
 gcc/testsuite/g++.dg/other/error32.C          |  2 +-
 gcc/testsuite/g++.dg/torture/dg-torture.exp   |  9 ++++++-
 gcc/testsuite/g++.dg/torture/pr34850.C        |  2 +-
 gcc/testsuite/g++.dg/tree-ssa/ivopts-3.C      |  2 +-
 gcc/testsuite/g++.dg/tree-ssa/pr33615.C       |  2 +-
 gcc/testsuite/g++.dg/warn/Wcatch-value-1.C    |  2 +-
 gcc/testsuite/g++.dg/warn/Wcatch-value-2.C    |  2 +-
 gcc/testsuite/g++.dg/warn/Wcatch-value-3.C    |  2 +-
 .../g++.dg/warn/Wstringop-truncation-2.C      |  2 +-
 gcc/testsuite/g++.dg/warn/Wterminate1.C       |  2 +-
 gcc/testsuite/g++.dg/warn/pr83054.C           |  2 +-
 gcc/testsuite/g++.old-deja/g++.other/cond5.C  |  2 +-
 gcc/testsuite/g++.old-deja/old-deja.exp       |  9 ++++++-
 gcc/testsuite/lib/gcc-dg.exp                  | 10 ++++++++
 gcc/testsuite/lib/target-supports.exp         | 24 ++++++++++++++++---
 libgcc/config.host                            |  3 ++-
 libgcc/config/msp430/t-msp430                 |  6 +++++
 32 files changed, 117 insertions(+), 35 deletions(-)

diff --git a/config-ml.in b/config-ml.in
index 3e37f875c88..0fccf41f7cd 100644
--- a/config-ml.in
+++ b/config-ml.in
@@ -383,6 +383,19 @@  mips*-*-*)
 	  done
 	fi
 	;;
+msp430-*-*)
+	if [ x$enable_exceptions = xno ]
+	then
+	  old_multidirs="${multidirs}"
+	  multidirs=""
+	  for x in ${old_multidirs}; do
+	    case "$x" in
+	      *exceptions* ) : ;;
+	      *) multidirs="${multidirs} ${x}" ;;
+	    esac
+	  done
+	fi
+	;;
 powerpc*-*-* | rs6000*-*-*)
 	if [ x$enable_aix64 = xno ]
 	then
diff --git a/gcc/config/msp430/msp430.h b/gcc/config/msp430/msp430.h
index 73afe2e2d16..90ceec0e947 100644
--- a/gcc/config/msp430/msp430.h
+++ b/gcc/config/msp430/msp430.h
@@ -46,11 +46,13 @@  extern bool msp430x;
 
 #undef  STARTFILE_SPEC
 #define STARTFILE_SPEC "%{pg:gcrt0.o%s}" \
-  "%{!pg:%{minrt:crt0-minrt.o%s}%{!minrt:crt0.o%s}} %{!minrt:crtbegin.o%s}"
+  "%{!pg:%{minrt:crt0-minrt.o%s}%{!minrt:crt0.o%s}} " \
+  "%{!minrt:%{fexceptions:crtbegin.o%s}%{!fexceptions:crtbegin_no_eh.o%s}}"
 
 /* -lgcc is included because crtend.o needs __mspabi_func_epilog_1.  */
 #undef  ENDFILE_SPEC
-#define ENDFILE_SPEC "%{!minrt:crtend.o%s} " \
+#define ENDFILE_SPEC \
+  "%{!minrt:%{fexceptions:crtend.o%s}%{!fexceptions:crtend_no_eh.o%s}} "  \
   "%{minrt:%:if-exists(crtn-minrt.o%s)}%{!minrt:%:if-exists(crtn.o%s)} -lgcc"
 
 #define ASM_SPEC "-mP " /* Enable polymorphic instructions.  */ \
@@ -104,6 +106,11 @@  extern const char *msp430_propagate_region_opt (int, const char **);
   { "msp430_check_path_for_devices", msp430_check_path_for_devices }, \
   { "msp430_propagate_region_opt", msp430_propagate_region_opt },
 
+#undef  CC1PLUS_SPEC
+#define CC1PLUS_SPEC	\
+  "%(cc1) "		\
+  "%{!fexceptions:-fno-exceptions} "
+
 /* Specify the libraries to include on the linker command line.
 
    Selecting the hardware multiply library to use is quite complex.
diff --git a/gcc/config/msp430/t-msp430 b/gcc/config/msp430/t-msp430
index f8ba7751123..2c27f94d19e 100644
--- a/gcc/config/msp430/t-msp430
+++ b/gcc/config/msp430/t-msp430
@@ -28,8 +28,8 @@  msp430-devices.o: $(srcdir)/config/msp430/msp430-devices.c \
 
 # Enable multilibs:
 
-MULTILIB_OPTIONS    = mcpu=msp430 mlarge  mdata-region=none
-MULTILIB_DIRNAMES   = 430	   large  full-memory-range
+MULTILIB_OPTIONS    = mcpu=msp430 mlarge  mdata-region=none fexceptions
+MULTILIB_DIRNAMES   = 430	   large  full-memory-range exceptions
 
 # Match -mcpu=430
 MULTILIB_MATCHES    = mcpu?msp430=mcpu?430
@@ -41,9 +41,10 @@  MULTILIB_MATCHES   += mdata-region?none=mdata-region?either
 # hard-coded data here, because DRIVER_SELF_SPECS will place the correct
 # -mcpu option for a given mcu onto the command line.
 
-MULTILIB_REQUIRED = mcpu=msp430
-MULTILIB_REQUIRED += mlarge
+MULTILIB_REQUIRED =		 mcpu=msp430		 mlarge
+MULTILIB_REQUIRED += fexceptions mcpu=msp430/fexceptions mlarge/fexceptions
 MULTILIB_REQUIRED += mlarge/mdata-region=none
+MULTILIB_REQUIRED += mlarge/mdata-region=none/fexceptions
 
 
 MULTILIB_EXTRA_OPTS =
diff --git a/gcc/doc/install.texi b/gcc/doc/install.texi
index 563de705881..fcdbc948b7e 100644
--- a/gcc/doc/install.texi
+++ b/gcc/doc/install.texi
@@ -1087,6 +1087,9 @@  softfloat, m68881, m68000, m68020.
 @item mips*-*-*
 single-float, biendian, softfloat.
 
+@item msp430-*-*
+exceptions
+
 @item powerpc*-*-*, rs6000*-*-*
 aix64, pthread, softfloat, powercpu, powerpccpu, powerpcos, biendian,
 sysv, aix.
diff --git a/gcc/doc/invoke.texi b/gcc/doc/invoke.texi
index 1407d019d14..6829b949b4b 100644
--- a/gcc/doc/invoke.texi
+++ b/gcc/doc/invoke.texi
@@ -13945,14 +13945,16 @@  Enable exception handling.  Generates extra code needed to propagate
 exceptions.  For some targets, this implies GCC generates frame
 unwind information for all functions, which can produce significant data
 size overhead, although it does not affect execution.  If you do not
-specify this option, GCC enables it by default for languages like
-C++ that normally require exception handling, and disables it for
+specify this option, for most targets GCC enables it by default for languages
+like C++ that normally require exception handling, and disables it for
 languages like C that do not normally require it.  However, you may need
 to enable this option when compiling C code that needs to interoperate
 properly with exception handlers written in C++.  You may also wish to
 disable this option if you are compiling older C++ programs that don't
 use exception handling.
 
+The msp430-elf target disables exceptions by default for C++.
+
 @item -fnon-call-exceptions
 @opindex fnon-call-exceptions
 Generate code that allows trapping instructions to throw exceptions.
diff --git a/gcc/testsuite/g++.dg/cpp1y/sized-dealloc2.C b/gcc/testsuite/g++.dg/cpp1y/sized-dealloc2.C
index 0a76cdccd32..71545409b79 100644
--- a/gcc/testsuite/g++.dg/cpp1y/sized-dealloc2.C
+++ b/gcc/testsuite/g++.dg/cpp1y/sized-dealloc2.C
@@ -2,7 +2,7 @@ 
 // placement deallocation function.  This will be a warning in C++98/11
 // modes and an error in C++14 mode.
 
-// { dg-options "-Wc++14-compat" }
+// { dg-options "-fexceptions -Wc++14-compat" }
 
 #include <new>
 void *operator new (std::size_t s, std::size_t)
diff --git a/gcc/testsuite/g++.dg/cpp2a/explicit1.C b/gcc/testsuite/g++.dg/cpp2a/explicit1.C
index b39f90f3397..4537977f767 100644
--- a/gcc/testsuite/g++.dg/cpp2a/explicit1.C
+++ b/gcc/testsuite/g++.dg/cpp2a/explicit1.C
@@ -1,6 +1,6 @@ 
 // P0892R2
 // { dg-do compile }
-// { dg-options "-std=c++2a" }
+// { dg-options "-fexceptions -std=c++2a" }
 
 constexpr int fn0 () { return 0; }
 constexpr int fn1 () { return 1; }
diff --git a/gcc/testsuite/g++.dg/cpp2a/explicit2.C b/gcc/testsuite/g++.dg/cpp2a/explicit2.C
index 7d1748c0f5e..791218f56c4 100644
--- a/gcc/testsuite/g++.dg/cpp2a/explicit2.C
+++ b/gcc/testsuite/g++.dg/cpp2a/explicit2.C
@@ -1,6 +1,6 @@ 
 // P0892R2
 // { dg-do compile }
-// { dg-options "-std=c++2a" }
+// { dg-options "-fexceptions -std=c++2a" }
 
 int foo() { return 42; }
 int g;
diff --git a/gcc/testsuite/g++.dg/cpp2a/explicit5.C b/gcc/testsuite/g++.dg/cpp2a/explicit5.C
index 70a106f1fcb..9a20bf62b86 100644
--- a/gcc/testsuite/g++.dg/cpp2a/explicit5.C
+++ b/gcc/testsuite/g++.dg/cpp2a/explicit5.C
@@ -1,6 +1,6 @@ 
 // P0892R2
 // { dg-do compile }
-// { dg-options "-std=c++2a" }
+// { dg-options "-fexceptions -std=c++2a" }
 
 constexpr int fn0 () { return 0; }
 constexpr int fn1 () { return 1; }
diff --git a/gcc/testsuite/g++.dg/dg.exp b/gcc/testsuite/g++.dg/dg.exp
index 233fdabd327..0c3e6d4f0d5 100644
--- a/gcc/testsuite/g++.dg/dg.exp
+++ b/gcc/testsuite/g++.dg/dg.exp
@@ -42,8 +42,15 @@  proc find-cxx-tests { dir suffix } {
 
 set tests [find-cxx-tests $srcdir/$subdir {C}]
 
+# Pass -fexceptions as a default flag if it's not implicitly enabled.
+set flag_exceptions ""
+if { [check_effective_target_exceptions]
+    && ![check_effective_target_exceptions_enabled_by_default] } {
+    set flag_exceptions "-fexceptions"
+}
+
 # Main loop.
-g++-dg-runtest $tests "" $DEFAULT_CXXFLAGS
+g++-dg-runtest $tests "" "$DEFAULT_CXXFLAGS $flag_exceptions"
 
 # C/C++ common tests.
 g++-dg-runtest [lsort [glob -nocomplain $srcdir/c-c++-common/*.\[cSi\]]] \
diff --git a/gcc/testsuite/g++.dg/eh/array1.C b/gcc/testsuite/g++.dg/eh/array1.C
index 30b035cfc52..3b04da0206a 100644
--- a/gcc/testsuite/g++.dg/eh/array1.C
+++ b/gcc/testsuite/g++.dg/eh/array1.C
@@ -1,6 +1,6 @@ 
 // Test that we have one EH cleanup region for the whole array
 // rather than one for each element.
-// { dg-options "-fdump-tree-gimple" }
+// { dg-options "-fexceptions -fdump-tree-gimple" }
 
 struct A
 {
diff --git a/gcc/testsuite/g++.dg/eh/spec11.C b/gcc/testsuite/g++.dg/eh/spec11.C
index 4615a640519..0414ec59158 100644
--- a/gcc/testsuite/g++.dg/eh/spec11.C
+++ b/gcc/testsuite/g++.dg/eh/spec11.C
@@ -8,7 +8,7 @@ 
 // { dg-final { scan-assembler-not "EHB" } }
 // { dg-final { scan-assembler "LSDA" } }
 
-// { dg-options "-fnothrow-opt" }
+// { dg-options "-fexceptions -fnothrow-opt" }
 
 struct A { ~A(); };
 void g();
diff --git a/gcc/testsuite/g++.dg/eh/spec6.C b/gcc/testsuite/g++.dg/eh/spec6.C
index d08bd865a9b..83f55598d58 100644
--- a/gcc/testsuite/g++.dg/eh/spec6.C
+++ b/gcc/testsuite/g++.dg/eh/spec6.C
@@ -2,7 +2,7 @@ 
 // for a definition, or at a call site.
 
 // { dg-do compile { target c++14_down } }
-// { dg-options "-fpermissive -w" }
+// { dg-options "-fexceptions -fpermissive -w" }
 
 struct A;			// { dg-message "" }
 
diff --git a/gcc/testsuite/g++.dg/ext/vla4.C b/gcc/testsuite/g++.dg/ext/vla4.C
index 90e4160679a..e83857f3c54 100644
--- a/gcc/testsuite/g++.dg/ext/vla4.C
+++ b/gcc/testsuite/g++.dg/ext/vla4.C
@@ -1,5 +1,5 @@ 
 // PR c++/29318
-// { dg-options "" }
+// { dg-options "-fexceptions" }
 
 #include <typeinfo>
 
diff --git a/gcc/testsuite/g++.dg/ipa/pr64612.C b/gcc/testsuite/g++.dg/ipa/pr64612.C
index b6fe39a3741..d23c9a48259 100644
--- a/gcc/testsuite/g++.dg/ipa/pr64612.C
+++ b/gcc/testsuite/g++.dg/ipa/pr64612.C
@@ -1,5 +1,5 @@ 
 /* { dg-do compile } */
-/* { dg-options "-O3 -std=c++11" } */
+/* { dg-options "-fexceptions -O3 -std=c++11" } */
 /* { dg-final { scan-assembler "_ZN5QListI7QStringED1Ev" { target comdat_group } } } */
 
 class A
diff --git a/gcc/testsuite/g++.dg/other/error32.C b/gcc/testsuite/g++.dg/other/error32.C
index 56d3b7aec8b..aad6dfb1ce3 100644
--- a/gcc/testsuite/g++.dg/other/error32.C
+++ b/gcc/testsuite/g++.dg/other/error32.C
@@ -1,5 +1,5 @@ 
 // PR c++/33492
-// { dg-options "" }
+// { dg-options "-fexceptions" }
 
 void foo()
 {
diff --git a/gcc/testsuite/g++.dg/torture/dg-torture.exp b/gcc/testsuite/g++.dg/torture/dg-torture.exp
index f42a6d21a39..5901d27634a 100644
--- a/gcc/testsuite/g++.dg/torture/dg-torture.exp
+++ b/gcc/testsuite/g++.dg/torture/dg-torture.exp
@@ -1,7 +1,14 @@ 
 # This harness is for tests that should be run at all optimisation levels.
 
 load_lib g++-dg.exp
+#
+# Pass -fexceptions as a default flag if it's not implicitly enabled.
+set flag_exceptions ""
+if { [check_effective_target_exceptions]
+    && ![check_effective_target_exceptions_enabled_by_default] } {
+    set flag_exceptions "-fexceptions"
+}
 
 dg-init
-gcc-dg-runtest [lsort [glob $srcdir/$subdir/*.C $srcdir/c-c++-common/torture/*.c]] "" ""
+gcc-dg-runtest [lsort [glob $srcdir/$subdir/*.C $srcdir/c-c++-common/torture/*.c]] "" "$flag_exceptions"
 dg-finish
diff --git a/gcc/testsuite/g++.dg/torture/pr34850.C b/gcc/testsuite/g++.dg/torture/pr34850.C
index 60a6c6ae57d..b224844192b 100644
--- a/gcc/testsuite/g++.dg/torture/pr34850.C
+++ b/gcc/testsuite/g++.dg/torture/pr34850.C
@@ -1,6 +1,6 @@ 
 /* { dg-do compile } */
 /* { dg-skip-if "" { *-*-* } { "-O0" } { "" } } */
-/* { dg-options "-ffat-lto-objects" } */
+/* { dg-options "-fexceptions -ffat-lto-objects" } */
 /* { dg-additional-options "-Wno-return-type" } */
 
 typedef unsigned char uint8_t;
diff --git a/gcc/testsuite/g++.dg/tree-ssa/ivopts-3.C b/gcc/testsuite/g++.dg/tree-ssa/ivopts-3.C
index b0da5e68abc..c8f17197ab4 100644
--- a/gcc/testsuite/g++.dg/tree-ssa/ivopts-3.C
+++ b/gcc/testsuite/g++.dg/tree-ssa/ivopts-3.C
@@ -1,5 +1,5 @@ 
 // { dg-do compile }
-// { dg-options "-O2 -fdump-tree-ivopts-details" }
+// { dg-options "-fexceptions -O2 -fdump-tree-ivopts-details" }
 
 class MinimalVec3
 {
diff --git a/gcc/testsuite/g++.dg/tree-ssa/pr33615.C b/gcc/testsuite/g++.dg/tree-ssa/pr33615.C
index 13e20e0cd2c..47e04964103 100644
--- a/gcc/testsuite/g++.dg/tree-ssa/pr33615.C
+++ b/gcc/testsuite/g++.dg/tree-ssa/pr33615.C
@@ -1,5 +1,5 @@ 
 /* { dg-do compile } */
-/* { dg-options "-O -fnon-call-exceptions -fdump-tree-lim2-details -w" } */
+/* { dg-options "-fexceptions -O -fnon-call-exceptions -fdump-tree-lim2-details -w" } */
 
 extern volatile int y;
 
diff --git a/gcc/testsuite/g++.dg/warn/Wcatch-value-1.C b/gcc/testsuite/g++.dg/warn/Wcatch-value-1.C
index 94ee934b6ae..1ce2ec40d9e 100644
--- a/gcc/testsuite/g++.dg/warn/Wcatch-value-1.C
+++ b/gcc/testsuite/g++.dg/warn/Wcatch-value-1.C
@@ -1,4 +1,4 @@ 
-// { dg-options "-Wcatch-value=1" }
+// { dg-options "-fexceptions -Wcatch-value=1" }
 
 struct A { virtual ~A() {} };
 struct B : A {};
diff --git a/gcc/testsuite/g++.dg/warn/Wcatch-value-2.C b/gcc/testsuite/g++.dg/warn/Wcatch-value-2.C
index 1bcf4056027..3894eeb2b63 100644
--- a/gcc/testsuite/g++.dg/warn/Wcatch-value-2.C
+++ b/gcc/testsuite/g++.dg/warn/Wcatch-value-2.C
@@ -1,4 +1,4 @@ 
-// { dg-options "-Wcatch-value=2" }
+// { dg-options "-fexceptions -Wcatch-value=2" }
 
 struct A { virtual ~A() {} };
 struct B : A {};
diff --git a/gcc/testsuite/g++.dg/warn/Wcatch-value-3.C b/gcc/testsuite/g++.dg/warn/Wcatch-value-3.C
index 88ae698caf6..94ff4b19dd8 100644
--- a/gcc/testsuite/g++.dg/warn/Wcatch-value-3.C
+++ b/gcc/testsuite/g++.dg/warn/Wcatch-value-3.C
@@ -1,4 +1,4 @@ 
-// { dg-options "-Wcatch-value=3" }
+// { dg-options "-fexceptions -Wcatch-value=3" }
 
 struct A { virtual ~A() {} };
 struct B : A {};
diff --git a/gcc/testsuite/g++.dg/warn/Wstringop-truncation-2.C b/gcc/testsuite/g++.dg/warn/Wstringop-truncation-2.C
index ebbd44307d9..4c24d02f6e7 100644
--- a/gcc/testsuite/g++.dg/warn/Wstringop-truncation-2.C
+++ b/gcc/testsuite/g++.dg/warn/Wstringop-truncation-2.C
@@ -3,7 +3,7 @@ 
 // Compile with -g to verify the warning deals properly with debug
 // statements.
 // { dg-do compile }
-// { dg-options "-O2 -Wstringop-truncation -g" }
+// { dg-options "-fexceptions -O2 -Wstringop-truncation -g" }
 
 extern "C" char* strncpy (char*, const char*, __SIZE_TYPE__);
 
diff --git a/gcc/testsuite/g++.dg/warn/Wterminate1.C b/gcc/testsuite/g++.dg/warn/Wterminate1.C
index affb48d3e8a..a611074301a 100644
--- a/gcc/testsuite/g++.dg/warn/Wterminate1.C
+++ b/gcc/testsuite/g++.dg/warn/Wterminate1.C
@@ -1,7 +1,7 @@ 
 // In C++98 mode this gets a -Wc++11-compat warning, in C++11 mode a
 // -Wterminate warning.
 
-// { dg-options "-Wall" }
+// { dg-options "-fexceptions -Wall" }
 
 struct A
 {
diff --git a/gcc/testsuite/g++.dg/warn/pr83054.C b/gcc/testsuite/g++.dg/warn/pr83054.C
index 506c9609b90..9a976da5386 100644
--- a/gcc/testsuite/g++.dg/warn/pr83054.C
+++ b/gcc/testsuite/g++.dg/warn/pr83054.C
@@ -1,5 +1,5 @@ 
 // PR ipa/83054
-// { dg-options "-O3 -Wsuggest-final-types" }
+// { dg-options "-fexceptions -O3 -Wsuggest-final-types" }
 // { dg-do compile }
 
 extern "C" int printf (const char *, ...);
diff --git a/gcc/testsuite/g++.old-deja/g++.other/cond5.C b/gcc/testsuite/g++.old-deja/g++.other/cond5.C
index 0d2baf9edf7..56e21b6aec2 100644
--- a/gcc/testsuite/g++.old-deja/g++.other/cond5.C
+++ b/gcc/testsuite/g++.old-deja/g++.other/cond5.C
@@ -1,5 +1,5 @@ 
 // { dg-do assemble  }
-// { dg-options "-W -pedantic -ansi" }
+// { dg-options "-fexceptions -W -pedantic -ansi" }
 
 // Copyright (C) 1999, 2000 Free Software Foundation, Inc.
 // Contributed by Nathan Sidwell 1 Sep 1999 <nathan@acm.org>
diff --git a/gcc/testsuite/g++.old-deja/old-deja.exp b/gcc/testsuite/g++.old-deja/old-deja.exp
index b214c1be5a1..d85f2ca9152 100644
--- a/gcc/testsuite/g++.old-deja/old-deja.exp
+++ b/gcc/testsuite/g++.old-deja/old-deja.exp
@@ -30,8 +30,15 @@  dg-init
 # that are handled specially.
 set tests [lsort [find $srcdir/$subdir *.C]]
 
+# Pass -fexceptions as a default flag if it's not implicitly enabled.
+set flag_exceptions ""
+if { [check_effective_target_exceptions]
+    && ![check_effective_target_exceptions_enabled_by_default] } {
+    set flag_exceptions "-fexceptions"
+}
+
 # Main loop.
-g++-dg-runtest $tests "" $DEFAULT_CXXFLAGS
+g++-dg-runtest $tests "" "$DEFAULT_CXXFLAGS $flag_exceptions"
 
 # All done.
 dg-finish
diff --git a/gcc/testsuite/lib/gcc-dg.exp b/gcc/testsuite/lib/gcc-dg.exp
index 1df645e283c..1ce449cb935 100644
--- a/gcc/testsuite/lib/gcc-dg.exp
+++ b/gcc/testsuite/lib/gcc-dg.exp
@@ -417,6 +417,16 @@  proc gcc-dg-prune { system text } {
 	return "::unsupported::large return values"
     }
 
+    # If exceptions are disabled, mark tests expecting exceptions to be enabled
+    # as unsupported.
+    if [regexp "(^|\n)\[^\n\]*: error: exception handling disabled" $text] {
+	return "::unsupported::exception handling disabled"
+    }
+
+    if [regexp "(^|\n)\[^\n\]*: error: #error .__cpp_exceptions." $text] {
+	return "::unsupported::exception handling disabled"
+    }
+
     return $text
 }
 
diff --git a/gcc/testsuite/lib/target-supports.exp b/gcc/testsuite/lib/target-supports.exp
index 6f224fa8141..6c836a4accc 100644
--- a/gcc/testsuite/lib/target-supports.exp
+++ b/gcc/testsuite/lib/target-supports.exp
@@ -8888,10 +8888,28 @@  proc check_effective_target_fenv_exceptions {} {
 # Return 1 if -fexceptions is supported.
 
 proc check_effective_target_exceptions {} {
-    if { [istarget amdgcn*-*-*] } {
+    return [check_cached_effective_target exceptions {
+	if { [istarget amdgcn*-*-*]
+	     || [check_configured_with "--disable-exceptions"] } {
+	    return 0
+	}
+	return 1
+    }]
+}
+
+proc check_effective_target_exceptions_enabled_by_default {} {
+    return [check_cached_effective_target exceptions_enabled_by_default {
+	if { [check_effective_target_exceptions] } {
+	    return [check_no_compiler_messages exceptions_enabled_by_default assembly {
+		void foo (void)
+		{
+		    throw 1;
+		}
+	    }]
+	}
+	# If exceptions aren't supported they're not enabled by default.
 	return 0
-    }
-    return 1
+    }]
 }
 
 
diff --git a/libgcc/config.host b/libgcc/config.host
index 122113fc519..99cd5d3ae7c 100644
--- a/libgcc/config.host
+++ b/libgcc/config.host
@@ -1029,7 +1029,8 @@  moxie-*-elf | moxie-*-moxiebox* | moxie-*-uclinux* | moxie-*-rtems*)
 	;;
 msp430*-*-elf)
 	tmake_file="$tm_file t-crtstuff t-fdpbit msp430/t-msp430"
-        extra_parts="$extra_parts libmul_none.a libmul_16.a libmul_32.a libmul_f5.a"
+	extra_parts="$extra_parts crtbegin_no_eh.o crtend_no_eh.o"
+	extra_parts="$extra_parts libmul_none.a libmul_16.a libmul_32.a libmul_f5.a"
 	;;
 nds32*-linux*)
 	# Basic makefile fragment and extra_parts for crt stuff.
diff --git a/libgcc/config/msp430/t-msp430 b/libgcc/config/msp430/t-msp430
index 17d85b6cb23..72ae93a8dae 100644
--- a/libgcc/config/msp430/t-msp430
+++ b/libgcc/config/msp430/t-msp430
@@ -42,6 +42,12 @@  LIB2ADD = \
 
 HOST_LIBGCC2_CFLAGS += -Os -ffunction-sections -fdata-sections -mhwmult=none
 
+crtbegin_no_eh.o: $(srcdir)/crtstuff.c
+	$(crt_compile) -U__LIBGCC_EH_FRAME_SECTION_NAME__ -c $< -DCRT_BEGIN
+
+crtend_no_eh.o: $(srcdir)/crtstuff.c
+	$(crt_compile) -U__LIBGCC_EH_FRAME_SECTION_NAME__ -c $< -DCRT_END
+
 mpy.o: $(srcdir)/config/msp430/mpy.c
 	$(gcc_compile) $< -c
 
-- 
2.17.1