Search code examples
cgccinitializationundefined-behavior

Possibility of uninitialized use of b in if (!a) { b = get_b(); } if (a || b) { ... }


When compiling the following (context) with -Oz,

extern void *get_table_index(struct table tbl, struct string name);

void inspircd2_protocol_propagate_privmsg(struct string from, struct string source, struct string target, struct string msg) {
    struct user_info *user = get_table_index(user_list, target);
    struct server_info *server;
    if (!user)
        server = get_table_index(server_list, target);

    if (user || server) {
        struct server_info *target_server;
        if (user) {
            target_server = get_table_index(server_list, user->server);
        } else {
            target_server = server;
        }
        /* ... */

gcc version 14.2.1 20240801 (Red Hat 14.2.1-1) (GCC) complains:

protocols/inspircd2.c: In function ‘inspircd2_protocol_propagate_privmsg’:
protocols/inspircd2.c:816:18: warning: ‘server’ may be used uninitialized [-Wmaybe-uninitialized]
  816 |         if (user || server) {
      |                  ^~
protocols/inspircd2.c:812:29: note: ‘server’ was declared here
  812 |         struct server_info *server;
      |                             ^~~~~~

My understanding is that if user is NULL, server would be defined. If user is not NULL, then server wouldn't even be accessed as part of user || server, since it would have checked user first, find nonzero, and proceed to the inside of the block already.

Is this warning something to be concerned about?


Solution

  • if user is NULL, server would be defined. If user is not NULL, then server wouldn't even be accessed as part of user || server, since it would have checked user first, find nonzero, and proceed to the inside of the block already.

    That is true. However, adding explicit initialization of server to NULL would be easy to do and silence the warning.

    But I would simplify code and reduce comparisons needed:

    struct user_info *user = get_table_index(user_list, target);
    struct server_info *target_server;
    if (user) {
        target_server = get_table_index(server_list, user->server);
    }
    else {
        target_server = get_table_index(server_list, target);
    }
    if (target_server) {
        /* ... */
    

    Or even more:

    struct user_info *user = get_table_index(user_list, target);
    struct string server_target = user ? user->server : target;
    struct server_info *target_server = get_table_index(server_list, server_target);
    if (target_server) {
        /* ... */