public inbox for gcc-patches@gcc.gnu.org
 help / color / mirror / Atom feed
* [PATCH] RFC: come up with startswith function.
@ 2021-03-18 10:46 Martin Liška
  2021-03-18 15:30 ` Martin Sebor
  2021-04-21  7:24 ` [PATCH 0/3] Come " Martin Liska
  0 siblings, 2 replies; 19+ messages in thread
From: Martin Liška @ 2021-03-18 10:46 UTC (permalink / raw)
  To: gcc-patches

Hey.

Recently, I noticed a cumbersome construct we use for string startswith function
(most notably in a situation when the prefix is a string literal).

Commonly used patterns are:
1) strncmp (arg, "--sysroot=", 10) == 0
2) strncmp (name, "not found", sizeof ("not found") - 1) == 0
3) strncmp (varname, "__builtin_", strlen ("__builtin_")) == 0
4) #define STR "-foffload-abi="
    if (strncmp (argv[i], STR, strlen (STR)) == 0)

I see all these quite error prone for the following reasons:
1) one needs to correctly calculate string length (in their head)
2) sizeof ("foo") - 1 == strlen ("foo")
3) one needs to undefine a temporary macros

Moreover, there are helper functions that already do the same:

gcc/ada/adadecode.c:
static int
has_prefix (const char *name, const char *prefix)
{
   return strncmp (name, prefix, strlen (prefix)) == 0;
}

gcc/fortran/gfortran.h:
#define gfc_str_startswith(str, pref) \
        (strncmp ((str), (pref), strlen (pref)) == 0)

That said, I'm suggesting a new function 'startswith' in system.h.
I prepared a patch that utilizes the function in gcc/ subfolder
(excluding all target code for now). I can prepare similar mechanical
patch for the rest of the compiler (and run-time libraries).

Thoughts?
Thanks,
Martin

---
  gcc/ada/adadecode.c                 | 14 +++--------
  gcc/ada/init.c                      |  8 +++----
  gcc/analyzer/sm-file.cc             |  5 ++--
  gcc/builtins.c                      | 10 +++-----
  gcc/c-family/c-ada-spec.c           |  2 +-
  gcc/c-family/c-common.c             |  2 +-
  gcc/c-family/c-format.c             |  2 +-
  gcc/collect2.c                      | 36 ++++++++++++++---------------
  gcc/cp/decl.c                       |  6 ++---
  gcc/cp/mangle.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.c                           |  4 ++--
  gcc/gencfn-macros.c                 |  2 +-
  gcc/gengtype.c                      |  6 ++---
  gcc/genmatch.c                      |  8 +++----
  gcc/genoutput.c                     |  2 +-
  gcc/go/gofrontend/runtime.cc        |  2 +-
  gcc/incpath.c                       |  2 +-
  gcc/langhooks.c                     |  8 +++----
  gcc/objc/objc-next-runtime-abi-02.c |  2 +-
  gcc/opts-common.c                   |  2 +-
  gcc/opts.c                          |  2 +-
  gcc/read-rtl-function.c             |  2 +-
  gcc/selftest.c                      |  3 +--
  gcc/system.h                        |  8 +++++++
  gcc/timevar.c                       |  2 +-
  gcc/tree.c                          |  2 +-
  gcc/ubsan.c                         |  2 +-
  gcc/varasm.c                        | 22 +++++++++---------
  40 files changed, 117 insertions(+), 127 deletions(-)

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/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 7a81c8ff632..1e19ddbec7a 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 196dda3fa5e..af71caf2f08 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 dd8e8bbd90a..9b95c9d1440 100644
--- a/gcc/c-family/c-ada-spec.c
+++ b/gcc/c-family/c-ada-spec.c
@@ -2693,7 +2693,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);
  }
diff --git a/gcc/c-family/c-common.c b/gcc/c-family/c-common.c
index d227686a030..071f5089361 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
      {
diff --git a/gcc/c-family/c-format.c b/gcc/c-family/c-format.c
index 0a63cacb0d9..73cc4edd42c 100644
--- a/gcc/c-family/c-format.c
+++ b/gcc/c-family/c-format.c
@@ -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/collect2.c b/gcc/collect2.c
index bd371430ab7..6c94a98c748 100644
--- a/gcc/collect2.c
+++ b/gcc/collect2.c
@@ -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;
@@ -2619,7 +2619,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/cp/decl.c b/gcc/cp/decl.c
index 8e8f37d060e..e7479e8e8a1 100644
--- a/gcc/cp/decl.c
+++ b/gcc/cp/decl.c
@@ -7569,9 +7569,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;
diff --git a/gcc/cp/mangle.c b/gcc/cp/mangle.c
index 0a9e5aa79a0..5ec7bf7af5a 100644
--- a/gcc/cp/mangle.c
+++ b/gcc/cp/mangle.c
@@ -4419,7 +4419,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);
diff --git a/gcc/d/dmd/dmangle.c b/gcc/d/dmd/dmangle.c
index 303ae617874..5a73b3e3a65 100644
--- a/gcc/d/dmd/dmangle.c
+++ b/gcc/d/dmd/dmangle.c
@@ -666,7 +666,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 a11c9c353d9..4959b480fe5 100644
--- a/gcc/d/dmd/hdrgen.c
+++ b/gcc/d/dmd/hdrgen.c
@@ -3189,7 +3189,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 b3ca159c3a8..760714c47e5 100644
--- a/gcc/dwarf2out.c
+++ b/gcc/dwarf2out.c
@@ -5465,7 +5465,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 ();
  }
@@ -24572,8 +24572,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));
@@ -24590,7 +24590,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;
@@ -24606,7 +24606,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 */)
@@ -24628,7 +24628,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 */)
@@ -24652,7 +24652,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 4db0a3ac76d..a55855548b4 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 6a4ed9bbfdd..fc8ccca9d63 100644
--- a/gcc/fortran/trans-decl.c
+++ b/gcc/fortran/trans-decl.c
@@ -1940,7 +1940,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 bffe0808dff..82698b411dd 100644
--- a/gcc/fortran/trans-expr.c
+++ b/gcc/fortran/trans-expr.c
@@ -6791,7 +6791,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.c b/gcc/gcc.c
index 7837553958b..3a870c6144a 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.  */
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 5f50242e857..64ea6348a68 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];
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 b88e13b90b6..bd5a007c6da 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/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/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/opts.c b/gcc/opts.c
index 24bb64198c8..8422e56faa7 100644
--- a/gcc/opts.c
+++ b/gcc/opts.c
@@ -47,7 +47,7 @@ const char *const debug_type_names[] =
     and set the flag variables. */
  
  #define MATCH( prefix, string ) \
-  ((strncmp (prefix, string, sizeof prefix - 1) == 0) \
+  ((startswith (prefix, string)) \
     ? ((string += sizeof prefix - 1), 1) : 0)
  
  void
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/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..3e384616d3a 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 1 if STR string starts with PREFIX.  */
+
+static inline int
+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 7c44c226a33..0763e3337f6 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 d752b897d64..767114ef1f6 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 811212244a5..4656a37dc09 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.30.2


^ permalink raw reply	[flat|nested] 19+ messages in thread

* Re: [PATCH] RFC: come up with startswith function.
  2021-03-18 10:46 [PATCH] RFC: come up with startswith function Martin Liška
@ 2021-03-18 15:30 ` Martin Sebor
  2021-04-21  7:24 ` [PATCH 0/3] Come " Martin Liska
  1 sibling, 0 replies; 19+ messages in thread
From: Martin Sebor @ 2021-03-18 15:30 UTC (permalink / raw)
  To: Martin Liška, gcc-patches

On 3/18/21 4:46 AM, Martin Liška wrote:
> Hey.
> 
> Recently, I noticed a cumbersome construct we use for string startswith 
> function
> (most notably in a situation when the prefix is a string literal).
> 
> Commonly used patterns are:
> 1) strncmp (arg, "--sysroot=", 10) == 0
> 2) strncmp (name, "not found", sizeof ("not found") - 1) == 0
> 3) strncmp (varname, "__builtin_", strlen ("__builtin_")) == 0
> 4) #define STR "-foffload-abi="
>     if (strncmp (argv[i], STR, strlen (STR)) == 0)
> 
> I see all these quite error prone for the following reasons:
> 1) one needs to correctly calculate string length (in their head)
> 2) sizeof ("foo") - 1 == strlen ("foo")

Right.  They could be alleviated by either developing a new warning
or extending -Wstring-compare to complain when the length of a string
literal argument isn't the same as the bound in these cases.

> 3) one needs to undefine a temporary macros
> 
> Moreover, there are helper functions that already do the same:
> 
> gcc/ada/adadecode.c:
> static int
> has_prefix (const char *name, const char *prefix)
> {
>    return strncmp (name, prefix, strlen (prefix)) == 0;
> }
> 
> gcc/fortran/gfortran.h:
> #define gfc_str_startswith(str, pref) \
>         (strncmp ((str), (pref), strlen (pref)) == 0)
> 
> That said, I'm suggesting a new function 'startswith' in system.h.
> I prepared a patch that utilizes the function in gcc/ subfolder
> (excluding all target code for now). I can prepare similar mechanical
> patch for the rest of the compiler (and run-time libraries).
> 
> Thoughts?
> Thanks,
> Martin

I like it.

...
> diff --git a/gcc/system.h b/gcc/system.h
> index a3f5948aaee..3e384616d3a 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 1 if STR string starts with PREFIX.  */
> +
> +static inline int
> +startswith (const char *str, const char *prefix)
> +{
> +  return strncmp (str, prefix, strlen (prefix)) == 0;
> +}

The return type of the function should be bool rather than int.

Martin

^ permalink raw reply	[flat|nested] 19+ messages in thread

* [PATCH 0/3] Come up with startswith function
  2021-03-18 10:46 [PATCH] RFC: come up with startswith function Martin Liška
  2021-03-18 15:30 ` Martin Sebor
@ 2021-04-21  7:24 ` Martin Liska
  2021-04-21  7:26   ` [PATCH 2/3] LTO plugin: use " Martin Liska
                     ` (3 more replies)
  1 sibling, 4 replies; 19+ messages in thread
From: Martin Liska @ 2021-04-21  7:24 UTC (permalink / raw)
  To: gcc-patches

The patchset is tested on x86_64-linux-gnu and I was able to build
all cross-compilers.

Ready to be installed to master once GCC 11.1 is released?
Thanks,
Martin

Martin Liska (3):
  Come up with startswith function.
  LTO plugin: use startswith function.
  Use startswith in targets.

 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/common/config/aarch64/aarch64-common.c    |   2 +-
 gcc/common/config/bfin/bfin-common.c          |   2 +-
 gcc/common/config/riscv/riscv-common.c        |   4 +-
 .../aarch64/aarch64-sve-builtins-shapes.cc    |   4 +-
 gcc/config/aarch64/aarch64.c                  |   2 +-
 gcc/config/alpha/alpha.c                      |   8 +-
 gcc/config/arm/aarch-common.c                 |   2 +-
 gcc/config/arm/arm.c                          |   8 +-
 gcc/config/arm/driver-arm.c                   |   4 +-
 gcc/config/avr/avr.c                          |  25 ++--
 gcc/config/c6x/c6x.c                          |  14 +-
 gcc/config/darwin-c.c                         |   9 +-
 gcc/config/darwin.c                           | 141 +++++++++---------
 gcc/config/frv/frv.c                          |  16 +-
 gcc/config/gcn/mkoffload.c                    |  10 +-
 gcc/config/i386/i386-builtins.c               |   2 +-
 gcc/config/i386/i386-options.c                |   2 +-
 gcc/config/i386/i386.c                        |   7 +-
 gcc/config/i386/intelmic-mkoffload.c          |   4 +-
 gcc/config/i386/winnt.c                       |   5 +-
 gcc/config/ia64/ia64.c                        |  20 +--
 gcc/config/mips/driver-native.c               |   2 +-
 gcc/config/mips/mips.c                        |  10 +-
 gcc/config/msp430/msp430.c                    |  13 +-
 gcc/config/nios2/nios2.c                      |  13 +-
 gcc/config/nvptx/mkoffload.c                  |  10 +-
 gcc/config/pa/som.h                           |  13 +-
 gcc/config/pdp11/pdp11.c                      |   2 +-
 gcc/config/riscv/riscv.c                      |   2 +-
 gcc/config/rs6000/rs6000.c                    |  18 +--
 gcc/config/s390/driver-native.c               |  12 +-
 gcc/config/sparc/driver-sparc.c               |   2 +-
 gcc/config/vax/vax.c                          |   8 +-
 gcc/config/vms/vms-ld.c                       |  22 ++-
 gcc/config/vms/vms.c                          |   2 +-
 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 +--
 lto-plugin/lto-plugin.c                       |  29 ++--
 93 files changed, 388 insertions(+), 438 deletions(-)

-- 
2.31.1


^ permalink raw reply	[flat|nested] 19+ messages in thread

