[1/3] Come up with startswith function.

Message ID 8477f38e1a6ea58f9fd1dc6f0f79aded098e68f8.1618989841.git.mliska@suse.cz
State New
Headers show
Series
  • Come up with startswith function
Related show

Commit Message

Martin Liška March 17, 2021, 3:36 p.m.
gcc/ada/ChangeLog:

	* adadecode.c (has_prefix): Remove has_prefix and replace it
	with startswith.
	(__gnat_decode): Likewise.
	* gcc-interface/utils.c (def_builtin_1): Use startswith
	function instead of strncmp.
	* init.c (__gnat_install_handler): Likewise.

gcc/analyzer/ChangeLog:

	* sm-file.cc (is_file_using_fn_p): Use startswith
	function instead of strncmp.

gcc/ChangeLog:

	* builtins.c (is_builtin_name): Use startswith
	function instead of strncmp.
	* collect2.c (main): Likewise.
	(has_lto_section): Likewise.
	(scan_libraries): Likewise.
	* coverage.c (coverage_checksum_string): Likewise.
	(coverage_init): Likewise.
	* dwarf2out.c (is_cxx): Likewise.
	(gen_compile_unit_die): Likewise.
	* gcc-ar.c (main): Likewise.
	* gcc.c (init_spec): Likewise.
	(read_specs): Likewise.
	(execute): Likewise.
	(check_live_switch): Likewise.
	* genattrtab.c (write_attr_case): Likewise.
	(IS_ATTR_GROUP): Likewise.
	* gencfn-macros.c (main): Likewise.
	* gengtype.c (type_for_name): Likewise.
	(gen_rtx_next): Likewise.
	(get_file_langdir): Likewise.
	(write_local): Likewise.
	* genmatch.c (get_operator): Likewise.
	(get_operand_type): Likewise.
	(expr::gen_transform): Likewise.
	* genoutput.c (validate_optab_operands): Likewise.
	* incpath.c (add_sysroot_to_chain): Likewise.
	* langhooks.c (lang_GNU_C): Likewise.
	(lang_GNU_CXX): Likewise.
	(lang_GNU_Fortran): Likewise.
	(lang_GNU_OBJC): Likewise.
	* lto-wrapper.c (run_gcc): Likewise.
	* omp-general.c (omp_max_simt_vf): Likewise.
	* omp-low.c (omp_runtime_api_call): Likewise.
	* opts-common.c (parse_options_from_collect_gcc_options): Likewise.
	* read-rtl-function.c (function_reader::read_rtx_operand_r): Likewise.
	* real.c (real_from_string): Likewise.
	* selftest.c (assert_str_startswith): Likewise.
	* timevar.c (timer::validate_phases): Likewise.
	* tree.c (get_file_function_name): Likewise.
	* ubsan.c (ubsan_use_new_style_p): Likewise.
	* varasm.c (default_function_rodata_section): Likewise.
	(incorporeal_function_p): Likewise.
	(default_section_type_flags): Likewise.
	* system.h (startswith): Define startswith.

gcc/c-family/ChangeLog:

	* c-ada-spec.c (print_destructor): Use startswith
	function instead of strncmp.
	(dump_ada_declaration): Likewise.
	* c-common.c (disable_builtin_function): Likewise.
	(def_builtin_1): Likewise.
	* c-format.c (check_tokens): Likewise.
	(check_plain): Likewise.
	(convert_format_name_to_system_name): Likewise.

gcc/c/ChangeLog:

	* c-aux-info.c (affix_data_type): Use startswith
	function instead of strncmp.
	* c-typeck.c (build_function_call_vec): Likewise.
	* gimple-parser.c (c_parser_gimple_parse_bb_spec): Likewise.

gcc/cp/ChangeLog:

	* decl.c (duplicate_decls): Use startswith
	function instead of strncmp.
	(cxx_builtin_function): Likewise.
	(omp_declare_variant_finalize_one): Likewise.
	(grokfndecl): Likewise.
	* error.c (dump_decl_name): Likewise.
	* mangle.c (find_decomp_unqualified_name): Likewise.
	(write_guarded_var_name): Likewise.
	(decl_tls_wrapper_p): Likewise.
	* parser.c (cp_parser_simple_type_specifier): Likewise.
	(cp_parser_tx_qualifier_opt): Likewise.
	* pt.c (template_parm_object_p): Likewise.
	(dguide_name_p): Likewise.

gcc/d/ChangeLog:

	* d-builtins.cc (do_build_builtin_fn): Use startswith
	function instead of strncmp.
	* dmd/dinterpret.c (evaluateIfBuiltin): Likewise.
	* dmd/dmangle.c: Likewise.
	* dmd/hdrgen.c: Likewise.
	* dmd/identifier.c (Identifier::toHChars2): Likewise.

gcc/fortran/ChangeLog:

	* decl.c (variable_decl): Use startswith
	function instead of strncmp.
	(gfc_match_end): Likewise.
	* gfortran.h (gfc_str_startswith): Likewise.
	* module.c (load_omp_udrs): Likewise.
	(read_module): Likewise.
	* options.c (gfc_handle_runtime_check_option): Likewise.
	* primary.c (match_arg_list_function): Likewise.
	* trans-decl.c (gfc_get_symbol_decl): Likewise.
	* trans-expr.c (gfc_conv_procedure_call): Likewise.
	* trans-intrinsic.c (gfc_conv_ieee_arithmetic_function): Likewise.

gcc/go/ChangeLog:

	* gofrontend/runtime.cc (Runtime::name_to_code): Use startswith
	function instead of strncmp.

gcc/objc/ChangeLog:

	* objc-act.c (objc_string_ref_type_p): Use startswith
	function instead of strncmp.
	* objc-encoding.c (encode_type): Likewise.
	* objc-next-runtime-abi-02.c (has_load_impl): Likewise.
---
 gcc/ada/adadecode.c                 | 14 ++-------
 gcc/ada/gcc-interface/utils.c       |  3 +-
 gcc/ada/init.c                      |  8 ++---
 gcc/analyzer/sm-file.cc             |  5 ++-
 gcc/builtins.c                      | 10 ++----
 gcc/c-family/c-ada-spec.c           |  8 ++---
 gcc/c-family/c-common.c             |  5 ++-
 gcc/c-family/c-format.c             | 20 ++++++------
 gcc/c/c-aux-info.c                  |  4 +--
 gcc/c/c-typeck.c                    |  4 +--
 gcc/c/gimple-parser.c               |  2 +-
 gcc/collect2.c                      | 48 +++++++++++++----------------
 gcc/coverage.c                      |  7 ++---
 gcc/cp/decl.c                       | 15 +++++----
 gcc/cp/error.c                      |  2 +-
 gcc/cp/mangle.c                     | 11 +++----
 gcc/cp/parser.c                     |  7 ++---
 gcc/cp/pt.c                         |  5 ++-
 gcc/d/d-builtins.cc                 |  3 +-
 gcc/d/dmd/dinterpret.c              |  2 +-
 gcc/d/dmd/dmangle.c                 |  2 +-
 gcc/d/dmd/hdrgen.c                  |  2 +-
 gcc/d/dmd/identifier.c              |  6 ++--
 gcc/dwarf2out.c                     | 14 ++++-----
 gcc/fortran/decl.c                  |  4 +--
 gcc/fortran/gfortran.h              |  4 ---
 gcc/fortran/module.c                | 10 +++---
 gcc/fortran/options.c               |  2 +-
 gcc/fortran/primary.c               |  6 ++--
 gcc/fortran/trans-decl.c            |  2 +-
 gcc/fortran/trans-expr.c            |  2 +-
 gcc/fortran/trans-intrinsic.c       | 22 ++++++-------
 gcc/gcc-ar.c                        |  2 +-
 gcc/gcc.c                           | 14 ++++-----
 gcc/genattrtab.c                    |  8 ++---
 gcc/gencfn-macros.c                 |  2 +-
 gcc/gengtype.c                      |  8 ++---
 gcc/genmatch.c                      |  8 ++---
 gcc/genoutput.c                     |  2 +-
 gcc/go/gofrontend/runtime.cc        |  2 +-
 gcc/incpath.c                       |  2 +-
 gcc/langhooks.c                     |  8 ++---
 gcc/lto-wrapper.c                   |  3 +-
 gcc/objc/objc-act.c                 |  2 +-
 gcc/objc/objc-encoding.c            |  2 +-
 gcc/objc/objc-next-runtime-abi-02.c |  2 +-
 gcc/omp-general.c                   |  2 +-
 gcc/omp-low.c                       |  2 +-
 gcc/opts-common.c                   |  2 +-
 gcc/read-rtl-function.c             |  2 +-
 gcc/real.c                          |  6 ++--
 gcc/selftest.c                      |  3 +-
 gcc/system.h                        |  8 +++++
 gcc/timevar.c                       |  2 +-
 gcc/tree.c                          |  2 +-
 gcc/ubsan.c                         |  2 +-
 gcc/varasm.c                        | 22 ++++++-------
 57 files changed, 176 insertions(+), 201 deletions(-)

Comments

Arnaud Charlet April 21, 2021, 7:32 a.m. | #1
> gcc/ada/ChangeLog:

> 

> 	* adadecode.c (has_prefix): Remove has_prefix and replace it

> 	with startswith.

> 	(__gnat_decode): Likewise.


This change is not OK: adadecode.c is also a runtime file and as such cannot
include compiler include files.

> 	* gcc-interface/utils.c (def_builtin_1): Use startswith

> 	function instead of strncmp.


> 	* init.c (__gnat_install_handler): Likewise.


Same for init.c which is both a host and a runtime/target file.

Only the change in utils.c is OK.

Arno
Martin Liška April 21, 2021, 8:37 a.m. | #2
On 4/21/21 9:32 AM, Arnaud Charlet wrote:
>> gcc/ada/ChangeLog:

>>

>> 	* adadecode.c (has_prefix): Remove has_prefix and replace it

>> 	with startswith.

>> 	(__gnat_decode): Likewise.

> 

> This change is not OK: adadecode.c is also a runtime file and as such cannot

> include compiler include files.

> 

>> 	* gcc-interface/utils.c (def_builtin_1): Use startswith

>> 	function instead of strncmp.

> 

>> 	* init.c (__gnat_install_handler): Likewise.

> 

> Same for init.c which is both a host and a runtime/target file.

> 

> Only the change in utils.c is OK.

> 

> Arno

> 


Thank you for a quick reply.

There's an updated version of the patch.

Cheers,
Martin
From 23431b3fa62222e0ad69e66cc7d3fe8bee5da29a Mon Sep 17 00:00:00 2001
From: Martin Liska <mliska@suse.cz>

Date: Wed, 17 Mar 2021 16:36:44 +0100
Subject: [PATCH 1/3] Come up with startswith function.

gcc/ada/ChangeLog:

	* gcc-interface/utils.c (def_builtin_1): Use startswith
	function instead of strncmp.

gcc/analyzer/ChangeLog:

	* sm-file.cc (is_file_using_fn_p): Use startswith
	function instead of strncmp.

gcc/ChangeLog:

	* builtins.c (is_builtin_name): Use startswith
	function instead of strncmp.
	* collect2.c (main): Likewise.
	(has_lto_section): Likewise.
	(scan_libraries): Likewise.
	* coverage.c (coverage_checksum_string): Likewise.
	(coverage_init): Likewise.
	* dwarf2out.c (is_cxx): Likewise.
	(gen_compile_unit_die): Likewise.
	* gcc-ar.c (main): Likewise.
	* gcc.c (init_spec): Likewise.
	(read_specs): Likewise.
	(execute): Likewise.
	(check_live_switch): Likewise.
	* genattrtab.c (write_attr_case): Likewise.
	(IS_ATTR_GROUP): Likewise.
	* gencfn-macros.c (main): Likewise.
	* gengtype.c (type_for_name): Likewise.
	(gen_rtx_next): Likewise.
	(get_file_langdir): Likewise.
	(write_local): Likewise.
	* genmatch.c (get_operator): Likewise.
	(get_operand_type): Likewise.
	(expr::gen_transform): Likewise.
	* genoutput.c (validate_optab_operands): Likewise.
	* incpath.c (add_sysroot_to_chain): Likewise.
	* langhooks.c (lang_GNU_C): Likewise.
	(lang_GNU_CXX): Likewise.
	(lang_GNU_Fortran): Likewise.
	(lang_GNU_OBJC): Likewise.
	* lto-wrapper.c (run_gcc): Likewise.
	* omp-general.c (omp_max_simt_vf): Likewise.
	* omp-low.c (omp_runtime_api_call): Likewise.
	* opts-common.c (parse_options_from_collect_gcc_options): Likewise.
	* read-rtl-function.c (function_reader::read_rtx_operand_r): Likewise.
	* real.c (real_from_string): Likewise.
	* selftest.c (assert_str_startswith): Likewise.
	* timevar.c (timer::validate_phases): Likewise.
	* tree.c (get_file_function_name): Likewise.
	* ubsan.c (ubsan_use_new_style_p): Likewise.
	* varasm.c (default_function_rodata_section): Likewise.
	(incorporeal_function_p): Likewise.
	(default_section_type_flags): Likewise.
	* system.h (startswith): Define startswith.

gcc/c-family/ChangeLog:

	* c-ada-spec.c (print_destructor): Use startswith
	function instead of strncmp.
	(dump_ada_declaration): Likewise.
	* c-common.c (disable_builtin_function): Likewise.
	(def_builtin_1): Likewise.
	* c-format.c (check_tokens): Likewise.
	(check_plain): Likewise.
	(convert_format_name_to_system_name): Likewise.

gcc/c/ChangeLog:

	* c-aux-info.c (affix_data_type): Use startswith
	function instead of strncmp.
	* c-typeck.c (build_function_call_vec): Likewise.
	* gimple-parser.c (c_parser_gimple_parse_bb_spec): Likewise.

gcc/cp/ChangeLog:

	* decl.c (duplicate_decls): Use startswith
	function instead of strncmp.
	(cxx_builtin_function): Likewise.
	(omp_declare_variant_finalize_one): Likewise.
	(grokfndecl): Likewise.
	* error.c (dump_decl_name): Likewise.
	* mangle.c (find_decomp_unqualified_name): Likewise.
	(write_guarded_var_name): Likewise.
	(decl_tls_wrapper_p): Likewise.
	* parser.c (cp_parser_simple_type_specifier): Likewise.
	(cp_parser_tx_qualifier_opt): Likewise.
	* pt.c (template_parm_object_p): Likewise.
	(dguide_name_p): Likewise.

gcc/d/ChangeLog:

	* d-builtins.cc (do_build_builtin_fn): Use startswith
	function instead of strncmp.
	* dmd/dinterpret.c (evaluateIfBuiltin): Likewise.
	* dmd/dmangle.c: Likewise.
	* dmd/hdrgen.c: Likewise.
	* dmd/identifier.c (Identifier::toHChars2): Likewise.

gcc/fortran/ChangeLog:

	* decl.c (variable_decl): Use startswith
	function instead of strncmp.
	(gfc_match_end): Likewise.
	* gfortran.h (gfc_str_startswith): Likewise.
	* module.c (load_omp_udrs): Likewise.
	(read_module): Likewise.
	* options.c (gfc_handle_runtime_check_option): Likewise.
	* primary.c (match_arg_list_function): Likewise.
	* trans-decl.c (gfc_get_symbol_decl): Likewise.
	* trans-expr.c (gfc_conv_procedure_call): Likewise.
	* trans-intrinsic.c (gfc_conv_ieee_arithmetic_function): Likewise.

gcc/go/ChangeLog:

	* gofrontend/runtime.cc (Runtime::name_to_code): Use startswith
	function instead of strncmp.

gcc/objc/ChangeLog:

	* objc-act.c (objc_string_ref_type_p): Use startswith
	function instead of strncmp.
	* objc-encoding.c (encode_type): Likewise.
	* objc-next-runtime-abi-02.c (has_load_impl): Likewise.
---
 gcc/ada/gcc-interface/utils.c       |  3 +-
 gcc/analyzer/sm-file.cc             |  5 ++-
 gcc/builtins.c                      | 10 ++----
 gcc/c-family/c-ada-spec.c           |  8 ++---
 gcc/c-family/c-common.c             |  5 ++-
 gcc/c-family/c-format.c             | 20 ++++++------
 gcc/c/c-aux-info.c                  |  4 +--
 gcc/c/c-typeck.c                    |  4 +--
 gcc/c/gimple-parser.c               |  2 +-
 gcc/collect2.c                      | 48 +++++++++++++----------------
 gcc/coverage.c                      |  7 ++---
 gcc/cp/decl.c                       | 15 +++++----
 gcc/cp/error.c                      |  2 +-
 gcc/cp/mangle.c                     | 11 +++----
 gcc/cp/parser.c                     |  7 ++---
 gcc/cp/pt.c                         |  5 ++-
 gcc/d/d-builtins.cc                 |  3 +-
 gcc/d/dmd/dinterpret.c              |  2 +-
 gcc/d/dmd/dmangle.c                 |  2 +-
 gcc/d/dmd/hdrgen.c                  |  2 +-
 gcc/d/dmd/identifier.c              |  6 ++--
 gcc/dwarf2out.c                     | 14 ++++-----
 gcc/fortran/decl.c                  |  4 +--
 gcc/fortran/gfortran.h              |  4 ---
 gcc/fortran/module.c                | 10 +++---
 gcc/fortran/options.c               |  2 +-
 gcc/fortran/primary.c               |  6 ++--
 gcc/fortran/trans-decl.c            |  2 +-
 gcc/fortran/trans-expr.c            |  2 +-
 gcc/fortran/trans-intrinsic.c       | 22 ++++++-------
 gcc/gcc-ar.c                        |  2 +-
 gcc/gcc.c                           | 14 ++++-----
 gcc/genattrtab.c                    |  8 ++---
 gcc/gencfn-macros.c                 |  2 +-
 gcc/gengtype.c                      |  8 ++---
 gcc/genmatch.c                      |  8 ++---
 gcc/genoutput.c                     |  2 +-
 gcc/go/gofrontend/runtime.cc        |  2 +-
 gcc/incpath.c                       |  2 +-
 gcc/langhooks.c                     |  8 ++---
 gcc/lto-wrapper.c                   |  3 +-
 gcc/objc/objc-act.c                 |  2 +-
 gcc/objc/objc-encoding.c            |  2 +-
 gcc/objc/objc-next-runtime-abi-02.c |  2 +-
 gcc/omp-general.c                   |  2 +-
 gcc/omp-low.c                       |  2 +-
 gcc/opts-common.c                   |  2 +-
 gcc/read-rtl-function.c             |  2 +-
 gcc/real.c                          |  6 ++--
 gcc/selftest.c                      |  3 +-
 gcc/system.h                        |  8 +++++
 gcc/timevar.c                       |  2 +-
 gcc/tree.c                          |  2 +-
 gcc/ubsan.c                         |  2 +-
 gcc/varasm.c                        | 22 ++++++-------
 55 files changed, 169 insertions(+), 186 deletions(-)

diff --git a/gcc/ada/gcc-interface/utils.c b/gcc/ada/gcc-interface/utils.c
index 952f032072b..2d5ca4ba456 100644
--- a/gcc/ada/gcc-interface/utils.c
+++ b/gcc/ada/gcc-interface/utils.c
@@ -7016,8 +7016,7 @@ def_builtin_1 (enum built_in_function fncode,
     return;
 
   gcc_assert ((!both_p && !fallback_p)
-	      || !strncmp (name, "__builtin_",
-			   strlen ("__builtin_")));
+	      || startswith (name, "__builtin_"));
 
   libname = name + strlen ("__builtin_");
   decl = add_builtin_function (name, fntype, fncode, fnclass,
diff --git a/gcc/analyzer/sm-file.cc b/gcc/analyzer/sm-file.cc
index d64c313e31c..3a5f95def34 100644
--- a/gcc/analyzer/sm-file.cc
+++ b/gcc/analyzer/sm-file.cc
@@ -312,9 +312,8 @@ is_file_using_fn_p (tree fndecl)
 
   /* Also support variants of these names prefixed with "_IO_".  */
   const char *name = IDENTIFIER_POINTER (DECL_NAME (fndecl));
-  if (strncmp (name, "_IO_", 4) == 0)
-    if (fs.contains_name_p (name + 4))
-      return true;
+  if (startswith (name, "_IO_") && fs.contains_name_p (name + 4))
+    return true;
 
   return false;
 }
