[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/

Fariborz Jahanian fjahanian at apple.com
Mon Jul 13 10:19:22 PDT 2009


Hi Steve,

I don't have much to add to Chris's detailed comments. Here are a few.

On Jul 10, 2009, at 4:35 PM, Steve Naroff wrote:

> urn a ObjCObjectPointerType type for the
>   /// given interface decl and the conforming protocol list.
> -  QualType getObjCObjectPointerType(ObjCInterfaceDecl *Decl,
> +  QualType getObjCObjectPointerType(QualType OIT = QualType(),
>                                     ObjCProtocolDecl **ProtocolList  
> = 0,
>                                     unsigned NumProtocols = 0);

No need to have default for OIT.

>
> +QualType Type::getPointeeType() const {
> +  if (const PointerType *PT = getAsPointerType())
> +    return PT->getPointeeType();
> +  if (const ObjCObjectPointerType *OPT =  
> getAsObjCObjectPointerType())
> +    return OPT->getPointeeType();
> +  if (const BlockPointerType *BPT = getAsBlockPointerType())
> +    return BPT->getPointeeType();
> +  return QualType();
> +}

If ObjCObjectPointerType is for an 'id' or 'Class' what will the  
PointeeType be for these two?

>
>
> const PointerType *Type::getAsPointerType() const {
>   // If this is directly a pointer type, return it.
> @@ -609,6 +621,14 @@
>   return 0;
> }
>
> +const ObjCObjectPointerType *Type::getAsObjCInterfacePointerType()  
> const {
> +  if (const ObjCObjectPointerType *OPT =  
> getAsObjCObjectPointerType()) {
> +    if (OPT->getInterfaceType())
> +      return OPT;
> +  }
> +  return 0;
> +}
> +
> const TemplateTypeParmType *Type::getAsTemplateTypeParmType() const {
>   // There is no sugar for template type parameters, so just return
>   // the canonical type pointer if it is the right class.
> @@ -1016,16 +1036,18 @@
> }
>
> void ObjCObjectPointerType::Profile(llvm::FoldingSetNodeID &ID,
> -                                    const ObjCInterfaceDecl *Decl,
> -                                    ObjCProtocolDecl **protocols,
> +                                    QualType OIT, ObjCProtocolDecl  
> **protocols,
>                                     unsigned NumProtocols) {
> -  ID.AddPointer(Decl);
> +  ID.AddPointer(OIT.getAsOpaquePtr());
>   for (unsigned i = 0; i != NumProtocols; i++)
>     ID.AddPointer(protocols[i]);
> }
>
> void ObjCObjectPointerType::Profile(llvm::FoldingSetNodeID &ID) {
> -  Profile(ID, getDecl(), &Protocols[0], getNumProtocols());
> +  if (getNumProtocols())
> +    Profile(ID, getPointeeType(), &Protocols[0], getNumProtocols());
> +  else
> +    Profile(ID, getPointeeType(), 0, 0);
> }
>
> void ObjCQualifiedInterfaceType::Profile(llvm::FoldingSetNodeID &ID,
> @@ -1663,6 +1685,14 @@
>     InnerString = MyString + ' ' + InnerString;
> }
>
> +bool ObjCInterfaceType::isObjCIdInterface() const {
> +  return this == ObjCObjectPointerType::getIdInterface();
> +}
> +
> +bool ObjCInterfaceType::isObjCClassInterface() const {
> +  return this == ObjCObjectPointerType::getClassInterface();
> +}
> +
> void ObjCInterfaceType::getAsStringInternal(std::string  
> &InnerString, const PrintingPolicy &Policy) const {
>   if (!InnerString.empty())    // Prefix the basic type, e.g.  
> 'typedefname X'.
>     InnerString = ' ' + InnerString;
> @@ -1671,15 +1701,7 @@
>
> void ObjCObjectPointerType::getAsStringInternal(std::string  
> &InnerString,
>                                                 const PrintingPolicy  
> &Policy) const {
> -  if (!InnerString.empty())    // Prefix the basic type, e.g.  
> 'typedefname X'.
> -    InnerString = ' ' + InnerString;
> -
> -  std::string ObjCQIString;
> -
> -  if (getDecl())
> -    ObjCQIString = getDecl()->getNameAsString();
> -  else
> -    ObjCQIString = "id";
> +  std::string ObjCQIString = getInterfaceType()->getDecl()- 
> >getNameAsString();
>
>   if (!qual_empty()) {
>     ObjCQIString += '<';
> @@ -1690,6 +1712,11 @@
>     }
>     ObjCQIString += '>';
>   }
> +  if (!isObjCIdType() && !isObjCQualifiedIdType())
> +    ObjCQIString += " *"; // Don't forget the implicit pointer.
> +  else if (!InnerString.empty()) // Prefix the basic type, e.g.  
> 'typedefname X'.
> +    InnerString = ' ' + InnerString;
> +
>   InnerString = ObjCQIString + InnerString;
> }
>
>
> Modified: cfe/trunk/lib/Analysis/BasicObjCFoundationChecks.cpp
> URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Analysis/BasicObjCFoundationChecks.cpp?rev=75314&r1=75313&r2=75314&view=diff
>
> = 
> = 
> = 
> = 
> = 
> = 
> = 
> = 
> ======================================================================
> --- cfe/trunk/lib/Analysis/BasicObjCFoundationChecks.cpp (original)
> +++ cfe/trunk/lib/Analysis/BasicObjCFoundationChecks.cpp Fri Jul 10  
> 18:34:53 2009
> @@ -31,26 +31,21 @@
>
> using namespace clang;
>
> -static ObjCInterfaceType* GetReceiverType(ObjCMessageExpr* ME) {
> -  Expr* Receiver = ME->getReceiver();
> +static const ObjCInterfaceType* GetReceiverType(const  
> ObjCMessageExpr* ME) {
> +  const Expr* Receiver = ME->getReceiver();
>
>   if (!Receiver)
>     return NULL;
>
> -  QualType X = Receiver->getType();
> -
> -  if (X->isPointerType()) {
> -    Type* TP = X.getTypePtr();
> -    const PointerType* T = TP->getAsPointerType();
> -    return dyn_cast<ObjCInterfaceType>(T- 
> >getPointeeType().getTypePtr());
> -  }
> +  if (const ObjCObjectPointerType *PT =
> +      Receiver->getType()->getAsObjCObjectPointerType())
> +    return PT->getInterfaceType();
>
> -  // FIXME: Support ObjCQualifiedIdType?
>   return NULL;
> }
>
> -static const char* GetReceiverNameType(ObjCMessageExpr* ME) {
> -  ObjCInterfaceType* ReceiverType = GetReceiverType(ME);
> +static const char* GetReceiverNameType(const ObjCMessageExpr* ME) {
> +  const ObjCInterfaceType *ReceiverType = GetReceiverType(ME);
>   return ReceiverType ? ReceiverType->getDecl()->getIdentifier()- 
> >getName()
>                       : NULL;
> }
> @@ -67,7 +62,7 @@
>   BugReporter& BR;
>   ASTContext &Ctx;
>
> -  bool isNSString(ObjCInterfaceType* T, const char* suffix);
> +  bool isNSString(const ObjCInterfaceType *T, const char* suffix);
>   bool AuditNSString(NodeTy* N, ObjCMessageExpr* ME);
>
>   void Warn(NodeTy* N, Expr* E, const std::string& s);
> @@ -114,7 +109,7 @@
>   ObjCMessageExpr* ME =
>     cast<ObjCMessageExpr>(cast<PostStmt>(N->getLocation()).getStmt());
>
> -  ObjCInterfaceType* ReceiverType = GetReceiverType(ME);
> +  const ObjCInterfaceType *ReceiverType = GetReceiverType(ME);
>
>   if (!ReceiverType)
>     return false;
> @@ -129,8 +124,7 @@
>
>   name += 2;
>
> -  // FIXME: Make all of this faster.
> -
> +  // FIXME: Make all of this faster.
>   if (isNSString(ReceiverType, name))
>     return AuditNSString(N, ME);
>
> @@ -163,9 +157,8 @@
> // NSString checking.
> // 
> = 
> = 
> = 
> ----------------------------------------------------------------------= 
> ==//
>
> -bool BasicObjCFoundationChecks::isNSString(ObjCInterfaceType* T,
> -                                           const char* suffix) {
> -
> +bool BasicObjCFoundationChecks::isNSString(const ObjCInterfaceType  
> *T,
> +                                           const char* suffix) {
>   return !strcmp("String", suffix) || !strcmp("MutableString",  
> suffix);
> }
>
>
> Modified: cfe/trunk/lib/Analysis/CFRefCount.cpp
> URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Analysis/CFRefCount.cpp?rev=75314&r1=75313&r2=75314&view=diff
>
> = 
> = 
> = 
> = 
> = 
> = 
> = 
> = 
> ======================================================================
> --- cfe/trunk/lib/Analysis/CFRefCount.cpp (original)
> +++ cfe/trunk/lib/Analysis/CFRefCount.cpp Fri Jul 10 18:34:53 2009
> @@ -547,14 +547,12 @@
>     return I == M.end() ? M.find(ObjCSummaryKey(S)) : I;
>   }
>
> -  ObjCInterfaceDecl* getReceiverDecl(Expr* E) {
> -
> -    const PointerType* PT = E->getType()->getAsPointerType();
> -    if (!PT) return 0;
> -
> -    ObjCInterfaceType* OI = dyn_cast<ObjCInterfaceType>(PT- 
> >getPointeeType());
> -
> -    return OI ? OI->getDecl() : 0;
> +  const ObjCInterfaceDecl* getReceiverDecl(Expr* E) {
> +    if (const ObjCObjectPointerType* PT =
> +        E->getType()->getAsObjCObjectPointerType())
> +      return PT->getInterfaceDecl();
> +
> +    return NULL;
>   }
>
>   iterator end() { return M.end(); }
> @@ -564,7 +562,7 @@
>     Selector S = ME->getSelector();
>
>     if (Expr* Receiver = ME->getReceiver()) {
> -      ObjCInterfaceDecl* OD = getReceiverDecl(Receiver);
> +      const ObjCInterfaceDecl* OD = getReceiverDecl(Receiver);
>       return OD ? M[ObjCSummaryKey(OD->getIdentifier(), S)] : M[S];
>     }
>
> @@ -886,20 +884,20 @@
>   if (!Ctx.isObjCObjectPointerType(Ty))
>     return false;
>
> -  // We assume that id<..>, id, and "Class" all represent tracked  
> objects.
> -  const PointerType *PT = Ty->getAsPointerType();
> -  if (PT == 0)
> +  const ObjCObjectPointerType *PT = Ty->getAsObjCObjectPointerType();
> +
> +  // Can be true for objects with the 'NSObject' attribute.
> +  if (!PT)
>     return true;
> -
> -  const ObjCInterfaceType *OT = PT->getPointeeType()- 
> >getAsObjCInterfaceType();
> -
> +
>   // We assume that id<..>, id, and "Class" all represent tracked  
> objects.
> -  if (!OT)
> +  if (PT->isObjCIdType() || PT->isObjCQualifiedIdType() ||
> +      PT->isObjCClassType())
>     return true;
> -
> +
>   // Does the interface subclass NSObject?
>   // FIXME: We can memoize here if this gets too expensive.
> -  ObjCInterfaceDecl* ID = OT->getDecl();
> +  const ObjCInterfaceDecl *ID = PT->getInterfaceDecl();
>
>   // Assume that anything declared with a forward declaration and no
>   // @interface subclasses NSObject.
> @@ -908,7 +906,6 @@
>
>   IdentifierInfo* NSObjectII = &Ctx.Idents.get("NSObject");
>
> -
>   for ( ; ID ; ID = ID->getSuperClass())
>     if (ID->getIdentifier() == NSObjectII)
>       return true;
> @@ -977,7 +974,7 @@
>       case 17:
>         // Handle: id NSMakeCollectable(CFTypeRef)
>         if (!memcmp(FName, "NSMakeCollectable", 17)) {
> -          S = (RetTy == Ctx.getObjCIdType())
> +          S = (RetTy->isObjCIdType())
>               ? getUnarySummary(FT, cfmakecollectable)
>               : getPersistentStopSummary();
>         }
> @@ -2726,34 +2723,26 @@
> ///  While the the return type can be queried directly from RetEx,  
> when
> ///  invoking class methods we augment to the return type to be that  
> of
> ///  a pointer to the class (as opposed it just being id).
> -static QualType GetReturnType(Expr* RetE, ASTContext& Ctx) {
> -
> +static QualType GetReturnType(const Expr* RetE, ASTContext& Ctx) {
>   QualType RetTy = RetE->getType();
> -
> -  // FIXME: We aren't handling id<...>.
> -  const PointerType* PT = RetTy->getAsPointerType();
> -  if (!PT)
> -    return RetTy;
> -
> -  // If RetEx is not a message expression just return its type.
> -  // If RetEx is a message expression, return its types if it is  
> something
> +  // If RetE is not a message expression just return its type.
> +  // If RetE is a message expression, return its types if it is  
> something
>   /// more specific than id.
> +  if (const ObjCMessageExpr *ME = dyn_cast<ObjCMessageExpr>(RetE))
> +    if (const ObjCObjectPointerType *PT = RetTy- 
> >getAsObjCObjectPointerType())
> +      if (PT->isObjCQualifiedIdType() || PT->isObjCIdType() ||
> +          PT->isObjCClassType()) {
> +        // At this point we know the return type of the message  
> expression is
> +        // id, id<...>, or Class. If we have an ObjCInterfaceDecl,  
> we know this
> +        // is a call to a class method whose type we can resolve.   
> In such
> +        // cases, promote the return type to XXX* (where XXX is the  
> class).
> +        const ObjCInterfaceDecl *D = ME->getClassInfo().first;
> +        return !D ? RetTy :  
> Ctx.getPointerType(Ctx.getObjCInterfaceType(D));
> +      }
>
> -  ObjCMessageExpr* ME = dyn_cast<ObjCMessageExpr>(RetE);
> -
> -  if (!ME || !Ctx.isObjCIdStructType(PT->getPointeeType()))
> -    return RetTy;
> -
> -  ObjCInterfaceDecl* D = ME->getClassInfo().first;
> -
> -  // At this point we know the return type of the message  
> expression is id.
> -  // If we have an ObjCInterceDecl, we know this is a call to a  
> class method
> -  // whose type we can resolve.  In such cases, promote the return  
> type to
> -  // Class*.
> -  return !D ? RetTy :  
> Ctx.getPointerType(Ctx.getObjCInterfaceType(D));
> +  return RetTy;
> }
>
> -
> void CFRefCount::EvalSummary(ExplodedNodeSet<GRState>& Dst,
>                              GRExprEngine& Eng,
>                              GRStmtNodeBuilder<GRState>& Builder,
> @@ -3009,26 +2998,21 @@
>     SVal V = St->getSValAsScalarOrLoc(Receiver);
>
>     SymbolRef Sym = V.getAsLocSymbol();
> +
>     if (Sym) {
>       if (const RefVal* T  = St->get<RefBindings>(Sym)) {
> -        QualType Ty = T->getType();
> -
> -        if (const PointerType* PT = Ty->getAsPointerType()) {
> -          QualType PointeeTy = PT->getPointeeType();
> -
> -          if (ObjCInterfaceType* IT =  
> dyn_cast<ObjCInterfaceType>(PointeeTy))
> -            ID = IT->getDecl();
> -        }
> +        if (const ObjCObjectPointerType* PT =
> +            T->getType()->getAsObjCObjectPointerType())
> +          ID = PT->getInterfaceDecl();
>       }
>     }
>
>     // FIXME: this is a hack.  This may or may not be the actual  
> method
>     //  that is called.
>     if (!ID) {
> -      if (const PointerType *PT = Receiver->getType()- 
> >getAsPointerType())
> -        if (const ObjCInterfaceType *p =
> -            PT->getPointeeType()->getAsObjCInterfaceType())
> -          ID = p->getDecl();
> +      if (const ObjCObjectPointerType *PT =
> +          Receiver->getType()->getAsObjCObjectPointerType())
> +        ID = PT->getInterfaceDecl();
>     }
>
>     // FIXME: The receiver could be a reference to a class, meaning  
> that
>
> Modified: cfe/trunk/lib/Analysis/CheckNSError.cpp
> URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Analysis/CheckNSError.cpp?rev=75314&r1=75313&r2=75314&view=diff
>
> = 
> = 
> = 
> = 
> = 
> = 
> = 
> = 
> ======================================================================
> --- cfe/trunk/lib/Analysis/CheckNSError.cpp (original)
> +++ cfe/trunk/lib/Analysis/CheckNSError.cpp Fri Jul 10 18:34:53 2009
> @@ -162,16 +162,22 @@
> bool NSErrorCheck::CheckNSErrorArgument(QualType ArgTy) {
>
>   const PointerType* PPT = ArgTy->getAsPointerType();
> -  if (!PPT) return false;
> +  if (!PPT)
> +    return false;
> +
> +  const ObjCObjectPointerType* PT =
> +    PPT->getPointeeType()->getAsObjCObjectPointerType();
> +
> +  if (!PT)
> +    return false;
>
> -  const PointerType* PT = PPT->getPointeeType()->getAsPointerType();
> -  if (!PT) return false;
> +  const ObjCInterfaceDecl *ID = PT->getInterfaceDecl();
>
> -  const ObjCInterfaceType *IT =
> -  PT->getPointeeType()->getAsObjCInterfaceType();
> +  // FIXME: Can ID ever be NULL?
> +  if (ID)
> +    return II == ID->getIdentifier();
>
> -  if (!IT) return false;
> -  return IT->getDecl()->getIdentifier() == II;
> +  return false;
> }
>
> bool NSErrorCheck::CheckCFErrorArgument(QualType ArgTy) {
>
> Modified: cfe/trunk/lib/Analysis/CheckObjCInstMethSignature.cpp
> URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Analysis/CheckObjCInstMethSignature.cpp?rev=75314&r1=75313&r2=75314&view=diff
>
> = 
> = 
> = 
> = 
> = 
> = 
> = 
> = 
> ======================================================================
> --- cfe/trunk/lib/Analysis/CheckObjCInstMethSignature.cpp (original)
> +++ cfe/trunk/lib/Analysis/CheckObjCInstMethSignature.cpp Fri Jul 10  
> 18:34:53 2009
> @@ -30,8 +30,8 @@
>
>   // Right now don't compare the compatibility of pointers.  That  
> involves
>   // looking at subtyping relationships.  FIXME: Future patch.
> -  if ((Derived->isPointerType() || Derived- 
> >isObjCQualifiedIdType())  &&
> -      (Ancestor->isPointerType() || Ancestor- 
> >isObjCQualifiedIdType()))
> +  if ((Derived->isPointerType() || Derived- 
> >isObjCObjectPointerType())  &&
> +      (Ancestor->isPointerType() || Ancestor- 
> >isObjCObjectPointerType()))
>     return true;
>
>   return C.typesAreCompatible(Derived, Ancestor);
>
> Modified: cfe/trunk/lib/CodeGen/CGDebugInfo.cpp
> URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/CGDebugInfo.cpp?rev=75314&r1=75313&r2=75314&view=diff
>
> = 
> = 
> = 
> = 
> = 
> = 
> = 
> = 
> ======================================================================
> --- cfe/trunk/lib/CodeGen/CGDebugInfo.cpp (original)
> +++ cfe/trunk/lib/CodeGen/CGDebugInfo.cpp Fri Jul 10 18:34:53 2009
> @@ -761,8 +761,10 @@
>     // Unsupported types
>     return llvm::DIType();
>   case Type::ObjCObjectPointer:   // Encode id<p> in debug info just  
> like id.
> -    return Slot = getOrCreateType(M->getContext().getObjCIdType(),  
> Unit);
> -
> +    {
> +    ObjCObjectPointerType *OPT = cast<ObjCObjectPointerType>(Ty);
> +    return Slot = CreateType(OPT->getInterfaceType(), Unit);
> +    }
>   case Type::ObjCQualifiedInterface:  // Drop protocols from  
> interface.
>   case Type::ObjCInterface:
>     return Slot = CreateType(cast<ObjCInterfaceType>(Ty), Unit);
>
> Modified: cfe/trunk/lib/CodeGen/CGExpr.cpp
> URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/CGExpr.cpp?rev=75314&r1=75313&r2=75314&view=diff
>
> = 
> = 
> = 
> = 
> = 
> = 
> = 
> = 
> ======================================================================
> --- cfe/trunk/lib/CodeGen/CGExpr.cpp (original)
> +++ cfe/trunk/lib/CodeGen/CGExpr.cpp Fri Jul 10 18:34:53 2009
> @@ -257,7 +257,6 @@
>       Addr = Builder.CreateBitCast(Addr, MemTy, "storetmp");
>     }
>   }
> -
>   Builder.CreateStore(Value, Addr, Volatile);
> }
>
> @@ -758,11 +757,11 @@
>   default: assert(0 && "Unknown unary operator lvalue!");
>   case UnaryOperator::Deref:
>     {
> -      QualType T =
> -        E->getSubExpr()->getType()->getAsPointerType()- 
> >getPointeeType();
> +      QualType T = E->getSubExpr()->getType()->getPointeeType();
> +      assert(!T.isNull() && "CodeGenFunction::EmitUnaryOpLValue:  
> Illegal type");
> +
>       LValue LV = LValue::MakeAddr(EmitScalarExpr(E->getSubExpr()),
> -                                   ExprTy->getAsPointerType()- 
> >getPointeeType()
> -                                      .getCVRQualifiers(),
> +                                   T.getCVRQualifiers(),
>                                    getContext().getObjCGCAttrKind(T));
>      // We should not generate __weak write barrier on indirect  
> reference
>      // of a pointer to object; as in void foo (__weak id *param);  
> *param = 0;
> @@ -900,7 +899,10 @@
>     Address = Builder.CreateGEP(Base, Idx, "arrayidx");
>   }
>
> -  QualType T = E->getBase()->getType()->getAsPointerType()- 
> >getPointeeType();
> +  QualType T = E->getBase()->getType()->getPointeeType();
> +  assert(!T.isNull() &&
> +         "CodeGenFunction::EmitArraySubscriptExpr(): Illegal base  
> type");
> +
>   LValue LV = LValue::MakeAddr(Address,
>                                T.getCVRQualifiers(),
>                                getContext().getObjCGCAttrKind(T));
> @@ -1261,8 +1263,7 @@
>   QualType ObjectTy;
>   if (E->isArrow()) {
>     BaseValue = EmitScalarExpr(BaseExpr);
> -    const PointerType *PTy = BaseExpr->getType()->getAsPointerType();
> -    ObjectTy = PTy->getPointeeType();
> +    ObjectTy = BaseExpr->getType()->getPointeeType();
>     CVRQualifiers = ObjectTy.getCVRQualifiers();
>   } else {
>     LValue BaseLV = EmitLValue(BaseExpr);
>
> Modified: cfe/trunk/lib/CodeGen/CGExprScalar.cpp
> URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/CGExprScalar.cpp?rev=75314&r1=75313&r2=75314&view=diff
>
> = 
> = 
> = 
> = 
> = 
> = 
> = 
> = 
> ======================================================================
> --- cfe/trunk/lib/CodeGen/CGExprScalar.cpp (original)
> +++ 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()) {
>     if (CGF.getContext().getLangOptions().OverflowChecking &&
>         Ops.Ty->isSignedIntegerType())
>       return EmitOverflowCheckedBinOp(Ops);
> @@ -998,20 +998,24 @@
>     return Builder.CreateAdd(Ops.LHS, Ops.RHS, "add");
>   }
>
> -  if (Ops.Ty->getAsPointerType()->isVariableArrayType()) {
> +  if (Ops.Ty->isPointerType() &&
> +      Ops.Ty->getAsPointerType()->isVariableArrayType()) {
>     // The amount of the addition needs to account for the VLA size
>     CGF.ErrorUnsupported(Ops.E, "VLA pointer addition");
>   }
>   Value *Ptr, *Idx;
>   Expr *IdxExp;
> -  const PointerType *PT;
> -  if ((PT = Ops.E->getLHS()->getType()->getAsPointerType())) {
> +  const PointerType *PT = Ops.E->getLHS()->getType()- 
> >getAsPointerType();
> +  const ObjCObjectPointerType *OPT =
> +    Ops.E->getLHS()->getType()->getAsObjCObjectPointerType();
> +  if (PT || OPT) {
>     Ptr = Ops.LHS;
>     Idx = Ops.RHS;
>     IdxExp = Ops.E->getRHS();
> -  } else {                                           // int + pointer
> +  } else {  // int + pointer
>     PT = Ops.E->getRHS()->getType()->getAsPointerType();
> -    assert(PT && "Invalid add expr");
> +    OPT = Ops.E->getRHS()->getType()->getAsObjCObjectPointerType();
> +    assert((PT || OPT) && "Invalid add expr");
>     Ptr = Ops.RHS;
>     Idx = Ops.LHS;
>     IdxExp = Ops.E->getLHS();
> @@ -1027,8 +1031,7 @@
>     else
>       Idx = Builder.CreateZExt(Idx, IdxType, "idx.ext");
>   }
> -
> -  const QualType ElementType = PT->getPointeeType();
> +  const QualType ElementType = PT ? PT->getPointeeType() : OPT- 
> >getPointeeType();
>   // Handle interface types, which are not represented with a concrete
>   // type.
>   if (const ObjCInterfaceType *OIT =  
> dyn_cast<ObjCInterfaceType>(ElementType)) {
> @@ -1066,7 +1069,8 @@
>     return Builder.CreateSub(Ops.LHS, Ops.RHS, "sub");
>   }
>
> -  if (Ops.E->getLHS()->getType()->getAsPointerType()- 
> >isVariableArrayType()) {
> +  if (Ops.E->getLHS()->getType()->isPointerType() &&
> +      Ops.E->getLHS()->getType()->getAsPointerType()- 
> >isVariableArrayType()) {
>     // The amount of the addition needs to account for the VLA size  
> for
>     // ptr-int
>     // The amount of the division needs to account for the VLA size  
> for
> @@ -1075,7 +1079,7 @@
>   }
>
>   const QualType LHSType = Ops.E->getLHS()->getType();
> -  const QualType LHSElementType = LHSType->getAsPointerType()- 
> >getPointeeType();
> +  const QualType LHSElementType = LHSType->getPointeeType();
>   if (!isa<llvm::PointerType>(Ops.RHS->getType())) {
>     // pointer - int
>     Value *Idx = Ops.RHS;
>
> Modified: cfe/trunk/lib/CodeGen/CGObjC.cpp
> URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/CGObjC.cpp?rev=75314&r1=75313&r2=75314&view=diff
>
> = 
> = 
> = 
> = 
> = 
> = 
> = 
> = 
> ======================================================================
> --- cfe/trunk/lib/CodeGen/CGObjC.cpp (original)
> +++ cfe/trunk/lib/CodeGen/CGObjC.cpp Fri Jul 10 18:34:53 2009
> @@ -305,8 +305,8 @@
> QualType CodeGenFunction::TypeOfSelfObject() {
>   const ObjCMethodDecl *OMD = cast<ObjCMethodDecl>(CurFuncDecl);
>   ImplicitParamDecl *selfDecl = OMD->getSelfDecl();
> -  const PointerType *PTy =
> -    cast<PointerType>(getContext().getCanonicalType(selfDecl- 
> >getType()));
> +  const ObjCObjectPointerType *PTy = cast<ObjCObjectPointerType>(
> +    getContext().getCanonicalType(selfDecl->getType()));
>   return PTy->getPointeeType();
> }
>
>
> Modified: cfe/trunk/lib/CodeGen/CGObjCGNU.cpp
> URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/CGObjCGNU.cpp?rev=75314&r1=75313&r2=75314&view=diff
>
> = 
> = 
> = 
> = 
> = 
> = 
> = 
> = 
> ======================================================================
> --- cfe/trunk/lib/CodeGen/CGObjCGNU.cpp (original)
> +++ cfe/trunk/lib/CodeGen/CGObjCGNU.cpp Fri Jul 10 18:34:53 2009
> @@ -1338,7 +1338,7 @@
>         Handlers.push_back(std::make_pair(CatchDecl, CatchStmt- 
> >getCatchBody()));
>
>         // @catch() and @catch(id) both catch any ObjC exception
> -        if (!CatchDecl || CGF.getContext().isObjCIdType(CatchDecl- 
> >getType())
> +        if (!CatchDecl || CatchDecl->getType()->isObjCIdType()
>             || CatchDecl->getType()->isObjCQualifiedIdType()) {
>           // Use i8* null here to signal this is a catch all, not a  
> cleanup.
>           ESelArgs.push_back(NULLPtr);
> @@ -1348,10 +1348,11 @@
>         }
>
>         // All other types should be Objective-C interface pointer  
> types.
> -        const PointerType *PT = CatchDecl->getType()- 
> >getAsPointerType();
> -        assert(PT && "Invalid @catch type.");
> +        const ObjCObjectPointerType *OPT =
> +          CatchDecl->getType()->getAsObjCObjectPointerType();
> +        assert(OPT && "Invalid @catch type.");
>         const ObjCInterfaceType *IT =
> -          PT->getPointeeType()->getAsObjCInterfaceType();
> +          OPT->getPointeeType()->getAsObjCInterfaceType();
>         assert(IT && "Invalid @catch type.");
>         llvm::Value *EHType =
>           MakeConstantString(IT->getDecl()->getNameAsString());
>
> Modified: cfe/trunk/lib/CodeGen/CGObjCMac.cpp
> URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/CGObjCMac.cpp?rev=75314&r1=75313&r2=75314&view=diff
>
> = 
> = 
> = 
> = 
> = 
> = 
> = 
> = 
> ======================================================================
> --- cfe/trunk/lib/CodeGen/CGObjCMac.cpp (original)
> +++ cfe/trunk/lib/CodeGen/CGObjCMac.cpp Fri Jul 10 18:34:53 2009
> @@ -2523,19 +2523,18 @@
>       llvm::BasicBlock *NextCatchBlock =  
> CGF.createBasicBlock("catch");
>
>       const ParmVarDecl *CatchParam = CatchStmt->getCatchParamDecl();
> -      const PointerType *PT = 0;
> +      const ObjCObjectPointerType *OPT = 0;
>
>       // catch(...) always matches.
>       if (!CatchParam) {
>         AllMatched = true;
>       } else {
> -        PT = CatchParam->getType()->getAsPointerType();
> +        OPT = CatchParam->getType()->getAsObjCObjectPointerType();
>
>         // catch(id e) always matches.
>         // FIXME: For the time being we also match id<X>; this should
>         // be rejected by Sema instead.
> -        if ((PT && CGF.getContext().isObjCIdStructType(PT- 
> >getPointeeType())) ||
> -            CatchParam->getType()->isObjCQualifiedIdType())
> +        if (OPT && (OPT->isObjCIdType()) || OPT- 
> >isObjCQualifiedIdType())
>           AllMatched = true;
>       }
>
> @@ -2551,8 +2550,8 @@
>         break;
>       }
>
> -      assert(PT && "Unexpected non-pointer type in @catch");
> -      QualType T = PT->getPointeeType();
> +      assert(OPT && "Unexpected non-object pointer type in @catch");
> +      QualType T = OPT->getPointeeType();
>       const ObjCInterfaceType *ObjCType = T->getAsObjCInterfaceType();
>       assert(ObjCType && "Catch parameter must have Objective-C  
> type!");
>
> @@ -5443,7 +5442,7 @@
>           break;
>         }
>
> -        if (CGF.getContext().isObjCIdType(CatchDecl->getType()) ||
> +        if (CatchDecl->getType()->isObjCIdType() ||
>             CatchDecl->getType()->isObjCQualifiedIdType()) {
>           llvm::Value *IDEHType =
>             CGM.getModule().getGlobalVariable("OBJC_EHTYPE_id");
> @@ -5459,10 +5458,10 @@
>         }
>
>         // All other types should be Objective-C interface pointer  
> types.
> -        const PointerType *PT = CatchDecl->getType()- 
> >getAsPointerType();
> +        const ObjCObjectPointerType *PT =
> +          CatchDecl->getType()->getAsObjCObjectPointerType();
>         assert(PT && "Invalid @catch type.");
> -        const ObjCInterfaceType *IT =
> -          PT->getPointeeType()->getAsObjCInterfaceType();
> +        const ObjCInterfaceType *IT = PT->getInterfaceType();
>         assert(IT && "Invalid @catch type.");
>         llvm::Value *EHType = GetInterfaceEHType(IT->getDecl(),  
> false);
>         SelectorArgs.push_back(EHType);
>
> Modified: cfe/trunk/lib/CodeGen/CodeGenTypes.cpp
> URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/CodeGenTypes.cpp?rev=75314&r1=75313&r2=75314&view=diff
>
> = 
> = 
> = 
> = 
> = 
> = 
> = 
> = 
> ======================================================================
> --- cfe/trunk/lib/CodeGen/CodeGenTypes.cpp (original)
> +++ cfe/trunk/lib/CodeGen/CodeGenTypes.cpp Fri Jul 10 18:34:53 2009
> @@ -215,6 +215,7 @@
> const llvm::Type *CodeGenTypes::ConvertNewType(QualType T) {
>   const clang::Type &Ty = *Context.getCanonicalType(T);
>
> +  //T->dump();
>   switch (Ty.getTypeClass()) {
> #define TYPE(Class, Base)
> #define ABSTRACT_TYPE(Class, Base)
> @@ -353,10 +354,14 @@
>     return T;
>   }
>
> -  case Type::ObjCObjectPointer:
> -    // Protocols don't influence the LLVM type.
> -    return ConvertTypeRecursive(Context.getObjCIdType());
> -
> +  case Type::ObjCObjectPointer: {
> +   // Qualified id types don't influence the LLVM type, here we  
> always return
> +   // an opaque type for 'id'.
> +   const llvm::Type *&T = InterfaceTypes[0];
> +   if (!T)
> +       T = llvm::OpaqueType::get();
> +   return llvm::PointerType::getUnqual(T);
> +  }
>   case Type::Record:
>   case Type::Enum: {
>     const TagDecl *TD = cast<TagType>(Ty).getDecl();
>
> Modified: cfe/trunk/lib/CodeGen/Mangle.cpp
> URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/Mangle.cpp?rev=75314&r1=75313&r2=75314&view=diff
>
> = 
> = 
> = 
> = 
> = 
> = 
> = 
> = 
> ======================================================================
> --- cfe/trunk/lib/CodeGen/Mangle.cpp (original)
> +++ cfe/trunk/lib/CodeGen/Mangle.cpp Fri Jul 10 18:34:53 2009
> @@ -480,6 +480,11 @@
>     Out << 'P';
>     mangleType(PT->getPointeeType());
>   }
> +  else if (const ObjCObjectPointerType *PT =
> +           dyn_cast<ObjCObjectPointerType>(T.getTypePtr())) {
> +    Out << 'P';
> +    mangleType(PT->getPointeeType());
> +  }
>   //         ::= R <type>   # reference-to
>   else if (const LValueReferenceType *RT =
>            dyn_cast<LValueReferenceType>(T.getTypePtr())) {
>
> Modified: cfe/trunk/lib/Frontend/PCHReader.cpp
> URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Frontend/PCHReader.cpp?rev=75314&r1=75313&r2=75314&view=diff
>
> = 
> = 
> = 
> = 
> = 
> = 
> = 
> = 
> ======================================================================
> --- cfe/trunk/lib/Frontend/PCHReader.cpp (original)
> +++ cfe/trunk/lib/Frontend/PCHReader.cpp Fri Jul 10 18:34:53 2009
> @@ -1531,6 +1531,7 @@
>     Context->setObjCProtoType(GetType(Proto));
>   if (unsigned Class = SpecialTypes[pch::SPECIAL_TYPE_OBJC_CLASS])
>     Context->setObjCClassType(GetType(Class));
> +
>   if (unsigned String =  
> SpecialTypes[pch::SPECIAL_TYPE_CF_CONSTANT_STRING])
>     Context->setCFConstantStringType(GetType(String));
>   if (unsigned FastEnum
> @@ -1934,13 +1935,12 @@
>
>   case pch::TYPE_OBJC_OBJECT_POINTER: {
>     unsigned Idx = 0;
> -    ObjCInterfaceDecl *ItfD =
> -      cast_or_null<ObjCInterfaceDecl>(GetDecl(Record[Idx++]));
> +    QualType OIT = GetType(Record[Idx++]);
>     unsigned NumProtos = Record[Idx++];
>     llvm::SmallVector<ObjCProtocolDecl*, 4> Protos;
>     for (unsigned I = 0; I != NumProtos; ++I)
>       Protos.push_back(cast<ObjCProtocolDecl>(GetDecl(Record[Idx+ 
> +])));
> -    return Context->getObjCObjectPointerType(ItfD, Protos.data(),  
> NumProtos);
> +    return Context->getObjCObjectPointerType(OIT, Protos.data(),  
> NumProtos);
>   }
>   }
>   // Suppress a GCC warning
>
> Modified: cfe/trunk/lib/Frontend/PCHWriter.cpp
> URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Frontend/PCHWriter.cpp?rev=75314&r1=75313&r2=75314&view=diff
>
> = 
> = 
> = 
> = 
> = 
> = 
> = 
> = 
> ======================================================================
> --- cfe/trunk/lib/Frontend/PCHWriter.cpp (original)
> +++ cfe/trunk/lib/Frontend/PCHWriter.cpp Fri Jul 10 18:34:53 2009
> @@ -255,7 +255,7 @@
>
> void
> PCHTypeWriter::VisitObjCObjectPointerType(const  
> ObjCObjectPointerType *T) {
> -  Writer.AddDeclRef(T->getDecl(), Record);
> +  Writer.AddTypeRef(T->getPointeeType(), Record);
>   Record.push_back(T->getNumProtocols());
>   for (ObjCInterfaceType::qual_iterator I = T->qual_begin(),
>        E = T->qual_end(); I != E; ++I)
>
> Modified: cfe/trunk/lib/Frontend/RewriteObjC.cpp
> URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Frontend/RewriteObjC.cpp?rev=75314&r1=75313&r2=75314&view=diff
>
> = 
> = 
> = 
> = 
> = 
> = 
> = 
> = 
> ======================================================================
> --- cfe/trunk/lib/Frontend/RewriteObjC.cpp (original)
> +++ cfe/trunk/lib/Frontend/RewriteObjC.cpp Fri Jul 10 18:34:53 2009
> @@ -2163,9 +2163,10 @@
>   if (!CurMethodDef || !CurMethodDef->isInstanceMethod()) return 0;
>
>   if (ObjCSuperExpr *Super = dyn_cast<ObjCSuperExpr>(recExpr)) {
> -      const PointerType *PT = Super->getType()->getAsPointerType();
> -      assert(PT);
> -      ObjCInterfaceType *IT = cast<ObjCInterfaceType>(PT- 
> >getPointeeType());
> +      const ObjCObjectPointerType *OPT =
> +        Super->getType()->getAsObjCObjectPointerType();
> +      assert(OPT);
> +      const ObjCInterfaceType *IT = OPT->getInterfaceType();
>       return IT->getDecl();
>     }
>   return 0;
>
> Modified: cfe/trunk/lib/Sema/Sema.cpp
> URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/Sema.cpp?rev=75314&r1=75313&r2=75314&view=diff
>
> = 
> = 
> = 
> = 
> = 
> = 
> = 
> = 
> ======================================================================
> --- cfe/trunk/lib/Sema/Sema.cpp (original)
> +++ cfe/trunk/lib/Sema/Sema.cpp Fri Jul 10 18:34:53 2009
> @@ -53,9 +53,9 @@
>
>         // Don't desugar magic Objective-C types.
>         Ty.getUnqualifiedType() != Context.getObjCIdType() &&
> +        Ty.getUnqualifiedType() != Context.getObjCClassType() &&
>         Ty.getUnqualifiedType() != Context.getObjCSelType() &&
>         Ty.getUnqualifiedType() != Context.getObjCProtoType() &&
> -        Ty.getUnqualifiedType() != Context.getObjCClassType() &&
>
>         // Not va_list.
>         Ty.getUnqualifiedType() != Context.getBuiltinVaListType()) {
> @@ -140,17 +140,6 @@
>     Context.setObjCSelType(Context.getTypeDeclType(SelTypedef));
>   }
>
> -  if (Context.getObjCClassType().isNull()) {
> -    RecordDecl *ClassTag = CreateStructDecl(Context, "objc_class");
> -    QualType ClassT =  
> Context.getPointerType(Context.getTagDeclType(ClassTag));
> -    TypedefDecl *ClassTypedef =
> -      TypedefDecl::Create(Context, CurContext, SourceLocation(),
> -                          &Context.Idents.get("Class"), ClassT);
> -    PushOnScopeChains(ClassTag, TUScope);
> -    PushOnScopeChains(ClassTypedef, TUScope);
> -    Context.setObjCClassType(Context.getTypeDeclType(ClassTypedef));
> -  }
> -
>   // Synthesize "@class Protocol;
>   if (Context.getObjCProtoType().isNull()) {
>     ObjCInterfaceDecl *ProtocolDecl =
> @@ -160,20 +149,38 @@
>      
> Context.setObjCProtoType(Context.getObjCInterfaceType(ProtocolDecl));
>     PushOnScopeChains(ProtocolDecl, TUScope);
>   }
> -
> -  // Synthesize "typedef struct objc_object { Class isa; } *id;"
> +  // Create the built-in decls/typedefs for 'id' and 'Class'.
>   if (Context.getObjCIdType().isNull()) {
> -    RecordDecl *ObjectTag = CreateStructDecl(Context, "objc_object");
> +    ObjCInterfaceDecl *IdIDecl =
> +      ObjCInterfaceDecl::Create(Context, CurContext,  
> SourceLocation(),
> +                                &Context.Idents.get("id"),
> +                                SourceLocation(), true);
> +    QualType IdIType = Context.getObjCInterfaceType(IdIDecl);
> +    QualType ObjCIdType = Context.getObjCObjectPointerType(IdIType);
>
> -    QualType ObjT =  
> Context.getPointerType(Context.getTagDeclType(ObjectTag));
> -    PushOnScopeChains(ObjectTag, TUScope);
>     TypedefDecl *IdTypedef = TypedefDecl::Create(Context, CurContext,
>                                                  SourceLocation(),
>                                                   
> &Context.Idents.get("id"),
> -                                                 ObjT);
> +                                                 ObjCIdType);
>     PushOnScopeChains(IdTypedef, TUScope);
>     Context.setObjCIdType(Context.getTypeDeclType(IdTypedef));
>   }
> +  // Create the built-in decls/typedefs and type for "Class".
> +  if (Context.getObjCClassType().isNull()) {
> +    ObjCInterfaceDecl *ClassIDecl =
> +      ObjCInterfaceDecl::Create(Context, CurContext,  
> SourceLocation(),
> +                                &Context.Idents.get("Class"),
> +                                SourceLocation(), true);
> +    QualType ClassIType = Context.getObjCInterfaceType(ClassIDecl);
> +    QualType ObjCClassType =  
> Context.getObjCObjectPointerType(ClassIType);
> +
> +    TypedefDecl *ClassTypedef = TypedefDecl::Create(Context,  
> CurContext,
> +                                                    SourceLocation(),
> +                                                     
> &Context.Idents.get("Class"),
> +                                                    ObjCClassType);
> +    PushOnScopeChains(ClassTypedef, TUScope);
> +    Context.setObjCClassType(Context.getTypeDeclType(ClassTypedef));
> +  }
> }
>
> Sema::Sema(Preprocessor &pp, ASTContext &ctxt, ASTConsumer &consumer,
>
> Modified: cfe/trunk/lib/Sema/Sema.h
> URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/Sema.h?rev=75314&r1=75313&r2=75314&view=diff
>
> = 
> = 
> = 
> = 
> = 
> = 
> = 
> = 
> ======================================================================
> --- cfe/trunk/lib/Sema/Sema.h (original)
> +++ cfe/trunk/lib/Sema/Sema.h Fri Jul 10 18:34:53 2009
> @@ -3037,6 +3037,8 @@
>   // Helper function for CheckAssignmentConstraints (C99 6.5.16.1p1)
>   AssignConvertType CheckPointerTypesForAssignment(QualType lhsType,
>                                                    QualType rhsType);
> +  AssignConvertType CheckPointeeTypesForAssignment(QualType lhsType,
> +                                                   QualType rhsType);
>
>   // Helper function for CheckAssignmentConstraints involving two
>   // block pointer types.
>
> Modified: cfe/trunk/lib/Sema/SemaDecl.cpp
> URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaDecl.cpp?rev=75314&r1=75313&r2=75314&view=diff
>
> = 
> = 
> = 
> = 
> = 
> = 
> = 
> = 
> ======================================================================
> --- cfe/trunk/lib/Sema/SemaDecl.cpp (original)
> +++ cfe/trunk/lib/Sema/SemaDecl.cpp Fri Jul 10 18:34:53 2009
> @@ -516,8 +516,6 @@
>   if (New->isInvalidDecl() || OldD->isInvalidDecl())
>     return New->setInvalidDecl();
>
> -  bool objc_types = false;
> -
>   // Allow multiple definitions for ObjC built-in typedefs.
>   // FIXME: Verify the underlying types are equivalent!
>   if (getLangOptions().ObjC1) {
> @@ -527,13 +525,15 @@
>     case 2:
>       if (!TypeID->isStr("id"))
>         break;
> -      Context.setObjCIdType(Context.getTypeDeclType(New));
> -      objc_types = true;
> +      // Install the built-in type for 'id', ignoring the current  
> definition.
> +      New->setTypeForDecl(Context.getObjCIdType().getTypePtr());
> +      return;
>       break;
>     case 5:
>       if (!TypeID->isStr("Class"))
>         break;
> -      Context.setObjCClassType(Context.getTypeDeclType(New));
> +      // Install the built-in type for 'Class', ignoring the  
> current definition.
> +      New->setTypeForDecl(Context.getObjCClassType().getTypePtr());
>       return;
>     case 3:
>       if (!TypeID->isStr("SEL"))
> @@ -578,7 +578,7 @@
>     return New->setInvalidDecl();
>   }
>
> -  if (objc_types || getLangOptions().Microsoft)
> +  if (getLangOptions().Microsoft)
>     return;
>
>   // C++ [dcl.typedef]p2:
>
> Modified: cfe/trunk/lib/Sema/SemaDeclAttr.cpp
> URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaDeclAttr.cpp?rev=75314&r1=75313&r2=75314&view=diff
>
> = 
> = 
> = 
> = 
> = 
> = 
> = 
> = 
> ======================================================================
> --- cfe/trunk/lib/Sema/SemaDeclAttr.cpp (original)
> +++ cfe/trunk/lib/Sema/SemaDeclAttr.cpp Fri Jul 10 18:34:53 2009
> @@ -117,7 +117,7 @@
> }
>
> static inline bool isNSStringType(QualType T, ASTContext &Ctx) {
> -  const PointerType *PT = T->getAsPointerType();
> +  const ObjCObjectPointerType *PT = T->getAsObjCObjectPointerType();
>   if (!PT)
>     return false;
>
> @@ -1690,7 +1690,8 @@
>     return;
>   }
>
> -  if (!(S.Context.isObjCNSObjectType(RetTy) || RetTy- 
> >getAsPointerType())) {
> +  if (!(S.Context.isObjCNSObjectType(RetTy) || RetTy- 
> >getAsPointerType()
> +        || RetTy->getAsObjCObjectPointerType())) {
>     S.Diag(Attr.getLoc(), diag::warn_ns_attribute_wrong_return_type)
>       << Attr.getName();
>     return;
>
> Modified: cfe/trunk/lib/Sema/SemaDeclObjC.cpp
> URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaDeclObjC.cpp?rev=75314&r1=75313&r2=75314&view=diff
>
> = 
> = 
> = 
> = 
> = 
> = 
> = 
> = 
> ======================================================================
> --- cfe/trunk/lib/Sema/SemaDeclObjC.cpp (original)
> +++ cfe/trunk/lib/Sema/SemaDeclObjC.cpp Fri Jul 10 18:34:53 2009
> @@ -2048,7 +2048,7 @@
>         << property->getDeclName() << Ivar->getDeclName();
>         // Fall thru - see previous comment
>       }
> -      if ((Context.isObjCObjectPointerType(property->getType()) ||
> +      if ((property->getType()->isObjCObjectPointerType() ||
>            PropType.isObjCGCStrong()) && IvarType.isObjCGCWeak() &&
>            getLangOptions().getGCMode() != LangOptions::NonGC) {
>         Diag(PropertyLoc, diag::error_strong_property)
>
> Modified: cfe/trunk/lib/Sema/SemaExpr.cpp
> URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaExpr.cpp?rev=75314&r1=75313&r2=75314&view=diff
>
> = 
> = 
> = 
> = 
> = 
> = 
> = 
> = 
> ======================================================================
> --- cfe/trunk/lib/Sema/SemaExpr.cpp (original)
> +++ cfe/trunk/lib/Sema/SemaExpr.cpp Fri Jul 10 18:34:53 2009
> @@ -925,8 +925,8 @@
>       QualType T;
>
>       if (getCurMethodDecl()->isInstanceMethod())
> -        T = Context.getPointerType(Context.getObjCInterfaceType(
> -                                   getCurMethodDecl()- 
> >getClassInterface()));
> +        T =  
> Context.getObjCObjectPointerType(Context.getObjCInterfaceType(
> +                                      getCurMethodDecl()- 
> >getClassInterface()));
>       else
>         T = Context.getObjCClassType();
>       return Owned(new (Context) ObjCSuperExpr(Loc, T));
> @@ -1844,6 +1844,17 @@
>     BaseExpr = RHSExp;
>     IndexExpr = LHSExp;
>     ResultType = PTy->getPointeeType();
> +  } else if (const ObjCObjectPointerType *PTy =
> +               LHSTy->getAsObjCObjectPointerType()) {
> +    BaseExpr = LHSExp;
> +    IndexExpr = RHSExp;
> +    ResultType = PTy->getPointeeType();
> +  } else if (const ObjCObjectPointerType *PTy =
> +               RHSTy->getAsObjCObjectPointerType()) {
> +     // Handle the uncommon case of "123[Ptr]".
> +    BaseExpr = RHSExp;
> +    IndexExpr = LHSExp;
> +    ResultType = PTy->getPointeeType();
>   } else if (const VectorType *VTy = LHSTy->getAsVectorType()) {
>     BaseExpr = LHSExp;    // vectors: V[123]
>     IndexExpr = RHSExp;
> @@ -2089,6 +2100,8 @@
>                                                          MemberLoc));
>     else if (const PointerType *PT = BaseType->getAsPointerType())
>       BaseType = PT->getPointeeType();
> +    else if (BaseType->isObjCObjectPointerType())
> +      ;
>     else if (getLangOptions().CPlusPlus && BaseType->isRecordType())
>       return Owned(BuildOverloadedArrowExpr(S, BaseExpr, OpLoc,
>                                             MemberLoc, Member));
> @@ -2212,12 +2225,71 @@
>       << DeclarationName(&Member) << int(OpKind == tok::arrow));
>   }
>
> +  // Handle properties on ObjC 'Class' types.
> +  if (OpKind == tok::period && (BaseType->isObjCClassType())) {
> +    // Also must look for a getter name which uses property syntax.
> +    Selector Sel = PP.getSelectorTable().getNullarySelector(&Member);
> +    if (ObjCMethodDecl *MD = getCurMethodDecl()) {
> +      ObjCInterfaceDecl *IFace = MD->getClassInterface();
> +      ObjCMethodDecl *Getter;
> +      // FIXME: need to also look locally in the implementation.
> +      if ((Getter = IFace->lookupClassMethod(Sel))) {
> +        // Check the use of this method.
> +        if (DiagnoseUseOfDecl(Getter, MemberLoc))
> +          return ExprError();
> +      }
> +      // If we found a getter then this may be a valid dot- 
> reference, we
> +      // will look for the matching setter, in case it is needed.
> +      Selector SetterSel =
> +        SelectorTable::constructSetterName(PP.getIdentifierTable(),
> +                                           PP.getSelectorTable(),  
> &Member);
> +      ObjCMethodDecl *Setter = IFace->lookupClassMethod(SetterSel);
> +      if (!Setter) {
> +        // If this reference is in an @implementation, also check  
> for 'private'
> +        // methods.
> +        Setter = FindMethodInNestedImplementations(IFace, SetterSel);
> +      }
> +      // Look through local category implementations associated  
> with the class.
> +      if (!Setter) {
> +        for (unsigned i = 0; i < ObjCCategoryImpls.size() && ! 
> Setter; i++) {
> +          if (ObjCCategoryImpls[i]->getClassInterface() == IFace)
> +            Setter = ObjCCategoryImpls[i]->getClassMethod(SetterSel);
> +        }
> +      }
> +
> +      if (Setter && DiagnoseUseOfDecl(Setter, MemberLoc))
> +        return ExprError();
> +
> +      if (Getter || Setter) {
> +        QualType PType;
> +
> +        if (Getter)
> +          PType = Getter->getResultType();
> +        else {
> +          for (ObjCMethodDecl::param_iterator PI = Setter- 
> >param_begin(),
> +               E = Setter->param_end(); PI != E; ++PI)
> +            PType = (*PI)->getType();
> +        }
> +        // FIXME: we must check that the setter has property type.
> +        return Owned(new (Context) ObjCKVCRefExpr(Getter, PType,
> +                                        Setter, MemberLoc,  
> BaseExpr));
> +      }
> +      return ExprError(Diag(MemberLoc, diag::err_property_not_found)
> +        << &Member << BaseType);
> +    }
> +  }
>   // Handle access to Objective-C instance variables, such as "Obj- 
> >ivar" and
>   // (*Obj).ivar.
> -  if (const ObjCInterfaceType *IFTy = BaseType- 
> >getAsObjCInterfaceType()) {
> +  if ((OpKind == tok::arrow && BaseType->isObjCObjectPointerType())  
> ||
> +      (OpKind == tok::period && BaseType->isObjCInterfaceType())) {
> +    const ObjCObjectPointerType *OPT = BaseType- 
> >getAsObjCObjectPointerType();
> +    const ObjCInterfaceType *IFaceT =
> +      OPT ? OPT->getInterfaceType() : BaseType- 
> >getAsObjCInterfaceType();
> +    ObjCInterfaceDecl *IDecl = IFaceT->getDecl();
>     ObjCInterfaceDecl *ClassDeclared;
> -    if (ObjCIvarDecl *IV = IFTy->getDecl()- 
> >lookupInstanceVariable(&Member,
> -                                                              
> ClassDeclared)) {
> +
> +    if (ObjCIvarDecl *IV = IDecl->lookupInstanceVariable(&Member,
> +                                                          
> ClassDeclared)) {
>       // If the decl being referenced had an error, return an error  
> for this
>       // sub-expr without emitting another error, in order to avoid  
> cascading
>       // error cases.
> @@ -2249,12 +2321,12 @@
>         }
>
>         if (IV->getAccessControl() == ObjCIvarDecl::Private) {
> -          if (ClassDeclared != IFTy->getDecl() ||
> +          if (ClassDeclared != IDecl ||
>               ClassOfMethodDecl != ClassDeclared)
>             Diag(MemberLoc, diag::error_private_ivar_access) << IV- 
> >getDeclName();
>         }
>         // @protected
> -        else if (!IFTy->getDecl()->isSuperClassOf(ClassOfMethodDecl))
> +        else if (!IDecl->isSuperClassOf(ClassOfMethodDecl))
>           Diag(MemberLoc, diag::error_protected_ivar_access) << IV- 
> >getDeclName();
>       }
>
> @@ -2263,18 +2335,46 @@
>                                                  OpKind ==  
> tok::arrow));
>     }
>     return ExprError(Diag(MemberLoc,  
> diag::err_typecheck_member_reference_ivar)
> -                       << IFTy->getDecl()->getDeclName() << &Member
> +                       << IDecl->getDeclName() << &Member
>                        << BaseExpr->getSourceRange());
>   }
> +  // Handle properties on qualified "id" protocols.
> +  const ObjCObjectPointerType *QIdTy;
> +  if (OpKind == tok::period && (QIdTy = BaseType- 
> >getAsObjCQualifiedIdType())) {
> +    // Check protocols on qualified interfaces.
> +    Selector Sel = PP.getSelectorTable().getNullarySelector(&Member);
> +    if (Decl *PMDecl = FindGetterNameDecl(QIdTy, Member, Sel,  
> Context)) {
> +      if (ObjCPropertyDecl *PD =  
> dyn_cast<ObjCPropertyDecl>(PMDecl)) {
> +        // Check the use of this declaration
> +        if (DiagnoseUseOfDecl(PD, MemberLoc))
> +          return ExprError();
> +
> +        return Owned(new (Context) ObjCPropertyRefExpr(PD, PD- 
> >getType(),
> +                                                       MemberLoc,  
> BaseExpr));
> +      }
> +      if (ObjCMethodDecl *OMD = dyn_cast<ObjCMethodDecl>(PMDecl)) {
> +        // Check the use of this method.
> +        if (DiagnoseUseOfDecl(OMD, MemberLoc))
> +          return ExprError();
> +
> +        return Owned(new (Context) ObjCMessageExpr(BaseExpr, Sel,
> +                                                   OMD- 
> >getResultType(),
> +                                                   OMD, OpLoc,  
> MemberLoc,
> +                                                   NULL, 0));
> +      }
> +    }
>
> +    return ExprError(Diag(MemberLoc, diag::err_property_not_found)
> +                       << &Member << BaseType);
> +  }
>   // Handle Objective-C property access, which is "Obj.property"  
> where Obj is a
>   // pointer to a (potentially qualified) interface type.
> -  const PointerType *PTy;
> -  const ObjCInterfaceType *IFTy;
> -  if (OpKind == tok::period && (PTy = BaseType->getAsPointerType())  
> &&
> -      (IFTy = PTy->getPointeeType()->getAsObjCInterfaceType())) {
> -    ObjCInterfaceDecl *IFace = IFTy->getDecl();
> -
> +  const ObjCObjectPointerType *OPT;
> +  if (OpKind == tok::period &&
> +      (OPT = BaseType->getAsObjCInterfacePointerType())) {
> +    const ObjCInterfaceType *IFaceT = OPT->getInterfaceType();
> +    ObjCInterfaceDecl *IFace = IFaceT->getDecl();
> +
>     // Search for a declared property first.
>     if (ObjCPropertyDecl *PD = IFace- 
> >FindPropertyDeclaration(&Member)) {
>       // Check whether we can reference this property.
> @@ -2288,10 +2388,9 @@
>       return Owned(new (Context) ObjCPropertyRefExpr(PD, ResTy,
>                                                      MemberLoc,  
> BaseExpr));
>     }
> -
>     // Check protocols on qualified interfaces.
> -    for (ObjCInterfaceType::qual_iterator I = IFTy->qual_begin(),
> -         E = IFTy->qual_end(); I != E; ++I)
> +    for (ObjCObjectPointerType::qual_iterator I = IFaceT- 
> >qual_begin(),
> +         E = IFaceT->qual_end(); I != E; ++I)
>       if (ObjCPropertyDecl *PD = (*I)- 
> >FindPropertyDeclaration(&Member)) {
>         // Check whether we can reference this property.
>         if (DiagnoseUseOfDecl(PD, MemberLoc))
> @@ -2300,7 +2399,16 @@
>         return Owned(new (Context) ObjCPropertyRefExpr(PD, PD- 
> >getType(),
>                                                        MemberLoc,  
> BaseExpr));
>       }
> +    for (ObjCObjectPointerType::qual_iterator I = OPT->qual_begin(),
> +         E = OPT->qual_end(); I != E; ++I)
> +      if (ObjCPropertyDecl *PD = (*I)- 
> >FindPropertyDeclaration(&Member)) {
> +        // Check whether we can reference this property.
> +        if (DiagnoseUseOfDecl(PD, MemberLoc))
> +          return ExprError();
>
> +        return Owned(new (Context) ObjCPropertyRefExpr(PD, PD- 
> >getType(),
> +                                                       MemberLoc,  
> BaseExpr));
> +      }
>     // If that failed, look for an "implicit" property by seeing if  
> the nullary
>     // selector is implemented.
>
> @@ -2365,88 +2473,6 @@
>     return ExprError(Diag(MemberLoc, diag::err_property_not_found)
>       << &Member << BaseType);
>   }
> -  // Handle properties on qualified "id" protocols.
> -  const ObjCObjectPointerType *QIdTy;
> -  if (OpKind == tok::period && (QIdTy = BaseType- 
> >getAsObjCQualifiedIdType())) {
> -    // Check protocols on qualified interfaces.
> -    Selector Sel = PP.getSelectorTable().getNullarySelector(&Member);
> -    if (Decl *PMDecl = FindGetterNameDecl(QIdTy, Member, Sel,  
> Context)) {
> -      if (ObjCPropertyDecl *PD =  
> dyn_cast<ObjCPropertyDecl>(PMDecl)) {
> -        // Check the use of this declaration
> -        if (DiagnoseUseOfDecl(PD, MemberLoc))
> -          return ExprError();
> -
> -        return Owned(new (Context) ObjCPropertyRefExpr(PD, PD- 
> >getType(),
> -                                                       MemberLoc,  
> BaseExpr));
> -      }
> -      if (ObjCMethodDecl *OMD = dyn_cast<ObjCMethodDecl>(PMDecl)) {
> -        // Check the use of this method.
> -        if (DiagnoseUseOfDecl(OMD, MemberLoc))
> -          return ExprError();
> -
> -        return Owned(new (Context) ObjCMessageExpr(BaseExpr, Sel,
> -                                                   OMD- 
> >getResultType(),
> -                                                   OMD, OpLoc,  
> MemberLoc,
> -                                                   NULL, 0));
> -      }
> -    }
> -
> -    return ExprError(Diag(MemberLoc, diag::err_property_not_found)
> -                       << &Member << BaseType);
> -  }
> -  // Handle properties on ObjC 'Class' types.
> -  if (OpKind == tok::period && (BaseType ==  
> Context.getObjCClassType())) {
> -    // Also must look for a getter name which uses property syntax.
> -    Selector Sel = PP.getSelectorTable().getNullarySelector(&Member);
> -    if (ObjCMethodDecl *MD = getCurMethodDecl()) {
> -      ObjCInterfaceDecl *IFace = MD->getClassInterface();
> -      ObjCMethodDecl *Getter;
> -      // FIXME: need to also look locally in the implementation.
> -      if ((Getter = IFace->lookupClassMethod(Sel))) {
> -        // Check the use of this method.
> -        if (DiagnoseUseOfDecl(Getter, MemberLoc))
> -          return ExprError();
> -      }
> -      // If we found a getter then this may be a valid dot- 
> reference, we
> -      // will look for the matching setter, in case it is needed.
> -      Selector SetterSel =
> -        SelectorTable::constructSetterName(PP.getIdentifierTable(),
> -                                           PP.getSelectorTable(),  
> &Member);
> -      ObjCMethodDecl *Setter = IFace->lookupClassMethod(SetterSel);
> -      if (!Setter) {
> -        // If this reference is in an @implementation, also check  
> for 'private'
> -        // methods.
> -        Setter = FindMethodInNestedImplementations(IFace, SetterSel);
> -      }
> -      // Look through local category implementations associated  
> with the class.
> -      if (!Setter) {
> -        for (unsigned i = 0; i < ObjCCategoryImpls.size() && ! 
> Setter; i++) {
> -          if (ObjCCategoryImpls[i]->getClassInterface() == IFace)
> -            Setter = ObjCCategoryImpls[i]->getClassMethod(SetterSel);
> -        }
> -      }
> -
> -      if (Setter && DiagnoseUseOfDecl(Setter, MemberLoc))
> -        return ExprError();
> -
> -      if (Getter || Setter) {
> -        QualType PType;
> -
> -        if (Getter)
> -          PType = Getter->getResultType();
> -        else {
> -          for (ObjCMethodDecl::param_iterator PI = Setter- 
> >param_begin(),
> -               E = Setter->param_end(); PI != E; ++PI)
> -            PType = (*PI)->getType();
> -        }
> -        // FIXME: we must check that the setter has property type.
> -        return Owned(new (Context) ObjCKVCRefExpr(Getter, PType,
> -                                        Setter, MemberLoc,  
> BaseExpr));
> -      }
> -      return ExprError(Diag(MemberLoc, diag::err_property_not_found)
> -        << &Member << BaseType);
> -    }
> -  }
>
>   // Handle 'field access' to vectors, such as 'V.xx'.
>   if (BaseType->isExtVectorType()) {
> @@ -3069,13 +3095,13 @@
>   // C99 6.5.15p6 - "if one operand is a null pointer constant, the  
> result has
>   // the type of the other operand."
>   if ((LHSTy->isPointerType() || LHSTy->isBlockPointerType() ||
> -       Context.isObjCObjectPointerType(LHSTy)) &&
> +       LHSTy->isObjCObjectPointerType()) &&
>       RHS->isNullPointerConstant(Context)) {
>     ImpCastExprToType(RHS, LHSTy); // promote the null to a pointer.
>     return LHSTy;
>   }
>   if ((RHSTy->isPointerType() || RHSTy->isBlockPointerType() ||
> -       Context.isObjCObjectPointerType(RHSTy)) &&
> +       RHSTy->isObjCObjectPointerType()) &&
>       LHS->isNullPointerConstant(Context)) {
>     ImpCastExprToType(LHS, RHSTy); // promote the null to a pointer.
>     return RHSTy;
> @@ -3119,46 +3145,15 @@
>     ImpCastExprToType(RHS, LHSTy);
>     return LHSTy;
>   }
> -  // Need to handle "id<xx>" explicitly. Unlike "id", whose  
> canonical type
> -  // evaluates to "struct objc_object *" (and is handled above when  
> comparing
> -  // id with statically typed objects).
> -  if (LHSTy->isObjCQualifiedIdType() || RHSTy- 
> >isObjCQualifiedIdType()) {
> -    // GCC allows qualified id and any Objective-C type to devolve to
> -    // id. Currently localizing to here until clear this should be
> -    // part of ObjCQualifiedIdTypesAreCompatible.
> -    if (ObjCQualifiedIdTypesAreCompatible(LHSTy, RHSTy, true) ||
> -        (LHSTy->isObjCQualifiedIdType() &&
> -         Context.isObjCObjectPointerType(RHSTy)) ||
> -        (RHSTy->isObjCQualifiedIdType() &&
> -         Context.isObjCObjectPointerType(LHSTy))) {
> -      // FIXME: This is not the correct composite type. This only  
> happens to
> -      // work because id can more or less be used anywhere, however  
> this may
> -      // change the type of method sends.
> -
> -      // FIXME: gcc adds some type-checking of the arguments and  
> emits
> -      // (confusing) incompatible comparison warnings in some
> -      // cases. Investigate.
> -      QualType compositeType = Context.getObjCIdType();
> -      ImpCastExprToType(LHS, compositeType);
> -      ImpCastExprToType(RHS, compositeType);
> -      return compositeType;
> -    }
> -  }
>   // Check constraints for Objective-C object pointers types.
> -  if (Context.isObjCObjectPointerType(LHSTy) &&
> -      Context.isObjCObjectPointerType(RHSTy)) {
> +  if (LHSTy->isObjCObjectPointerType() && RHSTy- 
> >isObjCObjectPointerType()) {
>
>     if (Context.getCanonicalType(LHSTy) ==  
> Context.getCanonicalType(RHSTy)) {
>       // Two identical object pointer types are always compatible.
>       return LHSTy;
>     }
> -    // No need to check for block pointer types or qualified id  
> types (they
> -    // were handled above).
> -    assert((LHSTy->isPointerType() && RHSTy->isPointerType()) &&
> -           "Sema::CheckConditionalOperands(): Unexpected type");
> -    QualType lhptee = LHSTy->getAsPointerType()->getPointeeType();
> -    QualType rhptee = RHSTy->getAsPointerType()->getPointeeType();
> -
> +    const ObjCObjectPointerType *LHSOPT = LHSTy- 
> >getAsObjCObjectPointerType();
> +    const ObjCObjectPointerType *RHSOPT = RHSTy- 
> >getAsObjCObjectPointerType();
>     QualType compositeType = LHSTy;
>
>     // If both operands are interfaces and either operand can be
> @@ -3174,16 +3169,19 @@
>
>     // FIXME: Consider unifying with 'areComparableObjCPointerTypes'.
>     // It could return the composite type.
> -    const ObjCInterfaceType* LHSIface = lhptee- 
> >getAsObjCInterfaceType();
> -    const ObjCInterfaceType* RHSIface = rhptee- 
> >getAsObjCInterfaceType();
> -    if (LHSIface && RHSIface &&
> -        Context.canAssignObjCInterfaces(LHSIface, RHSIface)) {
> +    if (Context.canAssignObjCInterfaces(LHSOPT, RHSOPT)) {
>       compositeType = LHSTy;
> -    } else if (LHSIface && RHSIface &&
> -               Context.canAssignObjCInterfaces(RHSIface, LHSIface)) {
> +    } else if (Context.canAssignObjCInterfaces(RHSOPT, LHSOPT)) {
>       compositeType = RHSTy;
> -    } else if (Context.isObjCIdStructType(lhptee) ||
> -               Context.isObjCIdStructType(rhptee)) {
> +    } else if ((LHSTy->isObjCQualifiedIdType() ||
> +                RHSTy->isObjCQualifiedIdType()) &&
> +                ObjCQualifiedIdTypesAreCompatible(LHSTy, RHSTy,  
> true)) {
> +      // Need to handle "id<xx>" explicitly.
> +      // GCC allows qualified id and any Objective-C type to  
> devolve to
> +      // id. Currently localizing to here until clear this should be
> +      // part of ObjCQualifiedIdTypesAreCompatible.
> +      compositeType = Context.getObjCIdType();
> +    } else if (LHSTy->isObjCIdType() || RHSTy->isObjCIdType()) {
>       compositeType = Context.getObjCIdType();
>     } else {
>       Diag(QuestionLoc,  
> diag::ext_typecheck_cond_incompatible_operands)
> @@ -3312,6 +3310,11 @@
>   lhptee = lhsType->getAsPointerType()->getPointeeType();
>   rhptee = rhsType->getAsPointerType()->getPointeeType();
>
> +  return CheckPointeeTypesForAssignment(lhptee, rhptee);
> +}
> +
> +Sema::AssignConvertType
> +Sema::CheckPointeeTypesForAssignment(QualType lhptee, QualType  
> rhptee) {
>   // make sure we operate on the canonical type
>   lhptee = Context.getCanonicalType(lhptee);
>   rhptee = Context.getCanonicalType(rhptee);
> @@ -3443,7 +3446,7 @@
>       return Compatible;
>     return Incompatible;
>   }
> -
> +  // FIXME: Look into removing. With ObjCObjectPointerType, I don't  
> see a need.
>   if (lhsType->isObjCQualifiedIdType() || rhsType- 
> >isObjCQualifiedIdType()) {
>     if (ObjCQualifiedIdTypesAreCompatible(lhsType, rhsType, false))
>       return Compatible;
> @@ -3454,7 +3457,6 @@
>       return PointerToInt;
>     return IncompatibleObjCQualifiedId;
>   }
> -
>   // Allow scalar to ExtVector assignments, and assignments of an  
> ExtVector type
>   // to the same ExtVector type.
>   if (lhsType->isExtVectorType()) {
> @@ -3486,13 +3488,18 @@
>     if (isa<PointerType>(rhsType))
>       return CheckPointerTypesForAssignment(lhsType, rhsType);
>
> +    if (isa<ObjCObjectPointerType>(rhsType)) {
> +      QualType rhptee = rhsType->getAsObjCObjectPointerType()- 
> >getPointeeType();
> +      QualType lhptee = lhsType->getAsPointerType()- 
> >getPointeeType();
> +      return CheckPointeeTypesForAssignment(lhptee, rhptee);
> +    }
> +
>     if (rhsType->getAsBlockPointerType()) {
>       if (lhsType->getAsPointerType()->getPointeeType()->isVoidType())
>         return Compatible;
>
>       // Treat block pointers as objects.
> -      if (getLangOptions().ObjC1 &&
> -          lhsType ==  
> Context.getCanonicalType(Context.getObjCIdType()))
> +      if (getLangOptions().ObjC1 && lhsType->isObjCIdType())
>         return Compatible;
>     }
>     return Incompatible;
> @@ -3503,8 +3510,7 @@
>       return IntToBlockPointer;
>
>     // Treat block pointers as objects.
> -    if (getLangOptions().ObjC1 &&
> -        rhsType == Context.getCanonicalType(Context.getObjCIdType()))
> +    if (getLangOptions().ObjC1 && rhsType->isObjCIdType())
>       return Compatible;
>
>     if (rhsType->isBlockPointerType())
> @@ -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);
> +    }
> +    if (rhsType->isObjCObjectPointerType()) {
> +      QualType lhptee = lhsType->getAsObjCObjectPointerType()- 
> >getPointeeType();
> +      QualType rhptee = rhsType->getAsObjCObjectPointerType()- 
> >getPointeeType();
> +      return CheckPointeeTypesForAssignment(lhptee, rhptee);
> +    }
> +    if (const PointerType *RHSPT = rhsType->getAsPointerType()) {
> +      if (RHSPT->getPointeeType()->isVoidType())
> +        return Compatible;
> +    }
> +    // Treat block pointers as objects.
> +    if (rhsType->isBlockPointerType())
> +      return Compatible;
> +    return Incompatible;
> +  }
>   if (isa<PointerType>(rhsType)) {
>     // C99 6.5.16.1p1: the left operand is _Bool and the right is a  
> pointer.
>     if (lhsType == Context.BoolTy)
> @@ -3533,6 +3562,24 @@
>       return Compatible;
>     return Incompatible;
>   }
> +  if (isa<ObjCObjectPointerType>(rhsType)) {
> +    // C99 6.5.16.1p1: the left operand is _Bool and the right is a  
> pointer.
> +    if (lhsType == Context.BoolTy)
> +      return Compatible;
> +
> +    if (lhsType->isIntegerType())
> +      return PointerToInt;
> +
> +    if (isa<PointerType>(lhsType)) {
> +      QualType rhptee = lhsType->getAsObjCObjectPointerType()- 
> >getPointeeType();
> +      QualType lhptee = rhsType->getAsPointerType()- 
> >getPointeeType();
> +      return CheckPointeeTypesForAssignment(lhptee, rhptee);
> +    }
> +    if (isa<BlockPointerType>(lhsType) &&
> +        rhsType->getAsPointerType()->getPointeeType()->isVoidType())
> +      return Compatible;
> +    return Incompatible;
> +  }
>
>   if (isa<TagType>(lhsType) && isa<TagType>(rhsType)) {
>     if (Context.typesAreCompatible(lhsType, rhsType))
> @@ -3628,7 +3675,7 @@
>   // C99 6.5.16.1p1: the left operand is a pointer and the right is
>   // a null pointer constant.
>   if ((lhsType->isPointerType() ||
> -       lhsType->isObjCQualifiedIdType() ||
> +       lhsType->isObjCObjectPointerType() ||
>        lhsType->isBlockPointerType())
>       && rExpr->isNullPointerConstant(Context)) {
>     ImpCastExprToType(rExpr, lhsType);
> @@ -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())
>     std::swap(PExp, IExp);
>
> -  if (const PointerType *PTy = PExp->getType()->getAsPointerType()) {
> +  if (PExp->getType()->isPointerType() ||
> +      PExp->getType()->isObjCObjectPointerType()) {
> +
>     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();
> +
>       // Check for arithmetic on pointers to incomplete types.
>       if (PointeeTy->isVoidType()) {
>         if (getLangOptions().CPlusPlus) {
> @@ -3803,7 +3861,7 @@
>         // GNU extension: arithmetic on pointer to function
>         Diag(Loc, diag::ext_gnu_ptr_func_arith)
>           << lex->getType() << lex->getSourceRange();
> -      } else if (!PTy->isDependentType() &&
> +      } else if (((PTy && !PTy->isDependentType()) || OPT) &&
>                  RequireCompleteType(Loc, PointeeTy,
>                                  
> diag::err_typecheck_arithmetic_incomplete_type,
>                                      PExp->getSourceRange(),  
> SourceRange(),
> @@ -3855,10 +3913,16 @@
>     if (CompLHSTy) *CompLHSTy = compType;
>     return compType;
>   }
> -
> +
>   // Either ptr - int   or   ptr - ptr.
> -  if (const PointerType *LHSPTy = lex->getType()- 
> >getAsPointerType()) {
> -    QualType lpointee = LHSPTy->getPointeeType();
> +  if (lex->getType()->isPointerType() ||
> +      lex->getType()->isObjCObjectPointerType()) {
> +    QualType lpointee;
> +    if (const PointerType *LHSPTy = lex->getType()- 
> >getAsPointerType())
> +      lpointee = LHSPTy->getPointeeType();
> +    else if (const ObjCObjectPointerType *OPT =
> +              lex->getType()->getAsObjCObjectPointerType())
> +      lpointee = OPT->getPointeeType();
>
>     // The LHS must be an completely-defined object type.
>
> @@ -4156,8 +4220,7 @@
>     if (!LHSIsNull && !RHSIsNull &&                       // C99  
> 6.5.9p2
>         !LCanPointeeTy->isVoidType() && !RCanPointeeTy->isVoidType()  
> &&
>         ! 
> Context.typesAreCompatible(LCanPointeeTy.getUnqualifiedType(),
> -                                     
> RCanPointeeTy.getUnqualifiedType()) &&
> -        !Context.areComparableObjCPointerTypes(lType, rType)) {
> +                                     
> RCanPointeeTy.getUnqualifiedType())) {
>       Diag(Loc, diag::ext_typecheck_comparison_of_distinct_pointers)
>         << lType << rType << lex->getSourceRange() << rex- 
> >getSourceRange();
>     }
> @@ -4207,7 +4270,7 @@
>     return ResultTy;
>   }
>
> -  if ((lType->isObjCQualifiedIdType() || rType- 
> >isObjCQualifiedIdType())) {
> +  if ((lType->isObjCObjectPointerType() || rType- 
> >isObjCObjectPointerType())) {
>     if (lType->isPointerType() || rType->isPointerType()) {
>       const PointerType *LPT = lType->getAsPointerType();
>       const PointerType *RPT = rType->getAsPointerType();
> @@ -4226,19 +4289,27 @@
>       ImpCastExprToType(rex, lType);
>       return ResultTy;
>     }
> -    if (ObjCQualifiedIdTypesAreCompatible(lType, rType, true)) {
> -      ImpCastExprToType(rex, lType);
> -      return ResultTy;
> -    } else {
> -      if ((lType->isObjCQualifiedIdType() && rType- 
> >isObjCQualifiedIdType())) {
> -        Diag(Loc, diag::warn_incompatible_qualified_id_operands)
> +    if (lType->isObjCObjectPointerType() && rType- 
> >isObjCObjectPointerType()) {
> +      if (!Context.areComparableObjCPointerTypes(lType, rType)) {
> +        Diag(Loc,  
> diag::ext_typecheck_comparison_of_distinct_pointers)
>           << lType << rType << lex->getSourceRange() << rex- 
> >getSourceRange();
> -        ImpCastExprToType(rex, lType);
> -        return ResultTy;
>       }
> +      if (lType->isObjCQualifiedIdType() && rType- 
> >isObjCQualifiedIdType()) {
> +        if (ObjCQualifiedIdTypesAreCompatible(lType, rType, true)) {
> +          ImpCastExprToType(rex, lType);
> +          return ResultTy;
> +        } else {
> +          Diag(Loc, diag::warn_incompatible_qualified_id_operands)
> +            << lType << rType << lex->getSourceRange() << rex- 
> >getSourceRange();
> +          ImpCastExprToType(rex, lType);
> +          return ResultTy;
> +        }
> +      }
> +      ImpCastExprToType(rex, lType);
> +      return ResultTy;
>     }
>   }
> -  if ((lType->isPointerType() || lType->isObjCQualifiedIdType()) &&
> +  if ((lType->isPointerType() || lType->isObjCObjectPointerType()) &&
>        rType->isIntegerType()) {
>     if (isRelational)
>       Diag(Loc,  
> diag::ext_typecheck_ordered_comparison_of_pointer_integer)
> @@ -4250,7 +4321,7 @@
>     return ResultTy;
>   }
>   if (lType->isIntegerType() &&
> -      (rType->isPointerType() || rType->isObjCQualifiedIdType())) {
> +      (rType->isPointerType() || rType->isObjCObjectPointerType())) {
>     if (isRelational)
>       Diag(Loc,  
> diag::ext_typecheck_ordered_comparison_of_pointer_integer)
>         << lType << rType << lex->getSourceRange() << rex- 
> >getSourceRange();
> @@ -4358,12 +4429,11 @@
>     const ObjCPropertyRefExpr* PropExpr =  
> cast<ObjCPropertyRefExpr>(E);
>     if (ObjCPropertyDecl *PDecl = PropExpr->getProperty()) {
>       QualType BaseType = PropExpr->getBase()->getType();
> -      if (const PointerType *PTy = BaseType->getAsPointerType())
> -        if (const ObjCInterfaceType *IFTy =
> -            PTy->getPointeeType()->getAsObjCInterfaceType())
> -          if (ObjCInterfaceDecl *IFace = IFTy->getDecl())
> -            if (S.isPropertyReadonly(PDecl, IFace))
> -              return true;
> +      if (const ObjCObjectPointerType *OPT =
> +            BaseType->getAsObjCInterfacePointerType())
> +        if (ObjCInterfaceDecl *IFace = OPT->getInterfaceDecl())
> +          if (S.isPropertyReadonly(PDecl, IFace))
> +            return true;
>     }
>   }
>   return false;
> @@ -4524,9 +4594,17 @@
>     Diag(OpLoc, diag::warn_increment_bool) << Op->getSourceRange();
>   } else if (ResType->isRealType()) {
>     // OK!
> -  } else if (const PointerType *PT = ResType->getAsPointerType()) {
> +  } else if (ResType->getAsPointerType() ||ResType- 
> >isObjCObjectPointerType()) {
> +    QualType PointeeTy;
> +
> +    if (const PointerType *PTy = ResType->getAsPointerType())
> +      PointeeTy = PTy->getPointeeType();
> +    else if (const ObjCObjectPointerType *OPT =
> +               ResType->getAsObjCObjectPointerType())
> +      PointeeTy = OPT->getPointeeType();
> +
>     // C99 6.5.2.4p2, 6.5.6p2
> -    if (PT->getPointeeType()->isVoidType()) {
> +    if (PointeeTy->isVoidType()) {
>       if (getLangOptions().CPlusPlus) {
>         Diag(OpLoc, diag::err_typecheck_pointer_arith_void_type)
>           << Op->getSourceRange();
> @@ -4535,7 +4613,7 @@
>
>       // Pointer to void is a GNU extension in C.
>       Diag(OpLoc, diag::ext_gnu_void_ptr) << Op->getSourceRange();
> -    } else if (PT->getPointeeType()->isFunctionType()) {
> +    } else if (PointeeTy->isFunctionType()) {
>       if (getLangOptions().CPlusPlus) {
>         Diag(OpLoc, diag::err_typecheck_pointer_arith_function_type)
>           << Op->getType() << Op->getSourceRange();
> @@ -4544,7 +4622,7 @@
>
>       Diag(OpLoc, diag::ext_gnu_ptr_func_arith)
>         << ResType << Op->getSourceRange();
> -    } else if (RequireCompleteType(OpLoc, PT->getPointeeType(),
> +    } else if (RequireCompleteType(OpLoc, PointeeTy,
>                                 
> diag::err_typecheck_arithmetic_incomplete_type,
>                                    Op->getSourceRange(),  
> SourceRange(),
>                                    ResType))
> @@ -4741,6 +4819,9 @@
>   if (const PointerType *PT = Ty->getAsPointerType())
>     return PT->getPointeeType();
>
> +  if (const ObjCObjectPointerType *OPT = Ty- 
> >getAsObjCObjectPointerType())
> +    return OPT->getPointeeType();
> +
>   Diag(OpLoc, diag::err_typecheck_indirection_requires_pointer)
>     << Ty << Op->getSourceRange();
>   return QualType();
>
> Modified: cfe/trunk/lib/Sema/SemaExprCXX.cpp
> URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaExprCXX.cpp?rev=75314&r1=75313&r2=75314&view=diff
>
> = 
> = 
> = 
> = 
> = 
> = 
> = 
> = 
> ======================================================================
> --- cfe/trunk/lib/Sema/SemaExprCXX.cpp (original)
> +++ cfe/trunk/lib/Sema/SemaExprCXX.cpp Fri Jul 10 18:34:53 2009
> @@ -1482,7 +1482,8 @@
> QualType Sema::FindCompositePointerType(Expr *&E1, Expr *&E2) {
>   assert(getLangOptions().CPlusPlus && "This function assumes C++");
>   QualType T1 = E1->getType(), T2 = E2->getType();
> -  if(!T1->isPointerType() && !T2->isPointerType())
> +  if(!T1->isPointerType() && !T2->isPointerType() &&
> +     !T1->isObjCObjectPointerType() && !T2- 
> >isObjCObjectPointerType())
>     return QualType();
>
>   // C++0x 5.9p2
>
> Modified: cfe/trunk/lib/Sema/SemaExprObjC.cpp
> URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaExprObjC.cpp?rev=75314&r1=75313&r2=75314&view=diff
>
> = 
> = 
> = 
> = 
> = 
> = 
> = 
> = 
> ======================================================================
> --- cfe/trunk/lib/Sema/SemaExprObjC.cpp (original)
> +++ cfe/trunk/lib/Sema/SemaExprObjC.cpp Fri Jul 10 18:34:53 2009
> @@ -74,14 +74,14 @@
>   // interface private (even though it appears in the header files).
>   QualType Ty = Context.getObjCConstantStringInterface();
>   if (!Ty.isNull()) {
> -    Ty = Context.getPointerType(Ty);
> +    Ty = Context.getObjCObjectPointerType(Ty);
>   } else {
>     IdentifierInfo *NSIdent = &Context.Idents.get("NSString");
>     NamedDecl *IF = LookupName(TUScope, NSIdent, LookupOrdinaryName);
>     if (ObjCInterfaceDecl *StrIF =  
> dyn_cast_or_null<ObjCInterfaceDecl>(IF)) {
>       Context.setObjCConstantStringInterface(StrIF);
>       Ty = Context.getObjCConstantStringInterface();
> -      Ty = Context.getPointerType(Ty);
> +      Ty = Context.getObjCObjectPointerType(Ty);
>     } else {
>       // If there is no NSString interface defined then treat constant
>       // strings as untyped objects and let the runtime figure it  
> out later.
> @@ -156,7 +156,7 @@
>   QualType Ty = Context.getObjCProtoType();
>   if (Ty.isNull())
>     return true;
> -  Ty = Context.getPointerType(Ty);
> +  Ty = Context.getObjCObjectPointerType(Ty);
>   return new (Context) ObjCProtocolExpr(Ty, PDecl, AtLoc, RParenLoc);
> }
>
> @@ -390,7 +390,7 @@
>         return Diag(lbrac, diag::error_no_super_class) << OID- 
> >getDeclName();
>       if (getCurMethodDecl()->isInstanceMethod()) {
>         QualType superTy = Context.getObjCInterfaceType(ClassDecl);
> -        superTy = Context.getPointerType(superTy);
> +        superTy = Context.getObjCObjectPointerType(superTy);
>         ExprResult ReceiverExpr = new (Context)  
> ObjCSuperExpr(SourceLocation(),
>                                                                
> superTy);
>         // We are really in an instance method, redirect.
> @@ -527,7 +527,7 @@
>                                          rbrac, ArgExprs, NumArgs);
>   }
>
> -  // Handle messages to id.
> +  // Handle messages to id.
>   if (ReceiverCType ==  
> Context.getCanonicalType(Context.getObjCIdType()) ||
>       ReceiverCType->isBlockPointerType() ||
>       Context.isObjCNSObjectType(RExpr->getType())) {
> @@ -602,11 +602,11 @@
>       if (PDecl && (Method = PDecl->lookupClassMethod(Sel)))
>         break;
>     }
> -  } else if (const ObjCInterfaceType *OCIType =
> -                ReceiverCType->getAsPointerToObjCInterfaceType()) {
> +  } else if (const ObjCObjectPointerType *OCIType =
> +                ReceiverCType->getAsObjCInterfacePointerType()) {
>     // We allow sending a message to a pointer to an interface (an  
> object).
>
> -    ClassDecl = OCIType->getDecl();
> +    ClassDecl = OCIType->getInterfaceDecl();
>     // FIXME: consider using LookupInstanceMethodInGlobalPool, since  
> it will be
>     // faster than the following method (which can do *many* linear  
> searches).
>     // The idea is to add class info to InstanceMethodPool.
> @@ -614,7 +614,7 @@
>
>     if (!Method) {
>       // Search protocol qualifiers.
> -      for (ObjCQualifiedInterfaceType::qual_iterator QI = OCIType- 
> >qual_begin(),
> +      for (ObjCObjectPointerType::qual_iterator QI = OCIType- 
> >qual_begin(),
>            E = OCIType->qual_end(); QI != E; ++QI) {
>         if ((Method = (*QI)->lookupInstanceMethod(Sel)))
>           break;
> @@ -631,9 +631,9 @@
>         if (OCIType->qual_empty()) {
>           Method = LookupInstanceMethodInGlobalPool(
>                                Sel, SourceRange(lbrac,rbrac));
> -          if (Method && !OCIType->getDecl()->isForwardDecl())
> +          if (Method && !OCIType->getInterfaceDecl()- 
> >isForwardDecl())
>             Diag(lbrac, diag::warn_maynot_respond)
> -              << OCIType->getDecl()->getIdentifier()->getName() <<  
> Sel;
> +              << OCIType->getInterfaceDecl()->getIdentifier()- 
> >getName() << Sel;
>         }
>       }
>     }
> @@ -741,60 +741,36 @@
> bool Sema::ObjCQualifiedIdTypesAreCompatible(QualType lhs, QualType  
> rhs,
>                                              bool compare) {
>   // Allow id<P..> and an 'id' or void* type in all cases.
> -  if (const PointerType *PT = lhs->getAsPointerType()) {
> -    QualType PointeeTy = PT->getPointeeType();
> -    if (PointeeTy->isVoidType() ||
> -        Context.isObjCIdStructType(PointeeTy) ||
> -        Context.isObjCClassStructType(PointeeTy))
> -      return true;
> -  } else if (const PointerType *PT = rhs->getAsPointerType()) {
> -    QualType PointeeTy = PT->getPointeeType();
> -    if (PointeeTy->isVoidType() ||
> -        Context.isObjCIdStructType(PointeeTy) ||
> -        Context.isObjCClassStructType(PointeeTy))
> -      return true;
> -  }
> -
> +  if (lhs->isVoidPointerType() ||
> +      lhs->isObjCIdType() || lhs->isObjCClassType())
> +    return true;
> +  else if (rhs->isVoidPointerType() ||
> +           rhs->isObjCIdType() || rhs->isObjCClassType())
> +    return true;
> +
>   if (const ObjCObjectPointerType *lhsQID = lhs- 
> >getAsObjCQualifiedIdType()) {
> -    const ObjCObjectPointerType *rhsQID = rhs- 
> >getAsObjCQualifiedIdType();
> -    const ObjCQualifiedInterfaceType *rhsQI = 0;
> -    QualType rtype;
> -
> -    if (!rhsQID) {
> -      // Not comparing two ObjCQualifiedIdType's?
> -      if (!rhs->isPointerType()) return false;
> -
> -      rtype = rhs->getAsPointerType()->getPointeeType();
> -      rhsQI = rtype->getAsObjCQualifiedInterfaceType();
> -      if (rhsQI == 0) {
> -        // If the RHS is a unqualified interface pointer "NSString*",
> -        // make sure we check the class hierarchy.
> -        if (const ObjCInterfaceType *IT = rtype- 
> >getAsObjCInterfaceType()) {
> -          ObjCInterfaceDecl *rhsID = IT->getDecl();
> -          for (ObjCObjectPointerType::qual_iterator I = lhsQID- 
> >qual_begin(),
> -               E = lhsQID->qual_end(); I != E; ++I) {
> -            // when comparing an id<P> on lhs with a static type on  
> rhs,
> -            // see if static class implements all of id's  
> protocols, directly or
> -            // through its super class and categories.
> -            if (!ClassImplementsProtocol(*I, rhsID, true))
> -              return false;
> -          }
> -          return true;
> -        }
> -      }
> -    }
> +    const ObjCObjectPointerType *rhsOPT = rhs- 
> >getAsObjCObjectPointerType();
>
> -    ObjCObjectPointerType::qual_iterator RHSProtoI, RHSProtoE;
> -    if (rhsQI) { // We have a qualified interface (e.g.  
> "NSObject<Proto> *").
> -      RHSProtoI = rhsQI->qual_begin();
> -      RHSProtoE = rhsQI->qual_end();
> -    } else if (rhsQID) { // We have a qualified id (e.g. "id<Proto>  
> *").
> -      RHSProtoI = rhsQID->qual_begin();
> -      RHSProtoE = rhsQID->qual_end();
> -    } else {
> -      return false;
> -    }
> +    if (!rhsOPT) return false;
>
> +    if (rhsOPT->qual_empty()) {
> +      // If the RHS is a unqualified interface pointer "NSString*",
> +      // make sure we check the class hierarchy.
> +      if (ObjCInterfaceDecl *rhsID = rhsOPT->getInterfaceDecl()) {
> +        for (ObjCObjectPointerType::qual_iterator I = lhsQID- 
> >qual_begin(),
> +             E = lhsQID->qual_end(); I != E; ++I) {
> +          // when comparing an id<P> on lhs with a static type on  
> rhs,
> +          // see if static class implements all of id's protocols,  
> directly or
> +          // through its super class and categories.
> +          if (!ClassImplementsProtocol(*I, rhsID, true))
> +            return false;
> +        }
> +        return true;
> +      }
> +      // If there are no qualifiers and no interface, we have an  
> 'id'.
> +      return true;
> +    }
> +    // Both the right and left sides have qualifiers.
>     for (ObjCObjectPointerType::qual_iterator I = lhsQID- 
> >qual_begin(),
>          E = lhsQID->qual_end(); I != E; ++I) {
>       ObjCProtocolDecl *lhsProto = *I;
> @@ -803,28 +779,26 @@
>       // when comparing an id<P> on lhs with a static type on rhs,
>       // see if static class implements all of id's protocols,  
> directly or
>       // through its super class and categories.
> -      for (; RHSProtoI != RHSProtoE; ++RHSProtoI) {
> -        ObjCProtocolDecl *rhsProto = *RHSProtoI;
> +      for (ObjCObjectPointerType::qual_iterator J = rhsOPT- 
> >qual_begin(),
> +           E = rhsOPT->qual_end(); J != E; ++J) {
> +        ObjCProtocolDecl *rhsProto = *J;
>         if (ProtocolCompatibleWithProtocol(lhsProto, rhsProto) ||
>             (compare && ProtocolCompatibleWithProtocol(rhsProto,  
> lhsProto))) {
>           match = true;
>           break;
>         }
>       }
> -      if (rhsQI) {
> -        // If the RHS is a qualified interface pointer  
> "NSString<P>*",
> -        // make sure we check the class hierarchy.
> -        if (const ObjCInterfaceType *IT = rtype- 
> >getAsObjCInterfaceType()) {
> -          ObjCInterfaceDecl *rhsID = IT->getDecl();
> -          for (ObjCObjectPointerType::qual_iterator I = lhsQID- 
> >qual_begin(),
> -               E = lhsQID->qual_end(); I != E; ++I) {
> -            // when comparing an id<P> on lhs with a static type on  
> rhs,
> -            // see if static class implements all of id's  
> protocols, directly or
> -            // through its super class and categories.
> -            if (ClassImplementsProtocol(*I, rhsID, true)) {
> -              match = true;
> -              break;
> -            }
> +      // If the RHS is a qualified interface pointer "NSString<P>*",
> +      // make sure we check the class hierarchy.
> +      if (ObjCInterfaceDecl *rhsID = rhsOPT->getInterfaceDecl()) {
> +        for (ObjCObjectPointerType::qual_iterator I = lhsQID- 
> >qual_begin(),
> +             E = lhsQID->qual_end(); I != E; ++I) {
> +          // when comparing an id<P> on lhs with a static type on  
> rhs,
> +          // see if static class implements all of id's protocols,  
> directly or
> +          // through its super class and categories.
> +          if (ClassImplementsProtocol(*I, rhsID, true)) {
> +            match = true;
> +            break;
>           }
>         }
>       }
> @@ -837,7 +811,52 @@
>
>   const ObjCObjectPointerType *rhsQID = rhs- 
> >getAsObjCQualifiedIdType();
>   assert(rhsQID && "One of the LHS/RHS should be id<x>");
> -
> +
> +  if (const ObjCObjectPointerType *lhsOPT =
> +        lhs->getAsObjCInterfacePointerType()) {
> +    if (lhsOPT->qual_empty()) {
> +      bool match = false;
> +      if (ObjCInterfaceDecl *lhsID = lhsOPT->getInterfaceDecl()) {
> +        for (ObjCObjectPointerType::qual_iterator I = rhsQID- 
> >qual_begin(),
> +             E = rhsQID->qual_end(); I != E; ++I) {
> +          // when comparing an id<P> on lhs with a static type on  
> rhs,
> +          // see if static class implements all of id's protocols,  
> directly or
> +          // through its super class and categories.
> +          if (ClassImplementsProtocol(*I, lhsID, true)) {
> +            match = true;
> +            break;
> +          }
> +        }
> +        if (!match)
> +          return false;
> +      }
> +      return true;
> +    }
> +    // Both the right and left sides have qualifiers.
> +    for (ObjCObjectPointerType::qual_iterator I = lhsOPT- 
> >qual_begin(),
> +         E = lhsOPT->qual_end(); I != E; ++I) {
> +      ObjCProtocolDecl *lhsProto = *I;
> +      bool match = false;
> +
> +      // when comparing an id<P> on lhs with a static type on rhs,
> +      // see if static class implements all of id's protocols,  
> directly or
> +      // through its super class and categories.
> +      for (ObjCObjectPointerType::qual_iterator J = rhsQID- 
> >qual_begin(),
> +           E = rhsQID->qual_end(); J != E; ++J) {
> +        ObjCProtocolDecl *rhsProto = *J;
> +        if (ProtocolCompatibleWithProtocol(lhsProto, rhsProto) ||
> +            (compare && ProtocolCompatibleWithProtocol(rhsProto,  
> lhsProto))) {
> +          match = true;
> +          break;
> +        }
> +      }
> +      if (!match)
> +        return false;
> +    }
> +    return true;
> +  }
> +  // FIXME: The code below will be removed when  
> ObjCQualifiedInterfaceType is
> +  // removed.
>   if (!lhs->isPointerType())
>     return false;
>
> @@ -864,17 +883,6 @@
>     return true;
>   }
>
> -  if (const ObjCInterfaceType *IT = ltype- 
> >getAsObjCInterfaceType()) {
> -    // for static type vs. qualified 'id' type, check that class  
> implements
> -    // all of 'id's protocols.
> -    ObjCInterfaceDecl *lhsID = IT->getDecl();
> -    for (ObjCObjectPointerType::qual_iterator I = rhsQID- 
> >qual_begin(),
> -         E = rhsQID->qual_end(); I != E; ++I) {
> -      if (!ClassImplementsProtocol(*I, lhsID, compare, true))
> -        return false;
> -    }
> -    return true;
> -  }
>   return false;
> }
>
>
> Modified: cfe/trunk/lib/Sema/SemaOverload.cpp
> URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaOverload.cpp?rev=75314&r1=75313&r2=75314&view=diff
>
> = 
> = 
> = 
> = 
> = 
> = 
> = 
> = 
> ======================================================================
> --- cfe/trunk/lib/Sema/SemaOverload.cpp (original)
> +++ cfe/trunk/lib/Sema/SemaOverload.cpp Fri Jul 10 18:34:53 2009
> @@ -1005,77 +1005,64 @@
>   if (!getLangOptions().ObjC1)
>     return false;
>
> -  // Conversions with Objective-C's id<...>.
> -  if ((FromType->isObjCQualifiedIdType() || ToType- 
> >isObjCQualifiedIdType()) &&
> -      ObjCQualifiedIdTypesAreCompatible(ToType, FromType, / 
> *compare=*/false)) {
> -    ConvertedType = ToType;
> -    return true;
> -  }
> +  // First, we handle all conversions on ObjC object pointer types.
> +  const ObjCObjectPointerType* ToObjCPtr = ToType- 
> >getAsObjCObjectPointerType();
> +  const ObjCObjectPointerType *FromObjCPtr =
> +    FromType->getAsObjCObjectPointerType();
> +
> +  if (ToObjCPtr && FromObjCPtr) {
> +    // Objective C++: We're able to convert between "id" and a  
> pointer
> +    // to any interface (in both directions).
> +    if (ToObjCPtr->isObjCIdType() && FromObjCPtr->isObjCIdType()) {
> +      ConvertedType = ToType;
> +      return true;
> +    }
> +    // Objective C++: Allow conversions between the Objective-C  
> "Class" and a
> +    // pointer to any interface (in both directions).
> +    if (ToObjCPtr->isObjCClassType() || FromObjCPtr- 
> >isObjCClassType()) {
> +      ConvertedType = ToType;
> +      return true;
> +    }
> +    // Conversions with Objective-C's id<...>.
> +    if ((FromObjCPtr->isObjCQualifiedIdType() ||
> +         ToObjCPtr->isObjCQualifiedIdType()) &&
> +        ObjCQualifiedIdTypesAreCompatible(ToType, FromType, / 
> *compare=*/false)) {
> +      ConvertedType = ToType;
> +      return true;
> +    }
> +    // Objective C++: We're able to convert from a pointer to an
> +    // interface to a pointer to a different interface.
> +    if (Context.canAssignObjCInterfaces(ToObjCPtr, FromObjCPtr)) {
> +      ConvertedType = ToType;
> +      return true;
> +    }
>
> -  // Beyond this point, both types need to be pointers or block  
> pointers.
> +    if (Context.canAssignObjCInterfaces(FromObjCPtr, ToObjCPtr)) {
> +      // Okay: this is some kind of implicit downcast of Objective-C
> +      // interfaces, which is permitted. However, we're going to
> +      // complain about it.
> +      IncompatibleObjC = true;
> +      ConvertedType = FromType;
> +      return true;
> +    }
> +  }
> +  // Beyond this point, both types need to be C pointers or block  
> pointers.
>   QualType ToPointeeType;
> -  const PointerType* ToTypePtr = ToType->getAsPointerType();
> -  if (ToTypePtr)
> -    ToPointeeType = ToTypePtr->getPointeeType();
> +  if (const PointerType *ToCPtr = ToType->getAsPointerType())
> +    ToPointeeType = ToCPtr->getPointeeType();
>   else if (const BlockPointerType *ToBlockPtr = ToType- 
> >getAsBlockPointerType())
>     ToPointeeType = ToBlockPtr->getPointeeType();
>   else
>     return false;
>
>   QualType FromPointeeType;
> -  const PointerType *FromTypePtr = FromType->getAsPointerType();
> -  if (FromTypePtr)
> -    FromPointeeType = FromTypePtr->getPointeeType();
> -  else if (const BlockPointerType *FromBlockPtr
> -             = FromType->getAsBlockPointerType())
> +  if (const PointerType *FromCPtr = FromType->getAsPointerType())
> +    FromPointeeType = FromCPtr->getPointeeType();
> +  else if (const BlockPointerType *FromBlockPtr = FromType- 
> >getAsBlockPointerType())
>     FromPointeeType = FromBlockPtr->getPointeeType();
>   else
>     return false;
>
> -  // Objective C++: We're able to convert from a pointer to an
> -  // interface to a pointer to a different interface.
> -  const ObjCInterfaceType* FromIface = FromPointeeType- 
> >getAsObjCInterfaceType();
> -  const ObjCInterfaceType* ToIface = ToPointeeType- 
> >getAsObjCInterfaceType();
> -  if (FromIface && ToIface &&
> -      Context.canAssignObjCInterfaces(ToIface, FromIface)) {
> -    ConvertedType = BuildSimilarlyQualifiedPointerType(FromTypePtr,
> -                                                       ToPointeeType,
> -                                                       ToType,  
> Context);
> -    return true;
> -  }
> -
> -  if (FromIface && ToIface &&
> -      Context.canAssignObjCInterfaces(FromIface, ToIface)) {
> -    // Okay: this is some kind of implicit downcast of Objective-C
> -    // interfaces, which is permitted. However, we're going to
> -    // complain about it.
> -    IncompatibleObjC = true;
> -    ConvertedType = BuildSimilarlyQualifiedPointerType(FromTypePtr,
> -                                                       ToPointeeType,
> -                                                       ToType,  
> Context);
> -    return true;
> -  }
> -
> -  // Objective C++: We're able to convert between "id" and a pointer
> -  // to any interface (in both directions).
> -  if ((FromIface && Context.isObjCIdStructType(ToPointeeType))
> -      || (ToIface && Context.isObjCIdStructType(FromPointeeType))) {
> -    ConvertedType = BuildSimilarlyQualifiedPointerType(FromTypePtr,
> -                                                       ToPointeeType,
> -                                                       ToType,  
> Context);
> -    return true;
> -  }
> -
> -  // Objective C++: Allow conversions between the Objective-C "id"  
> and
> -  // "Class", in either direction.
> -  if ((Context.isObjCIdStructType(FromPointeeType) &&
> -       Context.isObjCClassStructType(ToPointeeType)) ||
> -      (Context.isObjCClassStructType(FromPointeeType) &&
> -       Context.isObjCIdStructType(ToPointeeType))) {
> -    ConvertedType = ToType;
> -    return true;
> -  }
> -
>   // If we have pointers to pointers, recursively check whether this
>   // is an Objective-C conversion.
>   if (FromPointeeType->isPointerType() && ToPointeeType- 
> >isPointerType() &&
> @@ -1086,7 +1073,6 @@
>     ConvertedType = ToType;
>     return true;
>   }
> -
>   // If we have pointers to functions or blocks, check whether the  
> only
>   // differences in the argument and result types are in Objective-C
>   // pointer conversions. If so, we permit the conversion (but
> @@ -1167,15 +1153,6 @@
>       QualType FromPointeeType = FromPtrType->getPointeeType(),
>                ToPointeeType   = ToPtrType->getPointeeType();
>
> -      // Objective-C++ conversions are always okay.
> -      // FIXME: We should have a different class of conversions for  
> the
> -      // Objective-C++ implicit conversions.
> -      if (Context.isObjCIdStructType(FromPointeeType) ||
> -          Context.isObjCIdStructType(ToPointeeType) ||
> -          Context.isObjCClassStructType(FromPointeeType) ||
> -          Context.isObjCClassStructType(ToPointeeType))
> -        return false;
> -
>       if (FromPointeeType->isRecordType() &&
>           ToPointeeType->isRecordType()) {
>         // We must have a derived-to-base conversion. Check an
> @@ -1185,7 +1162,18 @@
>                                             From->getSourceRange());
>       }
>     }
> +  if (const ObjCObjectPointerType *FromPtrType =
> +        FromType->getAsObjCObjectPointerType())
> +    if (const ObjCObjectPointerType *ToPtrType =
> +          ToType->getAsObjCObjectPointerType()) {
> +      // Objective-C++ conversions are always okay.
> +      // FIXME: We should have a different class of conversions for  
> the
> +      // Objective-C++ implicit conversions.
> +      if (FromPtrType->isObjCIdType() || ToPtrType->isObjCIdType() ||
> +          FromPtrType->isObjCClassType() || ToPtrType- 
> >isObjCClassType())
> +        return false;
>
> +  }
>   return false;
> }
>
>
> Modified: cfe/trunk/lib/Sema/SemaType.cpp
> URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaType.cpp?rev=75314&r1=75313&r2=75314&view=diff
>
> = 
> = 
> = 
> = 
> = 
> = 
> = 
> = 
> ======================================================================
> --- cfe/trunk/lib/Sema/SemaType.cpp (original)
> +++ cfe/trunk/lib/Sema/SemaType.cpp Fri Jul 10 18:34:53 2009
> @@ -91,7 +91,8 @@
>   case DeclSpec::TST_unspecified:
>     // "<proto1,proto2>" is an objc qualified ID with a missing id.
>     if (DeclSpec::ProtocolQualifierListTy PQ =  
> DS.getProtocolQualifiers()) {
> -      Result = Context.getObjCObjectPointerType(0,  
> (ObjCProtocolDecl**)PQ,
> +      Result = Context.getObjCObjectPointerType(QualType(),
> +                                                 
> (ObjCProtocolDecl**)PQ,
>                                                  
> DS.getNumProtocolQualifiers());
>       break;
>     }
> @@ -197,14 +198,16 @@
>       // FIXME: Adding a TST_objcInterface clause doesn't seem  
> ideal, so we have
>       // this "hack" for now...
>       if (const ObjCInterfaceType *Interface = Result- 
> >getAsObjCInterfaceType())
> +        // FIXME: Remove ObjCQualifiedInterfaceType (by moving the  
> list of
> +        // protocols 'up' to ObjCInterfaceType).
>         Result = Context.getObjCQualifiedInterfaceType(Interface- 
> >getDecl(),
>                                                         
> (ObjCProtocolDecl**)PQ,
>                                                 
> DS.getNumProtocolQualifiers());
> -      else if (Result == Context.getObjCIdType())
> +      else if (Result->isObjCIdType())
>         // id<protocol-list>
> -        Result = Context.getObjCObjectPointerType(0,  
> (ObjCProtocolDecl**)PQ,
> -                                                  
> DS.getNumProtocolQualifiers());
> -      else if (Result == Context.getObjCClassType()) {
> +        Result = Context.getObjCObjectPointerType(QualType(),
> +                        (ObjCProtocolDecl**)PQ,  
> DS.getNumProtocolQualifiers());
> +      else if (Result->isObjCClassType()) {
>         if (DeclLoc.isInvalid())
>           DeclLoc = DS.getSourceRange().getBegin();
>         // Class<protocol-list>
> @@ -886,6 +889,13 @@
>         D.setInvalidType(true);
>         // Build the type anyway.
>       }
> +      if (getLangOptions().ObjC1 && T->isObjCInterfaceType()) {
> +        const ObjCInterfaceType *OIT = T->getAsObjCInterfaceType();
> +        T = Context.getObjCObjectPointerType(T,
> +                                       (ObjCProtocolDecl **)OIT- 
> >qual_begin(),
> +                                       OIT->getNumProtocols());
> +        break;
> +      }
>       T = BuildPointerType(T, DeclType.Ptr.TypeQuals, DeclType.Loc,  
> Name);
>       break;
>     case DeclaratorChunk::Reference:
>
> Modified: cfe/trunk/test/CodeGenObjC/encode-test.m
> URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CodeGenObjC/encode-test.m?rev=75314&r1=75313&r2=75314&view=diff
>
> = 
> = 
> = 
> = 
> = 
> = 
> = 
> = 
> ======================================================================
> --- cfe/trunk/test/CodeGenObjC/encode-test.m (original)
> +++ 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
>
> Modified: cfe/trunk/test/CodeGenObjC/overloadable.m
> URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CodeGenObjC/overloadable.m?rev=75314&r1=75313&r2=75314&view=diff
>
> = 
> = 
> = 
> = 
> = 
> = 
> = 
> = 
> ======================================================================
> --- cfe/trunk/test/CodeGenObjC/overloadable.m (original)
> +++ 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) { }
>
> Modified: cfe/trunk/test/PCH/objc_exprs.m
> URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/PCH/objc_exprs.m?rev=75314&r1=75313&r2=75314&view=diff
>
> = 
> = 
> = 
> = 
> = 
> = 
> = 
> = 
> ======================================================================
> --- cfe/trunk/test/PCH/objc_exprs.m (original)
> +++ cfe/trunk/test/PCH/objc_exprs.m Fri Jul 10 18:34:53 2009
> @@ -6,7 +6,7 @@
> // RUN: clang-cc -fblocks -include-pch %t -fsyntax-only -verify %s
>
> // Expressions
> -int *A1 = (objc_string)0;   // expected-warning {{'struct  
> objc_object *'}}
> +int *A1 = (objc_string)0;   // expected-warning {{aka 'id'}}
>
> char A2 = (objc_encode){};  // expected-error {{not a compile-time  
> constant}} \
>                                expected-warning {{char [2]}}
> @@ -15,8 +15,7 @@
>
>
> // Types.
> -int *T0 = (objc_id_protocol_ty)0; // expected-error {{not a compile- 
> time constant}} \
> -                                     expected-warning {{aka  
> 'id<foo>'}}
> +int *T0 = (objc_id_protocol_ty)0; // expected-warning {{aka  
> 'id<foo>'}}
>
> int *T1 = (objc_interface_ty)0; // expected-warning {{aka 'itf *'}}
> int *T2 = (objc_qual_interface_ty)0; // expected-warning {{aka  
> 'itf<foo> *'}}
>
> Modified: cfe/trunk/test/SemaObjC/comptypes-5.m
> URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/SemaObjC/comptypes-5.m?rev=75314&r1=75313&r2=75314&view=diff
>
> = 
> = 
> = 
> = 
> = 
> = 
> = 
> = 
> ======================================================================
> --- cfe/trunk/test/SemaObjC/comptypes-5.m (original)
> +++ 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;
>   obj_id_p = obj_c_cat_p;  /* Ok */
>   obj_id_p = obj_c_super_p; /* Ok */
>
>
> Modified: cfe/trunk/test/SemaObjC/conditional-expr-3.m
> URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/SemaObjC/conditional-expr-3.m?rev=75314&r1=75313&r2=75314&view=diff
>
> = 
> = 
> = 
> = 
> = 
> = 
> = 
> = 
> ======================================================================
> --- cfe/trunk/test/SemaObjC/conditional-expr-3.m (original)
> +++ cfe/trunk/test/SemaObjC/conditional-expr-3.m Fri Jul 10 18:34:53  
> 2009
> @@ -59,7 +59,7 @@
> }
>
> void f10(int cond, id<P0,P1> x0, id<P0,P2> x1) {
> -  barP2(cond ? x0 : x1);
> +  barP2(cond ? x0 : x1); // expected-warning {{incompatible type  
> passing 'id<P0,P1>', expected 'id<P2>'}}

Why does the warning does not say 'expected 'id<P0, P2>' ?

Also, as chris pointed out, we can't break abi compatibility with gcc  
for encoding 'id' and 'Class'. We need to hack our way into  
compatibility at any cost.

Great work.

- Fariborz


>
> }




More information about the cfe-commits mailing list