[cfe-commits] r75314 - in /cfe/trunk: include/clang/AST/ include/clang/Analysis/PathSensitive/ lib/AST/ lib/Analysis/ lib/CodeGen/ lib/Frontend/ lib/Sema/ test/CodeGenObjC/ test/PCH/ test/SemaObjC/ test/SemaObjCXX/
Steve Naroff
snaroff at apple.com
Fri Jul 10 16:35:08 PDT 2009
Author: snaroff
Date: Fri Jul 10 18:34:53 2009
New Revision: 75314
URL: http://llvm.org/viewvc/llvm-project?rev=75314&view=rev
Log:
This patch includes a conceptually simple, but very intrusive/pervasive change.
The idea is to segregate Objective-C "object" pointers from general C pointers (utilizing the recently added ObjCObjectPointerType). The fun starts in Sema::GetTypeForDeclarator(), where "SomeInterface *" is now represented by a single AST node (rather than a PointerType whose Pointee is an ObjCInterfaceType). Since a significant amount of code assumed ObjC object pointers where based on C pointers/structs, this patch is very tedious. It should also explain why it is hard to accomplish this in smaller, self-contained patches.
This patch does most of the "heavy lifting" related to moving from PointerType->ObjCObjectPointerType. It doesn't include all potential "cleanups". The good news is additional cleanups can be done later (some are noted in the code). This patch is so large that I didn't want to include any changes that are purely aesthetic.
By making the ObjC types truly built-in, they are much easier to work with (and require fewer "hacks"). For example, there is no need for ASTContext::isObjCIdStructType() or ASTContext::isObjCClassStructType()! We believe this change (and the follow-up cleanups) will pay dividends over time.
Given the amount of code change, I do expect some fallout from this change (though it does pass all of the clang tests). If you notice any problems, please let us know asap! Thanks.
Modified:
cfe/trunk/include/clang/AST/ASTContext.h
cfe/trunk/include/clang/AST/Type.h
cfe/trunk/include/clang/Analysis/PathSensitive/SVals.h
cfe/trunk/lib/AST/ASTContext.cpp
cfe/trunk/lib/AST/DeclObjC.cpp
cfe/trunk/lib/AST/Expr.cpp
cfe/trunk/lib/AST/ExprConstant.cpp
cfe/trunk/lib/AST/Type.cpp
cfe/trunk/lib/Analysis/BasicObjCFoundationChecks.cpp
cfe/trunk/lib/Analysis/CFRefCount.cpp
cfe/trunk/lib/Analysis/CheckNSError.cpp
cfe/trunk/lib/Analysis/CheckObjCInstMethSignature.cpp
cfe/trunk/lib/CodeGen/CGDebugInfo.cpp
cfe/trunk/lib/CodeGen/CGExpr.cpp
cfe/trunk/lib/CodeGen/CGExprScalar.cpp
cfe/trunk/lib/CodeGen/CGObjC.cpp
cfe/trunk/lib/CodeGen/CGObjCGNU.cpp
cfe/trunk/lib/CodeGen/CGObjCMac.cpp
cfe/trunk/lib/CodeGen/CodeGenTypes.cpp
cfe/trunk/lib/CodeGen/Mangle.cpp
cfe/trunk/lib/Frontend/PCHReader.cpp
cfe/trunk/lib/Frontend/PCHWriter.cpp
cfe/trunk/lib/Frontend/RewriteObjC.cpp
cfe/trunk/lib/Sema/Sema.cpp
cfe/trunk/lib/Sema/Sema.h
cfe/trunk/lib/Sema/SemaDecl.cpp
cfe/trunk/lib/Sema/SemaDeclAttr.cpp
cfe/trunk/lib/Sema/SemaDeclObjC.cpp
cfe/trunk/lib/Sema/SemaExpr.cpp
cfe/trunk/lib/Sema/SemaExprCXX.cpp
cfe/trunk/lib/Sema/SemaExprObjC.cpp
cfe/trunk/lib/Sema/SemaOverload.cpp
cfe/trunk/lib/Sema/SemaType.cpp
cfe/trunk/test/CodeGenObjC/encode-test.m
cfe/trunk/test/CodeGenObjC/overloadable.m
cfe/trunk/test/PCH/objc_exprs.m
cfe/trunk/test/SemaObjC/comptypes-5.m
cfe/trunk/test/SemaObjC/conditional-expr-3.m
cfe/trunk/test/SemaObjC/id.m
cfe/trunk/test/SemaObjC/message.m
cfe/trunk/test/SemaObjC/objc2-merge-gc-attribue-decl.m
cfe/trunk/test/SemaObjC/property-missing.m
cfe/trunk/test/SemaObjCXX/overload.mm
Modified: cfe/trunk/include/clang/AST/ASTContext.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/AST/ASTContext.h?rev=75314&r1=75313&r2=75314&view=diff
==============================================================================
--- cfe/trunk/include/clang/AST/ASTContext.h (original)
+++ cfe/trunk/include/clang/AST/ASTContext.h Fri Jul 10 18:34:53 2009
@@ -107,7 +107,6 @@
/// ObjCIdType - a pseudo built-in typedef type (set by Sema).
QualType ObjCIdType;
- const RecordType *IdStructType;
/// ObjCSelType - another pseudo built-in typedef type (set by Sema).
QualType ObjCSelType;
@@ -119,7 +118,6 @@
/// ObjCClassType - another pseudo built-in typedef type (set by Sema).
QualType ObjCClassType;
- const RecordType *ClassStructType;
QualType ObjCConstantStringType;
RecordDecl *CFConstantStringTypeDecl;
@@ -375,7 +373,7 @@
/// getObjCObjectPointerType - Return 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);
@@ -770,26 +768,18 @@
bool isObjCIdType(QualType T) const {
return T == ObjCIdType;
}
- bool isObjCIdStructType(QualType T) const {
- if (!IdStructType) // ObjC isn't enabled
- return false;
- return T->getAsStructureType() == IdStructType;
- }
bool isObjCClassType(QualType T) const {
return T == ObjCClassType;
}
- bool isObjCClassStructType(QualType T) const {
- if (!ClassStructType) // ObjC isn't enabled
- return false;
- return T->getAsStructureType() == ClassStructType;
- }
bool isObjCSelType(QualType T) const {
assert(SelStructType && "isObjCSelType used before 'SEL' type is built");
return T->getAsStructureType() == SelStructType;
}
// Check the safety of assignment from LHS to RHS
- bool canAssignObjCInterfaces(const ObjCInterfaceType *LHS,
+ bool canAssignObjCInterfaces(const ObjCObjectPointerType *LHSOPT,
+ const ObjCObjectPointerType *RHSOPT);
+ bool canAssignObjCInterfaces(const ObjCInterfaceType *LHS,
const ObjCInterfaceType *RHS);
bool areComparableObjCPointerTypes(QualType LHS, QualType RHS);
Modified: cfe/trunk/include/clang/AST/Type.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/AST/Type.h?rev=75314&r1=75313&r2=75314&view=diff
==============================================================================
--- cfe/trunk/include/clang/AST/Type.h (original)
+++ cfe/trunk/include/clang/AST/Type.h Fri Jul 10 18:34:53 2009
@@ -396,9 +396,13 @@
bool isVectorType() const; // GCC vector type.
bool isExtVectorType() const; // Extended vector type.
bool isObjCObjectPointerType() const; // Pointer to *any* ObjC object.
+ // FIXME: change this to 'raw' interface type, so we can used 'interface' type
+ // for the common case.
bool isObjCInterfaceType() const; // NSString or NSString<foo>
bool isObjCQualifiedInterfaceType() const; // NSString<foo>
bool isObjCQualifiedIdType() const; // id<foo>
+ bool isObjCIdType() const; // id
+ bool isObjCClassType() const; // Class
bool isTemplateTypeParmType() const; // C++ template type parameter
bool isNullPtrType() const; // C++0x nullptr_t
@@ -443,9 +447,12 @@
const ComplexType *getAsComplexIntegerType() const; // GCC complex int type.
const ExtVectorType *getAsExtVectorType() const; // Extended vector type.
const ObjCObjectPointerType *getAsObjCObjectPointerType() const;
+ // The following is a convenience method that returns an ObjCObjectPointerType
+ // for object declared using an interface.
+ const ObjCObjectPointerType *getAsObjCInterfacePointerType() const;
+ const ObjCObjectPointerType *getAsObjCQualifiedIdType() const;
const ObjCInterfaceType *getAsObjCInterfaceType() const;
const ObjCQualifiedInterfaceType *getAsObjCQualifiedInterfaceType() const;
- const ObjCObjectPointerType *getAsObjCQualifiedIdType() const;
const TemplateTypeParmType *getAsTemplateTypeParmType() const;
const TemplateSpecializationType *
@@ -460,6 +467,10 @@
/// This method should never be used when type qualifiers are meaningful.
const Type *getArrayElementTypeNoTypeQual() const;
+ /// getPointeeType - If this is a pointer or ObjC object pointer, this
+ /// returns the respective pointee.
+ QualType getPointeeType() const;
+
/// getDesugaredType - Return the specified type with any "sugar" removed from
/// the type. This takes off typedefs, typeof's etc. If the outer level of
/// the type is already concrete, it returns it unmodified. This is similar
@@ -1809,53 +1820,6 @@
static bool classof(const TypenameType *T) { return true; }
};
-/// ObjCObjectPointerType - Used to represent 'id', 'Interface *', 'id <p>',
-/// and 'Interface <p> *'.
-///
-/// Duplicate protocols are removed and protocol list is canonicalized to be in
-/// alphabetical order.
-class ObjCObjectPointerType : public Type, public llvm::FoldingSetNode {
- ObjCInterfaceDecl *Decl;
- // List of protocols for this protocol conforming object type
- // List is sorted on protocol name. No protocol is entered more than once.
- llvm::SmallVector<ObjCProtocolDecl*, 8> Protocols;
-
- ObjCObjectPointerType(ObjCInterfaceDecl *D,
- ObjCProtocolDecl **Protos, unsigned NumP) :
- Type(ObjCObjectPointer, QualType(), /*Dependent=*/false),
- Decl(D), Protocols(Protos, Protos+NumP) { }
- friend class ASTContext; // ASTContext creates these.
-
-public:
- ObjCInterfaceDecl *getDecl() const { return Decl; }
-
- /// isObjCQualifiedIdType - true for "id <p>".
- bool isObjCQualifiedIdType() const { return Decl == 0 && Protocols.size(); }
-
- /// qual_iterator and friends: this provides access to the (potentially empty)
- /// list of protocols qualifying this interface.
- typedef llvm::SmallVector<ObjCProtocolDecl*, 8>::const_iterator qual_iterator;
-
- qual_iterator qual_begin() const { return Protocols.begin(); }
- qual_iterator qual_end() const { return Protocols.end(); }
- bool qual_empty() const { return Protocols.size() == 0; }
-
- /// getNumProtocols - Return the number of qualifying protocols in this
- /// interface type, or 0 if there are none.
- unsigned getNumProtocols() const { return Protocols.size(); }
-
- void Profile(llvm::FoldingSetNodeID &ID);
- static void Profile(llvm::FoldingSetNodeID &ID,
- const ObjCInterfaceDecl *Decl,
- ObjCProtocolDecl **protocols, unsigned NumProtocols);
- virtual void getAsStringInternal(std::string &InnerString,
- const PrintingPolicy &Policy) const;
- static bool classof(const Type *T) {
- return T->getTypeClass() == ObjCObjectPointer;
- }
- static bool classof(const ObjCObjectPointerType *) { return true; }
-};
-
/// ObjCInterfaceType - Interfaces are the core concept in Objective-C for
/// object oriented design. They basically correspond to C++ classes. There
/// are two kinds of interface types, normal interfaces like "NSString" and
@@ -1868,10 +1832,15 @@
ObjCInterfaceType(TypeClass tc, ObjCInterfaceDecl *D) :
Type(tc, QualType(), /*Dependent=*/false), Decl(D) { }
friend class ASTContext; // ASTContext creates these.
+
+ // FIXME: These can go away when we move ASTContext::canAssignObjCInterfaces
+ // to this class (as a static helper).
+ bool isObjCIdInterface() const;
+ bool isObjCClassInterface() const;
public:
ObjCInterfaceDecl *getDecl() const { return Decl; }
-
+
/// qual_iterator and friends: this provides access to the (potentially empty)
/// list of protocols qualifying this interface. If this is an instance of
/// ObjCQualifiedInterfaceType it returns the list, otherwise it returns an
@@ -1893,11 +1862,85 @@
static bool classof(const ObjCInterfaceType *) { return true; }
};
+/// ObjCObjectPointerType - Used to represent 'id', 'Interface *', 'id <p>',
+/// and 'Interface <p> *'.
+///
+/// Duplicate protocols are removed and protocol list is canonicalized to be in
+/// alphabetical order.
+class ObjCObjectPointerType : public Type, public llvm::FoldingSetNode {
+ QualType PointeeType; // will always point to an interface type.
+
+ // List of protocols for this protocol conforming object type
+ // List is sorted on protocol name. No protocol is entered more than once.
+ llvm::SmallVector<ObjCProtocolDecl*, 8> Protocols;
+
+ ObjCObjectPointerType(QualType T, ObjCProtocolDecl **Protos, unsigned NumP) :
+ Type(ObjCObjectPointer, QualType(), /*Dependent=*/false),
+ PointeeType(T), Protocols(Protos, Protos+NumP) { }
+ friend class ASTContext; // ASTContext creates these.
+ friend class ObjCInterfaceType; // To enable 'id' and 'Class' predicates.
+
+ static ObjCInterfaceType *IdInterfaceT;
+ static ObjCInterfaceType *ClassInterfaceT;
+ static void setIdInterface(QualType T) {
+ IdInterfaceT = dyn_cast<ObjCInterfaceType>(T.getTypePtr());
+ }
+ static void setClassInterface(QualType T) {
+ ClassInterfaceT = dyn_cast<ObjCInterfaceType>(T.getTypePtr());
+ }
+ static ObjCInterfaceType *getIdInterface() { return IdInterfaceT; }
+ static ObjCInterfaceType *getClassInterface() { return ClassInterfaceT; }
+public:
+ // Get the pointee type. Pointee is required to always be an interface type.
+ // Note: Pointee can be a TypedefType whose canonical type is an interface.
+ // Example: typedef NSObject T; T *var;
+ QualType getPointeeType() const { return PointeeType; }
+
+ const ObjCInterfaceType *getInterfaceType() const {
+ return PointeeType->getAsObjCInterfaceType();
+ }
+ ObjCInterfaceDecl *getInterfaceDecl() const {
+ return getInterfaceType()->getDecl();
+ }
+ /// isObjCQualifiedIdType - true for "id <p>".
+ bool isObjCQualifiedIdType() const {
+ return getInterfaceType() == IdInterfaceT && Protocols.size();
+ }
+ bool isObjCIdType() const {
+ return getInterfaceType() == IdInterfaceT && !Protocols.size();
+ }
+ bool isObjCClassType() const {
+ return getInterfaceType() == ClassInterfaceT && !Protocols.size();
+ }
+ /// qual_iterator and friends: this provides access to the (potentially empty)
+ /// list of protocols qualifying this interface.
+ typedef llvm::SmallVector<ObjCProtocolDecl*, 8>::const_iterator qual_iterator;
+
+ qual_iterator qual_begin() const { return Protocols.begin(); }
+ qual_iterator qual_end() const { return Protocols.end(); }
+ bool qual_empty() const { return Protocols.size() == 0; }
+
+ /// getNumProtocols - Return the number of qualifying protocols in this
+ /// interface type, or 0 if there are none.
+ unsigned getNumProtocols() const { return Protocols.size(); }
+
+ void Profile(llvm::FoldingSetNodeID &ID);
+ static void Profile(llvm::FoldingSetNodeID &ID, QualType T,
+ ObjCProtocolDecl **protocols, unsigned NumProtocols);
+ virtual void getAsStringInternal(std::string &InnerString,
+ const PrintingPolicy &Policy) const;
+ static bool classof(const Type *T) {
+ return T->getTypeClass() == ObjCObjectPointer;
+ }
+ static bool classof(const ObjCObjectPointerType *) { return true; }
+};
+
/// ObjCQualifiedInterfaceType - This class represents interface types
/// conforming to a list of protocols, such as INTF<Proto1, Proto2, Proto1>.
///
/// Duplicate protocols are removed and protocol list is canonicalized to be in
/// alphabetical order.
+/// FIXME: Remove this class (converting uses to ObjCObjectPointerType).
class ObjCQualifiedInterfaceType : public ObjCInterfaceType,
public llvm::FoldingSetNode {
@@ -1983,7 +2026,7 @@
return AT->getElementType().getObjCGCAttr();
if (const ExtQualType *EXTQT = dyn_cast<ExtQualType>(CT))
return EXTQT->getObjCGCAttr();
- if (const PointerType *PT = CT->getAsPointerType())
+ if (const ObjCObjectPointerType *PT = CT->getAsObjCObjectPointerType())
return PT->getPointeeType().getObjCGCAttr();
return GCNone;
}
@@ -2115,6 +2158,18 @@
}
return false;
}
+inline bool Type::isObjCIdType() const {
+ if (const ObjCObjectPointerType *OPT = getAsObjCObjectPointerType()) {
+ return OPT->isObjCIdType();
+ }
+ return false;
+}
+inline bool Type::isObjCClassType() const {
+ if (const ObjCObjectPointerType *OPT = getAsObjCObjectPointerType()) {
+ return OPT->isObjCClassType();
+ }
+ return false;
+}
inline bool Type::isTemplateTypeParmType() const {
return isa<TemplateTypeParmType>(CanonicalType.getUnqualifiedType());
}
@@ -2134,12 +2189,12 @@
inline bool Type::hasPointerRepresentation() const {
return (isPointerType() || isReferenceType() || isBlockPointerType() ||
- isObjCInterfaceType() || isObjCQualifiedIdType() ||
+ isObjCInterfaceType() || isObjCObjectPointerType() ||
isObjCQualifiedInterfaceType() || isNullPtrType());
}
inline bool Type::hasObjCPointerRepresentation() const {
- return (isObjCInterfaceType() || isObjCQualifiedIdType() ||
+ return (isObjCInterfaceType() || isObjCObjectPointerType() ||
isObjCQualifiedInterfaceType());
}
Modified: cfe/trunk/include/clang/Analysis/PathSensitive/SVals.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Analysis/PathSensitive/SVals.h?rev=75314&r1=75313&r2=75314&view=diff
==============================================================================
--- cfe/trunk/include/clang/Analysis/PathSensitive/SVals.h (original)
+++ cfe/trunk/include/clang/Analysis/PathSensitive/SVals.h Fri Jul 10 18:34:53 2009
@@ -196,7 +196,7 @@
}
static inline bool IsLocType(QualType T) {
- return T->isPointerType() || T->isObjCQualifiedIdType()
+ return T->isPointerType() || T->isObjCObjectPointerType()
|| T->isBlockPointerType();
}
};
Modified: cfe/trunk/lib/AST/ASTContext.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/AST/ASTContext.cpp?rev=75314&r1=75313&r2=75314&view=diff
==============================================================================
--- cfe/trunk/lib/AST/ASTContext.cpp (original)
+++ cfe/trunk/lib/AST/ASTContext.cpp Fri Jul 10 18:34:53 2009
@@ -42,8 +42,8 @@
Idents(idents), Selectors(sels),
BuiltinInfo(builtins), ExternalSource(0), PrintingPolicy(LOpts) {
if (size_reserve > 0) Types.reserve(size_reserve);
- InitBuiltinTypes();
TUDecl = TranslationUnitDecl::Create(*this);
+ InitBuiltinTypes();
}
ASTContext::~ASTContext() {
@@ -190,11 +190,10 @@
LongDoubleComplexTy = getComplexType(LongDoubleTy);
BuiltinVaListType = QualType();
+
ObjCIdType = QualType();
- IdStructType = 0;
ObjCClassType = QualType();
- ClassStructType = 0;
-
+
ObjCConstantStringType = QualType();
// void * type
@@ -1071,7 +1070,7 @@
if (T->isPointerType()) {
QualType Pointee = T->getAsPointerType()->getPointeeType();
- if (Pointee->isPointerType()) {
+ if (Pointee->isPointerType() || Pointee->isObjCObjectPointerType()) {
QualType ResultType = getObjCGCQualType(Pointee, GCAttr);
return getPointerType(ResultType);
}
@@ -1847,15 +1846,18 @@
/// getObjCObjectPointerType - Return a ObjCObjectPointerType type for
/// the given interface decl and the conforming protocol list.
-QualType ASTContext::getObjCObjectPointerType(ObjCInterfaceDecl *Decl,
+QualType ASTContext::getObjCObjectPointerType(QualType InterfaceT,
ObjCProtocolDecl **Protocols,
unsigned NumProtocols) {
+ if (InterfaceT.isNull())
+ InterfaceT = QualType(ObjCObjectPointerType::getIdInterface(), 0);
+
// Sort the protocol list alphabetically to canonicalize it.
if (NumProtocols)
SortAndUniqueProtocols(Protocols, NumProtocols);
llvm::FoldingSetNodeID ID;
- ObjCObjectPointerType::Profile(ID, Decl, Protocols, NumProtocols);
+ ObjCObjectPointerType::Profile(ID, InterfaceT, Protocols, NumProtocols);
void *InsertPos = 0;
if (ObjCObjectPointerType *QT =
@@ -1864,7 +1866,7 @@
// No Match;
ObjCObjectPointerType *QType =
- new (*this,8) ObjCObjectPointerType(Decl, Protocols, NumProtocols);
+ new (*this,8) ObjCObjectPointerType(InterfaceT, Protocols, NumProtocols);
Types.push_back(QType);
ObjCObjectPointerTypes.InsertNode(QType, InsertPos);
@@ -2745,25 +2747,7 @@
S += 'j';
getObjCEncodingForTypeImpl(CT->getElementType(), S, false, false, 0, false,
false);
- } else if (T->isObjCQualifiedIdType()) {
- getObjCEncodingForTypeImpl(getObjCIdType(), S,
- ExpandPointedToStructures,
- ExpandStructures, FD);
- if (FD || EncodingProperty) {
- // Note that we do extended encoding of protocol qualifer list
- // Only when doing ivar or property encoding.
- const ObjCObjectPointerType *QIDT = T->getAsObjCQualifiedIdType();
- S += '"';
- for (ObjCObjectPointerType::qual_iterator I = QIDT->qual_begin(),
- E = QIDT->qual_end(); I != E; ++I) {
- S += '<';
- S += (*I)->getNameAsString();
- S += '>';
- }
- S += '"';
- }
- return;
- }
+ }
else if (const PointerType *PT = T->getAsPointerType()) {
QualType PointeeTy = PT->getPointeeType();
bool isReadOnly = false;
@@ -2797,42 +2781,7 @@
S.replace(S.end()-2, S.end(), replace);
}
}
- if (isObjCIdStructType(PointeeTy)) {
- S += '@';
- return;
- }
- else if (PointeeTy->isObjCInterfaceType()) {
- if (!EncodingProperty &&
- isa<TypedefType>(PointeeTy.getTypePtr())) {
- // Another historical/compatibility reason.
- // We encode the underlying type which comes out as
- // {...};
- S += '^';
- getObjCEncodingForTypeImpl(PointeeTy, S,
- false, ExpandPointedToStructures,
- NULL);
- return;
- }
- S += '@';
- if (FD || EncodingProperty) {
- const ObjCInterfaceType *OIT =
- PointeeTy.getUnqualifiedType()->getAsObjCInterfaceType();
- ObjCInterfaceDecl *OI = OIT->getDecl();
- S += '"';
- S += OI->getNameAsCString();
- for (ObjCInterfaceType::qual_iterator I = OIT->qual_begin(),
- E = OIT->qual_end(); I != E; ++I) {
- S += '<';
- S += (*I)->getNameAsString();
- S += '>';
- }
- S += '"';
- }
- return;
- } else if (isObjCClassStructType(PointeeTy)) {
- S += '#';
- return;
- } else if (isObjCSelType(PointeeTy)) {
+ if (isObjCSelType(PointeeTy)) {
S += ':';
return;
}
@@ -2937,7 +2886,61 @@
}
S += '}';
}
- else
+ else if (const ObjCObjectPointerType *OPT = T->getAsObjCObjectPointerType()) {
+ if (OPT->isObjCIdType()) {
+ S += '@';
+ return;
+ } else if (OPT->isObjCClassType()) {
+ S += '#';
+ return;
+ } else if (OPT->isObjCQualifiedIdType()) {
+ getObjCEncodingForTypeImpl(getObjCIdType(), S,
+ ExpandPointedToStructures,
+ ExpandStructures, FD);
+ if (FD || EncodingProperty) {
+ // Note that we do extended encoding of protocol qualifer list
+ // Only when doing ivar or property encoding.
+ const ObjCObjectPointerType *QIDT = T->getAsObjCQualifiedIdType();
+ S += '"';
+ for (ObjCObjectPointerType::qual_iterator I = QIDT->qual_begin(),
+ E = QIDT->qual_end(); I != E; ++I) {
+ S += '<';
+ S += (*I)->getNameAsString();
+ S += '>';
+ }
+ S += '"';
+ }
+ return;
+ } else {
+ QualType PointeeTy = OPT->getPointeeType();
+ if (!EncodingProperty &&
+ isa<TypedefType>(PointeeTy.getTypePtr())) {
+ // Another historical/compatibility reason.
+ // We encode the underlying type which comes out as
+ // {...};
+ S += '^';
+ getObjCEncodingForTypeImpl(PointeeTy, S,
+ false, ExpandPointedToStructures,
+ NULL);
+ return;
+ }
+ S += '@';
+ if (FD || EncodingProperty) {
+ const ObjCInterfaceType *OIT = OPT->getInterfaceType();
+ ObjCInterfaceDecl *OI = OIT->getDecl();
+ S += '"';
+ S += OI->getNameAsCString();
+ for (ObjCInterfaceType::qual_iterator I = OIT->qual_begin(),
+ E = OIT->qual_end(); I != E; ++I) {
+ S += '<';
+ S += (*I)->getNameAsString();
+ S += '>';
+ }
+ S += '"';
+ }
+ return;
+ }
+ } else
assert(0 && "@encode for type not implemented!");
}
@@ -2967,23 +2970,12 @@
void ASTContext::setObjCIdType(QualType T)
{
ObjCIdType = T;
-
const TypedefType *TT = T->getAsTypedefType();
- if (!TT)
- return;
-
- TypedefDecl *TD = TT->getDecl();
-
- // typedef struct objc_object *id;
- const PointerType *ptr = TD->getUnderlyingType()->getAsPointerType();
- // User error - caller will issue diagnostics.
- if (!ptr)
- return;
- const RecordType *rec = ptr->getPointeeType()->getAsStructureType();
- // User error - caller will issue diagnostics.
- if (!rec)
- return;
- IdStructType = rec;
+ assert(TT && "missing 'id' typedef");
+ const ObjCObjectPointerType *OPT =
+ TT->getDecl()->getUnderlyingType()->getAsObjCObjectPointerType();
+ assert(OPT && "missing 'id' type");
+ ObjCObjectPointerType::setIdInterface(OPT->getPointeeType());
}
void ASTContext::setObjCSelType(QualType T)
@@ -3013,18 +3005,12 @@
void ASTContext::setObjCClassType(QualType T)
{
ObjCClassType = T;
-
const TypedefType *TT = T->getAsTypedefType();
- if (!TT)
- return;
- TypedefDecl *TD = TT->getDecl();
-
- // typedef struct objc_class *Class;
- const PointerType *ptr = TD->getUnderlyingType()->getAsPointerType();
- assert(ptr && "'Class' incorrectly typed");
- const RecordType *rec = ptr->getPointeeType()->getAsStructureType();
- assert(rec && "'Class' incorrectly typed");
- ClassStructType = rec;
+ assert(TT && "missing 'Class' typedef");
+ const ObjCObjectPointerType *OPT =
+ TT->getDecl()->getUnderlyingType()->getAsObjCObjectPointerType();
+ assert(OPT && "missing 'Class' type");
+ ObjCObjectPointerType::setClassInterface(OPT->getPointeeType());
}
void ASTContext::setObjCConstantStringInterface(ObjCInterfaceDecl *Decl) {
@@ -3123,6 +3109,8 @@
/// to struct), Interface* (pointer to ObjCInterfaceType) and id<P> (qualified
/// ID type).
bool ASTContext::isObjCObjectPointerType(QualType Ty) const {
+ if (Ty->isObjCObjectPointerType())
+ return true;
if (Ty->isObjCQualifiedIdType())
return true;
@@ -3198,8 +3186,30 @@
/// compatible for assignment from RHS to LHS. This handles validation of any
/// protocol qualifiers on the LHS or RHS.
///
+/// FIXME: Move the following to ObjCObjectPointerType/ObjCInterfaceType.
+bool ASTContext::canAssignObjCInterfaces(const ObjCObjectPointerType *LHSOPT,
+ const ObjCObjectPointerType *RHSOPT) {
+ // If either interface represents the built-in 'id' or 'Class' types,
+ // then return true (no need to call canAssignObjCInterfaces()).
+ if (LHSOPT->isObjCIdType() || RHSOPT->isObjCIdType() ||
+ LHSOPT->isObjCClassType() || RHSOPT->isObjCClassType())
+ return true;
+
+ const ObjCInterfaceType* LHS = LHSOPT->getInterfaceType();
+ const ObjCInterfaceType* RHS = RHSOPT->getInterfaceType();
+ if (!LHS || !RHS)
+ return false;
+ return canAssignObjCInterfaces(LHS, RHS);
+}
+
bool ASTContext::canAssignObjCInterfaces(const ObjCInterfaceType *LHS,
const ObjCInterfaceType *RHS) {
+ // If either interface represents the built-in 'id' or 'Class' types,
+ // then return true.
+ if (LHS->isObjCIdInterface() || RHS->isObjCIdInterface() ||
+ LHS->isObjCClassInterface() || RHS->isObjCClassInterface())
+ return true;
+
// Verify that the base decls are compatible: the RHS must be a subclass of
// the LHS.
if (!LHS->getDecl()->isSuperClassOf(RHS->getDecl()))
@@ -3245,25 +3255,14 @@
bool ASTContext::areComparableObjCPointerTypes(QualType LHS, QualType RHS) {
// get the "pointed to" types
- const PointerType *LHSPT = LHS->getAsPointerType();
- const PointerType *RHSPT = RHS->getAsPointerType();
+ const ObjCObjectPointerType *LHSOPT = LHS->getAsObjCObjectPointerType();
+ const ObjCObjectPointerType *RHSOPT = RHS->getAsObjCObjectPointerType();
- if (!LHSPT || !RHSPT)
- return false;
-
- QualType lhptee = LHSPT->getPointeeType();
- QualType rhptee = RHSPT->getPointeeType();
- const ObjCInterfaceType* LHSIface = lhptee->getAsObjCInterfaceType();
- const ObjCInterfaceType* RHSIface = rhptee->getAsObjCInterfaceType();
- // ID acts sort of like void* for ObjC interfaces
- if (LHSIface && isObjCIdStructType(rhptee))
- return true;
- if (RHSIface && isObjCIdStructType(lhptee))
- return true;
- if (!LHSIface || !RHSIface)
+ if (!LHSOPT || !RHSOPT)
return false;
- return canAssignObjCInterfaces(LHSIface, RHSIface) ||
- canAssignObjCInterfaces(RHSIface, LHSIface);
+
+ return canAssignObjCInterfaces(LHSOPT, RHSOPT) ||
+ canAssignObjCInterfaces(RHSOPT, LHSOPT);
}
/// typesAreCompatible - C99 6.7.3p9: For two qualified types to be compatible,
@@ -3406,8 +3405,7 @@
// issue error.
if ((GCAttr == QualType::Weak && GCLHSAttr != GCAttr) ||
(GCAttr == QualType::Strong && GCLHSAttr != GCAttr &&
- LHSCan->isPointerType() && !isObjCObjectPointerType(LHSCan) &&
- !isObjCIdStructType(LHSCan->getAsPointerType()->getPointeeType())))
+ !LHSCan->isObjCObjectPointerType()))
return QualType();
RHS = QualType(cast<ExtQualType>(RHS.getDesugaredType())->getBaseType(),
@@ -3432,8 +3430,7 @@
// issue error.
if ((GCAttr == QualType::Weak && GCRHSAttr != GCAttr) ||
(GCAttr == QualType::Strong && GCRHSAttr != GCAttr &&
- RHSCan->isPointerType() && !isObjCObjectPointerType(RHSCan) &&
- !isObjCIdStructType(RHSCan->getAsPointerType()->getPointeeType())))
+ !RHSCan->isObjCObjectPointerType()))
return QualType();
LHS = QualType(cast<ExtQualType>(LHS.getDesugaredType())->getBaseType(),
@@ -3460,47 +3457,12 @@
if (RHSClass == Type::ExtVector) RHSClass = Type::Vector;
// Consider qualified interfaces and interfaces the same.
+ // FIXME: Remove (ObjCObjectPointerType should obsolete this funny business).
if (LHSClass == Type::ObjCQualifiedInterface) LHSClass = Type::ObjCInterface;
if (RHSClass == Type::ObjCQualifiedInterface) RHSClass = Type::ObjCInterface;
// If the canonical type classes don't match.
if (LHSClass != RHSClass) {
- const ObjCInterfaceType* LHSIface = LHS->getAsObjCInterfaceType();
- const ObjCInterfaceType* RHSIface = RHS->getAsObjCInterfaceType();
-
- // 'id' and 'Class' act sort of like void* for ObjC interfaces
- if (LHSIface && (isObjCIdStructType(RHS) || isObjCClassStructType(RHS)))
- return LHS;
- if (RHSIface && (isObjCIdStructType(LHS) || isObjCClassStructType(LHS)))
- return RHS;
-
- // ID is compatible with all qualified id types.
- if (LHS->isObjCQualifiedIdType()) {
- if (const PointerType *PT = RHS->getAsPointerType()) {
- QualType pType = PT->getPointeeType();
- if (isObjCIdStructType(pType) || isObjCClassStructType(pType))
- return LHS;
- // FIXME: need to use ObjCQualifiedIdTypesAreCompatible(LHS, RHS, true).
- // Unfortunately, this API is part of Sema (which we don't have access
- // to. Need to refactor. The following check is insufficient, since we
- // need to make sure the class implements the protocol.
- if (pType->isObjCInterfaceType())
- return LHS;
- }
- }
- if (RHS->isObjCQualifiedIdType()) {
- if (const PointerType *PT = LHS->getAsPointerType()) {
- QualType pType = PT->getPointeeType();
- if (isObjCIdStructType(pType) || isObjCClassStructType(pType))
- return RHS;
- // FIXME: need to use ObjCQualifiedIdTypesAreCompatible(LHS, RHS, true).
- // Unfortunately, this API is part of Sema (which we don't have access
- // to. Need to refactor. The following check is insufficient, since we
- // need to make sure the class implements the protocol.
- if (pType->isObjCInterfaceType())
- return RHS;
- }
- }
// C99 6.7.2.2p4: Each enumerated type shall be compatible with char,
// a signed integer type, or an unsigned integer type.
if (const EnumType* ETy = LHS->getAsEnumType()) {
@@ -3611,9 +3573,6 @@
return mergeFunctionTypes(LHS, RHS);
case Type::Record:
case Type::Enum:
- // FIXME: Why are these compatible?
- if (isObjCIdStructType(LHS) && isObjCClassStructType(RHS)) return LHS;
- if (isObjCClassStructType(LHS) && isObjCIdStructType(RHS)) return LHS;
return QualType();
case Type::Builtin:
// Only exactly equal builtin types are compatible, which is tested above.
@@ -3638,10 +3597,17 @@
return QualType();
}
- case Type::ObjCObjectPointer:
- // FIXME: finish
- // Distinct qualified id's are not compatible.
+ case Type::ObjCObjectPointer: {
+ // FIXME: Incorporate tests from Sema::ObjCQualifiedIdTypesAreCompatible().
+ if (LHS->isObjCQualifiedIdType() && RHS->isObjCQualifiedIdType())
+ return QualType();
+
+ if (canAssignObjCInterfaces(LHS->getAsObjCObjectPointerType(),
+ RHS->getAsObjCObjectPointerType()))
+ return LHS;
+
return QualType();
+ }
case Type::FixedWidthInt:
// Distinct fixed-width integers are not compatible.
return QualType();
Modified: cfe/trunk/lib/AST/DeclObjC.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/AST/DeclObjC.cpp?rev=75314&r1=75313&r2=75314&view=diff
==============================================================================
--- cfe/trunk/lib/AST/DeclObjC.cpp (original)
+++ cfe/trunk/lib/AST/DeclObjC.cpp Fri Jul 10 18:34:53 2009
@@ -280,7 +280,7 @@
// of the interface (which has been reported). Recover gracefully.
if (OID) {
selfTy = Context.getObjCInterfaceType(OID);
- selfTy = Context.getPointerType(selfTy);
+ selfTy = Context.getObjCObjectPointerType(selfTy);
} else {
selfTy = Context.getObjCIdType();
}
Modified: cfe/trunk/lib/AST/Expr.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/AST/Expr.cpp?rev=75314&r1=75313&r2=75314&view=diff
==============================================================================
--- cfe/trunk/lib/AST/Expr.cpp (original)
+++ cfe/trunk/lib/AST/Expr.cpp Fri Jul 10 18:34:53 2009
@@ -1095,6 +1095,7 @@
switch (getStmtClass()) {
default: break;
case StringLiteralClass:
+ case ObjCStringLiteralClass:
case ObjCEncodeExprClass:
return true;
case CompoundLiteralExprClass: {
@@ -1136,7 +1137,6 @@
return cast<CastExpr>(this)->getSubExpr()->isConstantInitializer(Ctx);
break;
}
-
return isEvaluatable(Ctx);
}
Modified: cfe/trunk/lib/AST/ExprConstant.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/AST/ExprConstant.cpp?rev=75314&r1=75313&r2=75314&view=diff
==============================================================================
--- cfe/trunk/lib/AST/ExprConstant.cpp (original)
+++ cfe/trunk/lib/AST/ExprConstant.cpp Fri Jul 10 18:34:53 2009
@@ -382,7 +382,8 @@
const Expr* SubExpr = E->getSubExpr();
// Check for pointer->pointer cast
- if (SubExpr->getType()->isPointerType()) {
+ if (SubExpr->getType()->isPointerType() ||
+ SubExpr->getType()->isObjCObjectPointerType()) {
APValue Result;
if (EvaluatePointer(SubExpr, Result, Info))
return Result;
Modified: cfe/trunk/lib/AST/Type.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/AST/Type.cpp?rev=75314&r1=75313&r2=75314&view=diff
==============================================================================
--- cfe/trunk/lib/AST/Type.cpp (original)
+++ cfe/trunk/lib/AST/Type.cpp Fri Jul 10 18:34:53 2009
@@ -22,6 +22,9 @@
#include "llvm/Support/raw_ostream.h"
using namespace clang;
+ObjCInterfaceType *ObjCObjectPointerType::IdInterfaceT;
+ObjCInterfaceType *ObjCObjectPointerType::ClassInterfaceT;
+
bool QualType::isConstant(ASTContext &Ctx) const {
if (isConstQualified())
return true;
@@ -295,6 +298,15 @@
return dyn_cast_or_null<FunctionProtoType>(getAsFunctionType());
}
+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();
+}
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>'}}
}
int f11(int cond, A* a, B* b) {
Modified: cfe/trunk/test/SemaObjC/id.m
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/SemaObjC/id.m?rev=75314&r1=75313&r2=75314&view=diff
==============================================================================
--- cfe/trunk/test/SemaObjC/id.m (original)
+++ cfe/trunk/test/SemaObjC/id.m Fri Jul 10 18:34:53 2009
@@ -15,6 +15,6 @@
}
// Test attempt to redefine 'id' in an incompatible fashion.
-typedef int id; // expected-error {{typedef redefinition with different types}}
+typedef int id; // FIXME: Decide how we want to deal with this (now that 'id' is more of a built-in type).
id b;
Modified: cfe/trunk/test/SemaObjC/message.m
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/SemaObjC/message.m?rev=75314&r1=75313&r2=75314&view=diff
==============================================================================
--- cfe/trunk/test/SemaObjC/message.m (original)
+++ cfe/trunk/test/SemaObjC/message.m Fri Jul 10 18:34:53 2009
@@ -95,6 +95,6 @@
void foo4() {
struct objc_object X[10];
- [X rect];
+ [(id)X rect];
}
Modified: cfe/trunk/test/SemaObjC/objc2-merge-gc-attribue-decl.m
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/SemaObjC/objc2-merge-gc-attribue-decl.m?rev=75314&r1=75313&r2=75314&view=diff
==============================================================================
--- cfe/trunk/test/SemaObjC/objc2-merge-gc-attribue-decl.m (original)
+++ cfe/trunk/test/SemaObjC/objc2-merge-gc-attribue-decl.m Fri Jul 10 18:34:53 2009
@@ -25,6 +25,5 @@
extern char* __strong p6; // expected-note {{previous definition is here}}
extern char* p6; // expected-error {{redefinition of 'p6' with a different type}}
-// FIXME. We do not issue error here because we don't put the attribute on the pointer type.
-extern __strong char* p7;
-extern char* p7;
+extern __strong char* p7; // expected-note {{previous definition is here}}
+extern char* p7; // expected-error {{redefinition of 'p7' with a different type}}
Modified: cfe/trunk/test/SemaObjC/property-missing.m
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/SemaObjC/property-missing.m?rev=75314&r1=75313&r2=75314&view=diff
==============================================================================
--- cfe/trunk/test/SemaObjC/property-missing.m (original)
+++ cfe/trunk/test/SemaObjC/property-missing.m Fri Jul 10 18:34:53 2009
@@ -17,6 +17,6 @@
void f3(id o)
{
- o.foo; // expected-error{{member reference base type 'id' is not a structure or union}}
+ o.foo; // expected-error{{property 'foo' not found on object of type 'id'}}
}
Modified: cfe/trunk/test/SemaObjCXX/overload.mm
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/SemaObjCXX/overload.mm?rev=75314&r1=75313&r2=75314&view=diff
==============================================================================
--- cfe/trunk/test/SemaObjCXX/overload.mm (original)
+++ cfe/trunk/test/SemaObjCXX/overload.mm Fri Jul 10 18:34:53 2009
@@ -1,4 +1,5 @@
// RUN: clang-cc -fsyntax-only -verify %s
+// XFAIL
@interface Foo
@end
More information about the cfe-commits
mailing list