[cfe-commits] r75314 - in /cfe/trunk: include/clang/AST/ include/clang/Analysis/PathSensitive/ lib/AST/ lib/Analysis/ lib/CodeGen/ lib/Frontend/ lib/Sema/ test/CodeGenObjC/ test/PCH/ test/SemaObjC/ test/SemaObjCXX/

steve naroff snaroff at apple.com
Mon Jul 13 13:47:24 PDT 2009


On Jul 13, 2009, at 4:18 PM, Chris Lattner wrote:
>
>>>> trunk/lib/AST/ExprConstant.cpp Fri Jul 10 18:34:53 2009
>>>> @@ -382,7 +382,8 @@
>>>>  const Expr* SubExpr = E->getSubExpr();
>>>>
>>>>   // Check for pointer->pointer cast
>>>> -  if (SubExpr->getType()->isPointerType()) {
>>>> +  if (SubExpr->getType()->isPointerType() ||
>>>> +      SubExpr->getType()->isObjCObjectPointerType()) {
>>>
>>> Would it make sense to add a "isAnyPointerType()" method to do  
>>> both these checks?
>>
>> I don't think so. It will save a few keystrokes, however I believe  
>> the above is clearer.
>
> What about block pointers?  getAsPointeeType works with blocks, are  
> there places that really want to be checking for "c pointer, objc  
> pointer, or block pointer"?  If so, it would make sense to introduce  
> a predicate for it.  To address Sebastian's concern, we would just  
> need to name the predicate right.

I'm sure there are places where block pointers should be included.

I agree that a predicate would be helpful (if we can come up with a  
clear name/semantic).

>
>>>>
>>>> +++ cfe/trunk/lib/CodeGen/CGExprScalar.cpp Fri Jul 10 18:34:53 2009
>>>> @@ -987,7 +987,7 @@
>>>> }
>>>>
>>>> Value *ScalarExprEmitter::EmitAdd(const BinOpInfo &Ops) {
>>>> -  if (!Ops.Ty->isPointerType()) {
>>>> +  if (!Ops.Ty->isPointerType() && !Ops.Ty- 
>>>> >isObjCObjectPointerType()) {
>>>
>>> Another candidate for "isAnyPointerType"?  What happens when you  
>>> add an objc pointer to an integer?
>>
>> You can't have an objc pointer to an integer (that's why I called  
>> the class ObjCObjectPointerType)....an ObjCObjectPointerType can  
>> only refer to an interface (built-in or user-defined).
>>
>> Maybe I don't understand your question.
>
> I mean something like:
>
> NSString *X;
>   X+4;
>

I see...I guess I read your response too quickly (sorry for the  
confusion).

clang allows this (for GCC compatibility). I'd have no problem  
rejecting code like this (since it is silly):

@interface XX
-self;
@end

static void func() {

   XX *x;

   [x+4 self];
}

>>> This doesn't seem like the right thing, can you check with Daniel  
>>> on this?
>>
>> Daniel suggested this solution to me (so I guess I've already  
>> checked:-)
>
> Ok.
>
>>> It seems that the objc and normal pointer type can be merged with  
>>> your new "getpointeetype" method.
>>>
>>
>> Makes sense. Note: This is an example of a cleanup that I wanted to  
>> defer (for this mega patch).
>
> Of course, no harm delaying the cleanups.
>
>>> This code looks like it is something that should be factored out  
>>> into a helper method.  Are there other pieces of code doing the  
>>> same lookup algorithm?
>>>
>>
>> Yep. I agree a helper would be nice. Since this doesn't really  
>> relate to the ObjCObjectPointerType related changes, I'll note this  
>> as a separate cleanup (the only reason in showed up in the patch is  
>> I move the code).
>
> Right, none of my comments really were meant to imply that you  
> should have included them in the original patch, they were meant for  
> follow up changes.
>
>>>> @@ -3517,6 +3523,29 @@
>>>>    return Incompatible;
>>>>  }
>>>>
>>>> +  if (isa<ObjCObjectPointerType>(lhsType)) {
>>>> +    if (rhsType->isIntegerType())
>>>> +      return IntToPointer;
>>>> +
>>>> +    if (isa<PointerType>(rhsType)) {
>>>> +      QualType lhptee = lhsType->getAsObjCObjectPointerType()- 
>>>> >getPointeeType();
>>>> +      QualType rhptee = rhsType->getAsPointerType()- 
>>>> >getPointeeType();
>>>> +      return CheckPointeeTypesForAssignment(lhptee, rhptee);
>>>
>>> Why not use lhsType->getPointeeType()  (and also for rhsType)?
>>
>> Since the routine is already doing the "isa" sniffing to determine  
>> what types we have, I didn't think it would be any clearer (or  
>> efficient).
>>
>>>
>>>
>>>> +    }
>>>> +    if (rhsType->isObjCObjectPointerType()) {
>>>> +      QualType lhptee = lhsType->getAsObjCObjectPointerType()- 
>>>> >getPointeeType();
>>>> +      QualType rhptee = rhsType->getAsObjCObjectPointerType()- 
>>>> >getPointeeType();
>>>> +      return CheckPointeeTypesForAssignment(lhptee, rhptee);
>>>
>>> That would allow merging this case in as well.
>>
>> Same response as above.
>
> The point of using the predicate is that it allows merging of these  
> two if blocks.
>
>>>> @@ -3776,12 +3823,23 @@
>>>>
>>>>  // Put any potential pointer into PExp
>>>>  Expr* PExp = lex, *IExp = rex;
>>>> -  if (IExp->getType()->isPointerType())
>>>> +  if (IExp->getType()->isPointerType() ||
>>>> +      IExp->getType()->isObjCObjectPointerType())
>>>
>>> ->isAnyPointerType()
>>
>> As a said earlier, I'm not convinced adding another predicate would  
>> make the code clearer (though it would definitely make it more  
>> terse).
>>
>> Maybe a better name would sway my opinion. isCOrObjCPointer() is  
>> more descriptive, however one of the uglier names I've ever seen:-)
>
> Sure, a better name than "isAnyPointerType" is definitely  
> appreciated, but I think it is useful to consider it.  There is a  
> bunch of code that uses this predicate now.
>

Agreed...will consider.

>>>>    if (IExp->getType()->isIntegerType()) {
>>>> -      QualType PointeeTy = PTy->getPointeeType();
>>>> +      QualType PointeeTy;
>>>> +      const PointerType *PTy;
>>>> +      const ObjCObjectPointerType *OPT;
>>>> +
>>>> +      if ((PTy = PExp->getType()->getAsPointerType()))
>>>> +        PointeeTy = PTy->getPointeeType();
>>>> +      else if ((OPT = PExp->getType()- 
>>>> >getAsObjCObjectPointerType()))
>>>> +        PointeeTy = OPT->getPointeeType();
>>>
>>> This should be able to use QualType::getPointeeType() instead of  
>>> the if/elseif
>>
>> This isn't possible without more code reorganization (I already  
>> tried it). The code that follows is interested in both PTy and OPT  
>> (not only the pointee type).
>
> Ok, I completely missed that.  This is really subtle, why not set  
> "PointeeTy" with a call to the getPointeeType() method, and then  
> change the places that look at PTy/OPT to query the original type  
> directly?  I think the code would be more clear that way.

I agree. Will do.

>
>>>> +++ cfe/trunk/test/CodeGenObjC/encode-test.m Fri Jul 10 18:34:53  
>>>> 2009
>>>> @@ -1,7 +1,7 @@
>>>> // RUN: clang-cc -triple=i686-apple-darwin9 -fnext-runtime -emit- 
>>>> llvm -o %t %s &&
>>>> // RUN: grep -e "\^{Innermost=CC}" %t | count 1 &&
>>>> -// RUN: grep -e "{Derived=#ib32b8b3b8sb16b8b8b2b8ccb6}" %t |  
>>>> count 1 &&
>>>> -// RUN: grep -e "{B1=#@c}" %t | count 1 &&
>>>> +// RUN: grep -e  
>>>> "{Derived=^{objc_class}ib32b8b3b8sb16b8b8b2b8ccb6}" %t | count 1 &&
>>>> +// RUN: grep -e "{B1=^{objc_class}@c}" %t | count 1 &&
>>>> // RUN: grep -e "v12 at 0:4\[3\[4@]]8" %t | count 1 &&
>>>> // RUN: grep -e "r\^{S=i}" %t | count 1 &&
>>>> // RUN: grep -e "\^{Object=#}" %t | count 1
>>>
>>> The output of @encode changed?  Isn't this an ABI bug??
>>
>> This following two issues are a result of moving away from the C- 
>> structure dependency (which is a hack). More info...
>>
>> We no longer treat "struct objc_class *" as synonymous with  
>> "Class". This is a side-effect of removing  
>> "ASTContext::isObjCClassStructType(T)".
>>
>> @interface B1
>> {
>>     struct objc_class *isa;
>>     Int1 *sBase;
>>     char c;
>> }
>> @end
>>
>> Since it does effect GCC binary compatibility, we could certainly  
>> add back a hack to make them synonymous.
>
> I think that we should do this for @encode and C++ mangling.   
> Compatibility is very important at this level because it isn't a  
> matter of the compiler rejecting or producing a warning, it is a  
> silent miscompilation.
>

O.K...will reintroduce a hack to treat "struct objc_object" and  
"struct objc_class" specially. Oh well:-)

>>>
>>>> +++ cfe/trunk/test/CodeGenObjC/overloadable.m Fri Jul 10 18:34:53  
>>>> 2009
>>>> @@ -3,8 +3,8 @@
>>>>
>>>> @class C;
>>>>
>>>> -// RUN: grep _Z1fP11objc_object %t | count 1 &&
>>>> -void __attribute__((overloadable)) f(C *c) { }
>>>> +// RUN: grep _Z1fP2id %t | count 1 &&
>>>> +void __attribute__((overloadable)) f(id c) { }
>>>>
>>>> // RUN: grep _Z1fP1C %t | count 1
>>>> -void __attribute__((overloadable)) f(id c) { }
>>>> +void __attribute__((overloadable)) f(C *c) { }
>>>
>>> Likewise, mangling changing sounds like a serious ABI bug.
>>
>> Same issue as above (but with ASTContext::isObjCIdStructType()). We  
>> now mangle "id" as "id" (not the underlying structure).
>>
>> Since it does effect GCC binary compatibility, we could certainly  
>> add back a hack to make them synonymous.
>
> Ok, please do.
>
>>>> +++ cfe/trunk/test/SemaObjC/comptypes-5.m Fri Jul 10 18:34:53 2009
>>>> @@ -26,8 +26,8 @@
>>>>  MyOtherClass<MyProtocol> *obj_c_super_p_q = nil;
>>>>  MyClass<MyProtocol> *obj_c_cat_p_q = nil;
>>>>
>>>> -  obj_c_cat_p = obj_id_p;   // expected-warning {{incompatible  
>>>> type assigning 'id<MyProtocol>', expected 'MyClass *'}}
>>>> -  obj_c_super_p = obj_id_p;  // expected-warning {{incompatible  
>>>> type assigning 'id<MyProtocol>', expected 'MyOtherClass *'}}
>>>> +  obj_c_cat_p = obj_id_p;
>>>> +  obj_c_super_p = obj_id_p;
>>>
>>> Is this supposed to be allowed?
>>
>> GCC warns...
>>
>> test/SemaObjC/comptypes-5.m:29: warning: assignment from distinct  
>> Objective-C type
>> test/SemaObjC/comptypes-5.m:30: warning: assignment from distinct  
>> Objective-C type
>>
>> I decided to allow it. Rationale: Both MyClass and MyOtherClass  
>> implement MyProtocol. Since the protocols "match", and you can  
>> assign any 'id' to an interface type (without warning), I decided  
>> to allow it. I'm happy to put back the warning if others feel  
>> strongly (Fariborz?).
>
> I'll let Fariborz make this call.
>
>>>>
>>>> +++ cfe/trunk/test/SemaObjC/message.m Fri Jul 10 18:34:53 2009
>>>> @@ -95,6 +95,6 @@
>>>> void foo4() {
>>>>  struct objc_object X[10];
>>>>
>>>> -  [X rect];
>>>> +  [(id)X rect];
>>>> }
>>>
>>> This is a bug, we should be performing unary "array -> pointer"  
>>> decay here.  This was in response to a bugzilla, we need to  
>>> support this.
>>
>> I don't see the issue here. Both GCC and clang warn if no cast is  
>> used.
>>
>> [steve-naroffs-imac-3:~/llvm/tools/clang] snaroff% cc -c xx.m
>> xx.m: In function ‘foo4’:
>> xx.m:29: warning: invalid receiver type ‘objc_object [10]’
>>
>> [steve-naroffs-imac-3:~/llvm/tools/clang] snaroff% ../../Debug/bin/ 
>> clang -c xx.m
>> xx.m:29:3: warning: receiver type 'struct objc_object *' is not  
>> 'id' or interface pointer, consider casting it to 'id'
>>   [X rect];
>>   ^~
>> xx.m:29:3: warning: method '-rect' not found (return type defaults  
>> to 'id')
>>   [X rect];
>>   ^~~~~~~~
>> 2 diagnostics generated.
>
> Ok, then please fix to test by adding an 'expected-warning' instead  
> of inserting the explicit cast.  The intent of the test is to verify  
> that passing an array as the receiver works.
>

Will do.

>>
>>>
>>>
>>>> +++ cfe/trunk/test/SemaObjCXX/overload.mm Fri Jul 10 18:34:53 2009
>>>> @@ -1,4 +1,5 @@
>>>> // RUN: clang-cc -fsyntax-only -verify %s
>>>> +// XFAIL
>>>> @interface Foo
>>>> @end
>>>
>>> What is the problem with this test?
>>
>> There were several problems (mostly related in incomplete handling  
>> of ObjC types in the C++ infrastructure). I discussed this with  
>> Doug and we decided to add the XFAIL.
>
> Ok, works for me.
>
>>> Thanks again for working on this Steve!  I know it's largely  
>>> thankless, but it's a huge cleanup.
>>
>> I appreciate the encouragement. I think this kind of hygiene is  
>> quite important. Kind of like getting my teeth cleaned:-)
>
> :)
>
> -Chris

-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.llvm.org/pipermail/cfe-commits/attachments/20090713/59688f71/attachment.html>


More information about the cfe-commits mailing list