diff --git a/gcc/builtins.c b/gcc/builtins.c
index d30c4eb62fc..b8764fed597 100644
--- a/gcc/builtins.c
+++ b/gcc/builtins.c
@@ -740,13 +740,9 @@ pointer_query::flush_cache ()
 static bool
 is_builtin_name (const char *name)
 {
-  if (strncmp (name, "__builtin_", 10) == 0)
-    return true;
-  if (strncmp (name, "__sync_", 7) == 0)
-    return true;
-  if (strncmp (name, "__atomic_", 9) == 0)
-    return true;
-  return false;
+  return (startswith (name, "__builtin_")
+	  || startswith (name, "__sync_")
+	  || startswith (name, "__atomic_"));
 }
 
 /* Return true if NODE should be considered for inline expansion regardless
diff --git a/gcc/c-family/c-ada-spec.c b/gcc/c-family/c-ada-spec.c
index 9fef5f05cc8..29eb0b01a91 100644
--- a/gcc/c-family/c-ada-spec.c
+++ b/gcc/c-family/c-ada-spec.c
@@ -2696,7 +2696,7 @@ print_destructor (pretty_printer *buffer, tree t, tree type)
   tree decl_name = DECL_NAME (TYPE_NAME (type));
 
   pp_string (buffer, "Delete_");
-  if (strncmp (IDENTIFIER_POINTER (DECL_NAME (t)), "__dt_del", 8) == 0)
+  if (startswith (IDENTIFIER_POINTER (DECL_NAME (t)), "__dt_del"))
     pp_string (buffer, "And_Free_");
   pp_ada_tree_identifier (buffer, decl_name, t, false);
 }
@@ -2980,9 +2980,9 @@ dump_ada_declaration (pretty_printer *buffer, tree t, tree type, int spc)
 	    return 0;
 
 	  /* Only consider complete constructors and deleting destructors.  */
-	  if (strncmp (IDENTIFIER_POINTER (decl_name), "__ct_comp", 9) != 0
-	      && strncmp (IDENTIFIER_POINTER (decl_name), "__dt_comp", 9) != 0
-	      && strncmp (IDENTIFIER_POINTER (decl_name), "__dt_del", 8) != 0)
+	  if (!startswith (IDENTIFIER_POINTER (decl_name), "__ct_comp")
+	      && !startswith (IDENTIFIER_POINTER (decl_name), "__dt_comp")
+	      && !startswith (IDENTIFIER_POINTER (decl_name), "__dt_del"))
 	    return 0;
 	}
 