* [PATCH 2/3] LTO plugin: use startswith function.
  2021-04-21  7:24 ` [PATCH 0/3] Come " Martin Liska
@ 2021-04-21  7:26   ` Martin Liska
  2021-04-29 12:17     ` Richard Biener
  2021-04-21  7:26   ` [PATCH 1/3] Come up with " Martin Liska
                     ` (2 subsequent siblings)
  3 siblings, 1 reply; 19+ messages in thread
From: Martin Liska @ 2021-04-21  7:26 UTC (permalink / raw)
  To: gcc-patches

[-- Attachment #1: Type: text/plain, Size: 655 bytes --]


lto-plugin/ChangeLog:

	* lto-plugin.c (LTO_SEGMENT_NAME): Remove.
	(LTO_SYMTAB_PREFIX): Likewise.
	(LTO_SYMTAB_PREFIX_LEN): Likewise.
	(LTO_SYMTAB_EXT_PREFIX): Likewise.
	(LTO_SYMTAB_EXT_PREFIX_LEN): Likewise.
	(LTO_LTO_PREFIX): Likewise.
	(LTO_LTO_PREFIX_LEN): Likewise.
	(OFFLOAD_SECTION): Likewise.
	(OFFLOAD_SECTION_LEN): Likewise.
	(startswith): New function.
	(all_symbols_read_handler): Use it.
	(process_symtab): Likewise.
	(process_symtab_extension): Likewise.
	(process_offload_section): Likewise.
	(process_option): Likewise.
---
 lto-plugin/lto-plugin.c | 29 +++++++++++++----------------
 1 file changed, 13 insertions(+), 16 deletions(-)


[-- Warning: decoded text below may be mangled, UTF-8 assumed --]
[-- Attachment #2: 0002-LTO-plugin-use-startswith-function.patch --]
[-- Type: text/x-patch; name="0002-LTO-plugin-use-startswith-function.patch", Size: 3666 bytes --]

diff --git a/lto-plugin/lto-plugin.c b/lto-plugin/lto-plugin.c
index 32478f070e8..cd57ebca677 100644
--- a/lto-plugin/lto-plugin.c
+++ b/lto-plugin/lto-plugin.c
@@ -89,16 +89,13 @@ along with this program; see the file COPYING3.  If not see
 
 #define LTO_SEGMENT_NAME "__GNU_LTO"
 
-/* LTO magic section name.  */
+/* Return true if STR string starts with PREFIX.  */
 
-#define LTO_SYMTAB_PREFIX	    ".gnu.lto_.symtab"
-#define LTO_SYMTAB_PREFIX_LEN	    (sizeof (LTO_SYMTAB_PREFIX) - 1)
-#define LTO_SYMTAB_EXT_PREFIX	    ".gnu.lto_.ext_symtab"
-#define LTO_SYMTAB_EXT_PREFIX_LEN   (sizeof (LTO_SYMTAB_EXT_PREFIX) - 1)
-#define LTO_LTO_PREFIX		    ".gnu.lto_.lto"
-#define LTO_LTO_PREFIX_LEN	    (sizeof (LTO_LTO_PREFIX) - 1)
-#define OFFLOAD_SECTION		    ".gnu.offload_lto_.opts"
-#define OFFLOAD_SECTION_LEN	    (sizeof (OFFLOAD_SECTION) - 1)
+static inline bool
+startswith (const char *str, const char *prefix)
+{
+  return strncmp (str, prefix, strlen (prefix)) == 0;
+}
 
 /* The part of the symbol table the plugin has to keep track of. Note that we
    must keep SYMS until all_symbols_read is called to give the linker time to
@@ -832,7 +829,7 @@ all_symbols_read_handler (void)
       unsigned int i;
       for (i = 0; i < num_pass_through_items; i++)
         {
-          if (strncmp (pass_through_items[i], "-l", 2) == 0)
+	  if (startswith (pass_through_items[i], "-l"))
             add_input_library (pass_through_items[i] + 2);
           else
             add_input_file (pass_through_items[i]);
@@ -1022,7 +1019,7 @@ process_symtab (void *data, const char *name, off_t offset, off_t length)
   char *s;
   char *secdatastart, *secdata;
 
-  if (strncmp (name, LTO_SYMTAB_PREFIX, LTO_SYMTAB_PREFIX_LEN) != 0)
+  if (!startswith (name, ".gnu.lto_.symtab"))
     return 1;
 
   s = strrchr (name, '.');
@@ -1074,7 +1071,7 @@ process_symtab_extension (void *data, const char *name, off_t offset,
   char *s;
   char *secdatastart, *secdata;
 
-  if (strncmp (name, LTO_SYMTAB_EXT_PREFIX, LTO_SYMTAB_EXT_PREFIX_LEN) != 0)
+  if (!startswith (name, ".gnu.lto_.ext_symtab"))
     return 1;
 
   s = strrchr (name, '.');
@@ -1122,7 +1119,7 @@ err:
 static int
 process_offload_section (void *data, const char *name, off_t offset, off_t len)
 {
-  if (!strncmp (name, OFFLOAD_SECTION, OFFLOAD_SECTION_LEN))
+  if (startswith (name, ".gnu.offload_lto_.opts"))
     {
       struct plugin_objfile *obj = (struct plugin_objfile *) data;
       obj->offload = 1;
@@ -1325,7 +1322,7 @@ process_option (const char *option)
     save_temps = true;
   else if (strcmp (option, "-nop") == 0)
     nop = 1;
-  else if (!strncmp (option, "-pass-through=", strlen("-pass-through=")))
+  else if (startswith (option, "-pass-through="))
     {
       num_pass_through_items++;
       pass_through_items = xrealloc (pass_through_items,
@@ -1333,7 +1330,7 @@ process_option (const char *option)
       pass_through_items[num_pass_through_items - 1] =
           xstrdup (option + strlen ("-pass-through="));
     }
-  else if (!strncmp (option, "-sym-style=", sizeof ("-sym-style=") - 1))
+  else if (startswith (option, "-sym-style="))
     {
       switch (option[sizeof ("-sym-style=") - 1])
 	{
@@ -1356,7 +1353,7 @@ process_option (const char *option)
       size = lto_wrapper_num_args * sizeof (char *);
       lto_wrapper_argv = (char **) xrealloc (lto_wrapper_argv, size);
       lto_wrapper_argv[lto_wrapper_num_args - 1] = opt;
-      if (strncmp (option, "-fresolution=", sizeof ("-fresolution=") - 1) == 0)
+      if (startswith (option, "-fresolution="))
 	resolution_file = opt + sizeof ("-fresolution=") - 1;
     }
   save_temps = save_temps || debug;

^ permalink raw reply	[flat|nested] 19+ messages in thread

* [PATCH 3/3] Use startswith in targets.
  2021-04-21  7:24 ` [PATCH 0/3] Come " Martin Liska
  2021-04-21  7:26   ` [PATCH 2/3] LTO plugin: use " Martin Liska
  2021-04-21  7:26   ` [PATCH 1/3] Come up with " Martin Liska
@ 2021-04-21  7:26   ` Martin Liska
  2021-04-21 20:31     ` Paul Koning
                       ` (2 more replies)
  2021-04-21  7:33   ` [PATCH 0/3] Come up with startswith function Arnaud Charlet
  3 siblings, 3 replies; 19+ messages in thread
From: Martin Liska @ 2021-04-21  7:26 UTC (permalink / raw)
  To: gcc-patches

