Topic: Possible defect in ambiguity resolution


Author: Michiel.Salters@cmg.nl (Michiel Salters)
Date: Mon, 14 Jan 2002 17:07:05 GMT
Raw View
"B. van Ingen Schenau" <bvis@universalmail.com> wrote in message news:<cacu3u07jkrfl5ti6tk7acsvn9totn6emh@4ax.com>...
> Hello all,
>
> During a discussion on alt.comp.lang.learn.c-c++ it was fount
> that two different compilers get completely different results
> from the following program.

Names, please ?

> And our subsequent reading of the standard makes me believe that both
> compilers are right.
>
> The program in question is:
> ----- 8< -----
> #include <iostream>

> struct Point    {
>    int j;
>    Point(int k): j(k){}
>    };
>
> struct Lattice     {
>    Point p1;
>    Point p2;
>    int i;
>    Lattice(Point pa1, Point pa2, int ii):p1(pa1), p2(pa2), i(ii){}
>    };
>
> int main(void)    {
>    int a=3;
>    int b=4;
>    Lattice latt(Point(a), Point(b), 3);   /* Line X */
>    Lattice l(Point(a));                           /* Line Y */
>    }
>
>
> Lattice l(Point b)    {
>    return Lattice(b, b, 0);
>    }
> ----- 8< -----
> The problem concerns the lines marked /* Line X */ and /* Line Y */,
> which are ambiguous declarations for either an object or a function.
> The clause that governs this ambiguity is 8.2/1, and reads:
>
> [dcl.ambig.res] 8.2 Ambiguity resolution
> 1 The ambiguity arising from the similarity between a function   style
> cast and a declaration mentioned in 6.8 can also occur in the context
> of a declaration. In that context, the choice is between a function
> declaration with a redundant set of parentheses around a parameter
> name and an object declaration with a function   style cast as the
> initializer. Just as for the ambiguities mentioned in 6.8, the
> resolution is to consider any construct that could possibly be a
> declaration a declaration. [Note: a declaration can be explicitly
> disambiguated by a nonfunction   style cast, by a = to indicate
> initialization or by removing the redundant parentheses around the
> parameter name. ] [Example:
>   struct S {
>     S(int);
>   };
>   void foo(double a)
>   {
>     S w(int(a));  // function declaration
>     S x(int());   // function declaration
>     S y((int)a);  // object declaration
>     S z = int(a); // object declaration
>   }
> -- end example]

Example S w (int(a)); is identical to line Y with
S==Lattice,w==l,int==Point and a==a. Thus l is a function declaration.

> Based on this clause was my interpretation (and that of my compiler)
> of the declarations in lines X and Y:
> - Both the declaration of latt and l are declarations of functions,
> wich will result in a syntax error on the constant in line X.

> Someone else came with another interpretation, also backed by his
> compiler and based on the clause above. His interpretation was:
> - The declaration of latt declares an object, because the other option
> (a function declaration) would result in a syntax error.
> - The declaration of l is a function declaration, because the
> sub-expression Point(a) can be taken as an declaration with redundant
> parentheses.

