http://gcc.gnu.org/bugzilla/show_bug.cgi?id=61039

            Bug ID: 61039
           Summary: Using a constexpr's address as a template variable
                    produces an unnecessary warning
           Product: gcc
           Version: 4.9.0
            Status: UNCONFIRMED
          Severity: normal
          Priority: P3
         Component: c++
          Assignee: unassigned at gcc dot gnu.org
          Reporter: lists at coryfields dot com

Tangentially related to bug #51440 and #52036. Present in 4.7-4.9.

Using the address of a non-type constexpr variable in the global namespace (or
specified namespace) as a template parameter produces the following warning:

test.h:14:8: warning: 'child1' has a base 'charptrbase<((const char*)(&
chararray))>' whose type uses the anonymous namespace
 struct child1 : public charptrbase<chararray>

Marking the constexpr as extern eliminates the warning, but I don't believe
that should be necessary for c++11. Use of the constant itself rather than the
address does not show the issue.

Preprocessed source for an offending example is very short, so I'll paste below
rather than attaching. The int parameter gives no warning, but the int* and
const char* do.

Clang compiles and gives the following warning when -Wc++98-compat is enabled,
which leads me to believe that this is a subtle c++11 gcc bug:

./test.h:14:36: warning: non-type template argument referring to object
'chararray' with internal linkage is incompatible with C++98 [-Wc++98-compat]
struct child1 : public charptrbase<chararray>

preprocessed source follows:
--

# 1 "test.cpp"
# 1 "/home/cory/dev//"
# 1 "<built-in>"
# 1 "<command-line>"
# 1 "/usr/include/stdc-predef.h" 1 3 4
# 30 "/usr/include/stdc-predef.h" 3 4
# 1 "/usr/include/x86_64-linux-gnu/bits/predefs.h" 1 3 4
# 31 "/usr/include/stdc-predef.h" 2 3 4
# 1 "<command-line>" 2
# 1 "test.cpp"
# 1 "test.h" 1
constexpr const int intval = 0;
constexpr const char chararray[] = "test";

template<const char*>
struct charptrbase {};

template<const int*>
struct intptrbase {};

template<int>
struct intbase {};


struct child1 : public charptrbase<chararray>
{};

struct child2 : public intptrbase<&intval>
{};

struct child3 : public intbase<intval>
{};
# 2 "test.cpp" 2

int main()
{
  child2 foo;
  (void)foo;
  return 0;
}

Reply via email to