[-- Attachment #1: Type: text/plain, Size: 5443 bytes --]


gcc/ChangeLog:

	* common/config/aarch64/aarch64-common.c (aarch64_parse_extension):
	Use startswith function instead of strncmp.
	* common/config/bfin/bfin-common.c (bfin_handle_option): Likewise.
	* common/config/riscv/riscv-common.c (riscv_subset_list::parse): Likewise.
	* config/aarch64/aarch64-sve-builtins-shapes.cc (parse_type): Likewise.
	* config/aarch64/aarch64.c (aarch64_process_one_target_attr): Likewise.
	* config/alpha/alpha.c (alpha_elf_section_type_flags): Likewise.
	* config/arm/aarch-common.c (arm_md_asm_adjust): Likewise.
	* config/arm/arm.c (arm_file_start): Likewise.
	(arm_valid_target_attribute_rec): Likewise.
	(thumb1_md_asm_adjust): Likewise.
	* config/arm/driver-arm.c (host_detect_local_cpu): Likewise.
	* config/avr/avr.c (STR_PREFIX_P): Likewise.
	(avr_set_current_function): Likewise.
	(avr_handle_addr_attribute): Likewise.
	(avr_asm_output_aligned_decl_common): Likewise.
	(avr_asm_named_section): Likewise.
	(avr_section_type_flags): Likewise.
	(avr_asm_select_section): Likewise.
	* config/c6x/c6x.c (c6x_in_small_data_p): Likewise.
	(c6x_section_type_flags): Likewise.
	* config/darwin-c.c (darwin_cfstring_ref_p): Likewise.
	(darwin_objc_declare_unresolved_class_reference): Likewise.
	(darwin_objc_declare_class_definition): Likewise.
	* config/darwin.c (indirect_data): Likewise.
	(darwin_encode_section_info): Likewise.
	(darwin_objc2_section): Likewise.
	(darwin_objc1_section): Likewise.
	(machopic_select_section): Likewise.
	(darwin_globalize_label): Likewise.
	(darwin_label_is_anonymous_local_objc_name): Likewise.
	(darwin_asm_named_section): Likewise.
	(darwin_asm_output_dwarf_offset): Likewise.
	* config/frv/frv.c (frv_string_begins_with): Likewise.
	(frv_in_small_data_p): Likewise.
	* config/gcn/mkoffload.c (STR): Likewise.
	(main): Likewise.
	* config/i386/i386-builtins.c (get_builtin_code_for_version): Likewise.
	* config/i386/i386-options.c (ix86_option_override_internal): Likewise.
	* config/i386/i386.c (x86_64_elf_section_type_flags): Likewise.
	(ix86_md_asm_adjust): Likewise.
	* config/i386/intelmic-mkoffload.c (STR): Likewise.
	* config/i386/winnt.c (i386_pe_asm_named_section): Likewise.
	(i386_pe_file_end): Likewise.
	* config/ia64/ia64.c (ia64_in_small_data_p): Likewise.
	(ia64_section_type_flags): Likewise.
	* config/mips/driver-native.c (host_detect_local_cpu): Likewise.
	* config/mips/mips.c (mips_handle_interrupt_attr): Likewise.
	(mips16_stub_function_p): Likewise.
	(mips_function_rodata_section): Likewise.
	* config/msp430/msp430.c (msp430_mcu_name): Likewise.
	(msp430_function_section): Likewise.
	(msp430_section_type_flags): Likewise.
	(msp430_expand_helper): Likewise.
	* config/nios2/nios2.c (nios2_small_section_name_p): Likewise.
	(nios2_valid_target_attribute_rec): Likewise.
	* config/nvptx/mkoffload.c (process): Likewise.
	(STR): Likewise.
	* config/pa/som.h: Likewise.
	* config/pdp11/pdp11.c (pdp11_output_ident): Likewise.
	* config/riscv/riscv.c (riscv_elf_select_rtx_section): Likewise.
	* config/rs6000/rs6000.c (VTABLE_NAME_P): Likewise.
	(rs6000_inner_target_options): Likewise.
	* config/s390/driver-native.c (s390_host_detect_local_cpu): Likewise.
	* config/sparc/driver-sparc.c (host_detect_local_cpu): Likewise.
	* config/vax/vax.c (vax_output_int_move): Likewise.
	* config/vms/vms-ld.c (startswith): Likewise.
	(process_args): Likewise.
	(main): Likewise.
	* config/vms/vms.c: Likewise.
---
 gcc/common/config/aarch64/aarch64-common.c    |   2 +-
 gcc/common/config/bfin/bfin-common.c          |   2 +-
 gcc/common/config/riscv/riscv-common.c        |   4 +-
 .../aarch64/aarch64-sve-builtins-shapes.cc    |   4 +-
 gcc/config/aarch64/aarch64.c                  |   2 +-
 gcc/config/alpha/alpha.c                      |   8 +-
 gcc/config/arm/aarch-common.c                 |   2 +-
 gcc/config/arm/arm.c                          |   8 +-
 gcc/config/arm/driver-arm.c                   |   4 +-
 gcc/config/avr/avr.c                          |  25 ++--
 gcc/config/c6x/c6x.c                          |  14 +-
 gcc/config/darwin-c.c                         |   9 +-
 gcc/config/darwin.c                           | 141 +++++++++---------
 gcc/config/frv/frv.c                          |  16 +-
 gcc/config/gcn/mkoffload.c                    |  10 +-
 gcc/config/i386/i386-builtins.c               |   2 +-
 gcc/config/i386/i386-options.c                |   2 +-
 gcc/config/i386/i386.c                        |   7 +-
 gcc/config/i386/intelmic-mkoffload.c          |   4 +-
 gcc/config/i386/winnt.c                       |   5 +-
 gcc/config/ia64/ia64.c                        |  20 +--
 gcc/config/mips/driver-native.c               |   2 +-
 gcc/config/mips/mips.c                        |  10 +-
 gcc/config/msp430/msp430.c                    |  13 +-
 gcc/config/nios2/nios2.c                      |  13 +-
 gcc/config/nvptx/mkoffload.c                  |  10 +-
 gcc/config/pa/som.h                           |  13 +-
 gcc/config/pdp11/pdp11.c                      |   2 +-
 gcc/config/riscv/riscv.c                      |   2 +-
 gcc/config/rs6000/rs6000.c                    |  18 +--
 gcc/config/s390/driver-native.c               |  12 +-
 gcc/config/sparc/driver-sparc.c               |   2 +-
 gcc/config/vax/vax.c                          |   8 +-
 gcc/config/vms/vms-ld.c                       |  22 ++-
 gcc/config/vms/vms.c                          |   2 +-
 35 files changed, 199 insertions(+), 221 deletions(-)


[-- Warning: decoded text below may be mangled, UTF-8 assumed --]
[-- Attachment #2: 0003-Use-startswith-in-targets.patch --]
[-- Type: text/x-patch; name="0003-Use-startswith-in-targets.patch", Size: 51498 bytes --]

diff --git a/gcc/common/config/aarch64/aarch64-common.c b/gcc/common/config/aarch64/aarch64-common.c
index 6763191af36..6d200a18660 100644
--- a/gcc/common/config/aarch64/aarch64-common.c
+++ b/gcc/common/config/aarch64/aarch64-common.c
@@ -219,7 +219,7 @@ aarch64_parse_extension (const char *str, uint64_t *isa_flags,
       else
 	len = strlen (str);
 
-      if (len >= 2 && strncmp (str, "no", 2) == 0)
+      if (len >= 2 && startswith (str, "no"))
 	{
 	  adding_ext = 0;
 	  len -= 2;
diff --git a/gcc/common/config/bfin/bfin-common.c b/gcc/common/config/bfin/bfin-common.c
index 48a6fe8ea0b..a3ee4b5544c 100644
--- a/gcc/common/config/bfin/bfin-common.c
+++ b/gcc/common/config/bfin/bfin-common.c
@@ -313,7 +313,7 @@ bfin_handle_option (struct gcc_options *opts,
 	i = 0;
 	while ((p = bfin_cpus[i].name) != NULL)
 	  {
-	    if (strncmp (arg, p, strlen (p)) == 0)
+	    if (startswith (arg, p))
 	      break;
 	    i++;
 	  }
diff --git a/gcc/common/config/riscv/riscv-common.c b/gcc/common/config/riscv/riscv-common.c
index 34b74e52a2d..d17bea687e0 100644
--- a/gcc/common/config/riscv/riscv-common.c
+++ b/gcc/common/config/riscv/riscv-common.c
@@ -804,12 +804,12 @@ riscv_subset_list::parse (const char *arch, location_t loc)
   riscv_subset_list *subset_list = new riscv_subset_list (arch, loc);
   riscv_subset_t *itr;
   const char *p = arch;
-  if (strncmp (p, "rv32", 4) == 0)
+  if (startswith (p, "rv32"))
     {
       subset_list->m_xlen = 32;
       p += 4;
     }
-  else if (strncmp (p, "rv64", 4) == 0)
+  else if (startswith (p, "rv64"))
     {
       subset_list->m_xlen = 64;
       p += 4;
diff --git a/gcc/config/aarch64/aarch64-sve-builtins-shapes.cc b/gcc/config/aarch64/aarch64-sve-builtins-shapes.cc
index e16c81c30ba..2cc3fbacbac 100644
--- a/gcc/config/aarch64/aarch64-sve-builtins-shapes.cc
+++ b/gcc/config/aarch64/aarch64-sve-builtins-shapes.cc
@@ -191,12 +191,12 @@ parse_type (const function_instance &instance, const char *&format)
 
   if (ch == 'e')
     {
-      if (strncmp (format, "pattern", 7) == 0)
+      if (startswith (format, "pattern"))
 	{
 	  format += 7;
 	  return acle_svpattern;
 	}
-      if (strncmp (format, "prfop", 5) == 0)
+      if (startswith (format, "prfop"))
 	{
 	  format += 5;
 	  return acle_svprfop;
diff --git a/gcc/config/aarch64/aarch64.c b/gcc/config/aarch64/aarch64.c
index 12625a4bee3..42be30d13ce 100644
--- a/gcc/config/aarch64/aarch64.c
+++ b/gcc/config/aarch64/aarch64.c
@@ -17379,7 +17379,7 @@ aarch64_process_one_target_attr (char *arg_str)
   if (*str_to_check == '+')
     return aarch64_handle_attr_isa_flags (str_to_check);
 
-  if (len > 3 && strncmp (str_to_check, "no-", 3) == 0)
+  if (len > 3 && startswith (str_to_check, "no-"))
     {
       invert = true;
       str_to_check += 3;
diff --git a/gcc/config/alpha/alpha.c b/gcc/config/alpha/alpha.c
index 335f1db5335..c702e683c31 100644
--- a/gcc/config/alpha/alpha.c
+++ b/gcc/config/alpha/alpha.c
@@ -9457,11 +9457,11 @@ alpha_elf_section_type_flags (tree decl, const char *name, int reloc)
   unsigned int flags = 0;
 
   if (strcmp (name, ".sdata") == 0
-      || strncmp (name, ".sdata.", 7) == 0
-      || strncmp (name, ".gnu.linkonce.s.", 16) == 0
+      || startswith (name, ".sdata.")
+      || startswith (name, ".gnu.linkonce.s.")
       || 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_SMALL;
 
   flags |= default_section_type_flags (decl, name, reloc);
diff --git a/gcc/config/arm/aarch-common.c b/gcc/config/arm/aarch-common.c
index 24711d5b4f7..0dbdc56f542 100644
--- a/gcc/config/arm/aarch-common.c
+++ b/gcc/config/arm/aarch-common.c
@@ -542,7 +542,7 @@ arm_md_asm_adjust (vec<rtx> &outputs, vec<rtx> & /*inputs*/,
   for (unsigned i = 0, n = outputs.length (); i < n; ++i)
     {
       const char *con = constraints[i];
-      if (strncmp (con, "=@cc", 4) != 0)
+      if (!startswith (con, "=@cc"))
 	continue;
       con += 4;
       if (strchr (con, ',') != NULL)
diff --git a/gcc/config/arm/arm.c b/gcc/config/arm/arm.c
index 340f7c95d76..052a0155cc2 100644
--- a/gcc/config/arm/arm.c
+++ b/gcc/config/arm/arm.c
@@ -28139,7 +28139,7 @@ arm_file_start (void)
 	  else
 	    arm_print_asm_arch_directives ();
 	}
-      else if (strncmp (arm_active_target.core_name, "generic", 7) == 0)
+      else if (startswith (arm_active_target.core_name, "generic"))
 	{
 	  asm_fprintf (asm_out_file, "\t.arch %s\n",
 		       arm_active_target.core_name + 8);
@@ -32887,7 +32887,7 @@ arm_valid_target_attribute_rec (tree args, struct gcc_options *opts)
       else if (!strcmp (q, "general-regs-only"))
 	opts->x_target_flags |= MASK_GENERAL_REGS_ONLY;
 
-      else if (!strncmp (q, "fpu=", 4))
+      else if (startswith (q, "fpu="))
 	{
 	  int fpu_index;
 	  if (! opt_enum_arg_to_value (OPT_mfpu_, q + 4,
@@ -32906,7 +32906,7 @@ arm_valid_target_attribute_rec (tree args, struct gcc_options *opts)
 	    }
 	  opts->x_arm_fpu_index = (enum fpu_type) fpu_index;
 	}
-      else if (!strncmp (q, "arch=", 5))
+      else if (startswith (q, "arch="))
 	{
 	  char *arch = q + 5;
 	  const arch_option *arm_selected_arch
@@ -33938,7 +33938,7 @@ thumb1_md_asm_adjust (vec<rtx> &outputs, vec<rtx> & /*inputs*/,
 		      HARD_REG_SET & /*clobbered_regs*/)
 {
   for (unsigned i = 0, n = outputs.length (); i < n; ++i)
-    if (strncmp (constraints[i], "=@cc", 4) == 0)
+    if (startswith (constraints[i], "=@cc"))
       {
 	sorry ("asm flags not supported in thumb1 mode");
 	break;
diff --git a/gcc/config/arm/driver-arm.c b/gcc/config/arm/driver-arm.c
index 21ae2d71336..247eab38780 100644
--- a/gcc/config/arm/driver-arm.c
+++ b/gcc/config/arm/driver-arm.c
@@ -82,7 +82,7 @@ host_detect_local_cpu (int argc, const char **argv)
   while (fgets (buf, sizeof (buf), f) != NULL)
     {
       /* Find the vendor table associated with this implementer.  */
-      if (strncmp (buf, "CPU implementer", sizeof ("CPU implementer") - 1) == 0)
+      if (startswith (buf, "CPU implementer"))
 	{
 	  int i;
 	  for (i = 0; vendors_table[i].vendor_no != NULL; i++)
@@ -94,7 +94,7 @@ host_detect_local_cpu (int argc, const char **argv)
 	}
 
       /* Detect arch/cpu.  */
-      if (strncmp (buf, "CPU part", sizeof ("CPU part") - 1) == 0)
+      if (startswith (buf, "CPU part"))
 	{
 	  int i;
 
diff --git a/gcc/config/avr/avr.c b/gcc/config/avr/avr.c
index 3a250dfb960..3490f907c0e 100644
--- a/gcc/config/avr/avr.c
+++ b/gcc/config/avr/avr.c
@@ -63,9 +63,6 @@
 /* Maximal allowed offset for an address in the LD command */
 #define MAX_LD_OFFSET(MODE) (64 - (signed)GET_MODE_SIZE (MODE))
 
-/* Return true if STR starts with PREFIX and false, otherwise.  */
-#define STR_PREFIX_P(STR,PREFIX) (strncmp (STR, PREFIX, strlen (PREFIX)) == 0)
-
 /* The 4 bits starting at SECTION_MACH_DEP are reserved to store the
    address space where data is to be located.
    As the only non-generic address spaces are all located in flash,
@@ -1079,7 +1076,7 @@ avr_set_current_function (tree decl)
          that the name of the function is "__vector_NN" so as to catch
          when the user misspells the vector name.  */
 
-      if (!STR_PREFIX_P (name, "__vector"))
+      if (!startswith (name, "__vector"))
         warning_at (loc, OPT_Wmisspelled_isr, "%qs appears to be a misspelled "
                     "%qs handler, missing %<__vector%> prefix", name, isr);
 #endif // AVR-LibC naming conventions
@@ -9746,7 +9743,7 @@ static tree
 avr_handle_addr_attribute (tree *node, tree name, tree args,
 			   int flags ATTRIBUTE_UNUSED, bool *no_add)
 {
-  bool io_p = (strncmp (IDENTIFIER_POINTER (name), "io", 2) == 0);
+  bool io_p = startswith (IDENTIFIER_POINTER (name), "io");
   location_t loc = DECL_SOURCE_LOCATION (*node);
 
   if (!VAR_P (*node))
@@ -10159,7 +10156,7 @@ avr_asm_output_aligned_decl_common (FILE * stream,
   /* __gnu_lto_slim is just a marker for the linker injected by toplev.c.
      There is no need to trigger __do_clear_bss code for them.  */
 
-  if (!STR_PREFIX_P (name, "__gnu_lto"))
+  if (!startswith (name, "__gnu_lto"))
     avr_need_clear_bss_p = true;
 
   if (local_p)
@@ -10258,7 +10255,7 @@ avr_asm_named_section (const char *name, unsigned int flags, tree decl)
       const char *old_prefix = ".rodata";
       const char *new_prefix = avr_addrspace[as].section_name;
 
-      if (STR_PREFIX_P (name, old_prefix))
+      if (startswith (name, old_prefix))
         {
           const char *sname = ACONCAT ((new_prefix,
                                         name + strlen (old_prefix), NULL));
@@ -10271,19 +10268,19 @@ avr_asm_named_section (const char *name, unsigned int flags, tree decl)
     }
 
   if (!avr_need_copy_data_p)
-    avr_need_copy_data_p = (STR_PREFIX_P (name, ".data")
-                            || STR_PREFIX_P (name, ".gnu.linkonce.d"));
+    avr_need_copy_data_p = (startswith (name, ".data")
+			    || startswith (name, ".gnu.linkonce.d"));
 
   if (!avr_need_copy_data_p
 #if defined HAVE_LD_AVR_AVRXMEGA3_RODATA_IN_FLASH
       && avr_arch->flash_pm_offset == 0
 #endif
       )
-    avr_need_copy_data_p = (STR_PREFIX_P (name, ".rodata")
-                            || STR_PREFIX_P (name, ".gnu.linkonce.r"));
+    avr_need_copy_data_p = (startswith (name, ".rodata")
+			    || startswith (name, ".gnu.linkonce.r"));
 
   if (!avr_need_clear_bss_p)
-    avr_need_clear_bss_p = STR_PREFIX_P (name, ".bss");
+    avr_need_clear_bss_p = startswith (name, ".bss");
 
   default_elf_asm_named_section (name, flags, decl);
 }
@@ -10296,7 +10293,7 @@ avr_section_type_flags (tree decl, const char *name, int reloc)
 {
   unsigned int flags = default_section_type_flags (decl, name, reloc);
 
-  if (STR_PREFIX_P (name, ".noinit"))
+  if (startswith (name, ".noinit"))
     {
       if (decl && TREE_CODE (decl) == VAR_DECL
 	  && DECL_INITIAL (decl) == NULL_TREE)
@@ -10506,7 +10503,7 @@ avr_asm_select_section (tree decl, int reloc, unsigned HOST_WIDE_INT align)
           const char * old_prefix = ".rodata";
           const char * new_prefix = avr_addrspace[as].section_name;
 
-          if (STR_PREFIX_P (name, old_prefix))
+	  if (startswith (name, old_prefix))
             {
               const char *sname = ACONCAT ((new_prefix,
                                             name + strlen (old_prefix), NULL));
diff --git a/gcc/config/c6x/c6x.c b/gcc/config/c6x/c6x.c
index f9ad1e5f6c5..e7e1d6c5d05 100644
--- a/gcc/config/c6x/c6x.c
+++ b/gcc/config/c6x/c6x.c
@@ -862,14 +862,14 @@ c6x_in_small_data_p (const_tree exp)
       const char *section = DECL_SECTION_NAME (exp);
 
       if (strcmp (section, ".neardata") == 0
-	  || strncmp (section, ".neardata.", 10) == 0
-	  || strncmp (section, ".gnu.linkonce.s.", 16) == 0
+	  || startswith (section, ".neardata.")
+	  || startswith (section, ".gnu.linkonce.s.")
 	  || strcmp (section, ".bss") == 0
-	  || strncmp (section, ".bss.", 5) == 0
-	  || strncmp (section, ".gnu.linkonce.sb.", 17) == 0
+	  || startswith (section, ".bss.")
+	  || startswith (section, ".gnu.linkonce.sb.")
 	  || strcmp (section, ".rodata") == 0
-	  || strncmp (section, ".rodata.", 8) == 0
-	  || strncmp (section, ".gnu.linkonce.s2.", 17) == 0)
+	  || startswith (section, ".rodata.")
+	  || startswith (section, ".gnu.linkonce.s2."))
 	return true;
     }
   else
@@ -1063,7 +1063,7 @@ c6x_section_type_flags (tree decl, const char *name, int reloc)
   unsigned int flags = 0;
 
   if (strcmp (name, ".far") == 0
-      || strncmp (name, ".far.", 5) == 0)
+      || startswith (name, ".far."))
     flags |= SECTION_BSS;
 
   flags |= default_section_type_flags (decl, name, reloc);
diff --git a/gcc/config/darwin-c.c b/gcc/config/darwin-c.c
index b0424a981e8..951a998775f 100644
--- a/gcc/config/darwin-c.c
+++ b/gcc/config/darwin-c.c
@@ -808,8 +808,7 @@ darwin_cfstring_ref_p (const_tree strp)
     tn = DECL_NAME (tn);
   return (tn 
 	  && IDENTIFIER_POINTER (tn)
-	  && !strncmp (IDENTIFIER_POINTER (tn), "CFStringRef",
-		       strlen ("CFStringRef")));
+	  && startswith (IDENTIFIER_POINTER (tn), "CFStringRef"));
 }
 
 /* At present the behavior of this is undefined and it does nothing.  */
@@ -843,7 +842,7 @@ darwin_objc_declare_unresolved_class_reference (const char *name)
   size_t len = strlen (reference) + strlen(name) + 2;
   char *buf = (char *) alloca (len);
 
-  gcc_checking_assert (!strncmp (name, ".objc_class_name_", 17));
+  gcc_checking_assert (startswith (name, ".objc_class_name_"));
 
   snprintf (buf, len, "%s%s", reference, name);
   symtab->finalize_toplevel_asm (build_string (strlen (buf), buf));
@@ -856,8 +855,8 @@ darwin_objc_declare_class_definition (const char *name)
   size_t len = strlen (xname) + 7 + 5;
   char *buf = (char *) alloca (len);
 
-  gcc_checking_assert (!strncmp (name, ".objc_class_name_", 17)
-		       || !strncmp (name, "*.objc_category_name_", 21));
+  gcc_checking_assert (startswith (name, ".objc_class_name_")
+		       || startswith (name, "*.objc_category_name_"));
 
   /* Mimic default_globalize_label.  */
   snprintf (buf, len, ".globl\t%s", xname);
diff --git a/gcc/config/darwin.c b/gcc/config/darwin.c
index 5d173919ee0..c4016fe20ef 100644
--- a/gcc/config/darwin.c
+++ b/gcc/config/darwin.c
@@ -329,7 +329,7 @@ indirect_data (rtx sym_ref)
 
   lprefix = (((name[0] == '*' || name[0] == '&')
               && (name[1] == 'L' || (name[1] == '"' && name[2] == 'L')))
-             || (strncmp (name, "_OBJC_", 6) == 0));
+	     || (startswith (name, "_OBJC_")));
 
   return ! lprefix;
 }
@@ -1284,7 +1284,7 @@ darwin_encode_section_info (tree decl, rtx rtl, int first)
   tree o2meta = lookup_attribute ("OBJC2META", DECL_ATTRIBUTES (decl));
   o2meta = o2meta ? TREE_VALUE (o2meta) : NULL_TREE;
 
-  if (o2meta && strncmp (IDENTIFIER_POINTER (o2meta), "V2_IVRF",7) == 0)
+  if (o2meta && startswith (IDENTIFIER_POINTER (o2meta), "V2_IVRF"))
     SYMBOL_REF_FLAGS (sym_ref) |= MACHO_SYMBOL_FLAG_MUST_INDIRECT;
 #endif
 }
@@ -1443,58 +1443,58 @@ darwin_objc2_section (tree decl ATTRIBUTE_UNUSED, tree meta, section * base)
 
   /* Most of the OBJC2 META-data end up in the base section, so check it
      first.  */
-  if      (!strncmp (p, "V2_BASE", 7))
+  if      (startswith (p, "V2_BASE"))
     return base;
-  else if (!strncmp (p, "V2_CNAM", 7))
+  else if (startswith (p, "V2_CNAM"))
     return darwin_sections[objc2_class_names_section];
-  else if (!strncmp (p, "V2_MNAM", 7))
+  else if (startswith (p, "V2_MNAM"))
     return darwin_sections[objc2_method_names_section];
-  else if (!strncmp (p, "V2_MTYP", 7))
+  else if (startswith (p, "V2_MTYP"))
     return darwin_sections[objc2_method_types_section];
-  else if (!strncmp (p, "V2_STRG", 7))
+  else if (startswith (p, "V2_STRG"))
     return darwin_sections[cstring_section];
 
-  else if (!strncmp (p, "G2_META", 7) || !strncmp (p, "G2_CLAS", 7))
+  else if (startswith (p, "G2_META") || startswith (p, "G2_CLAS"))
     return darwin_sections[objc2_classdefs_section];
-  else if (!strncmp (p, "V2_PCOL", 7))
+  else if (startswith (p, "V2_PCOL"))
     return ld_uses_coal_sects ? darwin_sections[data_coal_section]
 			      : darwin_sections[objc2_data_section];
-  else if (!strncmp (p, "V2_MREF", 7))
+  else if (startswith (p, "V2_MREF"))
     return darwin_sections[objc2_message_refs_section];
-  else if (!strncmp (p, "V2_CLRF", 7))
+  else if (startswith (p, "V2_CLRF"))
     return darwin_sections[objc2_classrefs_section];
-  else if (!strncmp (p, "V2_SURF", 7))
+  else if (startswith (p, "V2_SURF"))
     return darwin_sections[objc2_super_classrefs_section];
-  else if (!strncmp (p, "V2_NLCL", 7))
+  else if (startswith (p, "V2_NLCL"))
     return darwin_sections[objc2_nonlazy_class_section];
-  else if (!strncmp (p, "V2_CLAB", 7))
+  else if (startswith (p, "V2_CLAB"))
     {
       classes_seen = 1;
       return darwin_sections[objc2_classlist_section];
     }
-  else if (!strncmp (p, "V2_SRFS", 7))
+  else if (startswith (p, "V2_SRFS"))
     return darwin_sections[objc2_selector_refs_section];
-  else if (!strncmp (p, "V2_NLCA", 7))
+  else if (startswith (p, "V2_NLCA"))
     return darwin_sections[objc2_nonlazy_category_section];
-  else if (!strncmp (p, "V2_CALA", 7))
+  else if (startswith (p, "V2_CALA"))
     return darwin_sections[objc2_categorylist_section];
 
-  else if (!strncmp (p, "V2_PLST", 7))
+  else if (startswith (p, "V2_PLST"))
     return darwin_sections[objc2_protocollist_section];
-  else if (!strncmp (p, "V2_PRFS", 7))
+  else if (startswith (p, "V2_PRFS"))
     return darwin_sections[objc2_protocolrefs_section];
 
-  else if (!strncmp (p, "V2_INFO", 7))
+  else if (startswith (p, "V2_INFO"))
     return darwin_sections[objc2_image_info_section];
 
-  else if (!strncmp (p, "V2_EHTY", 7))
+  else if (startswith (p, "V2_EHTY"))
     return ld_uses_coal_sects ? darwin_sections[data_coal_section]
                               : data_section;
 
-  else if (!strncmp (p, "V2_CSTR", 7))
+  else if (startswith (p, "V2_CSTR"))
     return darwin_sections[objc2_constant_string_object_section];
 
-  else if (!strncmp (p, "V2_IVRF", 7))
+  else if (startswith (p, "V2_IVRF"))
     return darwin_sections[objc2_ivar_section];
 
   /* Not recognized, default.  */
@@ -1515,72 +1515,72 @@ darwin_objc1_section (tree decl ATTRIBUTE_UNUSED, tree meta, section * base)
   objc_metadata_seen = 1;
 
   /* String sections first, cos there are lots of strings.  */
-  if      (!strncmp (p, "V1_STRG", 7))
+  if      (startswith (p, "V1_STRG"))
     return darwin_sections[cstring_section];
-  else if (!strncmp (p, "V1_CLSN", 7))
+  else if (startswith (p, "V1_CLSN"))
     return darwin_sections[objc_class_names_section];
-  else if (!strncmp (p, "V1_METN", 7))
+  else if (startswith (p, "V1_METN"))
     return darwin_sections[objc_meth_var_names_section];
-  else if (!strncmp (p, "V1_METT", 7))
+  else if (startswith (p, "V1_METT"))
     return darwin_sections[objc_meth_var_types_section];
 
-  else if (!strncmp (p, "V1_CLAS", 7))
+  else if (startswith (p, "V1_CLAS"))
     {
       classes_seen = 1;
       return darwin_sections[objc_class_section];
     }
-  else if (!strncmp (p, "V1_META", 7))
+  else if (startswith (p, "V1_META"))
     return darwin_sections[objc_meta_class_section];
-  else if (!strncmp (p, "V1_CATG", 7))
+  else if (startswith (p, "V1_CATG"))
     return darwin_sections[objc_category_section];
-  else if (!strncmp (p, "V1_PROT", 7))
+  else if (startswith (p, "V1_PROT"))
     return darwin_sections[objc_protocol_section];
 
-  else if (!strncmp (p, "V1_CLCV", 7))
+  else if (startswith (p, "V1_CLCV"))
     return darwin_sections[objc_class_vars_section];
-  else if (!strncmp (p, "V1_CLIV", 7))
+  else if (startswith (p, "V1_CLIV"))
     return darwin_sections[objc_instance_vars_section];
 
-  else if (!strncmp (p, "V1_CLCM", 7))
+  else if (startswith (p, "V1_CLCM"))
     return darwin_sections[objc_cls_meth_section];
-  else if (!strncmp (p, "V1_CLIM", 7))
+  else if (startswith (p, "V1_CLIM"))
     return darwin_sections[objc_inst_meth_section];
-  else if (!strncmp (p, "V1_CACM", 7))
+  else if (startswith (p, "V1_CACM"))
     return darwin_sections[objc_cat_cls_meth_section];
-  else if (!strncmp (p, "V1_CAIM", 7))
+  else if (startswith (p, "V1_CAIM"))
     return darwin_sections[objc_cat_inst_meth_section];
-  else if (!strncmp (p, "V1_PNSM", 7))
+  else if (startswith (p, "V1_PNSM"))
     return darwin_sections[objc_cat_inst_meth_section];
-  else if (!strncmp (p, "V1_PCLM", 7))
+  else if (startswith (p, "V1_PCLM"))
     return darwin_sections[objc_cat_cls_meth_section];
 
-  else if (!strncmp (p, "V1_CLPR", 7))
+  else if (startswith (p, "V1_CLPR"))
     return darwin_sections[objc_cat_cls_meth_section];
-  else if (!strncmp (p, "V1_CAPR", 7))
+  else if (startswith (p, "V1_CAPR"))
     return darwin_sections[objc_category_section]; /* ??? CHECK me.  */
 
-  else if (!strncmp (p, "V1_PRFS", 7))
+  else if (startswith (p, "V1_PRFS"))
     return darwin_sections[objc_cat_cls_meth_section];
-  else if (!strncmp (p, "V1_CLRF", 7))
+  else if (startswith (p, "V1_CLRF"))
     return darwin_sections[objc_cls_refs_section];
-  else if (!strncmp (p, "V1_SRFS", 7))
+  else if (startswith (p, "V1_SRFS"))
     return darwin_sections[objc_selector_refs_section];
 
-  else if (!strncmp (p, "V1_MODU", 7))
+  else if (startswith (p, "V1_MODU"))
     return darwin_sections[objc_module_info_section];
-  else if (!strncmp (p, "V1_SYMT", 7))
+  else if (startswith (p, "V1_SYMT"))
     return darwin_sections[objc_symbols_section];
-  else if (!strncmp (p, "V1_INFO", 7))
+  else if (startswith (p, "V1_INFO"))
     return darwin_sections[objc_image_info_section];
 
-  else if (!strncmp (p, "V1_PLST", 7))
+  else if (startswith (p, "V1_PLST"))
     return darwin_sections[objc1_prop_list_section];
-  else if (!strncmp (p, "V1_PEXT", 7))
+  else if (startswith (p, "V1_PEXT"))
     return darwin_sections[objc1_protocol_ext_section];
-  else if (!strncmp (p, "V1_CEXT", 7))
+  else if (startswith (p, "V1_CEXT"))
     return darwin_sections[objc1_class_ext_section];
 
-  else if (!strncmp (p, "V2_CSTR", 7))
+  else if (startswith (p, "V2_CSTR"))
     return darwin_sections[objc_constant_string_object_section];
 
   return base;
@@ -1747,7 +1747,7 @@ machopic_select_section (tree decl,
 	   && DECL_NAME (decl)
 	   && TREE_CODE (DECL_NAME (decl)) == IDENTIFIER_NODE
 	   && IDENTIFIER_POINTER (DECL_NAME (decl))
-	   && !strncmp (IDENTIFIER_POINTER (DECL_NAME (decl)), "_OBJC_", 6))
+	   && startswith (IDENTIFIER_POINTER (DECL_NAME (decl)), "_OBJC_"))
     /* c) legacy meta-data selection was deprecated at 4.6, removed now.  */
     gcc_unreachable ();
 
@@ -1869,15 +1869,15 @@ finalize_dtors ()
 void
 darwin_globalize_label (FILE *stream, const char *name)
 {
-  if (!!strncmp (name, "_OBJC_", 6))
+  if (!startswith (name, "_OBJC_"))
     default_globalize_label (stream, name);
   /* We have some Objective C cases that need to be global, but only on newer
      OS versions.  */
   if (flag_objc_abi < 2 || flag_next_runtime < 100700)
     return;
-  if (!strncmp (name+6, "LabelPro", 8))
+  if (startswith (name+6, "LabelPro"))
     default_globalize_label (stream, name);
-  if (!strncmp (name+6, "Protocol_", 9))
+  if (startswith (name+6, "Protocol_"))
     default_globalize_label (stream, name);
 }
 
@@ -1897,7 +1897,7 @@ darwin_label_is_anonymous_local_objc_name (const char *name)
     while (*p >= '0' && *p <= '9')
       p++;
   }
-  if (strncmp ((const char *)p, "_OBJC_", 6) != 0)
+  if (!startswith ((const char *)p, "_OBJC_"))
     return false;
 
   /* We need some of the objective c meta-data symbols to be visible to the
@@ -1908,36 +1908,36 @@ darwin_label_is_anonymous_local_objc_name (const char *name)
     return true;
 
   p += 6;
-  if (!strncmp ((const char *)p, "ClassRef", 8))
+  if (startswith ((const char *)p, "ClassRef"))
     return false;
-  else if (!strncmp ((const char *)p, "SelRef", 6))
+  else if (startswith ((const char *)p, "SelRef"))
     return false;
-  else if (!strncmp ((const char *)p, "Category", 8))
+  else if (startswith ((const char *)p, "Category"))
     {
       if (p[8] == '_' || p[8] == 'I' || p[8] == 'P' || p[8] == 'C' )
 	return false;
       return true;
     }
-  else if (!strncmp ((const char *)p, "ClassMethods", 12))
+  else if (startswith ((const char *)p, "ClassMethods"))
     return false;
-  else if (!strncmp ((const char *)p, "Instance", 8))
+  else if (startswith ((const char *)p, "Instance"))
     {
       if (p[8] == 'I' || p[8] == 'M')
 	return false;
       return true;
     }
-  else if (!strncmp ((const char *)p, "CLASS_RO", 8))
+  else if (startswith ((const char *)p, "CLASS_RO"))
     return false;
-  else if (!strncmp ((const char *)p, "METACLASS_RO", 12))
+  else if (startswith ((const char *)p, "METACLASS_RO"))
     return false;
-  else if (!strncmp ((const char *)p, "Protocol", 8))
+  else if (startswith ((const char *)p, "Protocol"))
     {
       if (p[8] == '_' || p[8] == 'I' || p[8] == 'P'
 	  || p[8] == 'M' || p[8] == 'C' || p[8] == 'O')
 	return false;
       return true;
     }
-  else if (!strncmp ((const char *)p, "LabelPro", 8))
+  else if (startswith ((const char *)p, "LabelPro"))
     return false;
   return true;
 }
@@ -2032,8 +2032,7 @@ darwin_asm_named_section (const char *name,
 {
   /* LTO sections go in a special section that encapsulates the (unlimited)
      number of GNU LTO sections within a single mach-o one.  */
-  if (strncmp (name, LTO_SECTION_NAME_PREFIX,
-	       strlen (LTO_SECTION_NAME_PREFIX)) == 0)
+  if (startswith (name, LTO_SECTION_NAME_PREFIX))
     {
       darwin_lto_section_e e;
       /* We expect certain flags to be set...  */
@@ -2062,9 +2061,9 @@ darwin_asm_named_section (const char *name,
         vec_alloc (lto_section_names, 16);
       vec_safe_push (lto_section_names, e);
    }
-  else if (strncmp (name, "__DWARF,", 8) == 0)
+  else if (startswith (name, "__DWARF,"))
     darwin_asm_dwarf_section (name, flags, decl, false);
-  else if (strncmp (name, "__GNU_DWARF_LTO,", 16) == 0)
+  else if (startswith (name, "__GNU_DWARF_LTO,"))
     darwin_asm_dwarf_section (name, flags, decl, true);
   else
     fprintf (asm_out_file, "\t.section %s\n", name);
@@ -2973,9 +2972,9 @@ darwin_asm_output_dwarf_offset (FILE *file, int size, const char * lab,
   const char *lto_add = "";
 
   gcc_checking_assert (base->common.flags & SECTION_NAMED);
-  is_for_lto = strncmp (base->named.name, "__GNU_DWARF_LTO,", 16) == 0;
+  is_for_lto = startswith (base->named.name, "__GNU_DWARF_LTO,");
   gcc_checking_assert (is_for_lto
-		       || strncmp (base->named.name, "__DWARF,", 8) == 0);
+		       || startswith (base->named.name, "__DWARF,"));
   const char *name = strchr (base->named.name, ',') + 1;
   gcc_checking_assert (name);
 
diff --git a/gcc/config/frv/frv.c b/gcc/config/frv/frv.c
index 8201a20e24b..a7f7f086d17 100644
--- a/gcc/config/frv/frv.c
+++ b/gcc/config/frv/frv.c
@@ -262,7 +262,6 @@ static frv_stack_t *frv_stack_cache = (frv_stack_t *)0;
 static void frv_option_override			(void);
 static bool frv_legitimate_address_p		(machine_mode, rtx, bool);
 static int frv_default_flags_for_cpu		(void);
-static int frv_string_begins_with		(const char *, const char *);
 static FRV_INLINE bool frv_small_data_reloc_p	(rtx, int);
 static void frv_print_operand			(FILE *, rtx, int);
 static void frv_print_operand_address		(FILE *, machine_mode, rtx);
@@ -782,17 +781,6 @@ frv_option_override (void)
   init_machine_status = frv_init_machine_status;
 }
 
-\f
-/* Return true if NAME (a STRING_CST node) begins with PREFIX.  */
-
-static int
-frv_string_begins_with (const char *name, const char *prefix)
-{
-  const int prefix_len = strlen (prefix);
-
-  /* Remember: NAME's length includes the null terminator.  */
-  return (strncmp (name, prefix, prefix_len) == 0);
-}
 \f
 /* Implement TARGET_CONDITIONAL_REGISTER_USAGE.  */
 
@@ -9312,9 +9300,9 @@ frv_in_small_data_p (const_tree decl)
   section_name = DECL_SECTION_NAME (decl);
   if (section_name)
     {
-      if (frv_string_begins_with (section_name, ".sdata"))
+      if (startswith (section_name, ".sdata"))
 	return true;
-      if (frv_string_begins_with (section_name, ".sbss"))
+      if (startswith (section_name, ".sbss"))
 	return true;
       return false;
     }
diff --git a/gcc/config/gcn/mkoffload.c b/gcc/config/gcn/mkoffload.c
index dc9d5180a35..5432f9591db 100644
--- a/gcc/config/gcn/mkoffload.c
+++ b/gcc/config/gcn/mkoffload.c
@@ -825,8 +825,7 @@ main (int argc, char **argv)
   bool fpic = false;
   for (int i = 1; i < argc; i++)
     {
-#define STR "-foffload-abi="
-      if (strncmp (argv[i], STR, strlen (STR)) == 0)
+      if (startswith (argv[i], "-foffload-abi="))
 	{
 	  if (strcmp (argv[i] + strlen (STR), "lp64") == 0)
 	    offload_abi = OFFLOAD_ABI_LP64;
@@ -836,7 +835,6 @@ main (int argc, char **argv)
 	    fatal_error (input_location,
 			 "unrecognizable argument of option " STR);
 	}
-#undef STR
       else if (strcmp (argv[i], "-fopenmp") == 0)
 	fopenmp = true;
       else if (strcmp (argv[i], "-fopenacc") == 0)
@@ -995,9 +993,9 @@ main (int argc, char **argv)
       obstack_ptr_grow (&ld_argv_obstack, "-lgomp");
 
       for (int i = 1; i < argc; i++)
-	if (strncmp (argv[i], "-l", 2) == 0
-	    || strncmp (argv[i], "-Wl", 3) == 0
-	    || strncmp (argv[i], "-march", 6) == 0)
+	if (startswith (argv[i], "-l")
+	    || startswith (argv[i], "-Wl")
+	    || startswith (argv[i], "-march"))
 	  obstack_ptr_grow (&ld_argv_obstack, argv[i]);
 
       obstack_ptr_grow (&cc_argv_obstack, "-dumpdir");
diff --git a/gcc/config/i386/i386-builtins.c b/gcc/config/i386/i386-builtins.c
index 4fcdf4b89ee..4f6e1208e91 100644
--- a/gcc/config/i386/i386-builtins.c
+++ b/gcc/config/i386/i386-builtins.c
@@ -1974,7 +1974,7 @@ get_builtin_code_for_version (tree decl, tree *predicate_list)
   while (token != NULL)
     {
       /* Do not process "arch="  */
-      if (strncmp (token, "arch=", 5) == 0)
+      if (startswith (token, "arch="))
 	{
 	  token = strtok (NULL, ",");
 	  continue;
diff --git a/gcc/config/i386/i386-options.c b/gcc/config/i386/i386-options.c
index 7e59ccd988d..e343d12e8eb 100644
--- a/gcc/config/i386/i386-options.c
+++ b/gcc/config/i386/i386-options.c
@@ -1904,7 +1904,7 @@ ix86_option_override_internal (bool main_args_p,
 
       /* opts->x_ix86_tune_string is set to opts->x_ix86_arch_string
 	 or defaulted.  We need to use a sensible tune option.  */
-      if (!strncmp (opts->x_ix86_tune_string, "x86-64", 6)
+      if (startswith (opts->x_ix86_tune_string, "x86-64")
 	  && (opts->x_ix86_tune_string[6] == '\0'
 	      || (!strcmp (opts->x_ix86_tune_string + 6, "-v2")
 		  || !strcmp (opts->x_ix86_tune_string + 6, "-v3")
diff --git a/gcc/config/i386/i386.c b/gcc/config/i386/i386.c
index 7c41302c75b..84c1de47959 100644
--- a/gcc/config/i386/i386.c
+++ b/gcc/config/i386/i386.c
@@ -751,9 +751,8 @@ x86_64_elf_section_type_flags (tree decl, const char *name, int reloc)
     flags |= SECTION_RELRO;
 
   if (strcmp (name, ".lbss") == 0
-      || strncmp (name, ".lbss.", sizeof (".lbss.") - 1) == 0
-      || strncmp (name, ".gnu.linkonce.lb.",
-		  sizeof (".gnu.linkonce.lb.") - 1) == 0)
+      || startswith (name, ".lbss.")
+      || startswith (name, ".gnu.linkonce.lb."))
     flags |= SECTION_BSS;
 
   return flags;
@@ -21418,7 +21417,7 @@ ix86_md_asm_adjust (vec<rtx> &outputs, vec<rtx> & /*inputs*/,
   for (unsigned i = 0, n = outputs.length (); i < n; ++i)
     {
       const char *con = constraints[i];
-      if (strncmp (con, "=@cc", 4) != 0)
+      if (!startswith (con, "=@cc"))
 	continue;
       con += 4;
       if (strchr (con, ',') != NULL)
diff --git a/gcc/config/i386/intelmic-mkoffload.c b/gcc/config/i386/intelmic-mkoffload.c
index 475f071609f..cb946d61454 100644
--- a/gcc/config/i386/intelmic-mkoffload.c
+++ b/gcc/config/i386/intelmic-mkoffload.c
@@ -613,8 +613,7 @@ main (int argc, char **argv)
   /* Scan the argument vector.  */
   for (int i = 1; i < argc; i++)
     {
-#define STR "-foffload-abi="
-      if (strncmp (argv[i], STR, strlen (STR)) == 0)
+      if (startswith (argv[i], "-foffload-abi="))
 	{
 	  if (strcmp (argv[i] + strlen (STR), "lp64") == 0)
 	    offload_abi = OFFLOAD_ABI_LP64;
@@ -624,7 +623,6 @@ main (int argc, char **argv)
 	    fatal_error (input_location,
 			 "unrecognizable argument of option " STR);
 	}
-#undef STR
       else if (strcmp (argv[i], "-save-temps") == 0)
 	save_temps = true;
       else if (strcmp (argv[i], "-v") == 0)
diff --git a/gcc/config/i386/winnt.c b/gcc/config/i386/winnt.c
index b66263ad243..4158a45ac31 100644
--- a/gcc/config/i386/winnt.c
+++ b/gcc/config/i386/winnt.c
@@ -505,8 +505,7 @@ i386_pe_asm_named_section (const char *name, unsigned int flags,
 
   /* LTO sections need 1-byte alignment to avoid confusing the
      zlib decompression algorithm with trailing zero pad bytes.  */
-  if (strncmp (name, LTO_SECTION_NAME_PREFIX,
-			strlen (LTO_SECTION_NAME_PREFIX)) == 0)
+  if (startswith (name, LTO_SECTION_NAME_PREFIX))
     *f++ = '0';
 
   *f = '\0';
@@ -797,7 +796,7 @@ i386_pe_file_end (void)
 	  oname = name;
 	  if (name[0] == '.')
 	    ++name;
-	  if (strncmp (name, "refptr.", 7) != 0)
+	  if (!startswith (name, "refptr."))
 	    continue;
 	  name += 7;
 	  fprintf (asm_out_file, "\t.section\t.rdata$%s, \"dr\"\n"
diff --git a/gcc/config/ia64/ia64.c b/gcc/config/ia64/ia64.c
index f1a6de14cdd..632b9df1761 100644
--- a/gcc/config/ia64/ia64.c
+++ b/gcc/config/ia64/ia64.c
@@ -10007,11 +10007,11 @@ ia64_in_small_data_p (const_tree exp)
       const char *section = DECL_SECTION_NAME (exp);
 
       if (strcmp (section, ".sdata") == 0
-	  || strncmp (section, ".sdata.", 7) == 0
-	  || strncmp (section, ".gnu.linkonce.s.", 16) == 0
+	  || startswith (section, ".sdata.")
+	  || startswith (section, ".gnu.linkonce.s.")
 	  || strcmp (section, ".sbss") == 0
-	  || strncmp (section, ".sbss.", 6) == 0
-	  || strncmp (section, ".gnu.linkonce.sb.", 17) == 0)
+	  || startswith (section, ".sbss.")
+	  || startswith (section, ".gnu.linkonce.sb."))
 	return true;
     }
   else
@@ -10869,13 +10869,13 @@ ia64_section_type_flags (tree decl, const char *name, int reloc)
   unsigned int flags = 0;
 
   if (strcmp (name, ".sdata") == 0
-      || strncmp (name, ".sdata.", 7) == 0
-      || strncmp (name, ".gnu.linkonce.s.", 16) == 0
-      || strncmp (name, ".sdata2.", 8) == 0
-      || strncmp (name, ".gnu.linkonce.s2.", 17) == 0
+      || startswith (name, ".sdata.")
+      || startswith (name, ".gnu.linkonce.s.")
+      || startswith (name, ".sdata2.")
+      || startswith (name, ".gnu.linkonce.s2.")
       || 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_SMALL;
 
   flags |= default_section_type_flags (decl, name, reloc);
diff --git a/gcc/config/mips/driver-native.c b/gcc/config/mips/driver-native.c
index eaf5f7e92db..46bb3cad500 100644
--- a/gcc/config/mips/driver-native.c
+++ b/gcc/config/mips/driver-native.c
@@ -57,7 +57,7 @@ host_detect_local_cpu (int argc, const char **argv)
     return NULL;
 
   while (fgets (buf, sizeof (buf), f) != NULL)
-    if (strncmp (buf, "cpu model", sizeof ("cpu model") - 1) == 0)
+    if (startswith (buf, "cpu model"))
       {
 	if (strstr (buf, "Godson2 V0.2") != NULL
 	    || strstr (buf, "Loongson-2 V0.2") != NULL
diff --git a/gcc/config/mips/mips.c b/gcc/config/mips/mips.c
index 315545966f8..e5ba27331b0 100644
--- a/gcc/config/mips/mips.c
+++ b/gcc/config/mips/mips.c
@@ -1513,14 +1513,14 @@ mips_handle_interrupt_attr (tree *node ATTRIBUTE_UNUSED, tree name, tree args,
 	  *no_add_attrs = true;
 	}
       else if (strcmp (TREE_STRING_POINTER (cst), "eic") != 0
-	       && strncmp (TREE_STRING_POINTER (cst), "vector=", 7) != 0)
+	       && !startswith (TREE_STRING_POINTER (cst), "vector="))
 	{
 	  warning (OPT_Wattributes,
 		   "argument to %qE attribute is neither eic, nor "
 		   "vector=<line>", name);
 	  *no_add_attrs = true;
 	}
-      else if (strncmp (TREE_STRING_POINTER (cst), "vector=", 7) == 0)
+      else if (startswith (TREE_STRING_POINTER (cst), "vector="))
 	{
 	  const char *arg = TREE_STRING_POINTER (cst) + 7;
 
@@ -1849,7 +1849,7 @@ static bool
 mips16_stub_function_p (const_rtx x)
 {
   return (GET_CODE (x) == SYMBOL_REF
-	  && strncmp (XSTR (x, 0), "__mips16_", 9) == 0);
+	  && startswith (XSTR (x, 0), "__mips16_"));
 }
 
 /* Return true if function X is a locally-defined and locally-binding
@@ -9323,7 +9323,7 @@ mips_function_rodata_section (tree decl, bool)
   if (decl && DECL_SECTION_NAME (decl))
     {
       const char *name = DECL_SECTION_NAME (decl);
-      if (DECL_COMDAT_GROUP (decl) && strncmp (name, ".gnu.linkonce.t.", 16) == 0)
+      if (DECL_COMDAT_GROUP (decl) && startswith (name, ".gnu.linkonce.t."))
 	{
 	  char *rname = ASTRDUP (name);
 	  rname[14] = 'd';
@@ -9331,7 +9331,7 @@ mips_function_rodata_section (tree decl, bool)
 	}
       else if (flag_function_sections
 	       && flag_data_sections
-	       && strncmp (name, ".text.", 6) == 0)
+	       && startswith (name, ".text."))
 	{
 	  char *rname = ASTRDUP (name);
 	  memcpy (rname + 1, "data", 4);
diff --git a/gcc/config/msp430/msp430.c b/gcc/config/msp430/msp430.c
index 581e051f68f..1cdacb7f480 100644
--- a/gcc/config/msp430/msp430.c
+++ b/gcc/config/msp430/msp430.c
@@ -122,7 +122,7 @@ msp430_mcu_name (void)
 
       /* The 'i' in the device name symbol for msp430i* devices must be lower
 	 case, to match the expected symbol in msp430.h.  */
-      if (strncmp (target_mcu, "msp430i", 7) == 0)
+      if (startswith (target_mcu, "msp430i"))
 	{
 	  snprintf (mcu_name, sizeof (mcu_name) - 1, "__MSP430i%s__",
 		    target_mcu + 7);
@@ -2466,7 +2466,7 @@ msp430_function_section (tree decl, enum node_frequency freq, bool startup,
 
   const char * prefix = gen_prefix (decl);
   if (prefix == NULL
-      || strncmp (name, prefix, strlen (prefix)) == 0)
+      || startswith (name, prefix))
     return default_function_section (decl, freq, startup, exit);
 
   name = ACONCAT ((prefix, name, NULL));
@@ -2479,11 +2479,11 @@ msp430_function_section (tree decl, enum node_frequency freq, bool startup,
 unsigned int
 msp430_section_type_flags (tree decl, const char * name, int reloc)
 {
-  if (strncmp (name, lower_prefix, strlen (lower_prefix)) == 0)
+  if (startswith (name, lower_prefix))
     name += strlen (lower_prefix);
-  else if (strncmp (name, upper_prefix, strlen (upper_prefix)) == 0)
+  else if (startswith (name, upper_prefix))
     name += strlen (upper_prefix);
-  else if (strncmp (name, either_prefix, strlen (either_prefix)) == 0)
+  else if (startswith (name, either_prefix))
     name += strlen (either_prefix);
 
   return default_section_type_flags (decl, name, reloc);
@@ -3243,8 +3243,7 @@ msp430_expand_helper (rtx *operands, const char *helper_name,
   machine_mode arg0mode = GET_MODE (operands[0]);
   machine_mode arg1mode = GET_MODE (operands[1]);
   machine_mode arg2mode = GET_MODE (operands[2]);
-  int expand_mpy = strncmp (helper_name, "__mspabi_mpy",
-			    sizeof ("__mspabi_mpy") - 1) == 0;
+  int expand_mpy = startswith (helper_name, "__mspabi_mpy");
   /* This function has been used incorrectly if CONST_VARIANTS is TRUE for a
      hwmpy function.  */
   gcc_assert (!(expand_mpy && const_variants));
diff --git a/gcc/config/nios2/nios2.c b/gcc/config/nios2/nios2.c
index bf5e2be6244..26d43331f33 100644
--- a/gcc/config/nios2/nios2.c
+++ b/gcc/config/nios2/nios2.c
@@ -2336,9 +2336,9 @@ static bool
 nios2_small_section_name_p (const char *section)
 {
   return (strcmp (section, ".sbss") == 0
-	  || strncmp (section, ".sbss.", 6) == 0
+	  || startswith (section, ".sbss.")
 	  || strcmp (section, ".sdata") == 0
-	  || strncmp (section, ".sdata.", 7) == 0
+	  || startswith (section, ".sdata.")
 	  || (nios2_gprel_sec 
 	      && regexec (&nios2_gprel_sec_regex, section, 0, NULL, 0) == 0));
 }
@@ -4199,12 +4199,12 @@ nios2_valid_target_attribute_rec (tree args)
 	    *p = '\0';
 	  if (eq) *eq = '\0';
 
-	  if (!strncmp (argstr, "no-", 3))
+	  if (startswith (argstr, "no-"))
 	    {
 	      no_opt = true;
 	      argstr += 3;
 	    }
-	  if (!strncmp (argstr, "custom-fpu-cfg", 14))
+	  if (startswith (argstr, "custom-fpu-cfg"))
 	    {
 	      char *end_eq = p;
 	      if (no_opt)
@@ -4225,13 +4225,12 @@ nios2_valid_target_attribute_rec (tree args)
 
 	      nios2_handle_custom_fpu_cfg (eq, end_eq + 1, true);
 	    }
-	  else if (!strncmp (argstr, "custom-", 7))
+	  else if (startswith (argstr, "custom-"))
 	    {
 	      int code = -1;
 	      unsigned int i;
 	      for (i = 0; i < ARRAY_SIZE (nios2_fpu_insn); i++)
-		if (!strncmp (argstr + 7, N2FPU_NAME (i),
-			      strlen (N2FPU_NAME (i))))
+		if (startswith (argstr + 7, N2FPU_NAME (i)))
 		  {
 		    /* Found insn.  */
 		    code = i;
diff --git a/gcc/config/nvptx/mkoffload.c b/gcc/config/nvptx/mkoffload.c
index b0a4dfa466c..c46c85d3a7c 100644
--- a/gcc/config/nvptx/mkoffload.c
+++ b/gcc/config/nvptx/mkoffload.c
@@ -256,13 +256,13 @@ process (FILE *in, FILE *out)
 	    case '\n':
 	      fprintf (out, "\\n\"\n\t\"");
 	      /* Look for mappings on subsequent lines.  */
-	      while (strncmp (input + i, "//:", 3) == 0)
+	      while (startswith (input + i, "//:"))
 		{
 		  i += 3;
 
-		  if (strncmp (input + i, "VAR_MAP ", 8) == 0)
+		  if (startswith (input + i, "VAR_MAP "))
 		    record_id (input + i + 8, &vars_tail);
-		  else if (strncmp (input + i, "FUNC_MAP ", 9) == 0)
+		  else if (startswith (input + i, "FUNC_MAP "))
 		    record_id (input + i + 9, &funcs_tail);
 		  else
 		    abort ();
@@ -481,8 +481,7 @@ main (int argc, char **argv)
   bool fpic = false;
   for (int i = 1; i < argc; i++)
     {
-#define STR "-foffload-abi="
-      if (strncmp (argv[i], STR, strlen (STR)) == 0)
+      if (startswith (argv[i], "-foffload-abi="))
 	{
 	  if (strcmp (argv[i] + strlen (STR), "lp64") == 0)
 	    offload_abi = OFFLOAD_ABI_LP64;
@@ -492,7 +491,6 @@ main (int argc, char **argv)
 	    fatal_error (input_location,
 			 "unrecognizable argument of option " STR);
 	}
-#undef STR
       else if (strcmp (argv[i], "-fopenmp") == 0)
 	fopenmp = true;
       else if (strcmp (argv[i], "-fopenacc") == 0)
diff --git a/gcc/config/pa/som.h b/gcc/config/pa/som.h
index d25a2ed7b4a..05cc315b9f9 100644
--- a/gcc/config/pa/som.h
+++ b/gcc/config/pa/som.h
@@ -47,32 +47,29 @@ along with GCC; see the file COPYING3.  If not see
 do {								\
   static int in_shlib_list = 0;					\
   while (*PTR == ' ') PTR++;					\
-  if (strncmp (PTR, "shared library list:",			\
-	       sizeof ("shared library list:") - 1) == 0)	\
+  if (startswith (PTR, "shared library list:"))			\
     {								\
       PTR = 0;							\
       in_shlib_list = 1;					\
     }								\
-  else if (strncmp (PTR, "shared library binding:",		\
-		    sizeof ("shared library binding:") - 1) == 0)\
+  else if (startswith (PTR, "shared library binding:"))		\
     {								\
       PTR = 0;							\
       in_shlib_list = 0;					\
     }								\
-  else if (strncmp (PTR, "static branch prediction disabled",	\
-		    sizeof ("static branch prediction disabled") - 1) == 0)\
+  else if (startswith (PTR, "static branch prediction disabled")) \
     {								\
       PTR = 0;							\
       in_shlib_list = 0;					\
     }								\
   else if (in_shlib_list					\
-	   &&  strncmp (PTR, "dynamic", sizeof ("dynamic") - 1) == 0) \
+	   && startswith (PTR, "dynamic"))			\
     {								\
       PTR += sizeof ("dynamic") - 1;				\
       while (*p == ' ') PTR++;					\
     }								\
   else if (in_shlib_list					\
-	   && strncmp (PTR, "static", sizeof ("static") - 1) == 0) \
+	   && startswith (PTR, "static"))			\
     {								\
       PTR += sizeof ("static") - 1;				\
       while (*p == ' ') PTR++;					\
diff --git a/gcc/config/pdp11/pdp11.c b/gcc/config/pdp11/pdp11.c
index eb3bea497bf..b663b43a29c 100644
--- a/gcc/config/pdp11/pdp11.c
+++ b/gcc/config/pdp11/pdp11.c
@@ -2251,7 +2251,7 @@ static void pdp11_output_ident (const char *ident)
 {
   if (TARGET_DEC_ASM)
     {
-      if (strncmp (ident, "GCC:", 4) != 0)
+      if (!startswith (ident, "GCC:"))
 	fprintf (asm_out_file, "\t.ident\t\"%s\"\n", ident);
     }
   
diff --git a/gcc/config/riscv/riscv.c b/gcc/config/riscv/riscv.c
index 17cdf705c32..f377bca99b7 100644
--- a/gcc/config/riscv/riscv.c
+++ b/gcc/config/riscv/riscv.c
@@ -3588,7 +3588,7 @@ riscv_elf_select_rtx_section (machine_mode mode, rtx x,
 
   if (riscv_size_ok_for_small_data_p (GET_MODE_SIZE (mode)))
     {
-      if (strncmp (s->named.name, ".rodata.cst", strlen (".rodata.cst")) == 0)
+      if (startswith (s->named.name, ".rodata.cst"))
 	{
 	  /* Rename .rodata.cst* to .srodata.cst*. */
 	  char *name = (char *) alloca (strlen (s->named.name) + 2);
diff --git a/gcc/config/rs6000/rs6000.c b/gcc/config/rs6000/rs6000.c
index 844fee88cf3..46473b4fb64 100644
--- a/gcc/config/rs6000/rs6000.c
+++ b/gcc/config/rs6000/rs6000.c
@@ -17205,12 +17205,12 @@ toc_hasher::equal (toc_hash_struct *h1, toc_hash_struct *h2)
    instead, there should be some programmatic way of inquiring as
    to whether or not an object is a vtable.  */
 
-#define VTABLE_NAME_P(NAME)				\
-  (strncmp ("_vt.", name, strlen ("_vt.")) == 0		\
-  || strncmp ("_ZTV", name, strlen ("_ZTV")) == 0	\
-  || strncmp ("_ZTT", name, strlen ("_ZTT")) == 0	\
-  || strncmp ("_ZTI", name, strlen ("_ZTI")) == 0	\
-  || strncmp ("_ZTC", name, strlen ("_ZTC")) == 0)
+#define VTABLE_NAME_P(NAME)	  \
+  (startswith (name, "_vt.")	  \
+  || startswith (name, "_ZTV")	  \
+  || startswith (name, "_ZTT")	  \
+  || startswith (name, "_ZTI")	  \
+  || startswith (name, "_ZTC"))
 
 #ifdef NO_DOLLAR_IN_LABEL
 /* Return a GGC-allocated character string translating dollar signs in
@@ -24124,7 +24124,7 @@ rs6000_inner_target_options (tree args, bool attr_p)
 	  const char *cpu_opt = NULL;
 
 	  p = NULL;
-	  if (strncmp (q, "cpu=", 4) == 0)
+	  if (startswith (q, "cpu="))
 	    {
 	      int cpu_index = rs6000_cpu_name_lookup (q+4);
 	      if (cpu_index >= 0)
@@ -24135,7 +24135,7 @@ rs6000_inner_target_options (tree args, bool attr_p)
 		  cpu_opt = q+4;
 		}
 	    }
-	  else if (strncmp (q, "tune=", 5) == 0)
+	  else if (startswith (q, "tune="))
 	    {
 	      int tune_index = rs6000_cpu_name_lookup (q+5);
 	      if (tune_index >= 0)
@@ -24153,7 +24153,7 @@ rs6000_inner_target_options (tree args, bool attr_p)
 	      char *r = q;
 
 	      error_p = true;
-	      if (strncmp (r, "no-", 3) == 0)
+	      if (startswith (r, "no-"))
 		{
 		  invert = true;
 		  r += 3;
diff --git a/gcc/config/s390/driver-native.c b/gcc/config/s390/driver-native.c
index c0247154c0b..71c4ff672f8 100644
--- a/gcc/config/s390/driver-native.c
+++ b/gcc/config/s390/driver-native.c
@@ -73,7 +73,7 @@ s390_host_detect_local_cpu (int argc, const char **argv)
        (has_features == 0 || has_processor == 0)
 	 && fgets (buf, sizeof (buf), f) != NULL; )
     {
-      if (has_processor == 0 && strncmp (buf, "processor", 9) == 0)
+      if (has_processor == 0 && startswith (buf, "processor"))
 	{
 	  const char *p;
 	  long machine_id;
@@ -128,7 +128,7 @@ s390_host_detect_local_cpu (int argc, const char **argv)
 	      break;
 	    }
 	}
-      if (has_features == 0 && strncmp (buf, "features", 8) == 0)
+      if (has_features == 0 && startswith (buf, "features"))
 	{
 	  const char *p;
 
@@ -144,13 +144,13 @@ s390_host_detect_local_cpu (int argc, const char **argv)
 		p++;
 	      for (i = 0; !ISSPACE (p[i]) && p[i] != 0; i++)
 		;
-	      if (i == 3 && strncmp (p, "dfp", 3) == 0)
+	      if (i == 3 && startswith (p, "dfp"))
 		has_dfp = 1;
-	      else if (i == 2 && strncmp (p, "te", 2) == 0)
+	      else if (i == 2 && startswith (p, "te"))
 		has_te = 1;
-	      else if (i == 2 && strncmp (p, "vx", 2) == 0)
+	      else if (i == 2 && startswith (p, "vx"))
 		has_vx = 1;
-	      else if (i == 8 && strncmp (p, "highgprs", 8) == 0)
+	      else if (i == 8 && startswith (p, "highgprs"))
 		has_highgprs = 1;
 	      p += i;
 	    }
diff --git a/gcc/config/sparc/driver-sparc.c b/gcc/config/sparc/driver-sparc.c
index f70c53fc377..698c18e65d9 100644
--- a/gcc/config/sparc/driver-sparc.c
+++ b/gcc/config/sparc/driver-sparc.c
@@ -148,7 +148,7 @@ host_detect_local_cpu (int argc, const char **argv)
     return NULL;
 
   while (fgets (buf, sizeof (buf), f) != NULL)
-    if (strncmp (buf, "cpu\t\t:", sizeof ("cpu\t\t:") - 1) == 0)
+    if (startswith (buf, "cpu\t\t:"))
       {
         for (i = 0; cpu_names [i].name; i++)
           if (strstr (buf, cpu_names [i].name) != NULL)
diff --git a/gcc/config/vax/vax.c b/gcc/config/vax/vax.c
index 726c3719138..78f72ef3676 100644
--- a/gcc/config/vax/vax.c
+++ b/gcc/config/vax/vax.c
@@ -1320,10 +1320,10 @@ vax_output_int_move (rtx insn ATTRIBUTE_UNUSED, rtx *operands,
 	     be shorter (1 opcode byte + 1 addrmode byte + 8 immediate value
 	     bytes .vs. 2 opcode bytes + 2 addrmode bytes + 8 immediate value
 	     value bytes.  */
-	  if ((!strncmp (pattern_lo, "movl", 4)
-	      && !strncmp (pattern_hi, "movl", 4))
-	      || (!strncmp (pattern_lo, "pushl", 5)
-		  && !strncmp (pattern_hi, "pushl", 5)))
+	  if ((startswith (pattern_lo, "movl")
+	      && startswith (pattern_hi, "movl"))
+	      || (startswith (pattern_lo, "pushl")
+		  && startswith (pattern_hi, "pushl")))
 	    return "movq %1,%0";
 
 	  if (MEM_P (operands[0])
diff --git a/gcc/config/vms/vms-ld.c b/gcc/config/vms/vms-ld.c
index 451ad0d56fe..121aebdbe26 100644
--- a/gcc/config/vms/vms-ld.c
+++ b/gcc/config/vms/vms-ld.c
@@ -94,6 +94,14 @@ static int translate_unix (char *, int);
 #endif
 \f
 
+/* Return 1 if STR string starts with PREFIX.  */
+
+static inline int
+startswith (const char *str, const char *prefix)
+{
+  return strncmp (str, prefix, strlen (prefix)) == 0;
+}
+
 /* Append STR to the command line to invoke the linker.
    Expand the line as necessary to accommodate.  */
 
@@ -319,7 +327,7 @@ process_args (int argc, char **argv)
 
   for (i = 1; i < argc; i++)
     {
-      if (strncmp (argv[i], "-L", 2) == 0)
+      if (startswith (argv[i], "-L"))
 	{
           search_dirs = XRESIZEVEC(const char *, search_dirs,
                                    search_dirs_len + 1);
@@ -341,7 +349,7 @@ process_args (int argc, char **argv)
 	}
       else if (strcmp (argv[i], "-g0") == 0)
 	addarg ("/notraceback");
-      else if (strncmp (argv[i], "-g", 2) == 0)
+      else if (startswith (argv[i], "-g"))
 	{
 	  addarg ("/debug");
 	  debug = 1;
@@ -654,7 +662,7 @@ main (int argc, char **argv)
           /* Already handled.  */
           i++;
         }
-      else if (arg_len > 2 && strncmp (argv[i], "-l", 2) == 0)
+      else if (arg_len > 2 && startswith (argv[i], "-l"))
 	{
 	  const char *libname;
 
@@ -676,17 +684,17 @@ main (int argc, char **argv)
 	    }
 	}
       else if (strcmp (argv[i], "-v" ) == 0
-	       || strncmp (argv[i], "-g", 2 ) == 0
+	       || startswith (argv[i], "-g")
 	       || strcmp (argv[i], "-static" ) == 0
 	       || strcmp (argv[i], "-map" ) == 0
 	       || strcmp (argv[i], "-save-temps") == 0
 	       || strcmp (argv[i], "--noinhibit-exec") == 0
-	       || (arg_len > 2 && strncmp (argv[i], "-L", 2) == 0)
-	       || (arg_len >= 6 && strncmp (argv[i], "-share", 6) == 0))
+	       || (arg_len > 2 && startswith (argv[i], "-L"))
+	       || (arg_len >= 6 && startswith (argv[i], "-share")))
         {
           /* Already handled.  */
         }
-      else if (strncmp (argv[i], "--opt=", 6) == 0)
+      else if (startswith (argv[i], "--opt="))
 	fprintf (optfile, "%s\n", argv[i] + 6);
       else if (arg_len > 1 && argv[i][0] == '@')
 	{
diff --git a/gcc/config/vms/vms.c b/gcc/config/vms/vms.c
index 1ee1c86d1a4..bbf174e0dc9 100644
--- a/gcc/config/vms/vms.c
+++ b/gcc/config/vms/vms.c
@@ -302,7 +302,7 @@ vms_start_function (const char *fnname)
 #if VMS_DEBUGGING_INFO
   if (vms_debug_main
       && debug_info_level > DINFO_LEVEL_NONE
-      && strncmp (vms_debug_main, fnname, strlen (vms_debug_main)) == 0)
+      && startswith (vms_debug_main, fnname))
     {
       targetm.asm_out.globalize_label (asm_out_file, VMS_DEBUG_MAIN_POINTER);
       ASM_OUTPUT_DEF (asm_out_file, VMS_DEBUG_MAIN_POINTER, fnname);

^ permalink raw reply	[flat|nested] 19+ messages in thread

* [PATCH 1/3] Come up with startswith function.
  2021-04-21  7:24 ` [PATCH 0/3] Come " Martin Liska
  2021-04-21  7:26   ` [PATCH 2/3] LTO plugin: use " Martin Liska
@ 2021-04-21  7:26   ` Martin Liska
  2021-04-21  7:32     ` Arnaud Charlet
  2021-05-18 10:07     ` Iain Buclaw
  2021-04-21  7:26   ` [PATCH 3/3] Use startswith in targets Martin Liska
  2021-04-21  7:33   ` [PATCH 0/3] Come up with startswith function Arnaud Charlet
  3 siblings, 2 replies; 19+ messages in thread
From: Martin Liska @ 2021-04-21  7:26 UTC (permalink / raw)
  To: gcc-patches

[-- Attachment #1: Type: text/plain, Size: 7042 bytes --]


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(-)


[-- Warning: decoded text below may be mangled, UTF-8 assumed --]
[-- Attachment #2: 0001-Come-up-with-startswith-function.patch --]
[-- Type: text/x-patch; name="0001-Come-up-with-startswith-function.patch", Size: 54898 bytes --]

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)

^ permalink raw reply	[flat|nested] 19+ messages in thread

* Re: [PATCH 1/3] Come up with startswith function.
  2021-04-21  7:26   ` [PATCH 1/3] Come up with " Martin Liska
@ 2021-04-21  7:32     ` Arnaud Charlet
  2021-04-21  8:37       ` Martin Liška
  2021-05-18 10:07     ` Iain Buclaw
  1 sibling, 1 reply; 19+ messages in thread
From: Arnaud Charlet @ 2021-04-21  7:32 UTC (permalink / raw)
  To: Martin Liska; +Cc: gcc-patches, Arnaud Charlet

> 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

^ permalink raw reply	[flat|nested] 19+ messages in thread

* Re: [PATCH 0/3] Come up with startswith function
  2021-04-21  7:24 ` [PATCH 0/3] Come " Martin Liska
                     ` (2 preceding siblings ...)
  2021-04-21  7:26   ` [PATCH 3/3] Use startswith in targets Martin Liska
@ 2021-04-21  7:33   ` Arnaud Charlet
  3 siblings, 0 replies; 19+ messages in thread
From: Arnaud Charlet @ 2021-04-21  7:33 UTC (permalink / raw)
  To: Martin Liska; +Cc: gcc-patches, Arnaud Charlet

> The patchset is tested on x86_64-linux-gnu and I was able to build
> all cross-compilers.
> 
> Ready to be installed to master once GCC 11.1 is released?

Not for the Ada part as just mentioned under your 1/3 email.

^ permalink raw reply	[flat|nested] 19+ messages in thread

* Re: [PATCH 1/3] Come up with startswith function.
  2021-04-21  7:32     ` Arnaud Charlet
@ 2021-04-21  8:37       ` Martin Liška
  2021-04-25 14:47         ` Arnaud Charlet
  2021-05-10  7:16         ` Richard Biener
  0 siblings, 2 replies; 19+ messages in thread
From: Martin Liška @ 2021-04-21  8:37 UTC (permalink / raw)
  To: Arnaud Charlet; +Cc: gcc-patches

[-- Attachment #1: Type: text/plain, Size: 657 bytes --]

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

[-- Attachment #2: 0001-Come-up-with-startswith-function.patch --]
[-- Type: text/x-patch, Size: 59813 bytes --]

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


^ permalink raw reply	[flat|nested] 19+ messages in thread

* Re: [PATCH 3/3] Use startswith in targets.
  2021-04-21  7:26   ` [PATCH 3/3] Use startswith in targets Martin Liska
@ 2021-04-21 20:31     ` Paul Koning
  2021-04-21 20:43     ` Iain Sandoe
  2021-05-13  9:00     ` Martin Liška
  2 siblings, 0 replies; 19+ messages in thread
From: Paul Koning @ 2021-04-21 20:31 UTC (permalink / raw)
  To: Martin Liska; +Cc: gcc-patches



> On Mar 19, 2021, at 5:21 AM, Martin Liska <mliska@suse.cz> wrote:
> 
> 
> gcc/ChangeLog:
> 
> 	...
> 	* config/pdp11/pdp11.c (pdp11_output_ident): Likewise.

pdp11 is ok.  Thanks.

	paul



^ permalink raw reply	[flat|nested] 19+ messages in thread

* Re: [PATCH 3/3] Use startswith in targets.
  2021-04-21  7:26   ` [PATCH 3/3] Use startswith in targets Martin Liska
  2021-04-21 20:31     ` Paul Koning
@ 2021-04-21 20:43     ` Iain Sandoe
  2021-05-13  9:00     ` Martin Liška
  2 siblings, 0 replies; 19+ messages in thread
From: Iain Sandoe @ 2021-04-21 20:43 UTC (permalink / raw)
  To: Martin Liska; +Cc: gcc-patches

Martin Liska <mliska@suse.cz> wrote:

>
> gcc/config/darwin-c.c                         |   9 +-
> gcc/config/darwin.c                           | 141 +++++++++————

The darwin changes are OK, looks like a nice cleanup,
thanks
Iain


^ permalink raw reply	[flat|nested] 19+ messages in thread

* Re: [PATCH 1/3] Come up with startswith function.
  2021-04-21  8:37       ` Martin Liška
@ 2021-04-25 14:47         ` Arnaud Charlet
  2021-05-10  7:16         ` Richard Biener
  1 sibling, 0 replies; 19+ messages in thread
From: Arnaud Charlet @ 2021-04-25 14:47 UTC (permalink / raw)
  To: Martin Li??ka; +Cc: gcc-patches, Arnaud Charlet

> Thank you for a quick reply.
> There's an updated version of the patch.

The Ada part is OK now, thanks.

^ permalink raw reply	[flat|nested] 19+ messages in thread

* Re: [PATCH 2/3] LTO plugin: use startswith function.
  2021-04-21  7:26   ` [PATCH 2/3] LTO plugin: use " Martin Liska
@ 2021-04-29 12:17     ` Richard Biener
  0 siblings, 0 replies; 19+ messages in thread
From: Richard Biener @ 2021-04-29 12:17 UTC (permalink / raw)
  To: Martin Liska; +Cc: GCC Patches

On Wed, Apr 21, 2021 at 10:13 AM Martin Liska <mliska@suse.cz> wrote:
>

OK.

> lto-plugin/ChangeLog:
>
>         * lto-plugin.c (LTO_SEGMENT_NAME): Remove.
>         (LTO_SYMTAB_PREFIX): Likewise.
>         (LTO_SYMTAB_PREFIX_LEN): Likewise.
>         (LTO_SYMTAB_EXT_PREFIX): Likewise.
>         (LTO_SYMTAB_EXT_PREFIX_LEN): Likewise.
>         (LTO_LTO_PREFIX): Likewise.
>         (LTO_LTO_PREFIX_LEN): Likewise.
>         (OFFLOAD_SECTION): Likewise.
>         (OFFLOAD_SECTION_LEN): Likewise.
>         (startswith): New function.
>         (all_symbols_read_handler): Use it.
>         (process_symtab): Likewise.
>         (process_symtab_extension): Likewise.
>         (process_offload_section): Likewise.
>         (process_option): Likewise.
> ---
>  lto-plugin/lto-plugin.c | 29 +++++++++++++----------------
>  1 file changed, 13 insertions(+), 16 deletions(-)
>

^ permalink raw reply	[flat|nested] 19+ messages in thread

* Re: [PATCH 1/3] Come up with startswith function.
  2021-04-21  8:37       ` Martin Liška
  2021-04-25 14:47         ` Arnaud Charlet
@ 2021-05-10  7:16         ` Richard Biener
  1 sibling, 0 replies; 19+ messages in thread
From: Richard Biener @ 2021-05-10  7:16 UTC (permalink / raw)
  To: Martin Liška; +Cc: Arnaud Charlet, GCC Patches

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

^ permalink raw reply	[flat|nested] 19+ messages in thread

* Re: [PATCH 3/3] Use startswith in targets.
  2021-04-21  7:26   ` [PATCH 3/3] Use startswith in targets Martin Liska
  2021-04-21 20:31     ` Paul Koning
  2021-04-21 20:43     ` Iain Sandoe
@ 2021-05-13  9:00     ` Martin Liška
  2021-05-18  8:32       ` Richard Biener
  2 siblings, 1 reply; 19+ messages in thread
From: Martin Liška @ 2021-05-13  9:00 UTC (permalink / raw)
  To: gcc-patches

May I please ping this?

Martin

On 3/19/21 10:21 AM, Martin Liska wrote:
> 
> gcc/ChangeLog:
> 
> 	* common/config/aarch64/aarch64-common.c (aarch64_parse_extension):
> 	Use startswith function instead of strncmp.
> 	* common/config/bfin/bfin-common.c (bfin_handle_option): Likewise.
> 	* common/config/riscv/riscv-common.c (riscv_subset_list::parse): Likewise.
> 	* config/aarch64/aarch64-sve-builtins-shapes.cc (parse_type): Likewise.
> 	* config/aarch64/aarch64.c (aarch64_process_one_target_attr): Likewise.
> 	* config/alpha/alpha.c (alpha_elf_section_type_flags): Likewise.
> 	* config/arm/aarch-common.c (arm_md_asm_adjust): Likewise.
> 	* config/arm/arm.c (arm_file_start): Likewise.
> 	(arm_valid_target_attribute_rec): Likewise.
> 	(thumb1_md_asm_adjust): Likewise.
> 	* config/arm/driver-arm.c (host_detect_local_cpu): Likewise.
> 	* config/avr/avr.c (STR_PREFIX_P): Likewise.
> 	(avr_set_current_function): Likewise.
> 	(avr_handle_addr_attribute): Likewise.
> 	(avr_asm_output_aligned_decl_common): Likewise.
> 	(avr_asm_named_section): Likewise.
> 	(avr_section_type_flags): Likewise.
> 	(avr_asm_select_section): Likewise.
> 	* config/c6x/c6x.c (c6x_in_small_data_p): Likewise.
> 	(c6x_section_type_flags): Likewise.
> 	* config/darwin-c.c (darwin_cfstring_ref_p): Likewise.
> 	(darwin_objc_declare_unresolved_class_reference): Likewise.
> 	(darwin_objc_declare_class_definition): Likewise.
> 	* config/darwin.c (indirect_data): Likewise.
> 	(darwin_encode_section_info): Likewise.
> 	(darwin_objc2_section): Likewise.
> 	(darwin_objc1_section): Likewise.
> 	(machopic_select_section): Likewise.
> 	(darwin_globalize_label): Likewise.
> 	(darwin_label_is_anonymous_local_objc_name): Likewise.
> 	(darwin_asm_named_section): Likewise.
> 	(darwin_asm_output_dwarf_offset): Likewise.
> 	* config/frv/frv.c (frv_string_begins_with): Likewise.
> 	(frv_in_small_data_p): Likewise.
> 	* config/gcn/mkoffload.c (STR): Likewise.
> 	(main): Likewise.
> 	* config/i386/i386-builtins.c (get_builtin_code_for_version): Likewise.
> 	* config/i386/i386-options.c (ix86_option_override_internal): Likewise.
> 	* config/i386/i386.c (x86_64_elf_section_type_flags): Likewise.
> 	(ix86_md_asm_adjust): Likewise.
> 	* config/i386/intelmic-mkoffload.c (STR): Likewise.
> 	* config/i386/winnt.c (i386_pe_asm_named_section): Likewise.
> 	(i386_pe_file_end): Likewise.
> 	* config/ia64/ia64.c (ia64_in_small_data_p): Likewise.
> 	(ia64_section_type_flags): Likewise.
> 	* config/mips/driver-native.c (host_detect_local_cpu): Likewise.
> 	* config/mips/mips.c (mips_handle_interrupt_attr): Likewise.
> 	(mips16_stub_function_p): Likewise.
> 	(mips_function_rodata_section): Likewise.
> 	* config/msp430/msp430.c (msp430_mcu_name): Likewise.
> 	(msp430_function_section): Likewise.
> 	(msp430_section_type_flags): Likewise.
> 	(msp430_expand_helper): Likewise.
> 	* config/nios2/nios2.c (nios2_small_section_name_p): Likewise.
> 	(nios2_valid_target_attribute_rec): Likewise.
> 	* config/nvptx/mkoffload.c (process): Likewise.
> 	(STR): Likewise.
> 	* config/pa/som.h: Likewise.
> 	* config/pdp11/pdp11.c (pdp11_output_ident): Likewise.
> 	* config/riscv/riscv.c (riscv_elf_select_rtx_section): Likewise.
> 	* config/rs6000/rs6000.c (VTABLE_NAME_P): Likewise.
> 	(rs6000_inner_target_options): Likewise.
> 	* config/s390/driver-native.c (s390_host_detect_local_cpu): Likewise.
> 	* config/sparc/driver-sparc.c (host_detect_local_cpu): Likewise.
> 	* config/vax/vax.c (vax_output_int_move): Likewise.
> 	* config/vms/vms-ld.c (startswith): Likewise.
> 	(process_args): Likewise.
> 	(main): Likewise.
> 	* config/vms/vms.c: Likewise.
> ---
>   gcc/common/config/aarch64/aarch64-common.c    |   2 +-
>   gcc/common/config/bfin/bfin-common.c          |   2 +-
>   gcc/common/config/riscv/riscv-common.c        |   4 +-
>   .../aarch64/aarch64-sve-builtins-shapes.cc    |   4 +-
>   gcc/config/aarch64/aarch64.c                  |   2 +-
>   gcc/config/alpha/alpha.c                      |   8 +-
>   gcc/config/arm/aarch-common.c                 |   2 +-
>   gcc/config/arm/arm.c                          |   8 +-
>   gcc/config/arm/driver-arm.c                   |   4 +-
>   gcc/config/avr/avr.c                          |  25 ++--
>   gcc/config/c6x/c6x.c                          |  14 +-
>   gcc/config/darwin-c.c                         |   9 +-
>   gcc/config/darwin.c                           | 141 +++++++++---------
>   gcc/config/frv/frv.c                          |  16 +-
>   gcc/config/gcn/mkoffload.c                    |  10 +-
>   gcc/config/i386/i386-builtins.c               |   2 +-
>   gcc/config/i386/i386-options.c                |   2 +-
>   gcc/config/i386/i386.c                        |   7 +-
>   gcc/config/i386/intelmic-mkoffload.c          |   4 +-
>   gcc/config/i386/winnt.c                       |   5 +-
>   gcc/config/ia64/ia64.c                        |  20 +--
>   gcc/config/mips/driver-native.c               |   2 +-
>   gcc/config/mips/mips.c                        |  10 +-
>   gcc/config/msp430/msp430.c                    |  13 +-
>   gcc/config/nios2/nios2.c                      |  13 +-
>   gcc/config/nvptx/mkoffload.c                  |  10 +-
>   gcc/config/pa/som.h                           |  13 +-
>   gcc/config/pdp11/pdp11.c                      |   2 +-
>   gcc/config/riscv/riscv.c                      |   2 +-
>   gcc/config/rs6000/rs6000.c                    |  18 +--
>   gcc/config/s390/driver-native.c               |  12 +-
>   gcc/config/sparc/driver-sparc.c               |   2 +-
>   gcc/config/vax/vax.c                          |   8 +-
>   gcc/config/vms/vms-ld.c                       |  22 ++-
>   gcc/config/vms/vms.c                          |   2 +-
>   35 files changed, 199 insertions(+), 221 deletions(-)
> 


^ permalink raw reply	[flat|nested] 19+ messages in thread

* Re: [PATCH 3/3] Use startswith in targets.
  2021-05-13  9:00     ` Martin Liška
@ 2021-05-18  8:32       ` Richard Biener
  0 siblings, 0 replies; 19+ messages in thread
From: Richard Biener @ 2021-05-18  8:32 UTC (permalink / raw)
  To: Martin Liška; +Cc: GCC Patches

On Thu, May 13, 2021 at 11:00 AM Martin Liška <mliska@suse.cz> wrote:
>
> May I please ping this?

OK.

Please watch for fallout.

Richard.

> Martin
>
> On 3/19/21 10:21 AM, Martin Liska wrote:
> >
> > gcc/ChangeLog:
> >
> >       * common/config/aarch64/aarch64-common.c (aarch64_parse_extension):
> >       Use startswith function instead of strncmp.
> >       * common/config/bfin/bfin-common.c (bfin_handle_option): Likewise.
> >       * common/config/riscv/riscv-common.c (riscv_subset_list::parse): Likewise.
> >       * config/aarch64/aarch64-sve-builtins-shapes.cc (parse_type): Likewise.
> >       * config/aarch64/aarch64.c (aarch64_process_one_target_attr): Likewise.
> >       * config/alpha/alpha.c (alpha_elf_section_type_flags): Likewise.
> >       * config/arm/aarch-common.c (arm_md_asm_adjust): Likewise.
> >       * config/arm/arm.c (arm_file_start): Likewise.
> >       (arm_valid_target_attribute_rec): Likewise.
> >       (thumb1_md_asm_adjust): Likewise.
> >       * config/arm/driver-arm.c (host_detect_local_cpu): Likewise.
> >       * config/avr/avr.c (STR_PREFIX_P): Likewise.
> >       (avr_set_current_function): Likewise.
> >       (avr_handle_addr_attribute): Likewise.
> >       (avr_asm_output_aligned_decl_common): Likewise.
> >       (avr_asm_named_section): Likewise.
> >       (avr_section_type_flags): Likewise.
> >       (avr_asm_select_section): Likewise.
> >       * config/c6x/c6x.c (c6x_in_small_data_p): Likewise.
> >       (c6x_section_type_flags): Likewise.
> >       * config/darwin-c.c (darwin_cfstring_ref_p): Likewise.
> >       (darwin_objc_declare_unresolved_class_reference): Likewise.
> >       (darwin_objc_declare_class_definition): Likewise.
> >       * config/darwin.c (indirect_data): Likewise.
> >       (darwin_encode_section_info): Likewise.
> >       (darwin_objc2_section): Likewise.
> >       (darwin_objc1_section): Likewise.
> >       (machopic_select_section): Likewise.
> >       (darwin_globalize_label): Likewise.
> >       (darwin_label_is_anonymous_local_objc_name): Likewise.
> >       (darwin_asm_named_section): Likewise.
> >       (darwin_asm_output_dwarf_offset): Likewise.
> >       * config/frv/frv.c (frv_string_begins_with): Likewise.
> >       (frv_in_small_data_p): Likewise.
> >       * config/gcn/mkoffload.c (STR): Likewise.
> >       (main): Likewise.
> >       * config/i386/i386-builtins.c (get_builtin_code_for_version): Likewise.
> >       * config/i386/i386-options.c (ix86_option_override_internal): Likewise.
> >       * config/i386/i386.c (x86_64_elf_section_type_flags): Likewise.
> >       (ix86_md_asm_adjust): Likewise.
> >       * config/i386/intelmic-mkoffload.c (STR): Likewise.
> >       * config/i386/winnt.c (i386_pe_asm_named_section): Likewise.
> >       (i386_pe_file_end): Likewise.
> >       * config/ia64/ia64.c (ia64_in_small_data_p): Likewise.
> >       (ia64_section_type_flags): Likewise.
> >       * config/mips/driver-native.c (host_detect_local_cpu): Likewise.
> >       * config/mips/mips.c (mips_handle_interrupt_attr): Likewise.
> >       (mips16_stub_function_p): Likewise.
> >       (mips_function_rodata_section): Likewise.
> >       * config/msp430/msp430.c (msp430_mcu_name): Likewise.
> >       (msp430_function_section): Likewise.
> >       (msp430_section_type_flags): Likewise.
> >       (msp430_expand_helper): Likewise.
> >       * config/nios2/nios2.c (nios2_small_section_name_p): Likewise.
> >       (nios2_valid_target_attribute_rec): Likewise.
> >       * config/nvptx/mkoffload.c (process): Likewise.
> >       (STR): Likewise.
> >       * config/pa/som.h: Likewise.
> >       * config/pdp11/pdp11.c (pdp11_output_ident): Likewise.
> >       * config/riscv/riscv.c (riscv_elf_select_rtx_section): Likewise.
> >       * config/rs6000/rs6000.c (VTABLE_NAME_P): Likewise.
> >       (rs6000_inner_target_options): Likewise.
> >       * config/s390/driver-native.c (s390_host_detect_local_cpu): Likewise.
> >       * config/sparc/driver-sparc.c (host_detect_local_cpu): Likewise.
> >       * config/vax/vax.c (vax_output_int_move): Likewise.
> >       * config/vms/vms-ld.c (startswith): Likewise.
> >       (process_args): Likewise.
> >       (main): Likewise.
> >       * config/vms/vms.c: Likewise.
> > ---
> >   gcc/common/config/aarch64/aarch64-common.c    |   2 +-
> >   gcc/common/config/bfin/bfin-common.c          |   2 +-
> >   gcc/common/config/riscv/riscv-common.c        |   4 +-
> >   .../aarch64/aarch64-sve-builtins-shapes.cc    |   4 +-
> >   gcc/config/aarch64/aarch64.c                  |   2 +-
> >   gcc/config/alpha/alpha.c                      |   8 +-
> >   gcc/config/arm/aarch-common.c                 |   2 +-
> >   gcc/config/arm/arm.c                          |   8 +-
> >   gcc/config/arm/driver-arm.c                   |   4 +-
> >   gcc/config/avr/avr.c                          |  25 ++--
> >   gcc/config/c6x/c6x.c                          |  14 +-
> >   gcc/config/darwin-c.c                         |   9 +-
> >   gcc/config/darwin.c                           | 141 +++++++++---------
> >   gcc/config/frv/frv.c                          |  16 +-
> >   gcc/config/gcn/mkoffload.c                    |  10 +-
> >   gcc/config/i386/i386-builtins.c               |   2 +-
> >   gcc/config/i386/i386-options.c                |   2 +-
> >   gcc/config/i386/i386.c                        |   7 +-
> >   gcc/config/i386/intelmic-mkoffload.c          |   4 +-
> >   gcc/config/i386/winnt.c                       |   5 +-
> >   gcc/config/ia64/ia64.c                        |  20 +--
> >   gcc/config/mips/driver-native.c               |   2 +-
> >   gcc/config/mips/mips.c                        |  10 +-
> >   gcc/config/msp430/msp430.c                    |  13 +-
> >   gcc/config/nios2/nios2.c                      |  13 +-
> >   gcc/config/nvptx/mkoffload.c                  |  10 +-
> >   gcc/config/pa/som.h                           |  13 +-
> >   gcc/config/pdp11/pdp11.c                      |   2 +-
> >   gcc/config/riscv/riscv.c                      |   2 +-
> >   gcc/config/rs6000/rs6000.c                    |  18 +--
> >   gcc/config/s390/driver-native.c               |  12 +-
> >   gcc/config/sparc/driver-sparc.c               |   2 +-
> >   gcc/config/vax/vax.c                          |   8 +-
> >   gcc/config/vms/vms-ld.c                       |  22 ++-
> >   gcc/config/vms/vms.c                          |   2 +-
> >   35 files changed, 199 insertions(+), 221 deletions(-)
> >
>

^ permalink raw reply	[flat|nested] 19+ messages in thread

* Re: [PATCH 1/3] Come up with startswith function.
  2021-04-21  7:26   ` [PATCH 1/3] Come up with " Martin Liska
  2021-04-21  7:32     ` Arnaud Charlet
@ 2021-05-18 10:07     ` Iain Buclaw
  2021-05-18 12:32       ` Martin Liška
  1 sibling, 1 reply; 19+ messages in thread
From: Iain Buclaw @ 2021-05-18 10:07 UTC (permalink / raw)
  To: gcc-patches, Martin Liska; +Cc: ian

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.

^ permalink raw reply	[flat|nested] 19+ messages in thread

* Re: [PATCH 1/3] Come up with startswith function.
  2021-05-18 10:07     ` Iain Buclaw
@ 2021-05-18 12:32       ` Martin Liška
  2021-05-19  3:08         ` Ian Lance Taylor
  0 siblings, 1 reply; 19+ messages in thread
From: Martin Liška @ 2021-05-18 12:32 UTC (permalink / raw)
  To: Iain Buclaw, gcc-patches; +Cc: ian

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.
> 


^ permalink raw reply	[flat|nested] 19+ messages in thread

* Re: [PATCH 1/3] Come up with startswith function.
  2021-05-18 12:32       ` Martin Liška
@ 2021-05-19  3:08         ` Ian Lance Taylor
  0 siblings, 0 replies; 19+ messages in thread
From: Ian Lance Taylor @ 2021-05-19  3:08 UTC (permalink / raw)
  To: Martin Liška; +Cc: Iain Buclaw, gcc-patches, ian

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

^ permalink raw reply	[flat|nested] 19+ messages in thread

end of thread, other threads:[~2021-05-19  3:08 UTC | newest]

Thread overview: 19+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2021-03-18 10:46 [PATCH] RFC: come up with startswith function Martin Liška
2021-03-18 15:30 ` Martin Sebor
2021-04-21  7:24 ` [PATCH 0/3] Come " Martin Liska
2021-04-21  7:26   ` [PATCH 2/3] LTO plugin: use " Martin Liska
2021-04-29 12:17     ` Richard Biener
2021-04-21  7:26   ` [PATCH 1/3] Come up with " Martin Liska
2021-04-21  7:32     ` Arnaud Charlet
2021-04-21  8:37       ` Martin Liška
2021-04-25 14:47         ` Arnaud Charlet
2021-05-10  7:16         ` Richard Biener
2021-05-18 10:07     ` Iain Buclaw
2021-05-18 12:32       ` Martin Liška
2021-05-19  3:08         ` Ian Lance Taylor
2021-04-21  7:26   ` [PATCH 3/3] Use startswith in targets Martin Liska
2021-04-21 20:31     ` Paul Koning
2021-04-21 20:43     ` Iain Sandoe
2021-05-13  9:00     ` Martin Liška
2021-05-18  8:32       ` Richard Biener
2021-04-21  7:33   ` [PATCH 0/3] Come up with startswith function Arnaud Charlet

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).