[cfe-dev] fix for Clang PR 8419

Zhanyong Wan (λx.x x) wan at google.com
Thu Nov 18 20:22:14 PST 2010


On Thu, Nov 18, 2010 at 4:17 PM, Zhanyong Wan (λx.x x) <wan at google.com> wrote:
> On Thu, Nov 18, 2010 at 3:31 PM, Zhanyong Wan (λx.x x) <wan at google.com> wrote:
>> I'm not sure this is the case.  Given code:
>>
>> class Foo {
>>  public:
>>  char& get() const;
>> };
>>
>> char& get();
>>
>> void Test() {
>>  Foo foo;
>>  foo.get()++;
>>  get()++;  // Crashes.
>> }
>>
>> 'clang --analyze' has no trouble with "foo.get()++" but crashes on
>> "get()++", so the culprit seems to be in how CallExpr (as opposed to
>> CXXMethodCallExpr) is handled.
>>
>> While debugging this, I saw one thing that I don't understand:
>>
>> GRExprEngine::ProcessStmt() calls Visit() as opposed to VisitLValue()
>> when processing the "foo.get()" subexpression of "foo.get()++".
>>  Is this right or a bug?  My understanding is that "foo.get()" is an
>> L-value and thus should be handled by VisitLValue() -- what am I
>> missing?  Thanks,
>
> Now I see that ProcessStmt() actually processes "foo.get()" twice.
> The first time it's treated as a top-level expression, and Visit() is
> used.  (That's what I talked about in my previous message.)  The
> second time it's treated as a sub-expression of "foo.get()++", and
> VisitLValue() is used (more precisely, Visit("foo.get()++) is called,
> which then calls VisitLValue("foo.get()")).  This makes more sense
> now.  Though it's still unclear to me why the first time is needed.

Here's my theory of why "foo.get()" is processed before "foo.get()++":

The static analyzer executes the code symbolically by following the
control flow.  When

  foo.get()++;

is executed, first "foo.get()" needs to be evaluated, as dictated by
C++'s semantics.  Hence ProcessStmt() processes "foo.get()" first.
Next, "++" is done on the result of "foo.get()".  This causes
ProcessStmt() to process "foo.get()++" as a whole.  Even though the
call Visit("foo.get()++") looks to me like it's simulating the
execution of the entire "foo.get()++" expression, it actually only
simulates the "top-level" part of it -- that is, "x++" where "x" is
the result of "foo.get()".

Is my understanding correct?  Thanks,

-- 
Zhanyong




More information about the cfe-dev mailing list