delesley added inline comments.

================
Comment at: lib/Analysis/ThreadSafetyCommon.cpp:362
+  til::Project *P = new (Arena) til::Project(E, D);
+  if (hasCppPointerType(BE))
+    P->setArrow(true);
----------------
aaronpuchert wrote:
> rjmccall wrote:
> > aaron.ballman wrote:
> > > I feel like this will always return false. However, I wonder if 
> > > `IVRE->getBase()->isArrow()` is more appropriate here?
> > The base of an `ObjCIvarRefExpr` will never directly be a C pointer type.  
> > I don't know whether this data structure looks through casts, but it's 
> > certainly *possible* to cast arbitrarily weird C stuff to ObjC pointer 
> > type.  On the other hand, by and large nobody actually ever does that, so I 
> > wouldn't make a special case for it here.
> > 
> > `ObjCIvarRefExpr` just has an `isArrow()` method directly if this is just 
> > supposed to be capturing the difference between `.` and `->`.  But then, so 
> > does `MemberExpr`, and in that case you're doing this odd analysis of the 
> > base instead of trusting `isArrow()`, so I don't know what to tell you to 
> > do.
> > 
> > Overall it is appropriate to treat an ObjC ivar reference as a perfectly 
> > ordinary projection.  The only thing that's special about it is that the 
> > actual offset isn't necessarily statically known, but ivars still behave as 
> > if they're all independently declared, so I wouldn't worry about it.
> I had wondered about this as well, but when I changed `hasCppPointerType(BE)` 
> to `ME->isArrow()` in the `MemberExpr` case, I got some test failures. For 
> example:
> 
> ```
> struct Foo {
>   int a __attribute__((guarded_by(mu)));
>   Mutex mu;
> };
> 
> void f() {
>   Foo foo;
>   foo.a = 5; // \
>     // expected-warning{{writing variable 'a' requires holding mutex 'foo.mu' 
> exclusively}}
> }
> ```
> 
> Instead we warn `writing variable 'a' requires holding mutex 'foo->mu' 
> exclusively`. That's not right.
> 
> The expression (`ME`) we are processing is `mu` from the attribute on `a`, 
> which the compiler sees as `this->mu`. So we get `ME->isArrow() == true` and 
> `ME->getBase()` is a `CXXThisExpr`.
> 
> Basically the `translate*` functions do a substitution. They try to derive 
> `foo.mu` from `this->mu` on the `a` member and the expression `foo.a`. The 
> annotation `this->mu` is the expression we get as parameter, and `foo.a` is 
> encoded in the `CallingContext`.
> 
> The information whether `foo.a` is an arrow (it isn't) seems to be in the 
> `CallingContext`'s `SelfArrow` member.
This is a recurring problem.  The fundamental issue is the analysis must 
compare expressions for equality, but many C++ expressions are syntactically 
different but semantically the same, like  (&foo)->mu  and  foo.mu.  It's 
particularly problematic because (as Aaron notes) we frequently substitute 
arguments when constructing expressions, which makes it easy to get things like 
(&foo)->mu instead of foo.mu, when substituting &foo for a pointer argument. 

The purpose of the TIL is to translate C++ expressions into a simpler, 
lower-level IR, where syntactic equality in the IR corresponds to semantic 
equality between expressions.  The TIL doesn't distinguish between pointers and 
references, doesn't distinguish between -> and ., and ignores * and & as 
no-ops.  But then we have to recover the distinction between -> and . when we 
generate an error message.

In the presence of substitution, you can't go by whether the source syntax has 
an ->.  You have to look at whether the type of the underlying argument (after 
stripping away * and &) requires an arrow.

I know nothing about objective C, so I don't know what the right answer is here.


Repository:
  rC Clang

https://reviews.llvm.org/D52200



_______________________________________________
cfe-commits mailing list
cfe-commits@lists.llvm.org
http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to