title: Why does GCC 9.1.0 sometimes complain about this use of strncpy()?
body: <p>This is a 40-line MCVE (<a href="https://stackoverflow.com/help/mcve">Minimal, Complete, Verifiable Example</a>) — or something close to minimal — cut down from a 1675 line source file that originally included 32 headers (and most of those included multiple other headers — compiling it with <code>gcc -H</code> lists 464 headers from the project and the system, many of them several times).  That file is working code that previously compiled without warnings (GCC 8.3.0), but not with GCC 9.1.0.  All structure, function, type, variable names have been changed.</p>
  
  <h3><code>pf31.c</code></h3>
  
  <pre><code>#include &lt;string.h&gt;
  
  enum { SERVERNAME_LEN = 128 };
  
  typedef struct ServerQueue
  {
      char server_name[SERVERNAME_LEN + 1];
      struct ServerQueue *next;
  } ServerQueue;
  
  extern int function_under_test(char *servername);
  
  #ifdef SUPPRESS_BUG
  extern int function_using_name(char *name);
  #endif /* SUPPRESS_BUG */
  
  extern int GetServerQueue(const char *servername, ServerQueue *queue);
  
  int
  function_under_test(char *servername)
  {
      ServerQueue queue;
      char name[SERVERNAME_LEN + 1];
  
      if (GetServerQueue(servername, &amp;queue) != 0)
          return -1;
      char *name_in_queue = queue.server_name;
  
      if (name_in_queue)
          strncpy(name, name_in_queue, SERVERNAME_LEN);
      else
          strncpy(name, servername, SERVERNAME_LEN);
      name[SERVERNAME_LEN] = '\0';
  
  #ifdef SUPPRESS_BUG
      return function_using_name(name);
  #else
      return 0;
  #endif /* SUPPRESS_BUG */
  }
  </code></pre>
  
  <h3>Compilation</h3>
  
  <p>When compiled using GCC 9.1.0 (on a Mac running macOS 10.14.5 Mojave, or on a Linux VM running RedHat 5.x — don't ask!), with the option <code>-DSUPPRESS_BUG</code> I get no error, but with the option <code>-USUPPRESS_BUG</code>, I get an error:</p>
  
  <pre><code>$ gcc -std=c11 -O3 -g -Wall -Wextra -Werror -DSUPPRESS_BUG  -c pf31.c
  $ gcc -std=c11 -O3 -g -Wall -Wextra -Werror -USUPPRESS_BUG  -c pf31.c
  In file included from /usr/include/string.h:417,
                   from pf31.c:1:
  pf31.c: In function ‘function_under_test’:
  pf31.c:30:9: error: ‘__builtin_strncpy’ output may be truncated copying 128 bytes from a string of length 128 [-Werror=stringop-truncation]
     30 |         strncpy(name, name_in_queue, SERVERNAME_LEN);
        |         ^~~~~~~
  cc1: all warnings being treated as errors
  $
  </code></pre>
  
  <p>When I compile using GCC 8.3.0, I get no errors reported.</p>
  
  <h3>Question</h3>
  
  <p>Two sides of one question:</p>
  
  <ul>
  <li>Why does GCC 9.1.0 complain about the use of <code>strncpy()</code> when the code is compiled with <code>-USUPPRESS_BUG</code>?</li>
  <li>Why doesn't it complain when the code is compiled with <code>-DSUPPRESS_BUG</code>?
  
  <ul>
  <li>Corollary: is there a way to work around this unwanted warning that works with older GCC versions as well as 9.1.0.  I've not yet found one.  There's also a strong element of "I don't think it should be necessary, because this is using <code>strncpy()</code> to limit the amount of data copied, which is what it is designed for".</li>
  </ul></li>
  </ul>
  
  <h3>Another variant</h3>
  
  <p>I have another non-erroring variant, changing the signature of the <code>function_under_test()</code> — here's a set of diffs:</p>
  
  <pre><code>11c11
  &lt; extern int function_under_test(char *servername);
  ---
  &gt; extern int function_under_test(char *servername, ServerQueue *queue);
  20c20
  &lt; function_under_test(char *servername)
  ---
  &gt; function_under_test(char *servername, ServerQueue *queue)
  22d21
  &lt;     ServerQueue queue;
  25c24
  &lt;     if (GetServerQueue(servername, &amp;queue) != 0)
  ---
  &gt;     if (GetServerQueue(servername, queue) != 0)
  27c26
  &lt;     char *name_in_queue = queue.server_name;
  ---
  &gt;     char *name_in_queue = queue-&gt;server_name;
  </code></pre>
  
  <p>This compiles cleanly regardless of whether <code>SUPPRESS_BUG</code> is defined or not.</p>
  
  <p>As you can guess from the <code>SUPPRESS_BUG</code> terminology, I'm tending towards the view that this is bug in GCC, but I'm kinda cautious about claiming it is one just yet.</p>
  
  <hr>
  
  <p>More about the the original code: the function itself was 540 lines long; the <code>strncpy()</code> block occurs about 170 lines into the function; the variable corresponding to <code>name</code> was used further down the function in a number of function call, some of which take <code>name</code> as an argument and supply a return value for the function.  This corresponds more to the <code>-DSUPPRESS_BUG</code> code, except that in the 'real code', the bug is not suppressed.</p>