Different AST translations for the same body, why?

I'd like to understand the rationale underlying the different
translation of body of foo1 and foo2.

It seems that the presence of a totally unrelated operator* change the
translation.

I don't see any benefits in doing that (as template instantiation will
do the right thing in both cases).

I'm missing something?

$ cat p.cc
template <typename T>
class Foo {
  void foo1();
  void foo2();
};

template <typename T>
void Foo<T>::foo1() { sizeof(*this); }

struct Bar;
Bar& operator*(Bar&, Bar&);

template <typename T>
void Foo<T>::foo2() { sizeof(*this); }

$ ~/llvm_trunk/Debug+Asserts/bin/clang++ -cc1 -ast-dump p.cc
p.cc:8:23: warning: expression result unused
void Foo<T>::foo1() { sizeof(*this); }
                      ^~~~~~~~~~~~~
p.cc:14:23: warning: expression result unused
void Foo<T>::foo2() { sizeof(*this); }
                      ^~~~~~~~~~~~~
typedef __int128 __int128_t;
typedef unsigned __int128 __uint128_t;
struct __va_list_tag {
    struct __va_list_tag;
    unsigned int gp_offset;
    unsigned int fp_offset;
    void *overflow_arg_area;
    void *reg_save_area;
};
typedef struct __va_list_tag __va_list_tag;
typedef __va_list_tag __builtin_va_list[1];
template <typename T> class Foo {
    class Foo;
    void foo1();
    void foo2();
};
void foo1() (CompoundStmt 0x585d0c0 <p.cc:8:21, col:38>
  (UnaryExprOrTypeTraitExpr 0x585d0a0 <col:23, col:35> 'unsigned long'
sizeof
    (ParenExpr 0x585d080 <col:29, col:35> '<dependent type>'
      (UnaryOperator 0x585d060 <col:30, col:31> '<dependent type>'
prefix '*'
        (CXXThisExpr 0x585d048 <col:31> 'Foo<T> *' this)))))

struct Bar;
Bar &operator*(Bar &, Bar &);
void foo2() (CompoundStmt 0x585f510 <p.cc:14:21, col:38>
  (UnaryExprOrTypeTraitExpr 0x585f4f0 <col:23, col:35> 'unsigned long'
sizeof
    (ParenExpr 0x585f4d0 <col:29, col:35> '<dependent type>'
      (CXXOperatorCallExpr 0x585f498 <col:30, col:31> '<dependent type>'
        (UnresolvedLookupExpr 0x585f440 <col:30> '<overloaded function

' lvalue (ADL) = '1' 0x585d310)

        (CXXThisExpr 0x585f428 <col:31> 'Foo<T> *' this)))))

2 warnings generated.

I'd like to understand the rationale underlying the different
translation of body of foo1 and foo2.

It seems that the presence of a totally unrelated operator* change the
translation.

I don't see any benefits in doing that (as template instantiation will
do the right thing in both cases).

I'm missing something?

A UnaryOperator node is more lightweight than a CXXOperatorCallExpr node. Therefore, the more heavyweight node is only created if the definition-time name lookup had any results. These results need to be stored for correct two-phase name lookup, and only CXXOperatorCallExpr can do that.

void foo1() (CompoundStmt 0x585d0c0 <p.cc:8:21, col:38>
(UnaryExprOrTypeTraitExpr 0x585d0a0 <col:23, col:35> 'unsigned long'
sizeof
   (ParenExpr 0x585d080 <col:29, col:35> '<dependent type>'
     (UnaryOperator 0x585d060 <col:30, col:31> '<dependent type>'
prefix '*'
       (CXXThisExpr 0x585d048 <col:31> 'Foo<T> *' this)))))

struct Bar;
Bar &operator*(Bar &, Bar &);
void foo2() (CompoundStmt 0x585f510 <p.cc:14:21, col:38>
(UnaryExprOrTypeTraitExpr 0x585f4f0 <col:23, col:35> 'unsigned long'
sizeof
   (ParenExpr 0x585f4d0 <col:29, col:35> '<dependent type>'
     (CXXOperatorCallExpr 0x585f498 <col:30, col:31> '<dependent type>'
       (UnresolvedLookupExpr 0x585f440 <col:30> '<overloaded function
>' lvalue (ADL) = '1' 0x585d310)
       (CXXThisExpr 0x585f428 <col:31> 'Foo<T> *' this)))))

Sebastian