[cfe-commits] [PATCH] Remove PotentiallyPotentiallyEvaluated

John McCall rjmccall at apple.com
Wed Jan 18 20:02:16 PST 2012


On Jan 18, 2012, at 7:42 PM, Eli Friedman wrote:
> On Wed, Jan 18, 2012 at 6:58 PM, John McCall <rjmccall at apple.com> wrote:
>>  struct V { virtual void foo(); };
>>  V &foo(int);
>>  struct A { int x; };
>>  void test() { (void) typeid(foo(A::x)); }
> 
> Yes, that's what CXX/expr/expr.prim/expr.prim.general/p12-0x.cpp looks like.

I had an old checkout.

>> But it's not possible to notice that it's ill-formed except by walking back
>> over the operand to typeid and retroactively complaining about the use
>> of A::x in a PE context.
> 
> Well, you can sort of assume that it's unevaluated and buffer an error
> for if the context ends up potentially-evaluated.  I actually
> committed some code that tries to do that, but I don't think it
> actually works correctly in dependent contexts.

It's really better to just do a second pass over the AST, probably as part
of your transform.

> Anyway, you can distinguish this case from member pointer formation
> easily if you have the entire expression tree available; the issue is
> that the whole tree isn't really available when we're transforming a
> DeclRefExpr inside TreeTransform.

Just teach your transform to ignore unary &s of pointer-to-member type.

>> Memo to Doug:  our example doesn't quite work.  The rule is that it's
>> a member expression if 'this' is available and it's either PE *or* the
>> context is a (non-strict) subclass of the declaring class of the field.
>> In any context where it would be potentially valid as a member
>> expression, it is one.  The problem is in other contexts, like the test
>> above, where there's an "ambiguity" between being ill-formed
>> and being an abstract member reference.  Clearly this should be
>> resolved in favor of being an abstract member reference, with
>> this extra check being required after deciding that something is
>> really PE.  Up to you whether this rises to the level of a drafting error.
> 
> The standard is completely clear; granted, it's a bit stupid that
> sizeof(A::x) is legal in some, but not all contexts.

Formally, the standard states that an expression should be rewritten
(and accordingly analyzed differently) if a predicate holds when the
value of that predicate depends on whether or not the expression is
so rewritten.  That is unsound.

I mis-stated the test case;  it should be:

  struct V { virtual void foo(); };
  V &foo(int &);
  struct A { int x; };
  struct B {
    void test() { (void) typeid(foo(A::x)); }
  };

The analysis which leads to deciding that the typeid operand is PE
relies on the assumption that the typeid operand is not PE.

John.



More information about the cfe-commits mailing list