aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--include/clang/AST/ASTContext.h18
-rw-r--r--include/clang/AST/Type.h159
-rw-r--r--include/clang/Analysis/PathSensitive/SVals.h2
-rw-r--r--lib/AST/ASTContext.cpp274
-rw-r--r--lib/AST/DeclObjC.cpp2
-rw-r--r--lib/AST/Expr.cpp2
-rw-r--r--lib/AST/ExprConstant.cpp3
-rw-r--r--lib/AST/Type.cpp53
-rw-r--r--lib/Analysis/BasicObjCFoundationChecks.cpp31
-rw-r--r--lib/Analysis/CFRefCount.cpp94
-rw-r--r--lib/Analysis/CheckNSError.cpp20
-rw-r--r--lib/Analysis/CheckObjCInstMethSignature.cpp4
-rw-r--r--lib/CodeGen/CGDebugInfo.cpp6
-rw-r--r--lib/CodeGen/CGExpr.cpp17
-rw-r--r--lib/CodeGen/CGExprScalar.cpp24
-rw-r--r--lib/CodeGen/CGObjC.cpp4
-rw-r--r--lib/CodeGen/CGObjCGNU.cpp9
-rw-r--r--lib/CodeGen/CGObjCMac.cpp19
-rw-r--r--lib/CodeGen/CodeGenTypes.cpp13
-rw-r--r--lib/CodeGen/Mangle.cpp5
-rw-r--r--lib/Frontend/PCHReader.cpp6
-rw-r--r--lib/Frontend/PCHWriter.cpp2
-rw-r--r--lib/Frontend/RewriteObjC.cpp7
-rw-r--r--lib/Sema/Sema.cpp43
-rw-r--r--lib/Sema/Sema.h2
-rw-r--r--lib/Sema/SemaDecl.cpp12
-rw-r--r--lib/Sema/SemaDeclAttr.cpp5
-rw-r--r--lib/Sema/SemaDeclObjC.cpp2
-rw-r--r--lib/Sema/SemaExpr.cpp441
-rw-r--r--lib/Sema/SemaExprCXX.cpp3
-rw-r--r--lib/Sema/SemaExprObjC.cpp186
-rw-r--r--lib/Sema/SemaOverload.cpp126
-rw-r--r--lib/Sema/SemaType.cpp20
-rw-r--r--test/CodeGenObjC/encode-test.m4
-rw-r--r--test/CodeGenObjC/overloadable.m6
-rw-r--r--test/PCH/objc_exprs.m5
-rw-r--r--test/SemaObjC/comptypes-5.m4
-rw-r--r--test/SemaObjC/conditional-expr-3.m2
-rw-r--r--test/SemaObjC/id.m2
-rw-r--r--test/SemaObjC/message.m2
-rw-r--r--test/SemaObjC/objc2-merge-gc-attribue-decl.m5
-rw-r--r--test/SemaObjC/property-missing.m2
-rw-r--r--test/SemaObjCXX/overload.mm1
43 files changed, 892 insertions, 755 deletions
diff --git a/include/clang/AST/ASTContext.h b/include/clang/AST/ASTContext.h
index fbd56023d6..b13028d8f7 100644
--- a/include/clang/AST/ASTContext.h
+++ b/include/clang/AST/ASTContext.h
@@ -107,7 +107,6 @@ class ASTContext {
/// 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 @@ class ASTContext {
/// ObjCClassType - another pseudo built-in typedef type (set by Sema).
QualType ObjCClassType;
- const RecordType *ClassStructType;
QualType ObjCConstantStringType;
RecordDecl *CFConstantStringTypeDecl;
@@ -375,7 +373,7 @@ public:
/// 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 @@ public:
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);
diff --git a/include/clang/AST/Type.h b/include/clang/AST/Type.h
index 39eb1842b3..8de6a03c8f 100644
--- a/include/clang/AST/Type.h
+++ b/include/clang/AST/Type.h
@@ -396,9 +396,13 @@ public:
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 @@ public:
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 @@ public:
/// 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 @@ public:
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 @@ protected:
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 @@ public:
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 @@ inline QualType::GCAttrTypes QualType::getObjCGCAttr() const {
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 @@ inline bool Type::isObjCQualifiedIdType() const {
}
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::isOverloadableType() const {
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());
}
diff --git a/include/clang/Analysis/PathSensitive/SVals.h b/include/clang/Analysis/PathSensitive/SVals.h
index 4bc5e27aac..dd7c93639f 100644
--- a/include/clang/Analysis/PathSensitive/SVals.h
+++ b/include/clang/Analysis/PathSensitive/SVals.h
@@ -196,7 +196,7 @@ public:
}
static inline bool IsLocType(QualType T) {
- return T->isPointerType() || T->isObjCQualifiedIdType()
+ return T->isPointerType() || T->isObjCObjectPointerType()
|| T->isBlockPointerType();
}
};
diff --git a/lib/AST/ASTContext.cpp b/lib/AST/ASTContext.cpp
index 2bd1482adc..dbac120d26 100644
--- a/lib/AST/ASTContext.cpp
+++ b/lib/AST/ASTContext.cpp
@@ -42,8 +42,8 @@ ASTContext::ASTContext(const LangOptions& LOpts, SourceManager &SM,
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 @@ void ASTContext::InitBuiltinTypes() {
LongDoubleComplexTy = getComplexType(LongDoubleTy);
BuiltinVaListType = QualType();
+
ObjCIdType = QualType();
- IdStructType = 0;
ObjCClassType = QualType();
- ClassStructType = 0;
-
+
ObjCConstantStringType = QualType();
// void * type
@@ -1071,7 +1070,7 @@ QualType ASTContext::getObjCGCQualType(QualType T,
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 @@ static void SortAndUniqueProtocols(ObjCProtocolDecl **&Protocols,
/// 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 @@ QualType ASTContext::getObjCObjectPointerType(ObjCInterfaceDecl *Decl,
// 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 @@ void ASTContext::getObjCEncodingForTypeImpl(QualType T, std::string& S,
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 @@ void ASTContext::getObjCEncodingForTypeImpl(QualType T, std::string& S,
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 @@ void ASTContext::getObjCEncodingForTypeImpl(QualType T, std::string& S,
}
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::setBuiltinVaListType(QualType T)
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::setObjCProtoType(QualType QT)
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 @@ bool ASTContext::isObjCNSObjectType(QualType Ty) const {
/// 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 @@ static bool areCompatVectorTypes(const VectorType *LHS,
/// 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::canAssignObjCInterfaces(const ObjCInterfaceType *LHS,
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 @@ QualType ASTContext::mergeTypes(QualType LHS, QualType RHS) {
// 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 @@ QualType ASTContext::mergeTypes(QualType LHS, QualType RHS) {
// issue error.
if ((GCAttr == QualType::Weak &