diff --git a/gcc/c-family/c-common.c b/gcc/c-family/c-common.c
index d227686a030..7bd799d1825 100644
--- a/gcc/c-family/c-common.c
+++ b/gcc/c-family/c-common.c
@@ -4670,7 +4670,7 @@ static bool builtin_function_disabled_p (const char *);
 void
 disable_builtin_function (const char *name)
 {
-  if (strncmp (name, "__builtin_", strlen ("__builtin_")) == 0)
+  if (startswith (name, "__builtin_"))
     error ("cannot disable built-in function %qs", name);
   else
     {
@@ -4718,8 +4718,7 @@ def_builtin_1 (enum built_in_function fncode,
     return;
 
   gcc_assert ((!both_p && !fallback_p)
-	      || !strncmp (name, "__builtin_",
-			   strlen ("__builtin_")));
+	      || startswith (name, "__builtin_"));
 
   libname = name + strlen ("__builtin_");
   decl = add_builtin_function (name, fntype, fncode, fnclass,
diff --git a/gcc/c-family/c-format.c b/gcc/c-family/c-format.c
index 0a63cacb0d9..bda3b18fcd0 100644
--- a/gcc/c-family/c-format.c
+++ b/gcc/c-family/c-format.c
@@ -3097,7 +3097,7 @@ check_tokens (const token_t *tokens, unsigned ntoks,
       /* Allow this ugly warning for the time being.  */
       if (toklen == 2
 	  && format_chars - orig_format_chars > 6
-	  && !strncmp (format_chars - 7, " count >= width of ", 19))
+	  && startswith (format_chars - 7, " count >= width of "))
 	return format_chars + 10;
 
       /* The token is a type if it ends in an alphabetic character.  */
@@ -3127,7 +3127,7 @@ check_tokens (const token_t *tokens, unsigned ntoks,
   /* Diagnose unquoted __attribute__.  Consider any parenthesized
      argument to the attribute to avoid redundant warnings for
      the double parentheses that might follow.  */
-  if (!strncmp (format_chars, "__attribute", sizeof "__attribute" - 1))
+  if (startswith (format_chars, "__attribute"))
     {
       unsigned nchars = sizeof "__attribute" - 1;
       while ('_' == format_chars[nchars])
@@ -3178,9 +3178,9 @@ check_tokens (const token_t *tokens, unsigned ntoks,
   /* Diagnose unquoted built-ins.  */
   if (format_chars[0] == '_'
       && format_chars[1] == '_'
-      && (!strncmp (format_chars + 2, "atomic", sizeof "atomic" - 1)
-	  || !strncmp (format_chars + 2, "builtin", sizeof "builtin" - 1)
-	  || !strncmp (format_chars + 2, "sync", sizeof "sync" - 1)))
+      && (startswith (format_chars + 2, "atomic")
+	  || startswith (format_chars + 2, "builtin")
+	  || startswith (format_chars + 2, "sync")))
     {
       format_warning_substr (format_string_loc, format_string_cst,
 			     fmtchrpos, fmtchrpos + wlen, opt,
@@ -3267,7 +3267,7 @@ check_plain (location_t format_string_loc, tree format_string_cst,
   if (*format_chars == '%')
     {
       /* Diagnose %<%s%> and suggest using %qs instead.  */
-      if (!strncmp (format_chars, "%<%s%>", 6))
+      if (startswith (format_chars, "%<%s%>"))
 	format_warning_substr (format_string_loc, format_string_cst,
 			       fmtchrpos, fmtchrpos + 6, opt,
 			       "quoted %qs directive in format; "
@@ -3593,7 +3593,7 @@ check_plain (location_t format_string_loc, tree format_string_cst,
 
       if (nchars == 1)
 	{
-	  if (!strncmp (format_chars, "\"%s\"", 4))
+	  if (startswith (format_chars, "\"%s\""))
 	    {
 	      if (format_warning_substr (format_string_loc, format_string_cst,
 					 fmtchrpos, fmtchrpos + 4, opt,
@@ -3621,7 +3621,7 @@ check_plain (location_t format_string_loc, tree format_string_cst,
 	      && format_chars[0] == '(')
 	    ;   /* Text beginning in an open parenthesis.  */
 	  else if (nchars == 3
-	      && !strncmp (format_chars, "...", 3)
+	      && startswith (format_chars, "...")
 	      && format_chars[3])
 	    ;   /* Text beginning in an ellipsis.  */
 	  else
@@ -3663,7 +3663,7 @@ check_plain (location_t format_string_loc, tree format_string_cst,
 		   a period at the end of a capitalized sentence.  */
 	  else if (nchars == 3
 		   && format_chars - orig_format_chars > 0
-		   && !strncmp (format_chars, "...", 3))
+		   && startswith (format_chars, "..."))
 	    ;   /* Text ending in the ellipsis.  */
 	  else
 	    format_warning_substr (format_string_loc, format_string_cst,
@@ -5104,7 +5104,7 @@ convert_format_name_to_system_name (const char *attr_name)
   int i;
 
   if (attr_name == NULL || *attr_name == 0
-      || strncmp (attr_name, "gcc_", 4) == 0)
+      || startswith (attr_name, "gcc_"))
     return attr_name;
 #ifdef TARGET_OVERRIDES_FORMAT_INIT
   TARGET_OVERRIDES_FORMAT_INIT ();
diff --git a/gcc/c/c-aux-info.c b/gcc/c/c-aux-info.c
index bae5757ad13..81860cb48cb 100644
--- a/gcc/c/c-aux-info.c
+++ b/gcc/c/c-aux-info.c
@@ -67,12 +67,12 @@ affix_data_type (const char *param)
 
   for (;;)
     {
-      if (!strncmp (p, "volatile ", 9))
+      if (startswith (p, "volatile "))
 	{
 	  p += 9;
 	  continue;
 	}
-      if (!strncmp (p, "const ", 6))
+      if (startswith (p, "const "))
 	{
 	  p += 6;
 	  continue;
diff --git a/gcc/c/c-typeck.c b/gcc/c/c-typeck.c
index 51a62c800f7..a523b934303 100644
--- a/gcc/c/c-typeck.c
+++ b/gcc/c/c-typeck.c
@@ -3113,7 +3113,7 @@ build_function_call_vec (location_t loc, vec<location_t> arg_loc,
 	orig_fundecl = fundecl;
       /* Atomic functions have type checking/casting already done.  They are 
 	 often rewritten and don't match the original parameter list.  */
-      if (name && !strncmp (IDENTIFIER_POINTER (name), "__atomic_", 9))
+      if (name && startswith (IDENTIFIER_POINTER (name), "__atomic_"))
         origtypes = NULL;
     }
   if (TREE_CODE (TREE_TYPE (function)) == FUNCTION_TYPE)
@@ -3199,7 +3199,7 @@ build_function_call_vec (location_t loc, vec<location_t> arg_loc,
 					    nargs, argarray, &arg_loc);
 
   if (name != NULL_TREE
-      && !strncmp (IDENTIFIER_POINTER (name), "__builtin_", 10))
+      && startswith (IDENTIFIER_POINTER (name), "__builtin_"))
     {
       if (require_constant_value)
 	result
diff --git a/gcc/c/gimple-parser.c b/gcc/c/gimple-parser.c
index 58b161b7c76..3a6e72ef002 100644
--- a/gcc/c/gimple-parser.c
+++ b/gcc/c/gimple-parser.c
@@ -131,7 +131,7 @@ static void c_parser_gimple_expr_list (gimple_parser &, vec<tree> *);
 static bool
 c_parser_gimple_parse_bb_spec (tree val, int *index)
 {
-  if (strncmp (IDENTIFIER_POINTER (val), "__BB", 4) != 0)
+  if (!startswith (IDENTIFIER_POINTER (val), "__BB"))
     return false;
   for (const char *p = IDENTIFIER_POINTER (val) + 4; *p; ++p)
     if (!ISDIGIT (*p))
diff --git a/gcc/collect2.c b/gcc/collect2.c
index bd371430ab7..0ddb1693b67 100644
--- a/gcc/collect2.c
+++ b/gcc/collect2.c
@@ -956,7 +956,7 @@ main (int argc, char **argv)
       {
 	if (! strcmp (argv[i], "-debug"))
 	  debug = true;
-	else if (!strncmp (argv[i], "-fno-lto", 8))
+	else if (startswith (argv[i], "-fno-lto"))
 	  lto_mode = LTO_MODE_NONE;
         else if (! strcmp (argv[i], "-plugin"))
 	  {
@@ -970,7 +970,7 @@ main (int argc, char **argv)
 	  selected_linker = USE_GOLD_LD;
 	else if (strcmp (argv[i], "-fuse-ld=lld") == 0)
 	  selected_linker = USE_LLD_LD;
-	else if (strncmp (argv[i], "-o", 2) == 0)
+	else if (startswith (argv[i], "-o"))
 	  {
 	    /* Parse the output filename if it's given so that we can make
 	       meaningful temp filenames.  */
@@ -984,19 +984,19 @@ main (int argc, char **argv)
 	/* These flags are position independent, although their order
 	   is important - subsequent flags override earlier ones. */
 	else if (strcmp (argv[i], "-b64") == 0)
-	    aix64_flag = 1;
+	  aix64_flag = 1;
 	/* -bexport:filename always needs the :filename */
-	else if (strncmp (argv[i], "-bE:", 4) == 0
-	      || strncmp (argv[i], "-bexport:", 9) == 0)
-	    export_flag = 1;
+	else if (startswith (argv[i], "-bE:")
+		 || startswith (argv[i], "-bexport:"))
+	  export_flag = 1;
 	else if (strcmp (argv[i], "-brtl") == 0
 	      || strcmp (argv[i], "-bsvr4") == 0
 	      || strcmp (argv[i], "-G") == 0)
-	    aixrtl_flag = 1;
+	  aixrtl_flag = 1;
 	else if (strcmp (argv[i], "-bnortl") == 0)
-	    aixrtl_flag = 0;
+	  aixrtl_flag = 0;
 	else if (strcmp (argv[i], "-blazy") == 0)
-	    aixlazy_flag = 1;
+	  aixlazy_flag = 1;
 #endif
       }
 
@@ -1016,11 +1016,11 @@ main (int argc, char **argv)
 	const char *q = extract_string (&p);
 	if (*q == '-' && (q[1] == 'm' || q[1] == 'f'))
 	  num_c_args++;
-	if (strncmp (q, "-flto-partition=none", 20) == 0)
+	if (startswith (q, "-flto-partition=none"))
 	  no_partition = true;
-	else if (strncmp (q, "-fno-lto", 8) == 0)
+	else if (startswith (q, "-fno-lto"))
 	  lto_mode = LTO_MODE_NONE;
-	else if (strncmp (q, "-save-temps", 11) == 0)
+	else if (startswith (q, "-save-temps"))
 	  /* FIXME: Honour =obj.  */
 	  save_temps = true;
 	else if (strcmp (q, "-dumpdir") == 0)
@@ -1254,7 +1254,7 @@ main (int argc, char **argv)
 	(void) extract_string (&p);
 #ifdef COLLECT_EXPORT_LIST
       /* Detect any invocation with -fvisibility.  */
-      if (strncmp (q, "-fvisibility", 12) == 0)
+      if (startswith (q, "-fvisibility"))
 	visibility_flag = 1;
 #endif
     }
@@ -1303,7 +1303,7 @@ main (int argc, char **argv)
 	      break;
 
             case 'f':
-	      if (strncmp (arg, "-flto", 5) == 0)
+	      if (startswith (arg, "-flto"))
 		{
 #ifdef ENABLE_LTO
 		  /* Do not pass LTO flag to the linker. */
@@ -1315,13 +1315,13 @@ main (int argc, char **argv)
 #endif
 		}
 	      else if (!use_collect_ld
-		       && strncmp (arg, "-fuse-ld=", 9) == 0)
+		       && startswith (arg, "-fuse-ld="))
 		{
 		  /* Do not pass -fuse-ld={bfd|gold|lld} to the linker. */
 		  ld1--;
 		  ld2--;
 		}
-	      else if (strncmp (arg, "-fno-lto", 8) == 0)
+	      else if (startswith (arg, "-fno-lto"))
 		{
 		  /* Do not pass -fno-lto to the linker. */
 		  ld1--;
@@ -1462,7 +1462,7 @@ main (int argc, char **argv)
 		  ld2--;
 #endif
 		}
-	      else if (strncmp (arg, "--demangle", 10) == 0)
+	      else if (startswith (arg, "--demangle"))
 		{
 #ifndef HAVE_LD_DEMANGLE
 		  no_demangle = 0;
@@ -1479,7 +1479,7 @@ main (int argc, char **argv)
 		  ld2--;
 #endif
 		}
-	      else if (strncmp (arg, "--sysroot=", 10) == 0)
+	      else if (startswith (arg, "--sysroot="))
 		target_system_root = arg + 10;
 	      else if (strcmp (arg, "--version") == 0)
 		verbose = true;
@@ -2307,13 +2307,9 @@ has_lto_section (void *data, const char *name ATTRIBUTE_UNUSED,
 {
   int *found = (int *) data;
 
-  if (strncmp (name, LTO_SECTION_NAME_PREFIX,
-	       sizeof (LTO_SECTION_NAME_PREFIX) - 1) != 0)
-    {
-      if (strncmp (name, OFFLOAD_SECTION_NAME_PREFIX,
-	           sizeof (OFFLOAD_SECTION_NAME_PREFIX) - 1) != 0)
-        return 1;
-    }
+  if (!startswith (name, LTO_SECTION_NAME_PREFIX)
+      && !startswith (name, OFFLOAD_SECTION_NAME_PREFIX))
+    return 1;
 
   *found = 1;
 
@@ -2619,7 +2615,7 @@ scan_libraries (const char *prog_name)
 	continue;
 
       name = p;
-      if (strncmp (name, "not found", sizeof ("not found") - 1) == 0)
+      if (startswith (name, "not found"))
 	fatal_error (input_location, "dynamic dependency %s not found", buf);
 
       /* Find the end of the symbol name.  */
diff --git a/gcc/coverage.c b/gcc/coverage.c
index dc9ea6f3ee1..5a344cdfc17 100644
--- a/gcc/coverage.c
+++ b/gcc/coverage.c
@@ -488,9 +488,9 @@ coverage_checksum_string (unsigned chksum, const char *string)
   for (i = 0; string[i]; i++)
     {
       int offset = 0;
-      if (!strncmp (string + i, "_GLOBAL__N_", 11))
+      if (startswith (string + i, "_GLOBAL__N_"))
       offset = 11;
-      if (!strncmp (string + i, "_GLOBAL__", 9))
+      if (startswith (string + i, "_GLOBAL__"))
       offset = 9;
 
       /* C++ namespaces do have scheme:
@@ -1256,8 +1256,7 @@ coverage_init (const char *filename)
 	  filename = concat (getpwd (), separator, filename, NULL);
 	  if (profile_prefix_path)
 	    {
-	      if (!strncmp (filename, profile_prefix_path,
-			    strlen (profile_prefix_path)))
+	      if (startswith (filename, profile_prefix_path))
 		{
 		  filename += strlen (profile_prefix_path);
 		  while (*filename == *separator)
diff --git a/gcc/cp/decl.c b/gcc/cp/decl.c
index b81de8ef934..d6c7bc70823 100644
--- a/gcc/cp/decl.c
+++ b/gcc/cp/decl.c
@@ -1609,8 +1609,7 @@ duplicate_decls (tree newdecl, tree olddecl, bool hiding, bool was_hidden)
 
 		  if (name[0] == '_'
 		      && name[1] == '_'
-		      && (strncmp (name + 2, "builtin_",
-				   strlen ("builtin_")) == 0
+		      && (startswith (name + 2, "builtin_")
 			  || (len = strlen (name)) <= strlen ("___chk")
 			  || memcmp (name + len - strlen ("_chk"),
 				     "_chk", strlen ("_chk") + 1) != 0))
@@ -4828,7 +4827,7 @@ cxx_builtin_function (tree decl)
     /* In the user's namespace, it must be declared before use.  */
     hiding = true;
   else if (IDENTIFIER_LENGTH (id) > strlen ("___chk")
-	   && 0 != strncmp (name + 2, "builtin_", strlen ("builtin_"))
+	   && !startswith (name + 2, "builtin_")
 	   && 0 == memcmp (name + IDENTIFIER_LENGTH (id) - strlen ("_chk"),
 			   "_chk", strlen ("_chk") + 1))
     /* Treat __*_chk fortification functions as anticipated as well,
@@ -7565,9 +7564,9 @@ omp_declare_variant_finalize_one (tree decl, tree attr)
 	  return true;
 	}
       if (fndecl_built_in_p (variant)
-	  && (strncmp (varname, "__builtin_", strlen ("__builtin_")) == 0
-	      || strncmp (varname, "__sync_", strlen ("__sync_")) == 0
-	      || strncmp (varname, "__atomic_", strlen ("__atomic_")) == 0))
+	  && (startswith (varname, "__builtin_")
+	      || startswith (varname, "__sync_")
+	      || startswith (varname, "__atomic_")))
 	{
 	  error_at (varid_loc, "variant %qD is a built-in", variant);
 	  return true;
@@ -9833,8 +9832,8 @@ grokfndecl (tree ctype,
 	  || (IDENTIFIER_LENGTH (declarator) > 10
 	      && IDENTIFIER_POINTER (declarator)[0] == '_'
 	      && IDENTIFIER_POINTER (declarator)[1] == '_'
-	      && strncmp (IDENTIFIER_POINTER (declarator)+2,
-			  "builtin_", 8) == 0)
+	      && startswith (IDENTIFIER_POINTER (declarator) + 2,
+			     "builtin_"))
 	  || (targetcm.cxx_implicit_extern_c
 	      && (targetcm.cxx_implicit_extern_c
 		  (IDENTIFIER_POINTER (declarator))))))
diff --git a/gcc/cp/error.c b/gcc/cp/error.c
index ff4ae6f4b23..a4e9b2a6ad9 100644
--- a/gcc/cp/error.c
+++ b/gcc/cp/error.c
@@ -1138,7 +1138,7 @@ dump_decl_name (cxx_pretty_printer *pp, tree t, int flags)
     }
 
   const char *str = IDENTIFIER_POINTER (t);
-  if (!strncmp (str, "_ZGR", 4))
+  if (startswith (str, "_ZGR"))
     {
       pp_cxx_ws_string (pp, "<temporary>");
       return;
diff --git a/gcc/cp/mangle.c b/gcc/cp/mangle.c
index 49f1266bef3..f0e1f416804 100644
--- a/gcc/cp/mangle.c
+++ b/gcc/cp/mangle.c
@@ -1308,10 +1308,10 @@ find_decomp_unqualified_name (tree decl, size_t *len)
   const char *p = IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (decl));
   const char *end = p + IDENTIFIER_LENGTH (DECL_ASSEMBLER_NAME (decl));
   bool nested = false;
-  if (strncmp (p, "_Z", 2))
+  if (!startswith (p, "_Z"))
     return NULL;
   p += 2;
-  if (!strncmp (p, "St", 2))
+  if (startswith (p, "St"))
     p += 2;
   else if (*p == 'N')
     {
@@ -1327,7 +1327,7 @@ find_decomp_unqualified_name (tree decl, size_t *len)
 	    break;
 	}
     }
-  if (strncmp (p, "DC", 2))
+  if (!startswith (p, "DC"))
     return NULL;
   if (nested)
     {
@@ -4430,7 +4430,7 @@ static void
 write_guarded_var_name (const tree variable)
 {
   if (DECL_NAME (variable)
-      && strncmp (IDENTIFIER_POINTER (DECL_NAME (variable)), "_ZGR", 4) == 0)
+      && startswith (IDENTIFIER_POINTER (DECL_NAME (variable)), "_ZGR"))
     /* The name of a guard variable for a reference temporary should refer
        to the reference, not the temporary.  */
     write_string (IDENTIFIER_POINTER (DECL_NAME (variable)) + 4);
@@ -4488,8 +4488,7 @@ decl_tls_wrapper_p (const tree fn)
   if (TREE_CODE (fn) != FUNCTION_DECL)
     return false;
   tree name = DECL_NAME (fn);
-  return strncmp (IDENTIFIER_POINTER (name), TLS_WRAPPER_PREFIX,
-		  strlen (TLS_WRAPPER_PREFIX)) == 0;
+  return startswith (IDENTIFIER_POINTER (name), TLS_WRAPPER_PREFIX);
 }
 
 /* Return an identifier for the name of a temporary variable used to
diff --git a/gcc/cp/parser.c b/gcc/cp/parser.c
index 99eccf0c5e4..5e076ffa34a 100644
--- a/gcc/cp/parser.c
+++ b/gcc/cp/parser.c
@@ -18661,9 +18661,8 @@ cp_parser_simple_type_specifier (cp_parser* parser,
 	  decl_specs->int_n_idx = idx;
 	  /* Check if the alternate "__intN__" form has been used instead of
 	     "__intN".  */
-	  if (strncmp (IDENTIFIER_POINTER (token->u.value)
-			+ (IDENTIFIER_LENGTH (token->u.value) - 2),
-			"__", 2) == 0)
+	  if (startswith (IDENTIFIER_POINTER (token->u.value)
+			  + (IDENTIFIER_LENGTH (token->u.value) - 2), "__"))
 	    decl_specs->int_n_alt = true;
 	}
       type = int_n_trees [idx].signed_type;
@@ -22950,7 +22949,7 @@ cp_parser_tx_qualifier_opt (cp_parser *parser)
       tree name = token->u.value;
       const char *p = IDENTIFIER_POINTER (name);
       const int len = strlen ("transaction_safe");
-      if (!strncmp (p, "transaction_safe", len))
+      if (startswith (p, "transaction_safe"))
 	{
 	  p += len;
 	  if (*p == '\0'
diff --git a/gcc/cp/pt.c b/gcc/cp/pt.c
index 7bcbe6dc3ce..bf1ef09fe05 100644
--- a/gcc/cp/pt.c
+++ b/gcc/cp/pt.c
@@ -6994,7 +6994,7 @@ bool
 template_parm_object_p (const_tree t)
 {
   return (TREE_CODE (t) == VAR_DECL && DECL_ARTIFICIAL (t) && DECL_NAME (t)
-	  && !strncmp (IDENTIFIER_POINTER (DECL_NAME (t)), "_ZTA", 4));
+	  && startswith (IDENTIFIER_POINTER (DECL_NAME (t)), "_ZTA"));
 }
 
 /* Subroutine of convert_nontype_argument, to check whether EXPR, as an
@@ -28474,8 +28474,7 @@ dguide_name_p (tree name)
 {
   return (TREE_CODE (name) == IDENTIFIER_NODE
 	  && TREE_TYPE (name)
-	  && !strncmp (IDENTIFIER_POINTER (name), dguide_base,
-		       strlen (dguide_base)));
+	  && startswith (IDENTIFIER_POINTER (name), dguide_base));
 }
 
 /* True if FN is a deduction guide.  */
diff --git a/gcc/d/d-builtins.cc b/gcc/d/d-builtins.cc
index 400bce0a141..859a8ce2a59 100644
--- a/gcc/d/d-builtins.cc
+++ b/gcc/d/d-builtins.cc
@@ -739,8 +739,7 @@ do_build_builtin_fn (built_in_function fncode,
     return;
 
   gcc_assert ((!both_p && !fallback_p)
-	      || !strncmp (name, "__builtin_",
-			   strlen ("__builtin_")));
+	      || startswith (name, "__builtin_"));
 
   libname = name + strlen ("__builtin_");
 
diff --git a/gcc/d/dmd/dinterpret.c b/gcc/d/dmd/dinterpret.c
index 5e71f3b24a1..9e74a0dbf1f 100644
--- a/gcc/d/dmd/dinterpret.c
+++ b/gcc/d/dmd/dinterpret.c
@@ -6881,7 +6881,7 @@ Expression *evaluateIfBuiltin(UnionExp *pue, InterState *istate, Loc loc,
         const char *id = fd->ident->toChars();
         size_t idlen = strlen(id);
         if (nargs == 2 && (idlen == 10 || idlen == 11) &&
-            !strncmp(id, "_aApply", 7))
+            startswith (id, "_aApply"))
         {
             // Functions from aApply.d and aApplyR.d in the runtime
             bool rvs = (idlen == 11);   // true if foreach_reverse
diff --git a/gcc/d/dmd/dmangle.c b/gcc/d/dmd/dmangle.c
index 83f4c18bee8..f112243cf5f 100644
--- a/gcc/d/dmd/dmangle.c
+++ b/gcc/d/dmd/dmangle.c
@@ -673,7 +673,7 @@ public:
                 cd == ClassDeclaration::object ||
                 cd == Type::typeinfoclass ||
                 cd == Module::moduleinfo ||
-                strncmp(cd->ident->toChars(), "TypeInfo_", 9) == 0)
+                startswith (cd->ident->toChars(), "TypeInfo_"))
             {
                 // Don't mangle parent
                 ad->parent = NULL;
diff --git a/gcc/d/dmd/hdrgen.c b/gcc/d/dmd/hdrgen.c
index 9397b1e8abd..e72273b2dbd 100644
--- a/gcc/d/dmd/hdrgen.c
+++ b/gcc/d/dmd/hdrgen.c
@@ -3212,7 +3212,7 @@ public:
         }
         else if (p->type->ty == Tident &&
                  strlen(((TypeIdentifier *)p->type)->ident->toChars()) > 3 &&
-                 strncmp(((TypeIdentifier *)p->type)->ident->toChars(), "__T", 3) == 0)
+                 startswith (((TypeIdentifier *)p->type)->ident->toChars(), "__T"))
         {
             // print parameter name, instead of undetermined type parameter
             buf->writestring(p->ident->toChars());
diff --git a/gcc/d/dmd/identifier.c b/gcc/d/dmd/identifier.c
index 197d288e532..dd2c58fd657 100644
--- a/gcc/d/dmd/identifier.c
+++ b/gcc/d/dmd/identifier.c
@@ -73,11 +73,11 @@ const char *Identifier::toHChars2()
     {   p = toChars();
         if (*p == '_')
         {
-            if (strncmp(p, "_staticCtor", 11) == 0)
+            if (startswith(p, "_staticCtor"))
                 p = "static this";
-            else if (strncmp(p, "_staticDtor", 11) == 0)
+            else if (startswith(p, "_staticDtor"))
                 p = "static ~this";
-            else if (strncmp(p, "__invariant", 11) == 0)
+            else if (startswith(p, "__invariant"))
                 p = "invariant";
         }
     }
diff --git a/gcc/dwarf2out.c b/gcc/dwarf2out.c
index 7a15debcb48..728e89b331d 100644
--- a/gcc/dwarf2out.c
+++ b/gcc/dwarf2out.c
@@ -5474,7 +5474,7 @@ is_cxx (const_tree decl)
     {
       const_tree context = get_ultimate_context (decl);
       if (context && TRANSLATION_UNIT_LANGUAGE (context))
-	return strncmp (TRANSLATION_UNIT_LANGUAGE (context), "GNU C++", 7) == 0;
+	return startswith (TRANSLATION_UNIT_LANGUAGE (context), "GNU C++");
     }
   return is_cxx ();
 }
@@ -24732,8 +24732,8 @@ gen_compile_unit_die (const char *filename)
 	    common_lang = TRANSLATION_UNIT_LANGUAGE (t);
 	  else if (strcmp (common_lang, TRANSLATION_UNIT_LANGUAGE (t)) == 0)
 	    ;
-	  else if (strncmp (common_lang, "GNU C", 5) == 0
-		    && strncmp (TRANSLATION_UNIT_LANGUAGE (t), "GNU C", 5) == 0)
+	  else if (startswith (common_lang, "GNU C")
+		    && startswith (TRANSLATION_UNIT_LANGUAGE (t), "GNU C"))
 	    /* Mixing C and C++ is ok, use C++ in that case.  */
 	    common_lang = highest_c_language (common_lang,
 					      TRANSLATION_UNIT_LANGUAGE (t));
@@ -24750,7 +24750,7 @@ gen_compile_unit_die (const char *filename)
     }
 
   language = DW_LANG_C;
-  if (strncmp (language_string, "GNU C", 5) == 0
+  if (startswith (language_string, "GNU C")
       && ISDIGIT (language_string[5]))
     {
       language = DW_LANG_C89;
@@ -24766,7 +24766,7 @@ gen_compile_unit_die (const char *filename)
 	      language = DW_LANG_C11;
 	}
     }
-  else if (strncmp (language_string, "GNU C++", 7) == 0)
+  else if (startswith (language_string, "GNU C++"))
     {
       language = DW_LANG_C_plus_plus;
       if (dwarf_version >= 5 /* || !dwarf_strict */)
@@ -24788,7 +24788,7 @@ gen_compile_unit_die (const char *filename)
     {
       if (strcmp (language_string, "GNU Ada") == 0)
 	language = DW_LANG_Ada95;
-      else if (strncmp (language_string, "GNU Fortran", 11) == 0)
+      else if (startswith (language_string, "GNU Fortran"))
 	{
 	  language = DW_LANG_Fortran95;
 	  if (dwarf_version >= 5 /* || !dwarf_strict */)
@@ -24812,7 +24812,7 @@ gen_compile_unit_die (const char *filename)
 	}
     }
   /* Use a degraded Fortran setting in strict DWARF2 so is_fortran works.  */
-  else if (strncmp (language_string, "GNU Fortran", 11) == 0)
+  else if (startswith (language_string, "GNU Fortran"))
     language = DW_LANG_Fortran90;
   /* Likewise for Ada.  */
   else if (strcmp (language_string, "GNU Ada") == 0)
diff --git a/gcc/fortran/decl.c b/gcc/fortran/decl.c
index 947e4f868a1..413c7a75e0c 100644
--- a/gcc/fortran/decl.c
+++ b/gcc/fortran/decl.c
@@ -2721,7 +2721,7 @@ variable_decl (int elem)
     }
 
   /* %FILL components may not have initializers.  */
-  if (gfc_str_startswith (name, "%FILL") && gfc_match_eos () != MATCH_YES)
+  if (startswith (name, "%FILL") && gfc_match_eos () != MATCH_YES)
     {
       gfc_error ("%qs entity cannot have an initializer at %C", "%FILL");
       m = MATCH_ERROR;
@@ -8221,7 +8221,7 @@ gfc_match_end (gfc_statement *st)
     {
     case COMP_ASSOCIATE:
     case COMP_BLOCK:
-      if (gfc_str_startswith (block_name, "block@"))
+      if (startswith (block_name, "block@"))
 	block_name = NULL;
       break;
 
diff --git a/gcc/fortran/gfortran.h b/gcc/fortran/gfortran.h
index 7935aca23db..b8e67bcc03e 100644
--- a/gcc/fortran/gfortran.h
+++ b/gcc/fortran/gfortran.h
@@ -3514,10 +3514,6 @@ bool gfc_is_compile_time_shape (gfc_array_spec *);
 
 bool gfc_ref_dimen_size (gfc_array_ref *, int dimen, mpz_t *, mpz_t *);
 
-
-#define gfc_str_startswith(str, pref) \
-	(strncmp ((str), (pref), strlen (pref)) == 0)
-
 /* interface.c -- FIXME: some of these should be in symbol.c */
 void gfc_free_interface (gfc_interface *);
 bool gfc_compare_derived_types (gfc_symbol *, gfc_symbol *);
diff --git a/gcc/fortran/module.c b/gcc/fortran/module.c
index 089453caa03..321d3256eba 100644
--- a/gcc/fortran/module.c
+++ b/gcc/fortran/module.c
@@ -5029,7 +5029,7 @@ load_omp_udrs (void)
       mio_pool_string (&name);
       gfc_clear_ts (&ts);
       mio_typespec (&ts);
-      if (gfc_str_startswith (name, "operator "))
+      if (startswith (name, "operator "))
 	{
 	  const char *p = name + sizeof ("operator ") - 1;
 	  if (strcmp (p, "+") == 0)
@@ -5477,8 +5477,8 @@ read_module (void)
 
 	  /* Exception: Always import vtabs & vtypes.  */
 	  if (p == NULL && name[0] == '_'
-	      && (gfc_str_startswith (name, "__vtab_")
-		  || gfc_str_startswith (name, "__vtype_")))
+	      && (startswith (name, "__vtab_")
+		  || startswith (name, "__vtype_")))
 	    p = name;
 
 	  /* Skip symtree nodes not in an ONLY clause, unless there
@@ -5563,8 +5563,8 @@ read_module (void)
 		sym->attr.use_rename = 1;
 
 	      if (name[0] != '_'
-		  || (!gfc_str_startswith (name, "__vtab_")
-		      && !gfc_str_startswith (name, "__vtype_")))
+		  || (!startswith (name, "__vtab_")
+		      && !startswith (name, "__vtype_")))
 		sym->attr.use_only = only_flag;
 
 	      /* Store the symtree pointing to this symbol.  */
diff --git a/gcc/fortran/options.c b/gcc/fortran/options.c
index 3a0b98bf1ec..1723f689a57 100644
--- a/gcc/fortran/options.c
+++ b/gcc/fortran/options.c
@@ -615,7 +615,7 @@ gfc_handle_runtime_check_option (const char *arg)
 	      result = 1;
 	      break;
 	    }
-	  else if (optname[n] && pos > 3 && gfc_str_startswith (arg, "no-")
+	  else if (optname[n] && pos > 3 && startswith (arg, "no-")
 		   && strncmp (optname[n], arg+3, pos-3) == 0)
 	    {
 	      gfc_option.rtcheck &= ~optmask[n];
diff --git a/gcc/fortran/primary.c b/gcc/fortran/primary.c
index a6df885c80c..9fe8d1ee20c 100644
--- a/gcc/fortran/primary.c
+++ b/gcc/fortran/primary.c
@@ -1786,21 +1786,21 @@ match_arg_list_function (gfc_actual_arglist *result)
       switch (name[0])
 	{
 	case 'l':
-	  if (gfc_str_startswith (name, "loc"))
+	  if (startswith (name, "loc"))
 	    {
 	      result->name = "%LOC";
 	      break;
 	    }
 	  /* FALLTHRU */
 	case 'r':
-	  if (gfc_str_startswith (name, "ref"))
+	  if (startswith (name, "ref"))
 	    {
 	      result->name = "%REF";
 	      break;
 	    }
 	  /* FALLTHRU */
 	case 'v':
-	  if (gfc_str_startswith (name, "val"))
+	  if (startswith (name, "val"))
 	    {
 	      result->name = "%VAL";
 	      break;
diff --git a/gcc/fortran/trans-decl.c b/gcc/fortran/trans-decl.c
index cc9d85543ca..a1701887c8b 100644
--- a/gcc/fortran/trans-decl.c
+++ b/gcc/fortran/trans-decl.c
@@ -1941,7 +1941,7 @@ gfc_get_symbol_decl (gfc_symbol * sym)
      Marking this as artificial means that OpenMP will treat this as
      predetermined shared.  */
 
-  bool def_init = gfc_str_startswith (sym->name, "__def_init");
+  bool def_init = startswith (sym->name, "__def_init");
 
   if (sym->attr.vtab || def_init)
     {
diff --git a/gcc/fortran/trans-expr.c b/gcc/fortran/trans-expr.c
index 213f32b0a67..0295617a1ae 100644
--- a/gcc/fortran/trans-expr.c
+++ b/gcc/fortran/trans-expr.c
@@ -6840,7 +6840,7 @@ gfc_conv_procedure_call (gfc_se * se, gfc_symbol * sym,
       /* When calling __copy for character expressions to unlimited
 	 polymorphic entities, the dst argument needs a string length.  */
       if (sym->name[0] == '_' && e && e->ts.type == BT_CHARACTER
-	  && gfc_str_startswith (sym->name, "__vtab_CHARACTER")
+	  && startswith (sym->name, "__vtab_CHARACTER")
 	  && arg->next && arg->next->expr
 	  && (arg->next->expr->ts.type == BT_DERIVED
 	      || arg->next->expr->ts.type == BT_CLASS)
diff --git a/gcc/fortran/trans-intrinsic.c b/gcc/fortran/trans-intrinsic.c
index 5e53d1162fa..1369d2f76b9 100644
--- a/gcc/fortran/trans-intrinsic.c
+++ b/gcc/fortran/trans-intrinsic.c
@@ -10072,27 +10072,27 @@ gfc_conv_ieee_arithmetic_function (gfc_se * se, gfc_expr * expr)
 {
   const char *name = expr->value.function.name;
 
-  if (gfc_str_startswith (name, "_gfortran_ieee_is_nan"))
+  if (startswith (name, "_gfortran_ieee_is_nan"))
     conv_intrinsic_ieee_builtin (se, expr, BUILT_IN_ISNAN, 1);
-  else if (gfc_str_startswith (name, "_gfortran_ieee_is_finite"))
+  else if (startswith (name, "_gfortran_ieee_is_finite"))
     conv_intrinsic_ieee_builtin (se, expr, BUILT_IN_ISFINITE, 1);
-  else if (gfc_str_startswith (name, "_gfortran_ieee_unordered"))
+  else if (startswith (name, "_gfortran_ieee_unordered"))
     conv_intrinsic_ieee_builtin (se, expr, BUILT_IN_ISUNORDERED, 2);
-  else if (gfc_str_startswith (name, "_gfortran_ieee_is_normal"))
+  else if (startswith (name, "_gfortran_ieee_is_normal"))
     conv_intrinsic_ieee_is_normal (se, expr);
-  else if (gfc_str_startswith (name, "_gfortran_ieee_is_negative"))
+  else if (startswith (name, "_gfortran_ieee_is_negative"))
     conv_intrinsic_ieee_is_negative (se, expr);
-  else if (gfc_str_startswith (name, "_gfortran_ieee_copy_sign"))
+  else if (startswith (name, "_gfortran_ieee_copy_sign"))
     conv_intrinsic_ieee_copy_sign (se, expr);
-  else if (gfc_str_startswith (name, "_gfortran_ieee_scalb"))
+  else if (startswith (name, "_gfortran_ieee_scalb"))
     conv_intrinsic_ieee_scalb (se, expr);
-  else if (gfc_str_startswith (name, "_gfortran_ieee_next_after"))
+  else if (startswith (name, "_gfortran_ieee_next_after"))
     conv_intrinsic_ieee_next_after (se, expr);
-  else if (gfc_str_startswith (name, "_gfortran_ieee_rem"))
+  else if (startswith (name, "_gfortran_ieee_rem"))
     conv_intrinsic_ieee_rem (se, expr);
-  else if (gfc_str_startswith (name, "_gfortran_ieee_logb"))
+  else if (startswith (name, "_gfortran_ieee_logb"))
     conv_intrinsic_ieee_logb_rint (se, expr, BUILT_IN_LOGB);
-  else if (gfc_str_startswith (name, "_gfortran_ieee_rint"))
+  else if (startswith (name, "_gfortran_ieee_rint"))
     conv_intrinsic_ieee_logb_rint (se, expr, BUILT_IN_RINT);
   else
     /* It is not among the functions we translate directly.  We return
diff --git a/gcc/gcc-ar.c b/gcc/gcc-ar.c
index e76d4525e0c..cbc7662e03d 100644
--- a/gcc/gcc-ar.c
+++ b/gcc/gcc-ar.c
@@ -140,7 +140,7 @@ main (int ac, char **av)
 
   /* Not using getopt for now.  */
   for (i = 0; i < ac; i++)
-      if (!strncmp (av[i], "-B", 2))
+      if (startswith (av[i], "-B"))
 	{
 	  const char *arg = av[i] + 2;
 	  const char *end;
diff --git a/gcc/gcc.c b/gcc/gcc.c
index 7837553958b..0a17e86ccea 100644
--- a/gcc/gcc.c
+++ b/gcc/gcc.c
@@ -1900,7 +1900,7 @@ init_spec (void)
        when given the proper command line arguments.  */
     while (*p)
       {
-	if (in_sep && *p == '-' && strncmp (p, "-lgcc", 5) == 0)
+	if (in_sep && *p == '-' && startswith (p, "-lgcc"))
 	  {
 	    init_gcc_specs (&obstack,
 			    "-lgcc_s"
@@ -1923,7 +1923,7 @@ init_spec (void)
 	    p += 5;
 	    in_sep = 0;
 	  }
-	else if (in_sep && *p == 'l' && strncmp (p, "libgcc.a%s", 10) == 0)
+	else if (in_sep && *p == 'l' && startswith (p, "libgcc.a%s"))
 	  {
 	    /* Ug.  We don't know shared library extensions.  Hope that
 	       systems that use this form don't do shared libraries.  */
@@ -2378,7 +2378,7 @@ read_specs (const char *filename, bool main_p, bool user_p)
 	  /* Skip '\n'.  */
 	  p++;
 
-	  if (!strncmp (p1, "%include", sizeof ("%include") - 1)
+	  if (startswith (p1, "%include")
 	      && (p1[sizeof "%include" - 1] == ' '
 		  || p1[sizeof "%include" - 1] == '\t'))
 	    {
@@ -2399,7 +2399,7 @@ read_specs (const char *filename, bool main_p, bool user_p)
 	      read_specs (new_filename ? new_filename : p1, false, user_p);
 	      continue;
 	    }
-	  else if (!strncmp (p1, "%include_noerr", sizeof "%include_noerr" - 1)
+	  else if (startswith (p1, "%include_noerr")
 		   && (p1[sizeof "%include_noerr" - 1] == ' '
 		       || p1[sizeof "%include_noerr" - 1] == '\t'))
 	    {
@@ -2423,7 +2423,7 @@ read_specs (const char *filename, bool main_p, bool user_p)
 		fnotice (stderr, "could not find specs file %s\n", p1);
 	      continue;
 	    }
-	  else if (!strncmp (p1, "%rename", sizeof "%rename" - 1)
+	  else if (startswith (p1, "%rename")
 		   && (p1[sizeof "%rename" - 1] == ' '
 		       || p1[sizeof "%rename" - 1] == '\t'))
 	    {
@@ -3496,7 +3496,7 @@ execute (void)
 		&& WEXITSTATUS (status) == ICE_EXIT_CODE
 		&& i == 0
 		&& (p = strrchr (commands[0].argv[0], DIR_SEPARATOR))
-		&& ! strncmp (p + 1, "cc1", 3))
+		&& startswith (p + 1, "cc1"))
 	      try_generate_repro (commands[0].argv);
 	    if (WEXITSTATUS (status) > greatest_status)
 	      greatest_status = WEXITSTATUS (status);
@@ -7324,7 +7324,7 @@ check_live_switch (int switchnum, int prefix_length)
       break;
 
     case 'W':  case 'f':  case 'm': case 'g':
-      if (! strncmp (name + 1, "no-", 3))
+      if (startswith (name + 1, "no-"))
 	{
 	  /* We have Xno-YYY, search for XYYY.  */
 	  for (i = switchnum + 1; i < n_switches; i++)
diff --git a/gcc/genattrtab.c b/gcc/genattrtab.c
index afea3602e50..e69d175a05a 100644
--- a/gcc/genattrtab.c
+++ b/gcc/genattrtab.c
@@ -4344,7 +4344,7 @@ write_attr_case (FILE *outf, class attr_desc *attr, struct attr_value *av,
     write_attr_set (outf, attr, indent + 2, av->value, prefix, suffix,
 		    known_true, -2, 0, 0);
 
-  if (strncmp (prefix, "return", 6))
+  if (!startswith (prefix, "return"))
     {
       write_indent (outf, indent + 2);
       fprintf (outf, "break;\n");
@@ -5377,14 +5377,12 @@ main (int argc, const char **argv)
       {
         FILE *outf;
 
-#define IS_ATTR_GROUP(X) (!strncmp (attr->name, X, strlen (X)))
-	if (IS_ATTR_GROUP ("*internal_dfa_insn_code"))
+	if (startswith(attr->name, "*internal_dfa_insn_code"))
 	  outf = dfa_file;
-	else if (IS_ATTR_GROUP ("*insn_default_latency"))
+	else if (startswith (attr->name, "*insn_default_latency"))
 	  outf = latency_file;  
 	else
 	  outf = attr_file;
-#undef IS_ATTR_GROUP
 
 	if (! attr->is_special && ! attr->is_const)
 	  write_attr_get (outf, attr);
diff --git a/gcc/gencfn-macros.c b/gcc/gencfn-macros.c
index b620fe6aebc..fd9ae14fc04 100644
--- a/gcc/gencfn-macros.c
+++ b/gcc/gencfn-macros.c
@@ -208,7 +208,7 @@ main (int argc, char **argv)
   for (unsigned int i = 0; builtin_names[i]; ++i)
     {
       const char *name = builtin_names[i];
-      if (strncmp (name, "BUILT_IN_", 9) == 0)
+      if (startswith (name, "BUILT_IN_"))
 	{
 	  const char *root = name + 9;
 	  for (unsigned int j = 0; suffix_lists[j]; ++j)
diff --git a/gcc/gengtype.c b/gcc/gengtype.c
index 98d4626f87e..b94e2f126ec 100644
--- a/gcc/gengtype.c
+++ b/gcc/gengtype.c
@@ -671,7 +671,7 @@ type_for_name (const char *s)
          extern GTY(()) gcc::some_type *some_ptr;
      where the autogenerated functions will refer to simply "some_type",
      where they can be resolved into their namespace.  */
-  if (strncmp (s, "gcc::", 5) == 0)
+  if (startswith (s, "gcc::"))
     s += 5;
 
   for (p = typedefs; p != NULL; p = p->next)
@@ -1102,7 +1102,7 @@ gen_rtx_next (void)
       int k;
 
       rtx_next_new[i] = -1;
-      if (strncmp (rtx_format[i], "uu", 2) == 0)
+      if (startswith (rtx_format[i], "uu"))
 	rtx_next_new[i] = 1;
       else if (i == COND_EXEC || i == SET || i == EXPR_LIST || i == INSN_LIST)
 	rtx_next_new[i] = 1;
@@ -1828,7 +1828,7 @@ get_file_langdir (const input_file *inpf)
     return NULL;
 
   lang_index = get_prefix_langdir_index (srcdir_relative_path);
-  if (lang_index < 0 && strncmp (srcdir_relative_path, "c-family", 8) == 0)
+  if (lang_index < 0 && startswith (srcdir_relative_path, "c-family"))
     r = "c-family";
   else if (lang_index >= 0)
     r = lang_dir_names[lang_index];
@@ -4044,7 +4044,7 @@ write_local (outf_p output_header, type_p structures)
 	   || ((s)->gc_used == GC_MAYBE_POINTED_TO			\
 	       && s->u.s.line.file != NULL)				\
 	   || ((s)->gc_used == GC_USED					\
-	       && strncmp (s->u.s.tag, "anonymous", strlen ("anonymous"))) \
+	       && !startswith (s->u.s.tag, "anonymous"))		\
 	   || (s->u.s.base_class && opts_have (s->u.s.opt, "tag")))))
 
 
diff --git a/gcc/genmatch.c b/gcc/genmatch.c
index 8311f5d768a..332afc842b7 100644
--- a/gcc/genmatch.c
+++ b/gcc/genmatch.c
@@ -605,10 +605,10 @@ get_operator (const char *id, bool allow_null = false)
       for (unsigned int i = 0; id2[i]; ++i)
 	id2[i] = TOUPPER (id2[i]);
     }
-  else if (all_upper && strncmp (id, "IFN_", 4) == 0)
+  else if (all_upper && startswith (id, "IFN_"))
     /* Try CFN_ instead of IFN_.  */
     id2 = ACONCAT (("CFN_", id + 4, NULL));
-  else if (all_upper && strncmp (id, "BUILT_IN_", 9) == 0)
+  else if (all_upper && startswith (id, "BUILT_IN_"))
     /* Try prepending CFN_.  */
     id2 = ACONCAT (("CFN_", id, NULL));
   else
@@ -2391,7 +2391,7 @@ get_operand_type (id_base *op, unsigned pos,
   else if (*op == COND_EXPR
 	   && pos == 0)
     return "boolean_type_node";
-  else if (strncmp (op->id, "CFN_COND_", 9) == 0)
+  else if (startswith (op->id, "CFN_COND_"))
     {
       /* IFN_COND_* operands 1 and later by default have the same type
 	 as the result.  The type of operand 0 needs to be specified
@@ -2464,7 +2464,7 @@ expr::gen_transform (FILE *f, int indent, const char *dest, bool gimple,
     }
   else if (*opr == COND_EXPR
 	   || *opr == VEC_COND_EXPR
-	   || strncmp (opr->id, "CFN_COND_", 9) == 0)
+	   || startswith (opr->id, "CFN_COND_"))
     {
       /* Conditions are of the same type as their first alternative.  */
       snprintf (optype, sizeof (optype), "TREE_TYPE (_o%d[1])", depth);
diff --git a/gcc/genoutput.c b/gcc/genoutput.c
index 25af4375d9c..8e911cce2f5 100644
--- a/gcc/genoutput.c
+++ b/gcc/genoutput.c
@@ -841,7 +841,7 @@ validate_optab_operands (class data *d)
     return;
 
   /* Miscellaneous tests.  */
-  if (strncmp (d->name, "cstore", 6) == 0
+  if (startswith (d->name, "cstore")
       && d->name[strlen (d->name) - 1] == '4'
       && d->operand[0].mode == VOIDmode)
     {
diff --git a/gcc/go/gofrontend/runtime.cc b/gcc/go/gofrontend/runtime.cc
index 3cc5ded3617..514c045a68f 100644
--- a/gcc/go/gofrontend/runtime.cc
+++ b/gcc/go/gofrontend/runtime.cc
@@ -463,7 +463,7 @@ Runtime::name_to_code(const std::string& name)
       // The names in the table have "runtime." prefix. We may be
       // called with a name without the prefix. Try matching
       // without the prefix as well.
-      if (strncmp(runtime_function_name, "runtime.", 8) == 0
+      if (startswith(runtime_function_name, "runtime.")
           && strcmp(runtime_function_name + 8, name.c_str()) == 0)
         code = static_cast<Runtime::Function>(i);
     }
diff --git a/gcc/incpath.c b/gcc/incpath.c
index 446d280321d..52dbb806b1b 100644
--- a/gcc/incpath.c
+++ b/gcc/incpath.c
@@ -330,7 +330,7 @@ add_sysroot_to_chain (const char *sysroot, int chain)
 	{
 	  if (p->name[0] == '=')
 	    p->name = concat (sysroot, p->name + 1, NULL);
-	  if (strncmp (p->name, "$SYSROOT", strlen ("$SYSROOT")) == 0)
+	  if (startswith (p->name, "$SYSROOT"))
 	    p->name = concat (sysroot, p->name + strlen ("$SYSROOT"), NULL);
 	}
     }
diff --git a/gcc/langhooks.c b/gcc/langhooks.c
index 2354386f7b4..12c99888e6c 100644
--- a/gcc/langhooks.c
+++ b/gcc/langhooks.c
@@ -901,7 +901,7 @@ lhd_finalize_early_debug (void)
 bool
 lang_GNU_C (void)
 {
-  return (strncmp (lang_hooks.name, "GNU C", 5) == 0
+  return (startswith (lang_hooks.name, "GNU C")
 	  && (lang_hooks.name[5] == '\0' || ISDIGIT (lang_hooks.name[5])));
 }
 
@@ -910,7 +910,7 @@ lang_GNU_C (void)
 bool
 lang_GNU_CXX (void)
 {
-  return strncmp (lang_hooks.name, "GNU C++", 7) == 0;
+  return startswith (lang_hooks.name, "GNU C++");
 }
 
 /* Returns true if the current lang_hooks represents the GNU Fortran frontend.  */
@@ -918,7 +918,7 @@ lang_GNU_CXX (void)
 bool
 lang_GNU_Fortran (void)
 {
-  return strncmp (lang_hooks.name, "GNU Fortran", 11) == 0;
+  return startswith (lang_hooks.name, "GNU Fortran");
 }
 
 /* Returns true if the current lang_hooks represents the GNU Objective-C
@@ -927,5 +927,5 @@ lang_GNU_Fortran (void)
 bool
 lang_GNU_OBJC (void)
 {
-  return strncmp (lang_hooks.name, "GNU Objective-C", 15) == 0;
+  return startswith (lang_hooks.name, "GNU Objective-C");
 }
diff --git a/gcc/lto-wrapper.c b/gcc/lto-wrapper.c
index 03a5922f8ea..efb6ee644f4 100644
--- a/gcc/lto-wrapper.c
+++ b/gcc/lto-wrapper.c
@@ -1437,8 +1437,7 @@ run_gcc (unsigned argc, char *argv[])
       int consumed;
       char *filename = argv[i];
 
-      if (strncmp (argv[i], "-foffload-objects=",
-		   sizeof ("-foffload-objects=") - 1) == 0)
+      if (startswith (argv[i], "-foffload-objects="))
 	{
 	  have_offload = true;
 	  offload_objects_file_name
diff --git a/gcc/objc/objc-act.c b/gcc/objc/objc-act.c
index 1cbd586b8fb..796256d437e 100644
--- a/gcc/objc/objc-act.c
+++ b/gcc/objc/objc-act.c
@@ -10275,7 +10275,7 @@ objc_string_ref_type_p (tree strp)
   return (tmv
 	  && TREE_CODE (tmv) == IDENTIFIER_NODE
 	  && IDENTIFIER_POINTER (tmv)
-	  && !strncmp (IDENTIFIER_POINTER (tmv), "NSString", 8));
+	  && startswith (IDENTIFIER_POINTER (tmv), "NSString"));
 }
 
 /* At present the behavior of this is undefined and it does nothing.  */
diff --git a/gcc/objc/objc-encoding.c b/gcc/objc/objc-encoding.c
index c4067b1d527..7ad920a2c35 100644
--- a/gcc/objc/objc-encoding.c
+++ b/gcc/objc/objc-encoding.c
@@ -733,7 +733,7 @@ encode_type (tree type, int curtype, int format)
 	  char *enc = (char *) obstack_base (&util_obstack) + curtype;
 
 	  /* Rewrite "in const" from "nr" to "rn".  */
-	  if (curtype >= 1 && !strncmp (enc - 1, "nr", 2))
+	  if (curtype >= 1 && startswith (enc - 1, "nr"))
 	    memcpy (enc - 1, "rn", 2);
 	}
     }
diff --git a/gcc/objc/objc-next-runtime-abi-02.c b/gcc/objc/objc-next-runtime-abi-02.c
index af68c1c84a3..3cfcd0b1a57 100644
--- a/gcc/objc/objc-next-runtime-abi-02.c
+++ b/gcc/objc/objc-next-runtime-abi-02.c
@@ -2209,7 +2209,7 @@ has_load_impl (tree clsmeth)
     {
       tree id = METHOD_SEL_NAME (clsmeth);
       if (IDENTIFIER_LENGTH (id) == 4
-	  && strncmp (IDENTIFIER_POINTER (id), "load", 4) == 0)
+	  && startswith (IDENTIFIER_POINTER (id), "load"))
         return true;
       clsmeth = DECL_CHAIN (clsmeth);
     }
diff --git a/gcc/omp-general.c b/gcc/omp-general.c
index fa6de01722b..a1bb9d8d25d 100644
--- a/gcc/omp-general.c
+++ b/gcc/omp-general.c
@@ -968,7 +968,7 @@ omp_max_simt_vf (void)
   if (ENABLE_OFFLOADING)
     for (const char *c = getenv ("OFFLOAD_TARGET_NAMES"); c;)
       {
-	if (!strncmp (c, "nvptx", strlen ("nvptx")))
+	if (startswith (c, "nvptx"))
 	  return 32;
 	else if ((c = strchr (c, ':')))
 	  c++;
diff --git a/gcc/omp-low.c b/gcc/omp-low.c
index 7b122059c6e..e735af974ee 100644
--- a/gcc/omp-low.c
+++ b/gcc/omp-low.c
@@ -3786,7 +3786,7 @@ omp_runtime_api_call (const_tree fndecl)
     return false;
 
   const char *name = IDENTIFIER_POINTER (declname);
-  if (strncmp (name, "omp_", 4) != 0)
+  if (!startswith (name, "omp_"))
     return false;
 
   static const char *omp_runtime_apis[] =
diff --git a/gcc/opts-common.c b/gcc/opts-common.c
index 5e10edeb4cf..9d1914ff2ff 100644
--- a/gcc/opts-common.c
+++ b/gcc/opts-common.c
@@ -1805,7 +1805,7 @@ parse_options_from_collect_gcc_options (const char *collect_gcc_options,
 	      if (argv_storage[j] == '\0')
 		fatal_error (input_location,
 			     "malformed %<COLLECT_GCC_OPTIONS%>");
-	      else if (strncmp (&argv_storage[j], "'\\''", 4) == 0)
+	      else if (startswith (&argv_storage[j], "'\\''"))
 		{
 		  argv_storage[k++] = '\'';
 		  j += 4;
diff --git a/gcc/read-rtl-function.c b/gcc/read-rtl-function.c
index 2a1fb4bac9c..eaf380dd466 100644
--- a/gcc/read-rtl-function.c
+++ b/gcc/read-rtl-function.c
@@ -1082,7 +1082,7 @@ function_reader::read_rtx_operand_r (rtx x)
 	 "orig:%i", ORIGINAL_REGNO (rtx).
 	 Consume it, we don't set ORIGINAL_REGNO, since we can
 	 get that from the 2nd copy later.  */
-      if (strncmp (desc, "orig:", 5) == 0)
+      if (startswith (desc, "orig:"))
 	{
 	  expect_original_regno = true;
 	  desc_start += 5;
diff --git a/gcc/real.c b/gcc/real.c
index 09957a91b7c..555cf44c142 100644
--- a/gcc/real.c
+++ b/gcc/real.c
@@ -1972,17 +1972,17 @@ real_from_string (REAL_VALUE_TYPE *r, const char *str)
   else if (*str == '+')
     str++;
 
-  if (!strncmp (str, "QNaN", 4))
+  if (startswith (str, "QNaN"))
     {
       get_canonical_qnan (r, sign);
       return 0;
     }
-  else if (!strncmp (str, "SNaN", 4))
+  else if (startswith (str, "SNaN"))
     {
       get_canonical_snan (r, sign);
       return 0;
     }
-  else if (!strncmp (str, "Inf", 3))
+  else if (startswith (str, "Inf"))
     {
       get_inf (r, sign);
       return 0;
diff --git a/gcc/selftest.c b/gcc/selftest.c
index 6e26ea553f2..8f1cde0cc19 100644
--- a/gcc/selftest.c
+++ b/gcc/selftest.c
@@ -150,8 +150,7 @@ assert_str_startswith (const location &loc,
 		    "ASSERT_STR_STARTSWITH (%s, %s) str=\"%s\" prefix=NULL",
 		    desc_str, desc_prefix, val_str);
 
-  const char *test = strstr (val_str, val_prefix);
-  if (test == val_str)
+  if (startswith (val_str, val_prefix))
     pass (loc, "ASSERT_STR_STARTSWITH");
   else
     fail_formatted
diff --git a/gcc/system.h b/gcc/system.h
index a3f5948aaee..51ccf753fd4 100644
--- a/gcc/system.h
+++ b/gcc/system.h
@@ -1291,4 +1291,12 @@ void gcc_stablesort (void *, size_t, size_t,
 #define NULL nullptr
 #endif
 
+/* Return true if STR string starts with PREFIX.  */
+
+static inline bool
+startswith (const char *str, const char *prefix)
+{
+  return strncmp (str, prefix, strlen (prefix)) == 0;
+}
+
 #endif /* ! GCC_SYSTEM_H */
diff --git a/gcc/timevar.c b/gcc/timevar.c
index 5d4e1597f23..8fc122ba9fe 100644
--- a/gcc/timevar.c
+++ b/gcc/timevar.c
@@ -600,7 +600,7 @@ timer::validate_phases (FILE *fp) const
       if (!tv->used)
 	continue;
 
-      if (strncmp (tv->name, phase_prefix, sizeof phase_prefix - 1) == 0)
+      if (startswith (tv->name, phase_prefix))
 	{
 	  phase_user += tv->elapsed.user;
 	  phase_sys += tv->elapsed.sys;
diff --git a/gcc/tree.c b/gcc/tree.c
index e4e74ac8afc..3ed7ea349f6 100644
--- a/gcc/tree.c
+++ b/gcc/tree.c
@@ -9725,7 +9725,7 @@ get_file_function_name (const char *type)
      We also assign sub_I and sub_D sufixes to constructors called from
      the global static constructors.  These are always local.  */
   else if (((type[0] == 'I' || type[0] == 'D') && targetm.have_ctors_dtors)
-	   || (strncmp (type, "sub_", 4) == 0
+	   || (startswith (type, "sub_")
 	       && (type[4] == 'I' || type[4] == 'D')))
     {
       const char *file = main_input_filename;
diff --git a/gcc/ubsan.c b/gcc/ubsan.c
index 1089aef639f..7ee93436378 100644
--- a/gcc/ubsan.c
+++ b/gcc/ubsan.c
@@ -1783,7 +1783,7 @@ ubsan_use_new_style_p (location_t loc)
     return false;
 
   expanded_location xloc = expand_location (loc);
-  if (xloc.file == NULL || strncmp (xloc.file, "\1", 2) == 0
+  if (xloc.file == NULL || startswith (xloc.file, "\1")
       || xloc.file[0] == '\0' || xloc.file[0] == '\xff'
       || xloc.file[1] == '\xff')
     return false;
diff --git a/gcc/varasm.c b/gcc/varasm.c
index 8bb921faa26..bc2727c9303 100644
--- a/gcc/varasm.c
+++ b/gcc/varasm.c
@@ -792,7 +792,7 @@ default_function_rodata_section (tree decl, bool relocatable)
       /* For .gnu.linkonce.t.foo we want to use .gnu.linkonce.r.foo or
 	 .gnu.linkonce.d.rel.ro.local.foo if the jump table is relocatable.  */
       else if (DECL_COMDAT_GROUP (decl)
-	       && strncmp (name, ".gnu.linkonce.t.", 16) == 0)
+	       && startswith (name, ".gnu.linkonce.t."))
 	{
 	  size_t len;
 	  char *rname;
@@ -817,7 +817,7 @@ default_function_rodata_section (tree decl, bool relocatable)
 	}
       /* For .text.foo we want to use .rodata.foo.  */
       else if (flag_function_sections && flag_data_sections
-	       && strncmp (name, ".text.", 6) == 0)
+	       && startswith (name, ".text."))
 	{
 	  size_t len = strlen (name) + 1;
 	  char *rname = (char *) alloca (len + strlen (sname) - 5);
@@ -2485,7 +2485,7 @@ incorporeal_function_p (tree decl)
       name = IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (decl));
       /* Atomic or sync builtins which have survived this far will be
 	 resolved externally and therefore are not incorporeal.  */
-      if (strncmp (name, "__builtin_", 10) == 0)
+      if (startswith (name, "__builtin_"))
 	return true;
     }
   return false;
@@ -6713,22 +6713,22 @@ default_section_type_flags (tree decl, const char *name, int reloc)
     flags |= SECTION_TLS | SECTION_WRITE;
 
   if (strcmp (name, ".bss") == 0
-      || strncmp (name, ".bss.", 5) == 0
-      || strncmp (name, ".gnu.linkonce.b.", 16) == 0
+      || startswith (name, ".bss.")
+      || startswith (name, ".gnu.linkonce.b.")
       || strcmp (name, ".persistent.bss") == 0
       || strcmp (name, ".sbss") == 0
-      || strncmp (name, ".sbss.", 6) == 0
-      || strncmp (name, ".gnu.linkonce.sb.", 17) == 0)
+      || startswith (name, ".sbss.")
+      || startswith (name, ".gnu.linkonce.sb."))
     flags |= SECTION_BSS;
 
   if (strcmp (name, ".tdata") == 0
-      || strncmp (name, ".tdata.", 7) == 0
-      || strncmp (name, ".gnu.linkonce.td.", 17) == 0)
+      || startswith (name, ".tdata.")
+      || startswith (name, ".gnu.linkonce.td."))
     flags |= SECTION_TLS;
 
   if (strcmp (name, ".tbss") == 0
-      || strncmp (name, ".tbss.", 6) == 0
-      || strncmp (name, ".gnu.linkonce.tb.", 17) == 0)
+      || startswith (name, ".tbss.")
+      || startswith (name, ".gnu.linkonce.tb."))
     flags |= SECTION_TLS | SECTION_BSS;
 
   if (strcmp (name, ".noinit") == 0)
-- 
2.31.1
Arnaud Charlet April 25, 2021, 2:47 p.m. | #3
> Thank you for a quick reply.

> There's an updated version of the patch.


The Ada part is OK now, thanks.
Richard Sandiford via Gcc-patches May 10, 2021, 7:16 a.m. | #4
On Wed, Apr 21, 2021 at 11:39 AM Martin Liška <mliska@suse.cz> wrote:
>

> On 4/21/21 9:32 AM, Arnaud Charlet wrote:

> >> gcc/ada/ChangeLog:

> >>

> >>      * adadecode.c (has_prefix): Remove has_prefix and replace it

> >>      with startswith.

> >>      (__gnat_decode): Likewise.

> >

> > This change is not OK: adadecode.c is also a runtime file and as such cannot

> > include compiler include files.

> >

> >>      * gcc-interface/utils.c (def_builtin_1): Use startswith

> >>      function instead of strncmp.

> >

> >>      * init.c (__gnat_install_handler): Likewise.

> >

> > Same for init.c which is both a host and a runtime/target file.

> >

> > Only the change in utils.c is OK.

> >

> > Arno

> >

>

> Thank you for a quick reply.

>

> There's an updated version of the patch.


OK.

Thanks,
Richard.

> Cheers,

> Martin
Richard Sandiford via Gcc-patches May 18, 2021, 10:07 a.m. | #5
Excerpts from Martin Liska's message of March 17, 2021 4:36 pm:
> 

> gcc/d/ChangeLog:

> 

> 	* d-builtins.cc (do_build_builtin_fn): Use startswith

> 	function instead of strncmp.

> 	* dmd/dinterpret.c (evaluateIfBuiltin): Likewise.

> 	* dmd/dmangle.c: Likewise.

> 	* dmd/hdrgen.c: Likewise.

> 	* dmd/identifier.c (Identifier::toHChars2): Likewise.

> 


Hi,

Sorry for just noticing, but the sources in dmd/ (unless noted
otherwise) are maintained in an external repository.  All changes must
first go through there.

That aside, the DMD front-end is meant to be a common implementation
shared between two other compilers, therefore does not have any
dependency on GCC itself.  This patch changes that status quo.

So without prejudice, I'll revert the changes to dmd/ only.  There are,
I note, a few other places in d/*.cc that use strncmp() but could
instead use startswith().

d/d-incpath.cc:37:if (!strncmp (path, cpp_PREFIX, len))
d/d-incpath.cc:61:if (!strncmp (path, cpp_GCC_INCLUDE_DIR, len))
d/types.cc:877:gcc_assert (strncmp (ident, "__c_", strlen ("__c_")) == 0);


> gcc/go/ChangeLog:

> 

> 	* gofrontend/runtime.cc (Runtime::name_to_code): Use startswith

> 	function instead of strncmp.

> 


I might be wrong, but I'm pretty certain that Go is the same in having
an external repository for these sources.

Iain.
Martin Liška May 18, 2021, 12:32 p.m. | #6
On 5/18/21 12:07 PM, Iain Buclaw wrote:
> Excerpts from Martin Liska's message of March 17, 2021 4:36 pm:

>>

>> gcc/d/ChangeLog:

>>

>> 	* d-builtins.cc (do_build_builtin_fn): Use startswith

>> 	function instead of strncmp.

>> 	* dmd/dinterpret.c (evaluateIfBuiltin): Likewise.

>> 	* dmd/dmangle.c: Likewise.

>> 	* dmd/hdrgen.c: Likewise.

>> 	* dmd/identifier.c (Identifier::toHChars2): Likewise.

>>

> 

> Hi,

> 

> Sorry for just noticing, but the sources in dmd/ (unless noted

> otherwise) are maintained in an external repository.  All changes must

> first go through there.

> 

> That aside, the DMD front-end is meant to be a common implementation

> shared between two other compilers, therefore does not have any

> dependency on GCC itself.  This patch changes that status quo.

> 

> So without prejudice, I'll revert the changes to dmd/ only.  There are,

> I note, a few other places in d/*.cc that use strncmp() but could

> instead use startswith().

> 

> d/d-incpath.cc:37:if (!strncmp (path, cpp_PREFIX, len))

> d/d-incpath.cc:61:if (!strncmp (path, cpp_GCC_INCLUDE_DIR, len))

> d/types.cc:877:gcc_assert (strncmp (ident, "__c_", strlen ("__c_")) == 0);

> 

> 

>> gcc/go/ChangeLog:

>>

>> 	* gofrontend/runtime.cc (Runtime::name_to_code): Use startswith

>> 	function instead of strncmp.

>>

> 

> I might be wrong, but I'm pretty certain that Go is the same in having

> an external repository for these sources.


Hello.

Sorry for that. Feel free to revert these changes.

Martin

> 

> Iain.

>
Richard Sandiford via Gcc-patches May 19, 2021, 3:08 a.m. | #7
On Tue, May 18, 2021 at 5:32 AM Martin Liška <mliska@suse.cz> wrote:
>

> On 5/18/21 12:07 PM, Iain Buclaw wrote:

> > Excerpts from Martin Liska's message of March 17, 2021 4:36 pm:

> >>

> >> gcc/d/ChangeLog:

> >>

> >>      * d-builtins.cc (do_build_builtin_fn): Use startswith

> >>      function instead of strncmp.

> >>      * dmd/dinterpret.c (evaluateIfBuiltin): Likewise.

> >>      * dmd/dmangle.c: Likewise.

> >>      * dmd/hdrgen.c: Likewise.

> >>      * dmd/identifier.c (Identifier::toHChars2): Likewise.

> >>

> >

> > Hi,

> >

> > Sorry for just noticing, but the sources in dmd/ (unless noted

> > otherwise) are maintained in an external repository.  All changes must

> > first go through there.

> >

> > That aside, the DMD front-end is meant to be a common implementation

> > shared between two other compilers, therefore does not have any

> > dependency on GCC itself.  This patch changes that status quo.

> >

> > So without prejudice, I'll revert the changes to dmd/ only.  There are,

> > I note, a few other places in d/*.cc that use strncmp() but could

> > instead use startswith().

> >

> > d/d-incpath.cc:37:if (!strncmp (path, cpp_PREFIX, len))

> > d/d-incpath.cc:61:if (!strncmp (path, cpp_GCC_INCLUDE_DIR, len))

> > d/types.cc:877:gcc_assert (strncmp (ident, "__c_", strlen ("__c_")) == 0);

> >

> >

> >> gcc/go/ChangeLog:

> >>

> >>      * gofrontend/runtime.cc (Runtime::name_to_code): Use startswith

> >>      function instead of strncmp.

> >>

> >

> > I might be wrong, but I'm pretty certain that Go is the same in having

> > an external repository for these sources.

>

> Hello.

>

> Sorry for that. Feel free to revert these changes.



I've reverted the change in gcc/go/gofrontend.

Ian

Patch

diff --git a/gcc/ada/adadecode.c b/gcc/ada/adadecode.c
index 43a378f9058..1154e628311 100644
--- a/gcc/ada/adadecode.c
+++ b/gcc/ada/adadecode.c
@@ -29,8 +29,9 @@ 
  *                                                                          *
  ****************************************************************************/
 
+#include "config.h"
+#include "system.h"
 #include "runtime.h"
-#include <string.h>
 #include <stdio.h>
 #include <ctype.h>
 
@@ -47,7 +48,6 @@ 
 #include "adadecode.h"
 
 static void add_verbose (const char *, char *);
-static int has_prefix (const char *, const char *);
 static int has_suffix (const char *, const char *);
 
 /* This is a safe version of strcpy that can be used with overlapped
@@ -68,14 +68,6 @@  static void add_verbose (const char *text, char *ada_name)
   verbose_info = 1;
 }
 
-/* Returns 1 if NAME starts with PREFIX.  */
-
-static int
-has_prefix (const char *name, const char *prefix)
-{
-  return strncmp (name, prefix, strlen (prefix)) == 0;
-}
-
 /* Returns 1 if NAME ends with SUFFIX.  */
 
 static int
@@ -167,7 +159,7 @@  __gnat_decode (const char *coded_name, char *ada_name, int verbose)
     }
 
   /* Check for library level subprogram.  */
-  else if (has_prefix (coded_name, "_ada_"))
+  else if (startswith (coded_name, "_ada_"))
     {
       strcpy (ada_name, coded_name + 5);
       lib_subprog = 1;
diff --git a/gcc/ada/gcc-interface/utils.c b/gcc/ada/gcc-interface/utils.c
index 952f032072b..2d5ca4ba456 100644
--- a/gcc/ada/gcc-interface/utils.c
+++ b/gcc/ada/gcc-interface/utils.c
@@ -7016,8 +7016,7 @@  def_builtin_1 (enum built_in_function fncode,
     return;
 
   gcc_assert ((!both_p && !fallback_p)
-	      || !strncmp (name, "__builtin_",
-			   strlen ("__builtin_")));
+	      || startswith (name, "__builtin_"));
 
   libname = name + strlen ("__builtin_");
   decl = add_builtin_function (name, fntype, fncode, fnclass,
diff --git a/gcc/ada/init.c b/gcc/ada/init.c
index 3ceb1a31b02..24eb67bbf0d 100644
--- a/gcc/ada/init.c
+++ b/gcc/ada/init.c
@@ -2111,10 +2111,10 @@  __gnat_install_handler (void)
       prefix for vxsim when running on Linux and Windows.  */
   {
     char *model = sysModel ();
-    if ((strncmp (model, "Linux", 5) == 0)
-        || (strncmp (model, "Windows", 7) == 0)
-        || (strncmp (model, "SIMLINUX", 8) == 0) /* vx7 */
-        || (strncmp (model, "SIMNT", 5) == 0)) /* ditto */
+    if ((startswith(model, "Linux")
+        || startswith (model, "Windows")
+        || startswith (model, "SIMLINUX") /* vx7 */
+	|| startswith (model, "SIMNT")) /* ditto */
       __gnat_set_is_vxsim (TRUE);
   }
 #endif
diff --git a/gcc/analyzer/sm-file.cc b/gcc/analyzer/sm-file.cc
index d64c313e31c..3a5f95def34 100644
--- a/gcc/analyzer/sm-file.cc
+++ b/gcc/analyzer/sm-file.cc
@@ -312,9 +312,8 @@  is_file_using_fn_p (tree fndecl)
 
   /* Also support variants of these names prefixed with "_IO_".  */
   const char *name = IDENTIFIER_POINTER (DECL_NAME (fndecl));
-  if (strncmp (name, "_IO_", 4) == 0)
-    if (fs.contains_name_p (name + 4))
-      return true;
+  if (startswith (name, "_IO_") && fs.contains_name_p (name + 4))
+    return true;
 
   return false;
 }
diff --git a/gcc/builtins.c b/gcc/builtins.c
index d30c4eb62fc..b8764fed597 100644
--- a/gcc/builtins.c
+++ b/gcc/builtins.c
@@ -740,13 +740,9 @@  pointer_query::flush_cache ()
 static bool
 is_builtin_name (const char *name)
 {
-  if (strncmp (name, "__builtin_", 10) == 0)
-    return true;
-  if (strncmp (name, "__sync_", 7) == 0)
-    return true;
-  if (strncmp (name, "__atomic_", 9) == 0)
-    return true;
-  return false;
+  return (startswith (name, "__builtin_")
+	  || startswith (name, "__sync_")
+	  || startswith (name, "__atomic_"));
 }
 
 /* Return true if NODE should be considered for inline expansion regardless
diff --git a/gcc/c-family/c-ada-spec.c b/gcc/c-family/c-ada-spec.c
index 9fef5f05cc8..29eb0b01a91 100644
--- a/gcc/c-family/c-ada-spec.c
+++ b/gcc/c-family/c-ada-spec.c
@@ -2696,7 +2696,7 @@  print_destructor (pretty_printer *buffer, tree t, tree type)
   tree decl_name = DECL_NAME (TYPE_NAME (type));
 
   pp_string (buffer, "Delete_");
-  if (strncmp (IDENTIFIER_POINTER (DECL_NAME (t)), "__dt_del", 8) == 0)
+  if (startswith (IDENTIFIER_POINTER (DECL_NAME (t)), "__dt_del"))
     pp_string (buffer, "And_Free_");
   pp_ada_tree_identifier (buffer, decl_name, t, false);
 }
@@ -2980,9 +2980,9 @@  dump_ada_declaration (pretty_printer *buffer, tree t, tree type, int spc)
 	    return 0;
 
 	  /* Only consider complete constructors and deleting destructors.  */
-	  if (strncmp (IDENTIFIER_POINTER (decl_name), "__ct_comp", 9) != 0
-	      && strncmp (IDENTIFIER_POINTER (decl_name), "__dt_comp", 9) != 0
-	      && strncmp (IDENTIFIER_POINTER (decl_name), "__dt_del", 8) != 0)
+	  if (!startswith (IDENTIFIER_POINTER (decl_name), "__ct_comp")
+	      && !startswith (IDENTIFIER_POINTER (decl_name), "__dt_comp")
+	      && !startswith (IDENTIFIER_POINTER (decl_name), "__dt_del"))
 	    return 0;
 	}
 
diff --git a/gcc/c-family/c-common.c b/gcc/c-family/c-common.c
index d227686a030..7bd799d1825 100644
--- a/gcc/c-family/c-common.c
+++ b/gcc/c-family/c-common.c
@@ -4670,7 +4670,7 @@  static bool builtin_function_disabled_p (const char *);
 void
 disable_builtin_function (const char *name)
 {
-  if (strncmp (name, "__builtin_", strlen ("__builtin_")) == 0)
+  if (startswith (name, "__builtin_"))
     error ("cannot disable built-in function %qs", name);
   else
     {
@@ -4718,8 +4718,7 @@  def_builtin_1 (enum built_in_function fncode,
     return;
 
   gcc_assert ((!both_p && !fallback_p)
-	      || !strncmp (name, "__builtin_",
-			   strlen ("__builtin_")));
+	      || startswith (name, "__builtin_"));
 
   libname = name + strlen ("__builtin_");
   decl = add_builtin_function (name, fntype, fncode, fnclass,
diff --git a/gcc/c-family/c-format.c b/gcc/c-family/c-format.c
index 0a63cacb0d9..bda3b18fcd0 100644
--- a/gcc/c-family/c-format.c
+++ b/gcc/c-family/c-format.c
@@ -3097,7 +3097,7 @@  check_tokens (const token_t *tokens, unsigned ntoks,
       /* Allow this ugly warning for the time being.  */
       if (toklen == 2
 	  && format_chars - orig_format_chars > 6
-	  && !strncmp (format_chars - 7, " count >= width of ", 19))
+	  && startswith (format_chars - 7, " count >= width of "))
 	return format_chars + 10;
 
       /* The token is a type if it ends in an alphabetic character.  */
@@ -3127,7 +3127,7 @@  check_tokens (const token_t *tokens, unsigned ntoks,
   /* Diagnose unquoted __attribute__.  Consider any parenthesized
      argument to the attribute to avoid redundant warnings for
      the double parentheses that might follow.  */
-  if (!strncmp (format_chars, "__attribute", sizeof "__attribute" - 1))
+  if (startswith (format_chars, "__attribute"))
     {
       unsigned nchars = sizeof "__attribute" - 1;
       while ('_' == format_chars[nchars])
@@ -3178,9 +3178,9 @@  check_tokens (const token_t *tokens, unsigned ntoks,
   /* Diagnose unquoted built-ins.  */
   if (format_chars[0] == '_'
       && format_chars[1] == '_'
-      && (!strncmp (format_chars + 2, "atomic", sizeof "atomic" - 1)
-	  || !strncmp (format_chars + 2, "builtin", sizeof "builtin" - 1)
-	  || !strncmp (format_chars + 2, "sync", sizeof "sync" - 1)))
+      && (startswith (format_chars + 2, "atomic")
+	  || startswith (format_chars + 2, "builtin")
+	  || startswith (format_chars + 2, "sync")))
     {
       format_warning_substr (format_string_loc, format_string_cst,
 			     fmtchrpos, fmtchrpos + wlen, opt,
@@ -3267,7 +3267,7 @@  check_plain (location_t format_string_loc, tree format_string_cst,
   if (*format_chars == '%')
     {
       /* Diagnose %<%s%> and suggest using %qs instead.  */
-      if (!strncmp (format_chars, "%<%s%>", 6))
+      if (startswith (format_chars, "%<%s%>"))
 	format_warning_substr (format_string_loc, format_string_cst,
 			       fmtchrpos, fmtchrpos + 6, opt,
 			       "quoted %qs directive in format; "
@@ -3593,7 +3593,7 @@  check_plain (location_t format_string_loc, tree format_string_cst,
 
       if (nchars == 1)
 	{
-	  if (!strncmp (format_chars, "\"%s\"", 4))
+	  if (startswith (format_chars, "\"%s\""))
 	    {
 	      if (format_warning_substr (format_string_loc, format_string_cst,
 					 fmtchrpos, fmtchrpos + 4, opt,
@@ -3621,7 +3621,7 @@  check_plain (location_t format_string_loc, tree format_string_cst,
 	      && format_chars[0] == '(')
 	    ;   /* Text beginning in an open parenthesis.  */
 	  else if (nchars == 3
-	      && !strncmp (format_chars, "...", 3)
+	      && startswith (format_chars, "...")
 	      && format_chars[3])
 	    ;   /* Text beginning in an ellipsis.  */
 	  else
@@ -3663,7 +3663,7 @@  check_plain (location_t format_string_loc, tree format_string_cst,
 		   a period at the end of a capitalized sentence.  */
 	  else if (nchars == 3
 		   && format_chars - orig_format_chars > 0
-		   && !strncmp (format_chars, "...", 3))
+		   && startswith (format_chars, "..."))
 	    ;   /* Text ending in the ellipsis.  */
 	  else
 	    format_warning_substr (format_string_loc, format_string_cst,
@@ -5104,7 +5104,7 @@  convert_format_name_to_system_name (const char *attr_name)
   int i;
 
   if (attr_name == NULL || *attr_name == 0
-      || strncmp (attr_name, "gcc_", 4) == 0)
+      || startswith (attr_name, "gcc_"))
     return attr_name;
 #ifdef TARGET_OVERRIDES_FORMAT_INIT
   TARGET_OVERRIDES_FORMAT_INIT ();
diff --git a/gcc/c/c-aux-info.c b/gcc/c/c-aux-info.c
index bae5757ad13..81860cb48cb 100644
--- a/gcc/c/c-aux-info.c
+++ b/gcc/c/c-aux-info.c
@@ -67,12 +67,12 @@  affix_data_type (const char *param)
 
   for (;;)
     {
-      if (!strncmp (p, "volatile ", 9))
+      if (startswith (p, "volatile "))
 	{
 	  p += 9;
 	  continue;
 	}
-      if (!strncmp (p, "const ", 6))
+      if (startswith (p, "const "))
 	{
 	  p += 6;
 	  continue;
diff --git a/gcc/c/c-typeck.c b/gcc/c/c-typeck.c
index 51a62c800f7..a523b934303 100644
--- a/gcc/c/c-typeck.c
+++ b/gcc/c/c-typeck.c
@@ -3113,7 +3113,7 @@  build_function_call_vec (location_t loc, vec<location_t> arg_loc,
 	orig_fundecl = fundecl;
       /* Atomic functions have type checking/casting already done.  They are 
 	 often rewritten and don't match the original parameter list.  */
-      if (name && !strncmp (IDENTIFIER_POINTER (name), "__atomic_", 9))
+      if (name && startswith (IDENTIFIER_POINTER (name), "__atomic_"))
         origtypes = NULL;
     }
   if (TREE_CODE (TREE_TYPE (function)) == FUNCTION_TYPE)
@@ -3199,7 +3199,7 @@  build_function_call_vec (location_t loc, vec<location_t> arg_loc,
 					    nargs, argarray, &arg_loc);
 
   if (name != NULL_TREE
-      && !strncmp (IDENTIFIER_POINTER (name), "__builtin_", 10))
+      && startswith (IDENTIFIER_POINTER (name), "__builtin_"))
     {
       if (require_constant_value)
 	result
diff --git a/gcc/c/gimple-parser.c b/gcc/c/gimple-parser.c
index 58b161b7c76..3a6e72ef002 100644
--- a/gcc/c/gimple-parser.c
+++ b/gcc/c/gimple-parser.c
@@ -131,7 +131,7 @@  static void c_parser_gimple_expr_list (gimple_parser &, vec<tree> *);
 static bool
 c_parser_gimple_parse_bb_spec (tree val, int *index)
 {
-  if (strncmp (IDENTIFIER_POINTER (val), "__BB", 4) != 0)
+  if (!startswith (IDENTIFIER_POINTER (val), "__BB"))
     return false;
   for (const char *p = IDENTIFIER_POINTER (val) + 4; *p; ++p)
     if (!ISDIGIT (*p))
diff --git a/gcc/collect2.c b/gcc/collect2.c
index bd371430ab7..0ddb1693b67 100644
--- a/gcc/collect2.c
+++ b/gcc/collect2.c
@@ -956,7 +956,7 @@  main (int argc, char **argv)
       {
 	if (! strcmp (argv[i], "-debug"))
 	  debug = true;
-	else if (!strncmp (argv[i], "-fno-lto", 8))
+	else if (startswith (argv[i], "-fno-lto"))
 	  lto_mode = LTO_MODE_NONE;
         else if (! strcmp (argv[i], "-plugin"))
 	  {
@@ -970,7 +970,7 @@  main (int argc, char **argv)
 	  selected_linker = USE_GOLD_LD;
 	else if (strcmp (argv[i], "-fuse-ld=lld") == 0)
 	  selected_linker = USE_LLD_LD;
-	else if (strncmp (argv[i], "-o", 2) == 0)
+	else if (startswith (argv[i], "-o"))
 	  {
 	    /* Parse the output filename if it's given so that we can make
 	       meaningful temp filenames.  */
@@ -984,19 +984,19 @@  main (int argc, char **argv)
 	/* These flags are position independent, although their order
 	   is important - subsequent flags override earlier ones. */
 	else if (strcmp (argv[i], "-b64") == 0)
-	    aix64_flag = 1;
+	  aix64_flag = 1;
 	/* -bexport:filename always needs the :filename */
-	else if (strncmp (argv[i], "-bE:", 4) == 0
-	      || strncmp (argv[i], "-bexport:", 9) == 0)
-	    export_flag = 1;
+	else if (startswith (argv[i], "-bE:")
+		 || startswith (argv[i], "-bexport:"))
+	  export_flag = 1;
 	else if (strcmp (argv[i], "-brtl") == 0
 	      || strcmp (argv[i], "-bsvr4") == 0
 	      || strcmp (argv[i], "-G") == 0)
-	    aixrtl_flag = 1;
+	  aixrtl_flag = 1;
 	else if (strcmp (argv[i], "-bnortl") == 0)
-	    aixrtl_flag = 0;
+	  aixrtl_flag = 0;
 	else if (strcmp (argv[i], "-blazy") == 0)
-	    aixlazy_flag = 1;
+	  aixlazy_flag = 1;
 #endif
       }
 
@@ -1016,11 +1016,11 @@  main (int argc, char **argv)
 	const char *q = extract_string (&p);
 	if (*q == '-' && (q[1] == 'm' || q[1] == 'f'))
 	  num_c_args++;
-	if (strncmp (q, "-flto-partition=none", 20) == 0)
+	if (startswith (q, "-flto-partition=none"))
 	  no_partition = true;
-	else if (strncmp (q, "-fno-lto", 8) == 0)
+	else if (startswith (q, "-fno-lto"))
 	  lto_mode = LTO_MODE_NONE;
-	else if (strncmp (q, "-save-temps", 11) == 0)
+	else if (startswith (q, "-save-temps"))
 	  /* FIXME: Honour =obj.  */
 	  save_temps = true;
 	else if (strcmp (q, "-dumpdir") == 0)
@@ -1254,7 +1254,7 @@  main (int argc, char **argv)
 	(void) extract_string (&p);
 #ifdef COLLECT_EXPORT_LIST
       /* Detect any invocation with -fvisibility.  */
-      if (strncmp (q, "-fvisibility", 12) == 0)
+      if (startswith (q, "-fvisibility"))
 	visibility_flag = 1;
 #endif
     }
@@ -1303,7 +1303,7 @@  main (int argc, char **argv)
 	      break;
 
             case 'f':
-	      if (strncmp (arg, "-flto", 5) == 0)
+	      if (startswith (arg, "-flto"))
 		{
 #ifdef ENABLE_LTO
 		  /* Do not pass LTO flag to the linker. */
@@ -1315,13 +1315,13 @@  main (int argc, char **argv)
 #endif
 		}
 	      else if (!use_collect_ld
-		       && strncmp (arg, "-fuse-ld=", 9) == 0)
+		       && startswith (arg, "-fuse-ld="))
 		{
 		  /* Do not pass -fuse-ld={bfd|gold|lld} to the linker. */
 		  ld1--;
 		  ld2--;
 		}
-	      else if (strncmp (arg, "-fno-lto", 8) == 0)
+	      else if (startswith (arg, "-fno-lto"))
 		{
 		  /* Do not pass -fno-lto to the linker. */
 		  ld1--;
@@ -1462,7 +1462,7 @@  main (int argc, char **argv)
 		  ld2--;
 #endif
 		}
-	      else if (strncmp (arg, "--demangle", 10) == 0)
+	      else if (startswith (arg, "--demangle"))
 		{
 #ifndef HAVE_LD_DEMANGLE
 		  no_demangle = 0;
@@ -1479,7 +1479,7 @@  main (int argc, char **argv)
 		  ld2--;
 #endif
 		}
-	      else if (strncmp (arg, "--sysroot=", 10) == 0)
+	      else if (startswith (arg, "--sysroot="))
 		target_system_root = arg + 10;
 	      else if (strcmp (arg, "--version") == 0)
 		verbose = true;
@@ -2307,13 +2307,9 @@  has_lto_section (void *data, const char *name ATTRIBUTE_UNUSED,
 {
   int *found = (int *) data;
 
-  if (strncmp (name, LTO_SECTION_NAME_PREFIX,
-	       sizeof (LTO_SECTION_NAME_PREFIX) - 1) != 0)
-    {
-      if (strncmp (name, OFFLOAD_SECTION_NAME_PREFIX,
-	           sizeof (OFFLOAD_SECTION_NAME_PREFIX) - 1) != 0)
-        return 1;
-    }
+  if (!startswith (name, LTO_SECTION_NAME_PREFIX)
+      && !startswith (name, OFFLOAD_SECTION_NAME_PREFIX))
+    return 1;
 
   *found = 1;
 
@@ -2619,7 +2615,7 @@  scan_libraries (const char *prog_name)
 	continue;
 
       name = p;
-      if (strncmp (name, "not found", sizeof ("not found") - 1) == 0)
+      if (startswith (name, "not found"))
 	fatal_error (input_location, "dynamic dependency %s not found", buf);
 
       /* Find the end of the symbol name.  */
diff --git a/gcc/coverage.c b/gcc/coverage.c
index dc9ea6f3ee1..5a344cdfc17 100644
--- a/gcc/coverage.c
+++ b/gcc/coverage.c
@@ -488,9 +488,9 @@  coverage_checksum_string (unsigned chksum, const char *string)
   for (i = 0; string[i]; i++)
     {
       int offset = 0;
-      if (!strncmp (string + i, "_GLOBAL__N_", 11))
+      if (startswith (string + i, "_GLOBAL__N_"))
       offset = 11;
-      if (!strncmp (string + i, "_GLOBAL__", 9))
+      if (startswith (string + i, "_GLOBAL__"))
       offset = 9;
 
       /* C++ namespaces do have scheme:
@@ -1256,8 +1256,7 @@  coverage_init (const char *filename)
 	  filename = concat (getpwd (), separator, filename, NULL);
 	  if (profile_prefix_path)
 	    {
-	      if (!strncmp (filename, profile_prefix_path,
-			    strlen (profile_prefix_path)))
+	      if (startswith (filename, profile_prefix_path))
 		{
 		  filename += strlen (profile_prefix_path);
 		  while (*filename == *separator)
diff --git a/gcc/cp/decl.c b/gcc/cp/decl.c
index b81de8ef934..d6c7bc70823 100644
--- a/gcc/cp/decl.c
+++ b/gcc/cp/decl.c
@@ -1609,8 +1609,7 @@  duplicate_decls (tree newdecl, tree olddecl, bool hiding, bool was_hidden)
 
 		  if (name[0] == '_'
 		      && name[1] == '_'
-		      && (strncmp (name + 2, "builtin_",
-				   strlen ("builtin_")) == 0
+		      && (startswith (name + 2, "builtin_")
 			  || (len = strlen (name)) <= strlen ("___chk")
 			  || memcmp (name + len - strlen ("_chk"),
 				     "_chk", strlen ("_chk") + 1) != 0))
@@ -4828,7 +4827,7 @@  cxx_builtin_function (tree decl)
     /* In the user's namespace, it must be declared before use.  */
     hiding = true;
   else if (IDENTIFIER_LENGTH (id) > strlen ("___chk")
-	   && 0 != strncmp (name + 2, "builtin_", strlen ("builtin_"))
+	   && !startswith (name + 2, "builtin_")
 	   && 0 == memcmp (name + IDENTIFIER_LENGTH (id) - strlen ("_chk"),
 			   "_chk", strlen ("_chk") + 1))
     /* Treat __*_chk fortification functions as anticipated as well,
@@ -7565,9 +7564,9 @@  omp_declare_variant_finalize_one (tree decl, tree attr)
 	  return true;
 	}
       if (fndecl_built_in_p (variant)
-	  && (strncmp (varname, "__builtin_", strlen ("__builtin_")) == 0
-	      || strncmp (varname, "__sync_", strlen ("__sync_")) == 0
-	      || strncmp (varname, "__atomic_", strlen ("__atomic_")) == 0))
+	  && (startswith (varname, "__builtin_")
+	      || startswith (varname, "__sync_")
+	      || startswith (varname, "__atomic_")))
 	{
 	  error_at (varid_loc, "variant %qD is a built-in", variant);
 	  return true;
@@ -9833,8 +9832,8 @@  grokfndecl (tree ctype,
 	  || (IDENTIFIER_LENGTH (declarator) > 10
 	      && IDENTIFIER_POINTER (declarator)[0] == '_'
 	      && IDENTIFIER_POINTER (declarator)[1] == '_'
-	      && strncmp (IDENTIFIER_POINTER (declarator)+2,
-			  "builtin_", 8) == 0)
+	      && startswith (IDENTIFIER_POINTER (declarator) + 2,
+			     "builtin_"))
 	  || (targetcm.cxx_implicit_extern_c
 	      && (targetcm.cxx_implicit_extern_c
 		  (IDENTIFIER_POINTER (declarator))))))
diff --git a/gcc/cp/error.c b/gcc/cp/error.c
index ff4ae6f4b23..a4e9b2a6ad9 100644
--- a/gcc/cp/error.c
+++ b/gcc/cp/error.c
@@ -1138,7 +1138,7 @@  dump_decl_name (cxx_pretty_printer *pp, tree t, int flags)
     }
 
   const char *str = IDENTIFIER_POINTER (t);
-  if (!strncmp (str, "_ZGR", 4))
+  if (startswith (str, "_ZGR"))
     {
       pp_cxx_ws_string (pp, "<temporary>");
       return;
diff --git a/gcc/cp/mangle.c b/gcc/cp/mangle.c
index 49f1266bef3..f0e1f416804 100644
--- a/gcc/cp/mangle.c
+++ b/gcc/cp/mangle.c
@@ -1308,10 +1308,10 @@  find_decomp_unqualified_name (tree decl, size_t *len)
   const char *p = IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (decl));
   const char *end = p + IDENTIFIER_LENGTH (DECL_ASSEMBLER_NAME (decl));
   bool nested = false;
-  if (strncmp (p, "_Z", 2))
+  if (!startswith (p, "_Z"))
     return NULL;
   p += 2;
-  if (!strncmp (p, "St", 2))
+  if (startswith (p, "St"))
     p += 2;
   else if (*p == 'N')
     {
@@ -1327,7 +1327,7 @@  find_decomp_unqualified_name (tree decl, size_t *len)
 	    break;
 	}
     }
-  if (strncmp (p, "DC", 2))
+  if (!startswith (p, "DC"))
     return NULL;
   if (nested)
     {
@@ -4430,7 +4430,7 @@  static void
 write_guarded_var_name (const tree variable)
 {
   if (DECL_NAME (variable)
-      && strncmp (IDENTIFIER_POINTER (DECL_NAME (variable)), "_ZGR", 4) == 0)
+      && startswith (IDENTIFIER_POINTER (DECL_NAME (variable)), "_ZGR"))
     /* The name of a guard variable for a reference temporary should refer
        to the reference, not the temporary.  */
     write_string (IDENTIFIER_POINTER (DECL_NAME (variable)) + 4);
@@ -4488,8 +4488,7 @@  decl_tls_wrapper_p (const tree fn)
   if (TREE_CODE (fn) != FUNCTION_DECL)
     return false;
   tree name = DECL_NAME (fn);
-  return strncmp (IDENTIFIER_POINTER (name), TLS_WRAPPER_PREFIX,
-		  strlen (TLS_WRAPPER_PREFIX)) == 0;
+  return startswith (IDENTIFIER_POINTER (name), TLS_WRAPPER_PREFIX);
 }
 
 /* Return an identifier for the name of a temporary variable used to
diff --git a/gcc/cp/parser.c b/gcc/cp/parser.c
index 99eccf0c5e4..5e076ffa34a 100644
--- a/gcc/cp/parser.c
+++ b/gcc/cp/parser.c
@@ -18661,9 +18661,8 @@  cp_parser_simple_type_specifier (cp_parser* parser,
 	  decl_specs->int_n_idx = idx;
 	  /* Check if the alternate "__intN__" form has been used instead of
 	     "__intN".  */
-	  if (strncmp (IDENTIFIER_POINTER (token->u.value)
-			+ (IDENTIFIER_LENGTH (token->u.value) - 2),
-			"__", 2) == 0)
+	  if (startswith (IDENTIFIER_POINTER (token->u.value)
+			  + (IDENTIFIER_LENGTH (token->u.value) - 2), "__"))
 	    decl_specs->int_n_alt = true;
 	}
       type = int_n_trees [idx].signed_type;
@@ -22950,7 +22949,7 @@  cp_parser_tx_qualifier_opt (cp_parser *parser)
       tree name = token->u.value;
       const char *p = IDENTIFIER_POINTER (name);
       const int len = strlen ("transaction_safe");
-      if (!strncmp (p, "transaction_safe", len))
+      if (startswith (p, "transaction_safe"))
 	{
 	  p += len;
 	  if (*p == '\0'
diff --git a/gcc/cp/pt.c b/gcc/cp/pt.c
index 7bcbe6dc3ce..bf1ef09fe05 100644
--- a/gcc/cp/pt.c
+++ b/gcc/cp/pt.c
@@ -6994,7 +6994,7 @@  bool
 template_parm_object_p (const_tree t)
 {
   return (TREE_CODE (t) == VAR_DECL && DECL_ARTIFICIAL (t) && DECL_NAME (t)
-	  && !strncmp (IDENTIFIER_POINTER (DECL_NAME (t)), "_ZTA", 4));
+	  && startswith (IDENTIFIER_POINTER (DECL_NAME (t)), "_ZTA"));
 }
 
 /* Subroutine of convert_nontype_argument, to check whether EXPR, as an
@@ -28474,8 +28474,7 @@  dguide_name_p (tree name)
 {
   return (TREE_CODE (name) == IDENTIFIER_NODE
 	  && TREE_TYPE (name)
-	  && !strncmp (IDENTIFIER_POINTER (name), dguide_base,
-		       strlen (dguide_base)));
+	  && startswith (IDENTIFIER_POINTER (name), dguide_base));
 }
 
 /* True if FN is a deduction guide.  */
diff --git a/gcc/d/d-builtins.cc b/gcc/d/d-builtins.cc
index 400bce0a141..859a8ce2a59 100644
--- a/gcc/d/d-builtins.cc
+++ b/gcc/d/d-builtins.cc
@@ -739,8 +739,7 @@  do_build_builtin_fn (built_in_function fncode,
     return;
 
   gcc_assert ((!both_p && !fallback_p)
-	      || !strncmp (name, "__builtin_",
-			   strlen ("__builtin_")));
+	      || startswith (name, "__builtin_"));
 
   libname = name + strlen ("__builtin_");
 
diff --git a/gcc/d/dmd/dinterpret.c b/gcc/d/dmd/dinterpret.c
index 5e71f3b24a1..9e74a0dbf1f 100644
--- a/gcc/d/dmd/dinterpret.c
+++ b/gcc/d/dmd/dinterpret.c
@@ -6881,7 +6881,7 @@  Expression *evaluateIfBuiltin(UnionExp *pue, InterState *istate, Loc loc,
         const char *id = fd->ident->toChars();
         size_t idlen = strlen(id);
         if (nargs == 2 && (idlen == 10 || idlen == 11) &&
-            !strncmp(id, "_aApply", 7))
+            startswith (id, "_aApply"))
         {
             // Functions from aApply.d and aApplyR.d in the runtime
             bool rvs = (idlen == 11);   // true if foreach_reverse
diff --git a/gcc/d/dmd/dmangle.c b/gcc/d/dmd/dmangle.c
index 83f4c18bee8..f112243cf5f 100644
--- a/gcc/d/dmd/dmangle.c
+++ b/gcc/d/dmd/dmangle.c
@@ -673,7 +673,7 @@  public:
                 cd == ClassDeclaration::object ||
                 cd == Type::typeinfoclass ||
                 cd == Module::moduleinfo ||
-                strncmp(cd->ident->toChars(), "TypeInfo_", 9) == 0)
+                startswith (cd->ident->toChars(), "TypeInfo_"))
             {
                 // Don't mangle parent
                 ad->parent = NULL;
diff --git a/gcc/d/dmd/hdrgen.c b/gcc/d/dmd/hdrgen.c
index 9397b1e8abd..e72273b2dbd 100644
--- a/gcc/d/dmd/hdrgen.c
+++ b/gcc/d/dmd/hdrgen.c
@@ -3212,7 +3212,7 @@  public:
         }
         else if (p->type->ty == Tident &&
                  strlen(((TypeIdentifier *)p->type)->ident->toChars()) > 3 &&
-                 strncmp(((TypeIdentifier *)p->type)->ident->toChars(), "__T", 3) == 0)
+                 startswith (((TypeIdentifier *)p->type)->ident->toChars(), "__T"))
         {
             // print parameter name, instead of undetermined type parameter
             buf->writestring(p->ident->toChars());
diff --git a/gcc/d/dmd/identifier.c b/gcc/d/dmd/identifier.c
index 197d288e532..dd2c58fd657 100644
--- a/gcc/d/dmd/identifier.c
+++ b/gcc/d/dmd/identifier.c
@@ -73,11 +73,11 @@  const char *Identifier::toHChars2()
     {   p = toChars();
         if (*p == '_')
         {
-            if (strncmp(p, "_staticCtor", 11) == 0)
+            if (startswith(p, "_staticCtor"))
                 p = "static this";
-            else if (strncmp(p, "_staticDtor", 11) == 0)
+            else if (startswith(p, "_staticDtor"))
                 p = "static ~this";
-            else if (strncmp(p, "__invariant", 11) == 0)
+            else if (startswith(p, "__invariant"))
                 p = "invariant";
         }
     }
diff --git a/gcc/dwarf2out.c b/gcc/dwarf2out.c
index 7a15debcb48..728e89b331d 100644
--- a/gcc/dwarf2out.c
+++ b/gcc/dwarf2out.c
@@ -5474,7 +5474,7 @@  is_cxx (const_tree decl)
     {
       const_tree context = get_ultimate_context (decl);
       if (context && TRANSLATION_UNIT_LANGUAGE (context))
-	return strncmp (TRANSLATION_UNIT_LANGUAGE (context), "GNU C++", 7) == 0;
+	return startswith (TRANSLATION_UNIT_LANGUAGE (context), "GNU C++");
     }
   return is_cxx ();
 }
@@ -24732,8 +24732,8 @@  gen_compile_unit_die (const char *filename)
 	    common_lang = TRANSLATION_UNIT_LANGUAGE (t);
 	  else if (strcmp (common_lang, TRANSLATION_UNIT_LANGUAGE (t)) == 0)
 	    ;
-	  else if (strncmp (common_lang, "GNU C", 5) == 0
-		    && strncmp (TRANSLATION_UNIT_LANGUAGE (t), "GNU C", 5) == 0)
+	  else if (startswith (common_lang, "GNU C")
+		    && startswith (TRANSLATION_UNIT_LANGUAGE (t), "GNU C"))
 	    /* Mixing C and C++ is ok, use C++ in that case.  */
 	    common_lang = highest_c_language (common_lang,
 					      TRANSLATION_UNIT_LANGUAGE (t));
@@ -24750,7 +24750,7 @@  gen_compile_unit_die (const char *filename)
     }
 
   language = DW_LANG_C;
-  if (strncmp (language_string, "GNU C", 5) == 0
+  if (startswith (language_string, "GNU C")
       && ISDIGIT (language_string[5]))
     {
       language = DW_LANG_C89;
@@ -24766,7 +24766,7 @@  gen_compile_unit_die (const char *filename)
 	      language = DW_LANG_C11;
 	}
     }
-  else if (strncmp (language_string, "GNU C++", 7) == 0)
+  else if (startswith (language_string, "GNU C++"))
     {
       language = DW_LANG_C_plus_plus;
       if (dwarf_version >= 5 /* || !dwarf_strict */)
@@ -24788,7 +24788,7 @@  gen_compile_unit_die (const char *filename)
     {
       if (strcmp (language_string, "GNU Ada") == 0)
 	language = DW_LANG_Ada95;
-      else if (strncmp (language_string, "GNU Fortran", 11) == 0)
+      else if (startswith (language_string, "GNU Fortran"))
 	{
 	  language = DW_LANG_Fortran95;
 	  if (dwarf_version >= 5 /* || !dwarf_strict */)
@@ -24812,7 +24812,7 @@  gen_compile_unit_die (const char *filename)
 	}
     }
   /* Use a degraded Fortran setting in strict DWARF2 so is_fortran works.  */
-  else if (strncmp (language_string, "GNU Fortran", 11) == 0)
+  else if (startswith (language_string, "GNU Fortran"))
     language = DW_LANG_Fortran90;
   /* Likewise for Ada.  */
   else if (strcmp (language_string, "GNU Ada") == 0)
diff --git a/gcc/fortran/decl.c b/gcc/fortran/decl.c
index 947e4f868a1..413c7a75e0c 100644
--- a/gcc/fortran/decl.c
+++ b/gcc/fortran/decl.c
@@ -2721,7 +2721,7 @@  variable_decl (int elem)
     }
 
   /* %FILL components may not have initializers.  */
-  if (gfc_str_startswith (name, "%FILL") && gfc_match_eos () != MATCH_YES)
+  if (startswith (name, "%FILL") && gfc_match_eos () != MATCH_YES)
     {
       gfc_error ("%qs entity cannot have an initializer at %C", "%FILL");
       m = MATCH_ERROR;
@@ -8221,7 +8221,7 @@  gfc_match_end (gfc_statement *st)
     {
     case COMP_ASSOCIATE:
     case COMP_BLOCK:
-      if (gfc_str_startswith (block_name, "block@"))
+      if (startswith (block_name, "block@"))
 	block_name = NULL;
       break;
 
diff --git a/gcc/fortran/gfortran.h b/gcc/fortran/gfortran.h
index 7935aca23db..b8e67bcc03e 100644
--- a/gcc/fortran/gfortran.h
+++ b/gcc/fortran/gfortran.h
@@ -3514,10 +3514,6 @@  bool gfc_is_compile_time_shape (gfc_array_spec *);
 
 bool gfc_ref_dimen_size (gfc_array_ref *, int dimen, mpz_t *, mpz_t *);
 
-
-#define gfc_str_startswith(str, pref) \
-	(strncmp ((str), (pref), strlen (pref)) == 0)
-
 /* interface.c -- FIXME: some of these should be in symbol.c */
 void gfc_free_interface (gfc_interface *);
 bool gfc_compare_derived_types (gfc_symbol *, gfc_symbol *);
diff --git a/gcc/fortran/module.c b/gcc/fortran/module.c
index 089453caa03..321d3256eba 100644
--- a/gcc/fortran/module.c
+++ b/gcc/fortran/module.c
@@ -5029,7 +5029,7 @@  load_omp_udrs (void)
       mio_pool_string (&name);
       gfc_clear_ts (&ts);
       mio_typespec (&ts);
-      if (gfc_str_startswith (name, "operator "))
+      if (startswith (name, "operator "))
 	{
 	  const char *p = name + sizeof ("operator ") - 1;
 	  if (strcmp (p, "+") == 0)
@@ -5477,8 +5477,8 @@  read_module (void)
 
 	  /* Exception: Always import vtabs & vtypes.  */
 	  if (p == NULL && name[0] == '_'
-	      && (gfc_str_startswith (name, "__vtab_")
-		  || gfc_str_startswith (name, "__vtype_")))
+	      && (startswith (name, "__vtab_")
+		  || startswith (name, "__vtype_")))
 	    p = name;
 
 	  /* Skip symtree nodes not in an ONLY clause, unless there
@@ -5563,8 +5563,8 @@  read_module (void)
 		sym->attr.use_rename = 1;
 
 	      if (name[0] != '_'
-		  || (!gfc_str_startswith (name, "__vtab_")
-		      && !gfc_str_startswith (name, "__vtype_")))
+		  || (!startswith (name, "__vtab_")
+		      && !startswith (name, "__vtype_")))
 		sym->attr.use_only = only_flag;
 
 	      /* Store the symtree pointing to this symbol.  */
diff --git a/gcc/fortran/options.c b/gcc/fortran/options.c
index 3a0b98bf1ec..1723f689a57 100644
--- a/gcc/fortran/options.c
+++ b/gcc/fortran/options.c
@@ -615,7 +615,7 @@  gfc_handle_runtime_check_option (const char *arg)
 	      result = 1;
 	      break;
 	    }
-	  else if (optname[n] && pos > 3 && gfc_str_startswith (arg, "no-")
+	  else if (optname[n] && pos > 3 && startswith (arg, "no-")
 		   && strncmp (optname[n], arg+3, pos-3) == 0)
 	    {
 	      gfc_option.rtcheck &= ~optmask[n];
diff --git a/gcc/fortran/primary.c b/gcc/fortran/primary.c
index a6df885c80c..9fe8d1ee20c 100644
--- a/gcc/fortran/primary.c
+++ b/gcc/fortran/primary.c
@@ -1786,21 +1786,21 @@  match_arg_list_function (gfc_actual_arglist *result)
       switch (name[0])
 	{
 	case 'l':
-	  if (gfc_str_startswith (name, "loc"))
+	  if (startswith (name, "loc"))
 	    {
 	      result->name = "%LOC";
 	      break;
 	    }
 	  /* FALLTHRU */
 	case 'r':
-	  if (gfc_str_startswith (name, "ref"))
+	  if (startswith (name, "ref"))
 	    {
 	      result->name = "%REF";
 	      break;
 	    }
 	  /* FALLTHRU */
 	case 'v':
-	  if (gfc_str_startswith (name, "val"))
+	  if (startswith (name, "val"))
 	    {
 	      result->name = "%VAL";
 	      break;
diff --git a/gcc/fortran/trans-decl.c b/gcc/fortran/trans-decl.c
index cc9d85543ca..a1701887c8b 100644
--- a/gcc/fortran/trans-decl.c
+++ b/gcc/fortran/trans-decl.c
@@ -1941,7 +1941,7 @@  gfc_get_symbol_decl (gfc_symbol * sym)
      Marking this as artificial means that OpenMP will treat this as
      predetermined shared.  */
 
-  bool def_init = gfc_str_startswith (sym->name, "__def_init");
+  bool def_init = startswith (sym->name, "__def_init");
 
   if (sym->attr.vtab || def_init)
     {
diff --git a/gcc/fortran/trans-expr.c b/gcc/fortran/trans-expr.c
index 213f32b0a67..0295617a1ae 100644
--- a/gcc/fortran/trans-expr.c
+++ b/gcc/fortran/trans-expr.c
@@ -6840,7 +6840,7 @@  gfc_conv_procedure_call (gfc_se * se, gfc_symbol * sym,
       /* When calling __copy for character expressions to unlimited
 	 polymorphic entities, the dst argument needs a string length.  */
       if (sym->name[0] == '_' && e && e->ts.type == BT_CHARACTER
-	  && gfc_str_startswith (sym->name, "__vtab_CHARACTER")
+	  && startswith (sym->name, "__vtab_CHARACTER")
 	  && arg->next && arg->next->expr
 	  && (arg->next->expr->ts.type == BT_DERIVED
 	      || arg->next->expr->ts.type == BT_CLASS)
diff --git a/gcc/fortran/trans-intrinsic.c b/gcc/fortran/trans-intrinsic.c
index 5e53d1162fa..1369d2f76b9 100644
--- a/gcc/fortran/trans-intrinsic.c
+++ b/gcc/fortran/trans-intrinsic.c
@@ -10072,27 +10072,27 @@  gfc_conv_ieee_arithmetic_function (gfc_se * se, gfc_expr * expr)
 {
   const char *name = expr->value.function.name;
 
-  if (gfc_str_startswith (name, "_gfortran_ieee_is_nan"))
+  if (startswith (name, "_gfortran_ieee_is_nan"))
     conv_intrinsic_ieee_builtin (se, expr, BUILT_IN_ISNAN, 1);
-  else if (gfc_str_startswith (name, "_gfortran_ieee_is_finite"))
+  else if (startswith (name, "_gfortran_ieee_is_finite"))
     conv_intrinsic_ieee_builtin (se, expr, BUILT_IN_ISFINITE, 1);
-  else if (gfc_str_startswith (name, "_gfortran_ieee_unordered"))
+  else if (startswith (name, "_gfortran_ieee_unordered"))
     conv_intrinsic_ieee_builtin (se, expr, BUILT_IN_ISUNORDERED, 2);
-  else if (gfc_str_startswith (name, "_gfortran_ieee_is_normal"))
+  else if (startswith (name, "_gfortran_ieee_is_normal"))
     conv_intrinsic_ieee_is_normal (se, expr);
-  else if (gfc_str_startswith (name, "_gfortran_ieee_is_negative"))
+  else if (startswith (name, "_gfortran_ieee_is_negative"))
     conv_intrinsic_ieee_is_negative (se, expr);
-  else if (gfc_str_startswith (name, "_gfortran_ieee_copy_sign"))
+  else if (startswith (name, "_gfortran_ieee_copy_sign"))
     conv_intrinsic_ieee_copy_sign (se, expr);
-  else if (gfc_str_startswith (name, "_gfortran_ieee_scalb"))
+  else if (startswith (name, "_gfortran_ieee_scalb"))
     conv_intrinsic_ieee_scalb (se, expr);
-  else if (gfc_str_startswith (name, "_gfortran_ieee_next_after"))
+  else if (startswith (name, "_gfortran_ieee_next_after"))
     conv_intrinsic_ieee_next_after (se, expr);
-  else if (gfc_str_startswith (name, "_gfortran_ieee_rem"))
+  else if (startswith (name, "_gfortran_ieee_rem"))
     conv_intrinsic_ieee_rem (se, expr);
-  else if (gfc_str_startswith (name, "_gfortran_ieee_logb"))
+  else if (startswith (name, "_gfortran_ieee_logb"))
     conv_intrinsic_ieee_logb_rint (se, expr, BUILT_IN_LOGB);
-  else if (gfc_str_startswith (name, "_gfortran_ieee_rint"))
+  else if (startswith (name, "_gfortran_ieee_rint"))
     conv_intrinsic_ieee_logb_rint (se, expr, BUILT_IN_RINT);
   else
     /* It is not among the functions we translate directly.  We return
diff --git a/gcc/gcc-ar.c b/gcc/gcc-ar.c
index e76d4525e0c..cbc7662e03d 100644
--- a/gcc/gcc-ar.c
+++ b/gcc/gcc-ar.c
@@ -140,7 +140,7 @@  main (int ac, char **av)
 
   /* Not using getopt for now.  */
   for (i = 0; i < ac; i++)
-      if (!strncmp (av[i], "-B", 2))
+      if (startswith (av[i], "-B"))
 	{
 	  const char *arg = av[i] + 2;
 	  const char *end;
diff --git a/gcc/gcc.c b/gcc/gcc.c
index 7837553958b..0a17e86ccea 100644
--- a/gcc/gcc.c
+++ b/gcc/gcc.c
@@ -1900,7 +1900,7 @@  init_spec (void)
        when given the proper command line arguments.  */
     while (*p)
       {
-	if (in_sep && *p == '-' && strncmp (p, "-lgcc", 5) == 0)
+	if (in_sep && *p == '-' && startswith (p, "-lgcc"))
 	  {
 	    init_gcc_specs (&obstack,
 			    "-lgcc_s"
@@ -1923,7 +1923,7 @@  init_spec (void)
 	    p += 5;
 	    in_sep = 0;
 	  }
-	else if (in_sep && *p == 'l' && strncmp (p, "libgcc.a%s", 10) == 0)
+	else if (in_sep && *p == 'l' && startswith (p, "libgcc.a%s"))
 	  {
 	    /* Ug.  We don't know shared library extensions.  Hope that
 	       systems that use this form don't do shared libraries.  */
@@ -2378,7 +2378,7 @@  read_specs (const char *filename, bool main_p, bool user_p)
 	  /* Skip '\n'.  */
 	  p++;
 
-	  if (!strncmp (p1, "%include", sizeof ("%include") - 1)
+	  if (startswith (p1, "%include")
 	      && (p1[sizeof "%include" - 1] == ' '
 		  || p1[sizeof "%include" - 1] == '\t'))
 	    {
@@ -2399,7 +2399,7 @@  read_specs (const char *filename, bool main_p, bool user_p)
 	      read_specs (new_filename ? new_filename : p1, false, user_p);
 	      continue;
 	    }
-	  else if (!strncmp (p1, "%include_noerr", sizeof "%include_noerr" - 1)
+	  else if (startswith (p1, "%include_noerr")
 		   && (p1[sizeof "%include_noerr" - 1] == ' '
 		       || p1[sizeof "%include_noerr" - 1] == '\t'))
 	    {
@@ -2423,7 +2423,7 @@  read_specs (const char *filename, bool main_p, bool user_p)
 		fnotice (stderr, "could not find specs file %s\n", p1);
 	      continue;
 	    }
-	  else if (!strncmp (p1, "%rename", sizeof "%rename" - 1)
+	  else if (startswith (p1, "%rename")
 		   && (p1[sizeof "%rename" - 1] == ' '
 		       || p1[sizeof "%rename" - 1] == '\t'))
 	    {
@@ -3496,7 +3496,7 @@  execute (void)
 		&& WEXITSTATUS (status) == ICE_EXIT_CODE
 		&& i == 0
 		&& (p = strrchr (commands[0].argv[0], DIR_SEPARATOR))
-		&& ! strncmp (p + 1, "cc1", 3))
+		&& startswith (p + 1, "cc1"))
 	      try_generate_repro (commands[0].argv);
 	    if (WEXITSTATUS (status) > greatest_status)
 	      greatest_status = WEXITSTATUS (status);
@@ -7324,7 +7324,7 @@  check_live_switch (int switchnum, int prefix_length)
       break;
 
     case 'W':  case 'f':  case 'm': case 'g':
-      if (! strncmp (name + 1, "no-", 3))
+      if (startswith (name + 1, "no-"))
 	{
 	  /* We have Xno-YYY, search for XYYY.  */
 	  for (i = switchnum + 1; i < n_switches; i++)
diff --git a/gcc/genattrtab.c b/gcc/genattrtab.c
index afea3602e50..e69d175a05a 100644
--- a/gcc/genattrtab.c
+++ b/gcc/genattrtab.c
@@ -4344,7 +4344,7 @@  write_attr_case (FILE *outf, class attr_desc *attr, struct attr_value *av,
     write_attr_set (outf, attr, indent + 2, av->value, prefix, suffix,
 		    known_true, -2, 0, 0);
 
-  if (strncmp (prefix, "return", 6))
+  if (!startswith (prefix, "return"))
     {
       write_indent (outf, indent + 2);
       fprintf (outf, "break;\n");
@@ -5377,14 +5377,12 @@  main (int argc, const char **argv)
       {
         FILE *outf;
 
-#define IS_ATTR_GROUP(X) (!strncmp (attr->name, X, strlen (X)))
-	if (IS_ATTR_GROUP ("*internal_dfa_insn_code"))
+	if (startswith(attr->name, "*internal_dfa_insn_code"))
 	  outf = dfa_file;
-	else if (IS_ATTR_GROUP ("*insn_default_latency"))
+	else if (startswith (attr->name, "*insn_default_latency"))
 	  outf = latency_file;  
 	else
 	  outf = attr_file;
-#undef IS_ATTR_GROUP
 
 	if (! attr->is_special && ! attr->is_const)
 	  write_attr_get (outf, attr);
diff --git a/gcc/gencfn-macros.c b/gcc/gencfn-macros.c
index b620fe6aebc..fd9ae14fc04 100644
--- a/gcc/gencfn-macros.c
+++ b/gcc/gencfn-macros.c
@@ -208,7 +208,7 @@  main (int argc, char **argv)
   for (unsigned int i = 0; builtin_names[i]; ++i)
     {
       const char *name = builtin_names[i];
-      if (strncmp (name, "BUILT_IN_", 9) == 0)
+      if (startswith (name, "BUILT_IN_"))
 	{
 	  const char *root = name + 9;
 	  for (unsigned int j = 0; suffix_lists[j]; ++j)
diff --git a/gcc/gengtype.c b/gcc/gengtype.c
index 98d4626f87e..b94e2f126ec 100644
--- a/gcc/gengtype.c
+++ b/gcc/gengtype.c
@@ -671,7 +671,7 @@  type_for_name (const char *s)
          extern GTY(()) gcc::some_type *some_ptr;
      where the autogenerated functions will refer to simply "some_type",
      where they can be resolved into their namespace.  */
-  if (strncmp (s, "gcc::", 5) == 0)
+  if (startswith (s, "gcc::"))
     s += 5;
 
   for (p = typedefs; p != NULL; p = p->next)
@@ -1102,7 +1102,7 @@  gen_rtx_next (void)
       int k;
 
       rtx_next_new[i] = -1;
-      if (strncmp (rtx_format[i], "uu", 2) == 0)
+      if (startswith (rtx_format[i], "uu"))
 	rtx_next_new[i] = 1;
       else if (i == COND_EXEC || i == SET || i == EXPR_LIST || i == INSN_LIST)
 	rtx_next_new[i] = 1;
@@ -1828,7 +1828,7 @@  get_file_langdir (const input_file *inpf)
     return NULL;
 
   lang_index = get_prefix_langdir_index (srcdir_relative_path);
-  if (lang_index < 0 && strncmp (srcdir_relative_path, "c-family", 8) == 0)
+  if (lang_index < 0 && startswith (srcdir_relative_path, "c-family"))
     r = "c-family";
   else if (lang_index >= 0)
     r = lang_dir_names[lang_index];
@@ -4044,7 +4044,7 @@  write_local (outf_p output_header, type_p structures)
 	   || ((s)->gc_used == GC_MAYBE_POINTED_TO			\
 	       && s->u.s.line.file != NULL)				\
 	   || ((s)->gc_used == GC_USED					\
-	       && strncmp (s->u.s.tag, "anonymous", strlen ("anonymous"))) \
+	       && !startswith (s->u.s.tag, "anonymous"))		\
 	   || (s->u.s.base_class && opts_have (s->u.s.opt, "tag")))))
 
 
diff --git a/gcc/genmatch.c b/gcc/genmatch.c
index 8311f5d768a..332afc842b7 100644
--- a/gcc/genmatch.c
+++ b/gcc/genmatch.c
@@ -605,10 +605,10 @@  get_operator (const char *id, bool allow_null = false)
       for (unsigned int i = 0; id2[i]; ++i)
 	id2[i] = TOUPPER (id2[i]);
     }
-  else if (all_upper && strncmp (id, "IFN_", 4) == 0)
+  else if (all_upper && startswith (id, "IFN_"))
     /* Try CFN_ instead of IFN_.  */
     id2 = ACONCAT (("CFN_", id + 4, NULL));
-  else if (all_upper && strncmp (id, "BUILT_IN_", 9) == 0)
+  else if (all_upper && startswith (id, "BUILT_IN_"))
     /* Try prepending CFN_.  */
     id2 = ACONCAT (("CFN_", id, NULL));
   else
@@ -2391,7 +2391,7 @@  get_operand_type (id_base *op, unsigned pos,
   else if (*op == COND_EXPR
 	   && pos == 0)
     return "boolean_type_node";
-  else if (strncmp (op->id, "CFN_COND_", 9) == 0)
+  else if (startswith (op->id, "CFN_COND_"))
     {
       /* IFN_COND_* operands 1 and later by default have the same type
 	 as the result.  The type of operand 0 needs to be specified
@@ -2464,7 +2464,7 @@  expr::gen_transform (FILE *f, int indent, const char *dest, bool gimple,
     }
   else if (*opr == COND_EXPR
 	   || *opr == VEC_COND_EXPR
-	   || strncmp (opr->id, "CFN_COND_", 9) == 0)
+	   || startswith (opr->id, "CFN_COND_"))
     {
       /* Conditions are of the same type as their first alternative.  */
       snprintf (optype, sizeof (optype), "TREE_TYPE (_o%d[1])", depth);
diff --git a/gcc/genoutput.c b/gcc/genoutput.c
index 25af4375d9c..8e911cce2f5 100644
--- a/gcc/genoutput.c
+++ b/gcc/genoutput.c
@@ -841,7 +841,7 @@  validate_optab_operands (class data *d)
     return;
 
   /* Miscellaneous tests.  */
-  if (strncmp (d->name, "cstore", 6) == 0
+  if (startswith (d->name, "cstore")
       && d->name[strlen (d->name) - 1] == '4'
       && d->operand[0].mode == VOIDmode)
     {
diff --git a/gcc/go/gofrontend/runtime.cc b/gcc/go/gofrontend/runtime.cc
index 3cc5ded3617..514c045a68f 100644
--- a/gcc/go/gofrontend/runtime.cc
+++ b/gcc/go/gofrontend/runtime.cc
@@ -463,7 +463,7 @@  Runtime::name_to_code(const std::string& name)
       // The names in the table have "runtime." prefix. We may be
       // called with a name without the prefix. Try matching
       // without the prefix as well.
-      if (strncmp(runtime_function_name, "runtime.", 8) == 0
+      if (startswith(runtime_function_name, "runtime.")
           && strcmp(runtime_function_name + 8, name.c_str()) == 0)
         code = static_cast<Runtime::Function>(i);
     }
diff --git a/gcc/incpath.c b/gcc/incpath.c
index 446d280321d..52dbb806b1b 100644
--- a/gcc/incpath.c
+++ b/gcc/incpath.c
@@ -330,7 +330,7 @@  add_sysroot_to_chain (const char *sysroot, int chain)
 	{
 	  if (p->name[0] == '=')
 	    p->name = concat (sysroot, p->name + 1, NULL);
-	  if (strncmp (p->name, "$SYSROOT", strlen ("$SYSROOT")) == 0)
+	  if (startswith (p->name, "$SYSROOT"))
 	    p->name = concat (sysroot, p->name + strlen ("$SYSROOT"), NULL);
 	}
     }
diff --git a/gcc/langhooks.c b/gcc/langhooks.c
index 2354386f7b4..12c99888e6c 100644
--- a/gcc/langhooks.c
+++ b/gcc/langhooks.c
@@ -901,7 +901,7 @@  lhd_finalize_early_debug (void)
 bool
 lang_GNU_C (void)
 {
-  return (strncmp (lang_hooks.name, "GNU C", 5) == 0
+  return (startswith (lang_hooks.name, "GNU C")
 	  && (lang_hooks.name[5] == '\0' || ISDIGIT (lang_hooks.name[5])));
 }
 
@@ -910,7 +910,7 @@  lang_GNU_C (void)
 bool
 lang_GNU_CXX (void)
 {
-  return strncmp (lang_hooks.name, "GNU C++", 7) == 0;
+  return startswith (lang_hooks.name, "GNU C++");
 }
 
 /* Returns true if the current lang_hooks represents the GNU Fortran frontend.  */
@@ -918,7 +918,7 @@  lang_GNU_CXX (void)
 bool
 lang_GNU_Fortran (void)
 {
-  return strncmp (lang_hooks.name, "GNU Fortran", 11) == 0;
+  return startswith (lang_hooks.name, "GNU Fortran");
 }
 
 /* Returns true if the current lang_hooks represents the GNU Objective-C
@@ -927,5 +927,5 @@  lang_GNU_Fortran (void)
 bool
 lang_GNU_OBJC (void)
 {
-  return strncmp (lang_hooks.name, "GNU Objective-C", 15) == 0;
+  return startswith (lang_hooks.name, "GNU Objective-C");
 }
diff --git a/gcc/lto-wrapper.c b/gcc/lto-wrapper.c
index 03a5922f8ea..efb6ee644f4 100644
--- a/gcc/lto-wrapper.c
+++ b/gcc/lto-wrapper.c
@@ -1437,8 +1437,7 @@  run_gcc (unsigned argc, char *argv[])
       int consumed;
       char *filename = argv[i];
 
-      if (strncmp (argv[i], "-foffload-objects=",
-		   sizeof ("-foffload-objects=") - 1) == 0)
+      if (startswith (argv[i], "-foffload-objects="))
 	{
 	  have_offload = true;
 	  offload_objects_file_name
diff --git a/gcc/objc/objc-act.c b/gcc/objc/objc-act.c
index 1cbd586b8fb..796256d437e 100644
--- a/gcc/objc/objc-act.c
+++ b/gcc/objc/objc-act.c
@@ -10275,7 +10275,7 @@  objc_string_ref_type_p (tree strp)
   return (tmv
 	  && TREE_CODE (tmv) == IDENTIFIER_NODE
 	  && IDENTIFIER_POINTER (tmv)
-	  && !strncmp (IDENTIFIER_POINTER (tmv), "NSString", 8));
+	  && startswith (IDENTIFIER_POINTER (tmv), "NSString"));
 }
 
 /* At present the behavior of this is undefined and it does nothing.  */
diff --git a/gcc/objc/objc-encoding.c b/gcc/objc/objc-encoding.c
index c4067b1d527..7ad920a2c35 100644
--- a/gcc/objc/objc-encoding.c
+++ b/gcc/objc/objc-encoding.c
@@ -733,7 +733,7 @@  encode_type (tree type, int curtype, int format)
 	  char *enc = (char *) obstack_base (&util_obstack) + curtype;
 
 	  /* Rewrite "in const" from "nr" to "rn".  */
-	  if (curtype >= 1 && !strncmp (enc - 1, "nr", 2))
+	  if (curtype >= 1 && startswith (enc - 1, "nr"))
 	    memcpy (enc - 1, "rn", 2);
 	}
     }
diff --git a/gcc/objc/objc-next-runtime-abi-02.c b/gcc/objc/objc-next-runtime-abi-02.c
index af68c1c84a3..3cfcd0b1a57 100644
--- a/gcc/objc/objc-next-runtime-abi-02.c
+++ b/gcc/objc/objc-next-runtime-abi-02.c
@@ -2209,7 +2209,7 @@  has_load_impl (tree clsmeth)
     {
       tree id = METHOD_SEL_NAME (clsmeth);
       if (IDENTIFIER_LENGTH (id) == 4
-	  && strncmp (IDENTIFIER_POINTER (id), "load", 4) == 0)
+	  && startswith (IDENTIFIER_POINTER (id), "load"))
         return true;
       clsmeth = DECL_CHAIN (clsmeth);
     }
diff --git a/gcc/omp-general.c b/gcc/omp-general.c
index fa6de01722b..a1bb9d8d25d 100644
--- a/gcc/omp-general.c
+++ b/gcc/omp-general.c
@@ -968,7 +968,7 @@  omp_max_simt_vf (void)
   if (ENABLE_OFFLOADING)
     for (const char *c = getenv ("OFFLOAD_TARGET_NAMES"); c;)
       {
-	if (!strncmp (c, "nvptx", strlen ("nvptx")))
+	if (startswith (c, "nvptx"))
 	  return 32;
 	else if ((c = strchr (c, ':')))
 	  c++;
diff --git a/gcc/omp-low.c b/gcc/omp-low.c
index 7b122059c6e..e735af974ee 100644
--- a/gcc/omp-low.c
+++ b/gcc/omp-low.c
@@ -3786,7 +3786,7 @@  omp_runtime_api_call (const_tree fndecl)
     return false;
 
   const char *name = IDENTIFIER_POINTER (declname);
-  if (strncmp (name, "omp_", 4) != 0)
+  if (!startswith (name, "omp_"))
     return false;
 
   static const char *omp_runtime_apis[] =
diff --git a/gcc/opts-common.c b/gcc/opts-common.c
index 5e10edeb4cf..9d1914ff2ff 100644
--- a/gcc/opts-common.c
+++ b/gcc/opts-common.c
@@ -1805,7 +1805,7 @@  parse_options_from_collect_gcc_options (const char *collect_gcc_options,
 	      if (argv_storage[j] == '\0')
 		fatal_error (input_location,
 			     "malformed %<COLLECT_GCC_OPTIONS%>");
-	      else if (strncmp (&argv_storage[j], "'\\''", 4) == 0)
+	      else if (startswith (&argv_storage[j], "'\\''"))
 		{
 		  argv_storage[k++] = '\'';
 		  j += 4;
diff --git a/gcc/read-rtl-function.c b/gcc/read-rtl-function.c
index 2a1fb4bac9c..eaf380dd466 100644
--- a/gcc/read-rtl-function.c
+++ b/gcc/read-rtl-function.c
@@ -1082,7 +1082,7 @@  function_reader::read_rtx_operand_r (rtx x)
 	 "orig:%i", ORIGINAL_REGNO (rtx).
 	 Consume it, we don't set ORIGINAL_REGNO, since we can
 	 get that from the 2nd copy later.  */
-      if (strncmp (desc, "orig:", 5) == 0)
+      if (startswith (desc, "orig:"))
 	{
 	  expect_original_regno = true;
 	  desc_start += 5;
diff --git a/gcc/real.c b/gcc/real.c
index 09957a91b7c..555cf44c142 100644
--- a/gcc/real.c
+++ b/gcc/real.c
@@ -1972,17 +1972,17 @@  real_from_string (REAL_VALUE_TYPE *r, const char *str)
   else if (*str == '+')
     str++;
 
-  if (!strncmp (str, "QNaN", 4))
+  if (startswith (str, "QNaN"))
     {
       get_canonical_qnan (r, sign);
       return 0;
     }
-  else if (!strncmp (str, "SNaN", 4))
+  else if (startswith (str, "SNaN"))
     {
       get_canonical_snan (r, sign);
       return 0;
     }
-  else if (!strncmp (str, "Inf", 3))
+  else if (startswith (str, "Inf"))
     {
       get_inf (r, sign);
       return 0;
diff --git a/gcc/selftest.c b/gcc/selftest.c
index 6e26ea553f2..8f1cde0cc19 100644
--- a/gcc/selftest.c
+++ b/gcc/selftest.c
@@ -150,8 +150,7 @@  assert_str_startswith (const location &loc,
 		    "ASSERT_STR_STARTSWITH (%s, %s) str=\"%s\" prefix=NULL",
 		    desc_str, desc_prefix, val_str);
 
-  const char *test = strstr (val_str, val_prefix);
-  if (test == val_str)
+  if (startswith (val_str, val_prefix))
     pass (loc, "ASSERT_STR_STARTSWITH");
   else
     fail_formatted
diff --git a/gcc/system.h b/gcc/system.h
index a3f5948aaee..51ccf753fd4 100644
--- a/gcc/system.h
+++ b/gcc/system.h
@@ -1291,4 +1291,12 @@  void gcc_stablesort (void *, size_t, size_t,
 #define NULL nullptr
 #endif
 
+/* Return true if STR string starts with PREFIX.  */
+
+static inline bool
+startswith (const char *str, const char *prefix)
+{
+  return strncmp (str, prefix, strlen (prefix)) == 0;
+}
+
 #endif /* ! GCC_SYSTEM_H */
diff --git a/gcc/timevar.c b/gcc/timevar.c
index 5d4e1597f23..8fc122ba9fe 100644
--- a/gcc/timevar.c
+++ b/gcc/timevar.c
@@ -600,7 +600,7 @@  timer::validate_phases (FILE *fp) const
       if (!tv->used)
 	continue;
 
-      if (strncmp (tv->name, phase_prefix, sizeof phase_prefix - 1) == 0)
+      if (startswith (tv->name, phase_prefix))
 	{
 	  phase_user += tv->elapsed.user;
 	  phase_sys += tv->elapsed.sys;
diff --git a/gcc/tree.c b/gcc/tree.c
index e4e74ac8afc..3ed7ea349f6 100644
--- a/gcc/tree.c
+++ b/gcc/tree.c
@@ -9725,7 +9725,7 @@  get_file_function_name (const char *type)
      We also assign sub_I and sub_D sufixes to constructors called from
      the global static constructors.  These are always local.  */
   else if (((type[0] == 'I' || type[0] == 'D') && targetm.have_ctors_dtors)
-	   || (strncmp (type, "sub_", 4) == 0
+	   || (startswith (type, "sub_")
 	       && (type[4] == 'I' || type[4] == 'D')))
     {
       const char *file = main_input_filename;
diff --git a/gcc/ubsan.c b/gcc/ubsan.c
index 1089aef639f..7ee93436378 100644
--- a/gcc/ubsan.c
+++ b/gcc/ubsan.c
@@ -1783,7 +1783,7 @@  ubsan_use_new_style_p (location_t loc)
     return false;
 
   expanded_location xloc = expand_location (loc);
-  if (xloc.file == NULL || strncmp (xloc.file, "\1", 2) == 0
+  if (xloc.file == NULL || startswith (xloc.file, "\1")
       || xloc.file[0] == '\0' || xloc.file[0] == '\xff'
       || xloc.file[1] == '\xff')
     return false;
diff --git a/gcc/varasm.c b/gcc/varasm.c
index 8bb921faa26..bc2727c9303 100644
--- a/gcc/varasm.c
+++ b/gcc/varasm.c
@@ -792,7 +792,7 @@  default_function_rodata_section (tree decl, bool relocatable)
       /* For .gnu.linkonce.t.foo we want to use .gnu.linkonce.r.foo or
 	 .gnu.linkonce.d.rel.ro.local.foo if the jump table is relocatable.  */
       else if (DECL_COMDAT_GROUP (decl)
-	       && strncmp (name, ".gnu.linkonce.t.", 16) == 0)
+	       && startswith (name, ".gnu.linkonce.t."))
 	{
 	  size_t len;
 	  char *rname;
@@ -817,7 +817,7 @@  default_function_rodata_section (tree decl, bool relocatable)
 	}
       /* For .text.foo we want to use .rodata.foo.  */
       else if (flag_function_sections && flag_data_sections
-	       && strncmp (name, ".text.", 6) == 0)
+	       && startswith (name, ".text."))
 	{
 	  size_t len = strlen (name) + 1;
 	  char *rname = (char *) alloca (len + strlen (sname) - 5);
@@ -2485,7 +2485,7 @@  incorporeal_function_p (tree decl)
       name = IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (decl));
       /* Atomic or sync builtins which have survived this far will be
 	 resolved externally and therefore are not incorporeal.  */
-      if (strncmp (name, "__builtin_", 10) == 0)
+      if (startswith (name, "__builtin_"))
 	return true;
     }
   return false;
@@ -6713,22 +6713,22 @@  default_section_type_flags (tree decl, const char *name, int reloc)
     flags |= SECTION_TLS | SECTION_WRITE;
 
   if (strcmp (name, ".bss") == 0
-      || strncmp (name, ".bss.", 5) == 0
-      || strncmp (name, ".gnu.linkonce.b.", 16) == 0
+      || startswith (name, ".bss.")
+      || startswith (name, ".gnu.linkonce.b.")
       || strcmp (name, ".persistent.bss") == 0
       || strcmp (name, ".sbss") == 0
-      || strncmp (name, ".sbss.", 6) == 0
-      || strncmp (name, ".gnu.linkonce.sb.", 17) == 0)
+      || startswith (name, ".sbss.")
+      || startswith (name, ".gnu.linkonce.sb."))
     flags |= SECTION_BSS;
 
   if (strcmp (name, ".tdata") == 0
-      || strncmp (name, ".tdata.", 7) == 0
-      || strncmp (name, ".gnu.linkonce.td.", 17) == 0)
+      || startswith (name, ".tdata.")
+      || startswith (name, ".gnu.linkonce.td."))
     flags |= SECTION_TLS;
 
   if (strcmp (name, ".tbss") == 0
-      || strncmp (name, ".tbss.", 6) == 0
-      || strncmp (name, ".gnu.linkonce.tb.", 17) == 0)
+      || startswith (name, ".tbss.")
+      || startswith (name, ".gnu.linkonce.tb."))
     flags |= SECTION_TLS | SECTION_BSS;
 
   if (strcmp (name, ".noinit") == 0)