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

             Bug #: 50479
           Summary: Unevaluated usage of parameters in function default
                    arguments is accepted
    Classification: Unclassified
           Product: gcc
           Version: 4.7.0
            Status: UNCONFIRMED
          Severity: normal
          Priority: P3
         Component: c++
        AssignedTo: unassig...@gcc.gnu.org
        ReportedBy: daniel.krueg...@googlemail.com
                CC: ja...@redhat.com


gcc 4.7.0 20110917 (experimental) accepts the following program with or without
-Wall, -pedantic, or -std=c++0x:

//---
long foo;
void bar(char foo = sizeof(foo)) {}

int main() {
  bar();
}
//---

But according to 3.4.1 p11:

"During the lookup for a name used as a default argument (8.3.6) in a function
parameter-declaration-clause or used in the expression of a mem-initializer for
a constructor (12.6.2), the function parameter names are visible and hide the
names of entities declared in the block, class or namespace scopes containing
the function declaration."

and to 8.3.6 p9:

"Consequently, parameters of a function shall not be used in a default
argument,
even if they are not evaluated. Parameters of a function declared before a
default argument are in scope and can hide namespace and class member names."

[The references refer to N3190, but also apply to C++03, 14882:2003(E)]

the name 'foo' in the expression 'sizeof(foo)' should resolve to the parameter
name and after this should make the program ill-formed. Refining this program
to

//---
extern "C" int printf(const char*, ...);

long foo;
void bar(char foo = sizeof(foo)) {
  int v = foo;
  printf("%d", v);
}

int main() {
  bar();
}
//---

produces the output

4

leading to the conclusion that the name 'foo' is resolved to the name of the
global variable, not to the parameter name.

A similar example can be constructed via decltype and compiled successfully
with -std=c++0x:

//---
template<class>
struct A;

template<>
struct A<long> {
  static const int value = 1;
};

long foo;

void bar(char foo = A<decltype(foo)>::value) {}

int main() {
  bar();
}
//---

This example should also be rejected for similar reasons as above, because the
name 'foo' in the default argument should resolve to the parameter, but again
the global variable name is found instead.

Reply via email to