[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