Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

name lookup for typedef is buggy in GNU compiler?

The following code

#include <iostream>

typedef double A; // a global typedef

template <class Z> struct B // a template class...
{
    A i{22.2}; // global typedef is in scope
    typedef int A; // now  a local typedef with the same name is introduced
    A b{24};  // now the local typedef is in scope
    Z c{36}; // a simple member of the template type
};

template <class Z> struct C : B<Z> // a template struct inheriting B
{
    A a;  // global typedef is in scope because we are in a template struct
    C(  ) : a(2.2){  }
};

int main(  )
{
    C<int> c;
    std::cout << "c's members: "
           << c.a << ' '
           << c.i << ' '
           << c.b << ' '
           << c.c << std::endl;
    std::cout << "their sizeof: "
           << sizeof(c.a) << ' ' 
           << sizeof(c.i) << ' '
           << sizeof(c.b) << ' '
           << sizeof(c.c) <<  std::endl;
}

is NOT compiled by GNU-g++ 4.9.2 while it is by clang 3.5.0 and behaves as I tried to explain in the embedded comments and as it can be seen by the output produced. Is this a bug in the GNU compiler? The diagnostic says that the line typedef int A; in the scope of the struct B

error: changes meaning of ‘A’ from ‘typedef double A’

Note that when the hierarchy is not made of template (and of course the Z c{36}; declaration is removed) the lookup performed by clang in the scope of C (correctly, as I suppose) finds the typedef in the scope of B and considers the member a to be of type int; then it issues a warning about the narrowing of the initializing double constant 2.2...

like image 804
GSi Avatar asked Nov 06 '15 15:11

GSi


People also ask

How to use nameoftype typedef in C language?

This typedef can also be used with structures of C language. Here how it looks like: Here nameOfType correspond to the definition of structure allied with it. Now, this nameOfType can be implemented by declaring a variable of this structure type.

Can a typedef be the same as a class type?

If the typedef name is the same as a class type name, it can only be so if that typedef is a synonym of the class name. A C++ class defined in a typedef definition without being named is given a dummy name. Such a class cannot have constructors or destructors.

What is the name space for a typedef name?

The name space for a typedef name is the same as other identifiers. When an object is defined using a typedef identifier, the properties of the defined object are exactly the same as if the object were defined by explicitly listing the data type associated with the identifier.


1 Answers

From the c++ standard draft (N4140)

§3.3.7 [basic.scope.class]

2) A name N used in a class S shall refer to the same declaration in its context and when re-evaluated in the completed scope of S. No diagnostic is required for a violation of this rule.

A i{22.2} initially refers to the global ::A. But after B::A is declared, when re-evaluated in the completed scope of B, it would refer to B::A. This violates the rule above.

To fix it, use the fully qualified name: ::A i{22.2}. ::A always refers to the global A even after B::A is declared, so it doesn't violate the rule.

This is not a bug in g++; it's just an ill-formed program. The compiler is not required not give you a diagnostic for the violation of the rule, but it's not required to accept it either.

like image 59
eerorika Avatar answered Oct 19 '22 23:10

eerorika