[cfe-dev] Doubt about AST

Douglas Gregor dgregor at apple.com
Thu Jun 17 08:39:54 PDT 2010


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





More information about the cfe-dev mailing list