Doubt about AST

classic Classic list List threaded Threaded
3 messages Options
Reply | Threaded
Open this post in threaded view
|

Doubt about AST

Abramo Bagnara-2
$ cat y1.cc
template <typename T>
struct S {
  int operator=(int v);
  int f() {
    return *this = 2;
  }
};

$ ~/llvm/Debug/bin/clang -cc1 -ast-dump y1.cc
typedef char *__builtin_va_list;
template <typename T> struct S {
    struct S;
    int operator=(int v);
    int f() (CompoundStmt 0xa839ed0 <y1.cc:4:11, line:6:3>
  (ReturnStmt 0xa839eb8 <line:5:5, col:20>
    (BinaryOperator 0xa839e90 <col:12, col:20> '<dependent type>' '='
      (CXXOperatorCallExpr 0xa839e40 <col:12, col:13> '<dependent type>'
        (UnresolvedLookupExpr 0xa839e08 <col:12> '<dependent type>'
(ADL) = '1' empty)
        (CXXThisExpr 0xa839de8 <col:13> 'S<T> *' this))
      (IntegerLiteral 0xa839e68 <col:20> 'int' 2))))


};

I'd like to understand why *this is converted in CXXOperatorCallExpr of
UnresolvedLookupExpr instead of UnaryOperator deref.

The deref operator for this might be overloaded? How?

I'd like also to understand in which situations clang choose to emit
something like BinaryOperator (then instantiated in operator call) and
when choose to emit an operator call also on primary template (of course
when both choices might be done).
_______________________________________________
cfe-dev mailing list
[hidden email]
http://lists.cs.uiuc.edu/mailman/listinfo/cfe-dev
Reply | Threaded
Open this post in threaded view
|

Re: Doubt about AST

Douglas Gregor

On Jun 17, 2010, at 4:43 AM, Abramo Bagnara wrote:

> $ cat y1.cc
> template <typename T>
> struct S {
>  int operator=(int v);
>  int f() {
>    return *this = 2;
>  }
> };
>
> $ ~/llvm/Debug/bin/clang -cc1 -ast-dump y1.cc
> typedef char *__builtin_va_list;
> template <typename T> struct S {
>    struct S;
>    int operator=(int v);
>    int f() (CompoundStmt 0xa839ed0 <y1.cc:4:11, line:6:3>
>  (ReturnStmt 0xa839eb8 <line:5:5, col:20>
>    (BinaryOperator 0xa839e90 <col:12, col:20> '<dependent type>' '='
>      (CXXOperatorCallExpr 0xa839e40 <col:12, col:13> '<dependent type>'
>        (UnresolvedLookupExpr 0xa839e08 <col:12> '<dependent type>'
> (ADL) = '1' empty)
>        (CXXThisExpr 0xa839de8 <col:13> 'S<T> *' this))
>      (IntegerLiteral 0xa839e68 <col:20> 'int' 2))))
>
>
> };
>
> I'd like to understand why *this is converted in CXXOperatorCallExpr of
> UnresolvedLookupExpr instead of UnaryOperator deref.
>
> The deref operator for this might be overloaded? How?

Clang is seeing that the type of 'this' is dependent, so it uses the general type-dependent representation of a dereference operation, which is the CXXOperatorCallExpr you see there. We could perform a little more analysis to determine that it has pointer type and, therefore, actually build a UnaryOperator... but I don't know that it would make a big difference. Maybe it would matter for something like

  (*this).getAs<T>()

because we'd actually know the type of *this.

> I'd like also to understand in which situations clang choose to emit
> something like BinaryOperator (then instantiated in operator call) and
> when choose to emit an operator call also on primary template (of course
> when both choices might be done).

In non-dependent cases, BinaryOperator is for builtin types and CXXOperatorCallExpr is for uses of overloaded operators.

In dependent cases, we use CXXOperatorCallExpr when name lookup has found overloaded operators in the current scope, because we need to save those overloaded operators until instantiation time. (These are results from the first "phase" of two-phase name lookup). If no overloaded operators were found, we use BinaryOperator instead.

UnaryOperator should be doing the same thing here... so yes, there's a bug here :)

        - Doug


_______________________________________________
cfe-dev mailing list
[hidden email]
http://lists.cs.uiuc.edu/mailman/listinfo/cfe-dev
Reply | Threaded
Open this post in threaded view
|

Re: Doubt about AST

Douglas Gregor

On Jun 17, 2010, at 8:39 AM, Douglas Gregor wrote:

>
> On Jun 17, 2010, at 4:43 AM, Abramo Bagnara wrote:
>
>> I'd like also to understand in which situations clang choose to emit
>> something like BinaryOperator (then instantiated in operator call) and
>> when choose to emit an operator call also on primary template (of course
>> when both choices might be done).
>
> In non-dependent cases, BinaryOperator is for builtin types and CXXOperatorCallExpr is for uses of overloaded operators.
>
> In dependent cases, we use CXXOperatorCallExpr when name lookup has found overloaded operators in the current scope, because we need to save those overloaded operators until instantiation time. (These are results from the first "phase" of two-phase name lookup). If no overloaded operators were found, we use BinaryOperator instead.
>
> UnaryOperator should be doing the same thing here... so yes, there's a bug here :)

Fixed in r106222.

I didn't try to teach Clang about the return type of *this when 'this' is dependent. It's not clear that we're actually allowed by the standard to do such a thing.

        - Doug
_______________________________________________
cfe-dev mailing list
[hidden email]
http://lists.cs.uiuc.edu/mailman/listinfo/cfe-dev