> Note that the last sentence before the [Note: is not much help,
> because both options are declarations.

Good point, it doesn't help now. I'll file a DR.
I think it applies to the parameter/expression like Point(a),
though. That can be a (parameter) declaration and an expression,
and the sentence says that Point(a) must be a (parameter)
declaration. So I'm inclined to side with your explanation.
I have to admit, though, that my first reading was just the
opposite.

Regards,
--
Michiel Salters

---
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://www.research.att.com/~austern/csc/faq.html                ]





Author: "B. van Ingen Schenau" <bvisNOSPAM@universalmail.com>
Date: Mon, 14 Jan 2002 19:55:19 GMT
Raw View
On Mon, 14 Jan 2002 17:07:05 GMT, Michiel.Salters@cmg.nl (Michiel
Salters) wrote:

>"B. van Ingen Schenau" <bvis@universalmail.com> wrote in message news:<c=
acu3u07jkrfl5ti6tk7acsvn9totn6emh@4ax.com>...
>> Hello all,
>>=20
>> During a discussion on alt.comp.lang.learn.c-c++ it was fount
>> that two different compilers get completely different results
>> from the following program.
>
>Names, please ?

The compilers in question are gcc 2.95.2 (mingw port) and comeau
(version unknown), although I don't think that it is relevant to the
question.

>
>> And our subsequent reading of the standard makes me believe that both
>> compilers are right.
>>=20
>> The program in question is:
>> ----- 8< -----
>> #include <iostream>=20
>
>> struct Point    {
>>    int j;
>>    Point(int k): j(k){}
>>    };
>>=20
>> struct Lattice     {
>>    Point p1;
>>    Point p2;
>>    int i;
>>    Lattice(Point pa1, Point pa2, int ii):p1(pa1), p2(pa2), i(ii){}
>>    };
>>=20
>> int main(void)    {
>>    int a=3D3;
>>    int b=3D4;
>>    Lattice latt(Point(a), Point(b), 3);   /* Line X */
>>    Lattice l(Point(a));                           /* Line Y */
>>    }
>>=20
>>=20
>> Lattice l(Point b)    {
>>    return Lattice(b, b, 0);
>>    }
>> ----- 8< -----
>> The problem concerns the lines marked /* Line X */ and /* Line Y */,
>> which are ambiguous declarations for either an object or a function.
>> The clause that governs this ambiguity is 8.2/1, and reads:
>>=20
>> [dcl.ambig.res] 8.2 Ambiguity resolution
>> 1 The ambiguity arising from the similarity between a function=ADstyle
>> cast and a declaration mentioned in 6.8 can also occur in the context
>> of a declaration. In that context, the choice is between a function
>> declaration with a redundant set of parentheses around a parameter
>> name and an object declaration with a function=ADstyle cast as the
>> initializer. Just as for the ambiguities mentioned in 6.8, the
>> resolution is to consider any construct that could possibly be a
>> declaration a declaration. [Note: a declaration can be explicitly
>> disambiguated by a nonfunction=ADstyle cast, by a =3D to indicate
>> initialization or by removing the redundant parentheses around the
>> parameter name. ] [Example:
>>   struct S {
>>     S(int);
>>   };
>>   void foo(double a)
>>   {
>>     S w(int(a));  // function declaration
>>     S x(int());   // function declaration
>>     S y((int)a);  // object declaration
>>     S z =3D int(a); // object declaration
>>   }
>> -- end example]
>
>Example S w (int(a)); is identical to line Y with=20
>S=3D=3DLattice,w=3D=3Dl,int=3D=3DPoint and a=3D=3Da. Thus l is a functio=
n declaration.

There is full agreement on that part.
>
>> Based on this clause was my interpretation (and that of my compiler)
>> of the declarations in lines X and Y:
>> - Both the declaration of latt and l are declarations of functions,
>> wich will result in a syntax error on the constant in line X.
>
>> Someone else came with another interpretation, also backed by his
>> compiler and based on the clause above. His interpretation was:
>> - The declaration of latt declares an object, because the other option
>> (a function declaration) would result in a syntax error.
>> - The declaration of l is a function declaration, because the
>> sub-expression Point(a) can be taken as an declaration with redundant
>> parentheses.
>
>> Note that the last sentence before the [Note: is not much help,
>> because both options are declarations.
>
>Good point, it doesn't help now. I'll file a DR.
>I think it applies to the parameter/expression like Point(a),
>though. That can be a (parameter) declaration and an expression,
>and the sentence says that Point(a) must be a (parameter)
>declaration. So I'm inclined to side with your explanation.
>I have to admit, though, that my first reading was just the
>opposite.

Well, I admit that it goes against my current interpretation of the
standard, but I think the proper resolution for this issue is, also in
view of clause 6.8, that the entire declaration should be taken into
account and if that leaves open the possibility of a function
declaration, the declaration should be regarded a function
declaration.

This resolution is consistent with the behaviour of the second
compiler (for the record: the comeau compiler) and causes, in my
opinion, the least surprises.

>
>Regards,

Bart v Ingen Schenau

---
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://www.research.att.com/~austern/csc/faq.html                ]





Author: "B. van Ingen Schenau" <bvis@universalmail.com>
Date: Fri, 11 Jan 2002 13:12:01 CST
Raw View
Hello all,

During a discussion on alt.comp.lang.learn.c-c++ it was fount that two
different compilers get completely different results from the
following program.
And our subsequent reading of the standard makes me believe that both
compilers are right.

The program in question is:
----- 8< -----
#include <iostream>
#define PRINT1(X)  (std::cout<<#X": "<<(X)<<'\n')
#define PRINT2(X, I)  (std::cout<<#I": "<<(I)<<", "#X": "<<(X)<<'\n')

struct Point
   {
   int j;
   Point(int k): j(k){}
   };

struct Lattice
   {
   Point p1;
   Point p2;
   int i;
   Lattice(Point pa1, Point pa2, int ii):p1(pa1), p2(pa2), i(ii){}
   };

int main(void)
   {
   int a=3;
   int b=4;
   Lattice latt(Point(a), Point(b), 3);   /* Line X */
   PRINT1(latt.i);
   PRINT2(latt.p1.j, latt.p2.j);
   Lattice l(Point(a));                           /* Line Y */
   PRINT1(l(a).i);
   }


Lattice l(Point b)
   {
   return Lattice(b, b, 0);
   }
----- 8< -----
The problem concerns the lines marked /* Line X */ and /* Line Y */,
which are ambiguous declarations for either an object or a function.
The clause that governs this ambiguity is 8.2/1, and reads:

[dcl.ambig.res] 8.2 Ambiguity resolution
1 The ambiguity arising from the similarity between a function   style
cast and a declaration mentioned in 6.8 can also occur in the context
of a declaration. In that context, the choice is between a function
declaration with a redundant set of parentheses around a parameter
name and an object declaration with a function   style cast as the
initializer. Just as for the ambiguities mentioned in 6.8, the
resolution is to consider any construct that could possibly be a
declaration a declaration. [Note: a declaration can be explicitly
disambiguated by a nonfunction   style cast, by a = to indicate
initialization or by removing the redundant parentheses around the
parameter name. ] [Example:
  struct S {
    S(int);
  };
  void foo(double a)
  {
    S w(int(a));  // function declaration
    S x(int());   // function declaration
    S y((int)a);  // object declaration
    S z = int(a); // object declaration
  }
-- end example]

Based on this clause was my interpretation (and that of my compiler)
of the declarations in lines X and Y:
- Both the declaration of latt and l are declarations of functions,
wich will result in a syntax error on the constant in line X.

Someone else came with another interpretation, also backed by his
compiler and based on the clause above. His interpretation was:
- The declaration of latt declares an object, because the other option
(a function declaration) would result in a syntax error.
- The declaration of l is a function declaration, because the
sub-expression Point(a) can be taken as an declaration with redundant
parentheses.

Note that the last sentence before the [Note: is not much help,
because both options are declarations.

Can someone give an indication if this is a defect or that one of the
interpretations is wrong? And if one interpretation is wrong, why?

Thanks,

Bart v Ingen Schenau

---
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://www.research.att.com/~austern/csc/faq.html                ]