Bug 80351 - Inconsistent warning for constexpr auto constant when using initializer list (-Wunused-variable)
Summary: Inconsistent warning for constexpr auto constant when using initializer list ...
Status: NEW
Alias: None
Product: gcc
Classification: Unclassified
Component: c++ (show other bugs)
Version: 6.2.0
: P3 normal
Target Milestone: ---
Assignee: Not yet assigned to anyone
URL:
Keywords: diagnostic
Depends on:
Blocks: constexpr Wunused
  Show dependency treegraph
 
Reported: 2017-04-07 02:28 UTC by Jacek Sieka
Modified: 2022-04-29 18:23 UTC (History)
5 users (show)

See Also:
Host:
Target:
Build:
Known to work:
Known to fail:
Last reconfirmed: 2017-08-23 00:00:00


Attachments

Note You need to log in before you can comment on or make changes to this bug.
Description Jacek Sieka 2017-04-07 02:28:02 UTC
In the following snippet, these similar variables give different warnings, when compiled with -Wall - I would expect all of them to not give a warning:

#include <initializer_list>

enum class E { A, B };

constexpr E no_warn2[] = { E::A, E::B };

constexpr auto warn = { E::A, E::B };

constexpr auto no_warn = { E::A, E::B };  // No warning second time around

Results in:

<source>:7:16: warning: 'warn' defined but not used [-Wunused-variable]
 constexpr auto warn = { E::A, E::B };
                ^~~~
Compiler exited with result code 0


See: https://godbolt.org/g/bHGxar
Comment 1 Eric Gallager 2017-08-23 00:58:10 UTC
Confirmed that it warns where you say it does.
Comment 2 Eric Gallager 2018-10-10 01:53:05 UTC
cc-ing diagnostics maintainers
Comment 3 Pokechu22 2022-01-17 17:52:47 UTC
Still an issue in GCC 11.2.

Here are some additional examples: https://godbolt.org/z/hvEs6bb95 https://godbolt.org/z/674seG3bn https://godbolt.org/z/6esEs1fsr https://godbolt.org/z/s8eqsnzP9 https://godbolt.org/z/1TjnP6GeG https://godbolt.org/z/czefeKWsf

The use of an enum class isn't needed; the issue also happens with int.

In GCC 7.1+, marking warn as [[maybe_unused]] removes the warning (it doesn't get shifted to no_warn); GCC 6.4- give an additional warning that "'maybe_unused' attribute directive ignored" (it may not have been implemented then).

Explicitly using std::initializer_list<int> instead of auto resolves the issue.  In GCC 9.2+, only warn needs to be changed to have an explicit type (no_warn can remain as auto without a warning being generated), but in GCC 9.1-, the first use of auto will generate the warning (meaning no_warn will generate a warning unless it too is changed).

If different types are used, then one warning is generated for each type (e.g. {1, 2} and {1u, 2u} each generate one warning).

The behavior of only one warning being generated started in GCC 4.8.1+; multiple warnings were generated in 4.7.4-.
Comment 4 Pokechu22 2022-03-22 02:36:15 UTC
This also affects const variables, not just constexpr ones.  See https://godbolt.org/z/5coadhr8a.

The source of the issue is that the type is not complete the first time when cp_apply_type_quals_to_decl (in cp/typeck.cc) is called by cp_finish_decl (in cp/decl.cc); since it is not complete, cp_apply_type_quals_to_decl removes the const qualifier on the assumption that cp_finish_decl will later add it, but it's too late for that.  (cp_apply_type_quals_to_decl is also called earlier on by grokdeclarator (cp/decl.cc) where that assumption is valid).  The type is already complete when a second variable is declared, which is why the warning only appears once.  Presumably, initializer lists are the only type where auto can deduce to something that hasn't been completed yet (though I'm not 100% sure of this).

This change fixes the issue:

```
--- a/gcc/cp/decl.cc
+++ b/gcc/cp/decl.cc
@@@ -8098,7 -8098,7 +8098,7 @@@ cp_finish_decl (tree decl, tree init, b
         TREE_TYPE (decl) = error_mark_node;
         return;
       }
-      cp_apply_type_quals_to_decl (cp_type_quals (type), decl);
+      cp_apply_type_quals_to_decl (cp_type_quals (complete_type (type)), decl);
     }

   if (ensure_literal_type_for_constexpr_object (decl) == error_mark_node)
```

I am working on sending in a proper patch with testcases.  (I assume I will not need to fill out the contributing agreement for a change this small.)
Comment 5 GCC Commits 2022-04-29 18:23:53 UTC
The master branch has been updated by Jason Merrill <jason@gcc.gnu.org>:

https://gcc.gnu.org/g:8d0fcf135857869f7cff36d29bc3527c482372a9

commit r13-50-g8d0fcf135857869f7cff36d29bc3527c482372a9
Author: Jason Merrill <jason@redhat.com>
Date:   Wed Mar 23 18:01:20 2022 -0700

    c++: check completeness after auto deduction [PR80351]
    
    Normally we check for incomplete type in start_decl, but that obviously
    doesn't work for auto variables. Thanks to Pokechu22 for the analysis and
    testcases:
    
    "When cp_finish_decl calls cp_apply_type_quals_to_decl on a const auto or
    constexpr auto variable, the type might not be complete the first time
    (this happened when auto deduces to an initializer_list).
    cp_apply_type_quals_to_decl removes the const qualifier if the type is
    not complete, which is appropriate for grokdeclarator, on the assumption
    that the type will be complete when called by cp_finish_decl."
    
            PR c++/80351
    
    gcc/cp/ChangeLog:
    
            * decl.cc (cp_finish_decl): Check completeness of deduced type.
    
    gcc/testsuite/ChangeLog:
    
            * g++.dg/cpp0x/constexpr-77482.C: Adjust message.
            * g++.dg/cpp1y/auto-fn27.C: Likewise.
            * g++.dg/cpp1y/lambda-generic-variadic22.C: Likewise.
            * g++.dg/cpp1z/decomp54.C: Likewise.
            * g++.dg/cpp0x/initlist-const1.C: New test.
            * g++.dg/warn/Wunused-var-37.C: New test.
            * g++.dg/warn/Wunused-var-38.C: New test.
            * g++.dg/warn/Wunused-var-39.C: New test.