aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--include/clang/AST/ASTContext.h13
-rw-r--r--include/clang/AST/Type.h59
-rw-r--r--include/clang/Basic/DiagnosticSemaKinds.td2
-rw-r--r--include/clang/Frontend/PCHBitCodes.h6
-rw-r--r--lib/AST/ASTContext.cpp64
-rw-r--r--lib/AST/Type.cpp22
-rw-r--r--lib/CodeGen/CodeGenTypes.cpp2
-rw-r--r--lib/CodeGen/Mangle.cpp2
-rw-r--r--lib/Frontend/PCHReader.cpp2
-rw-r--r--lib/Frontend/PCHWriter.cpp2
-rw-r--r--lib/Sema/Sema.cpp36
-rw-r--r--lib/Sema/SemaExpr.cpp15
-rw-r--r--lib/Sema/SemaOverload.cpp13
-rw-r--r--test/SemaObjC/comptypes-3.m12
-rw-r--r--test/SemaObjC/conditional-expr-3.m6
15 files changed, 127 insertions, 129 deletions
diff --git a/include/clang/AST/ASTContext.h b/include/clang/AST/ASTContext.h
index 56b3e69833..f52d828f67 100644
--- a/include/clang/AST/ASTContext.h
+++ b/include/clang/AST/ASTContext.h
@@ -106,7 +106,7 @@ class ASTContext {
QualType BuiltinVaListType;
/// ObjCIdType - a pseudo built-in typedef type (set by Sema).
- QualType ObjCIdType;
+ QualType ObjCIdTypedefType;
/// ObjCSelType - another pseudo built-in typedef type (set by Sema).
QualType ObjCSelType;
@@ -117,7 +117,7 @@ class ASTContext {
const RecordType *ProtoStructType;
/// ObjCClassType - another pseudo built-in typedef type (set by Sema).
- QualType ObjCClassType;
+ QualType ObjCClassTypedefType;
QualType ObjCConstantStringType;
RecordDecl *CFConstantStringTypeDecl;
@@ -210,6 +210,7 @@ public:
QualType OverloadTy;
QualType DependentTy;
QualType UndeducedAutoTy;
+ QualType ObjCBuiltinIdTy, ObjCBuiltinClassTy;
ASTContext(const LangOptions& LOpts, SourceManager &SM, TargetInfo &t,
IdentifierTable &idents, SelectorTable &sels,
@@ -490,7 +491,7 @@ public:
/// This setter/getter represents the ObjC 'id' type. It is setup lazily, by
/// Sema. id is always a (typedef for a) pointer type, a pointer to a struct.
- QualType getObjCIdType() const { return ObjCIdType; }
+ QualType getObjCIdType() const { return ObjCIdTypedefType; }
void setObjCIdType(QualType T);
void setObjCSelType(QualType T);
@@ -502,7 +503,7 @@ public:
/// This setter/getter repreents the ObjC 'Class' type. It is setup lazily, by
/// Sema. 'Class' is always a (typedef for a) pointer type, a pointer to a
/// struct.
- QualType getObjCClassType() const { return ObjCClassType; }
+ QualType getObjCClassType() const { return ObjCClassTypedefType; }
void setObjCClassType(QualType T);
void setBuiltinVaListType(QualType T);
@@ -768,10 +769,10 @@ public:
bool typesAreCompatible(QualType, QualType); // C99 6.2.7p1
bool isObjCIdType(QualType T) const {
- return T == ObjCIdType;
+ return T == ObjCIdTypedefType;
}
bool isObjCClassType(QualType T) const {
- return T == ObjCClassType;
+ return T == ObjCClassTypedefType;
}
bool isObjCSelType(QualType T) const {
assert(SelStructType && "isObjCSelType used before 'SEL' type is built");
diff --git a/include/clang/AST/Type.h b/include/clang/AST/Type.h
index 7ddf90bcab..9843bbb012 100644
--- a/include/clang/AST/Type.h
+++ b/include/clang/AST/Type.h
@@ -404,6 +404,7 @@ public:
bool isObjCQualifiedIdType() const; // id<foo>
bool isObjCIdType() const; // id
bool isObjCClassType() const; // Class
+ bool isObjCBuiltinType() const; // 'id' or 'Class'
bool isTemplateTypeParmType() const; // C++ template type parameter
bool isNullPtrType() const; // C++0x nullptr_t
@@ -592,8 +593,10 @@ public:
Overload, // This represents the type of an overloaded function declaration.
Dependent, // This represents the type of a type-dependent expression.
- UndeducedAuto // In C++0x, this represents the type of an auto variable
+ UndeducedAuto, // In C++0x, this represents the type of an auto variable
// that has not been deduced yet.
+ ObjCId, // This represents the ObjC 'id' type.
+ ObjCClass // This represents the ObjC 'Class' type.
};
private:
Kind TypeKind;
@@ -1899,7 +1902,7 @@ public:
/// 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.
+ QualType PointeeType; // A builin or interface type.
// List of protocols for this protocol conforming object type
// List is sorted on protocol name. No protocol is entered more than once.
@@ -1909,20 +1912,10 @@ class ObjCObjectPointerType : public Type, public llvm::FoldingSetNode {
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.
+ // Get the pointee type. Pointee will either be a built-in type (for 'id' and
+ // 'Class') or will be an interface type (for user-defined types).
// Note: Pointee can be a TypedefType whose canonical type is an interface.
// Example: typedef NSObject T; T *var;
QualType getPointeeType() const { return PointeeType; }
@@ -1930,18 +1923,29 @@ public:
const ObjCInterfaceType *getInterfaceType() const {
return PointeeType->getAsObjCInterfaceType();
}
+ /// getInterfaceDecl - returns an interface decl for user-defined types.
ObjCInterfaceDecl *getInterfaceDecl() const {
- return getInterfaceType()->getDecl();
- }
- /// isObjCQualifiedIdType - true for "id <p>".
- bool isObjCQualifiedIdType() const {
- return getInterfaceType() == IdInterfaceT && Protocols.size();
+ return getInterfaceType() ? getInterfaceType()->getDecl() : 0;
}
+ /// isObjCIdType - true for "id".
bool isObjCIdType() const {
- return getInterfaceType() == IdInterfaceT && !Protocols.size();
+ return getPointeeType()->isSpecificBuiltinType(BuiltinType::ObjCId) &&
+ !Protocols.size();
}
+ /// isObjCClassType - true for "Class".
bool isObjCClassType() const {
- return getInterfaceType() == ClassInterfaceT && !Protocols.size();
+ return getPointeeType()->isSpecificBuiltinType(BuiltinType::ObjCClass) &&
+ !Protocols.size();
+ }
+ /// isObjCQualifiedIdType - true for "id <p>".
+ bool isObjCQualifiedIdType() const {
+ return getPointeeType()->isSpecificBuiltinType(BuiltinType::ObjCId) &&
+ Protocols.size();
+ }
+ /// isObjCQualifiedClassType - true for "Class <p>".
+ bool isQualifiedClassType() const {
+ return getPointeeType()->isSpecificBuiltinType(BuiltinType::ObjCClass) &&
+ Protocols.size();
}
/// qual_iterator and friends: this provides access to the (potentially empty)
/// list of protocols qualifying this interface.
@@ -2188,23 +2192,24 @@ inline bool Type::isObjCQualifiedInterfaceType() const {
return isa<ObjCQualifiedInterfaceType>(CanonicalType.getUnqualifiedType());
}
inline bool Type::isObjCQualifiedIdType() const {
- if (const ObjCObjectPointerType *OPT = getAsObjCObjectPointerType()) {
+ if (const ObjCObjectPointerType *OPT = getAsObjCObjectPointerType())
return OPT->isObjCQualifiedIdType();
- }
return false;
}
inline bool Type::isObjCIdType() const {
- if (const ObjCObjectPointerType *OPT = getAsObjCObjectPointerType()) {
+ if (const ObjCObjectPointerType *OPT = getAsObjCObjectPointerType())
return OPT->isObjCIdType();
- }
return false;
}
inline bool Type::isObjCClassType() const {
- if (const ObjCObjectPointerType *OPT = getAsObjCObjectPointerType()) {
+ if (const ObjCObjectPointerType *OPT = getAsObjCObjectPointerType())
return OPT->isObjCClassType();
- }
return false;
}
+inline bool Type::isObjCBuiltinType() const {
+ return isObjCIdType() || isObjCClassType();
+}
+
inline bool Type::isTemplateTypeParmType() const {
return isa<TemplateTypeParmType>(CanonicalType.getUnqualifiedType());
}
diff --git a/include/clang/Basic/DiagnosticSemaKinds.td b/include/clang/Basic/DiagnosticSemaKinds.td
index 6926633a40..f552a2faf0 100644
--- a/include/clang/Basic/DiagnosticSemaKinds.td
+++ b/include/clang/Basic/DiagnosticSemaKinds.td
@@ -1457,8 +1457,6 @@ def err_cannot_initialize_decl : Error<
"cannot initialize %0 with an %select{rvalue|lvalue}1 of type %2">;
def warn_incompatible_qualified_id : Warning<
"incompatible type %2 %1, expected %0">;
-def warn_incompatible_qualified_id_operands : Warning<
- "invalid operands to binary expression (%0 and %1)">;
def ext_typecheck_convert_pointer_int : ExtWarn<
"incompatible pointer to integer conversion %2 %1, expected %0">;
def ext_typecheck_convert_int_pointer : ExtWarn<
diff --git a/include/clang/Frontend/PCHBitCodes.h b/include/clang/Frontend/PCHBitCodes.h
index a1feec3a6a..3e3b95efff 100644
--- a/include/clang/Frontend/PCHBitCodes.h
+++ b/include/clang/Frontend/PCHBitCodes.h
@@ -333,7 +333,11 @@ namespace clang {
/// \brief The C++ 'char16_t' type.
PREDEF_TYPE_CHAR16_ID = 24,
/// \brief The C++ 'char32_t' type.
- PREDEF_TYPE_CHAR32_ID = 25
+ PREDEF_TYPE_CHAR32_ID = 25,
+ /// \brief The ObjC 'id' type.
+ PREDEF_TYPE_OBJC_ID = 26,
+ /// \brief The ObjC 'Class' type.
+ PREDEF_TYPE_OBJC_CLASS = 27
};
/// \brief The number of predefined type IDs that are reserved for
diff --git a/lib/AST/ASTContext.cpp b/lib/AST/ASTContext.cpp
index 13f35dc3a0..fb28188789 100644
--- a/lib/AST/ASTContext.cpp
+++ b/lib/AST/ASTContext.cpp
@@ -201,8 +201,13 @@ void ASTContext::InitBuiltinTypes() {
BuiltinVaListType = QualType();
- ObjCIdType = QualType();
- ObjCClassType = QualType();
+ // "Builtin" typedefs set by Sema::ActOnTranslationUnitScope().
+ ObjCIdTypedefType = QualType();
+ ObjCClassTypedefType = QualType();
+
+ // Builtin types for 'id' and 'Class'.
+ InitBuiltinType(ObjCBuiltinIdTy, BuiltinType::ObjCId);
+ InitBuiltinType(ObjCBuiltinClassTy, BuiltinType::ObjCClass);
ObjCConstantStringType = QualType();
@@ -1868,7 +1873,7 @@ QualType ASTContext::getObjCObjectPointerType(QualType InterfaceT,
ObjCProtocolDecl **Protocols,
unsigned NumProtocols) {
if (InterfaceT.isNull())
- InterfaceT = QualType(ObjCObjectPointerType::getIdInterface(), 0);
+ InterfaceT = ObjCBuiltinIdTy;
// Sort the protocol list alphabetically to canonicalize it.
if (NumProtocols)
@@ -2471,7 +2476,7 @@ QualType ASTContext::getObjCFastEnumerationStateType()
QualType FieldTypes[] = {
UnsignedLongTy,
- getPointerType(ObjCIdType),
+ getPointerType(ObjCIdTypedefType),
getPointerType(UnsignedLongTy),
getConstantArrayType(UnsignedLongTy,
llvm::APInt(32, 5), ArrayType::Normal, 0)
@@ -3018,13 +3023,7 @@ void ASTContext::setBuiltinVaListType(QualType T) {
}
void ASTContext::setObjCIdType(QualType T) {
- ObjCIdType = T;
- const TypedefType *TT = T->getAsTypedefType();
- assert(TT && "missing 'id' typedef");
- const ObjCObjectPointerType *OPT =
- TT->getDecl()->getUnderlyingType()->getAsObjCObjectPointerType();
- assert(OPT && "missing 'id' type");
- ObjCObjectPointerType::setIdInterface(OPT->getPointeeType());
+ ObjCIdTypedefType = T;
}
void ASTContext::setObjCSelType(QualType T) {
@@ -3050,13 +3049,7 @@ void ASTContext::setObjCProtoType(QualType QT) {
}
void ASTContext::setObjCClassType(QualType T) {
- ObjCClassType = T;
- const TypedefType *TT = T->getAsTypedefType();
- assert(TT && "missing 'Class' typedef");
- const ObjCObjectPointerType *OPT =
- TT->getDecl()->getUnderlyingType()->getAsObjCObjectPointerType();
- assert(OPT && "missing 'Class' type");
- ObjCObjectPointerType::setClassInterface(OPT->getPointeeType());
+ ObjCClassTypedefType = T;
}
void ASTContext::setObjCConstantStringInterface(ObjCInterfaceDecl *Decl) {
@@ -3235,27 +3228,38 @@ static bool areCompatVectorTypes(const VectorType *LHS,
/// 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())
+ // If either type represents the built-in 'id' or 'Class' types, return true.
+ if (LHSOPT->isObjCBuiltinType() || RHSOPT->isObjCBuiltinType())
return true;
const ObjCInterfaceType* LHS = LHSOPT->getInterfaceType();
const ObjCInterfaceType* RHS = RHSOPT->getInterfaceType();
- if (!LHS || !RHS)
- return false;
+ if (!LHS || !RHS) {
+ // We have qualified builtin types.
+ // Both the right and left sides have qualifiers.
+ for (ObjCObjectPointerType::qual_iterator I = LHSOPT->qual_begin(),
+ E = LHSOPT->qual_end(); I != E; ++I) {
+ bool RHSImplementsProtocol = 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 = RHSOPT->qual_begin(),
+ E = RHSOPT->qual_end(); J != E; ++J) {
+ if ((*J)->lookupProtocolNamed((*I)->getIdentifier()))
+ RHSImplementsProtocol = true;
+ }
+ if (!RHSImplementsProtocol)
+ return false;
+ }
+ // The RHS implements all protocols listed on the LHS.
+ return true;
+ }
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()))
diff --git a/lib/AST/Type.cpp b/lib/AST/Type.cpp
index 9edb9c046d..18fa76bf25 100644
--- a/lib/AST/Type.cpp
+++ b/lib/AST/Type.cpp
@@ -22,9 +22,6 @@
#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;
@@ -1009,6 +1006,8 @@ const char *BuiltinType::getName(const LangOptions &LO) const {
case Overload: return "<overloaded function type>";
case Dependent: return "<dependent type>";
case UndeducedAuto: return "auto";
+ case ObjCId: return "id";
+ case ObjCClass: return "Class";
}
}
@@ -1687,14 +1686,6 @@ void TypenameType::getAsStringInternal(std::string &InnerString, const PrintingP
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;
@@ -1703,7 +1694,14 @@ void ObjCInterfaceType::getAsStringInternal(std::string &InnerString, const Prin
void ObjCObjectPointerType::getAsStringInternal(std::string &InnerString,
const PrintingPolicy &Policy) const {
- std::string ObjCQIString = getInterfaceType()->getDecl()->getNameAsString();
+ std::string ObjCQIString;
+
+ if (isObjCIdType() || isObjCQualifiedIdType())
+ ObjCQIString = "id";
+ else if (isObjCClassType())
+ ObjCQIString = "Class";
+ else
+ ObjCQIString = getInterfaceDecl()->getNameAsString();
if (!qual_empty()) {
ObjCQIString += '<';
diff --git a/lib/CodeGen/CodeGenTypes.cpp b/lib/CodeGen/CodeGenTypes.cpp
index c617939e35..e97cbbd66c 100644
--- a/lib/CodeGen/CodeGenTypes.cpp
+++ b/lib/CodeGen/CodeGenTypes.cpp
@@ -228,6 +228,8 @@ const llvm::Type *CodeGenTypes::ConvertNewType(QualType T) {
switch (cast<BuiltinType>(Ty).getKind()) {
default: assert(0 && "Unknown builtin type!");
case BuiltinType::Void:
+ case BuiltinType::ObjCId:
+ case BuiltinType::ObjCClass:
// LLVM void type can only be used as the result of a function call. Just
// map to the same as char.
return llvm::IntegerType::get(8);
diff --git a/lib/CodeGen/Mangle.cpp b/lib/CodeGen/Mangle.cpp
index cd0e2eae7d..5340cd7262 100644
--- a/lib/CodeGen/Mangle.cpp
+++ b/lib/CodeGen/Mangle.cpp
@@ -577,6 +577,8 @@ void CXXNameMangler::mangleType(const BuiltinType *T) {
case BuiltinType::UndeducedAuto:
assert(0 && "Should not see undeduced auto here");
break;
+ case BuiltinType::ObjCId: Out << "2id"; break;
+ case BuiltinType::ObjCClass: Out << "5Class"; break;
}
}
diff --git a/lib/Frontend/PCHReader.cpp b/lib/Frontend/PCHReader.cpp
index 012c6fecfe..8c26607b7c 100644
--- a/lib/Frontend/PCHReader.cpp
+++ b/lib/Frontend/PCHReader.cpp
@@ -1986,6 +1986,8 @@ QualType PCHReader::GetType(pch::TypeID ID) {
case pch::PREDEF_TYPE_NULLPTR_ID: T = Context->NullPtrTy; break;
case pch::PREDEF_TYPE_CHAR16_ID: T = Context->Char16Ty; break;
case pch::PREDEF_TYPE_CHAR32_ID: T = Context->Char32Ty; break;
+ case pch::PREDEF_TYPE_OBJC_ID: T = Context->ObjCBuiltinIdTy; break;
+ case pch::PREDEF_TYPE_OBJC_CLASS: T = Context->ObjCBuiltinClassTy; break;
}
assert(!T.isNull() && "Unknown predefined type");
diff --git a/lib/Frontend/PCHWriter.cpp b/lib/Frontend/PCHWriter.cpp
index 333bcc9893..6a17f39f43 100644
--- a/lib/Frontend/PCHWriter.cpp
+++ b/lib/Frontend/PCHWriter.cpp
@@ -2009,6 +2009,8 @@ void PCHWriter::AddTypeRef(QualType T, RecordData &Record) {
case BuiltinType::Char32: ID = pch::PREDEF_TYPE_CHAR32_ID; break;
case BuiltinType::Overload: ID = pch::PREDEF_TYPE_OVERLOAD_ID; break;
case BuiltinType::Dependent: ID = pch::PREDEF_TYPE_DEPENDENT_ID; break;
+ case BuiltinType::ObjCId: ID = pch::PREDEF_TYPE_OBJC_ID; break;
+ case BuiltinType::ObjCClass: ID = pch::PREDEF_TYPE_OBJC_CLASS; break;
case BuiltinType::UndeducedAuto:
assert(0 && "Should not see undeduced auto here");
break;
diff --git a/lib/Sema/Sema.cpp b/lib/Sema/Sema.cpp
index 9b58e47746..39662511f1 100644
--- a/lib/Sema/Sema.cpp
+++ b/lib/Sema/Sema.cpp
@@ -149,35 +149,23 @@ void Sema::ActOnTranslationUnitScope(SourceLocation Loc, Scope *S) {
Context.setObjCProtoType(Context.getObjCInterfaceType(ProtocolDecl));
PushOnScopeChains(ProtocolDecl, TUScope);
}
- // Create the built-in decls/typedefs for 'id' and 'Class'.
+ // Create the built-in typedef for 'id'.
if (Context.getObjCIdType().isNull()) {
- ObjCInterfaceDecl *IdIDecl =
- ObjCInterfaceDecl::Create(Context, CurContext, SourceLocation(),
- &Context.Idents.get("id"),
- SourceLocation(), true);
- QualType IdIType = Context.getObjCInterfaceType(IdIDecl);
- QualType ObjCIdType = Context.getObjCObjectPointerType(IdIType);
-
- TypedefDecl *IdTypedef = TypedefDecl::Create(Context, CurContext,
- SourceLocation(),
- &Context.Idents.get("id"),
- ObjCIdType);
+ TypedefDecl *IdTypedef =
+ TypedefDecl::Create(
+ Context, CurContext, SourceLocation(), &Context.Idents.get("id"),
+ Context.getObjCObjectPointerType(Context.ObjCBuiltinIdTy)
+ );
PushOnScopeChains(IdTypedef, TUScope);
Context.setObjCIdType(Context.getTypeDeclType(IdTypedef));
}
- // Create the built-in decls/typedefs and type for "Class".
+ // Create the built-in typedef 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);
+ TypedefDecl *ClassTypedef =
+ TypedefDecl::Create(
+ Context, CurContext, SourceLocation(), &Context.Idents.get("Class"),
+ Context.getObjCObjectPointerType(Context.ObjCBuiltinClassTy)
+ );
PushOnScopeChains(ClassTypedef, TUScope);
Context.setObjCClassType(Context.getTypeDeclType(ClassTypedef));
}
diff --git a/lib/Sema/SemaExpr.cpp b/lib/Sema/SemaExpr.cpp
index 66d2cdcb38..19d890851a 100644
--- a/lib/Sema/SemaExpr.cpp
+++ b/lib/Sema/SemaExpr.cpp
@@ -2338,9 +2338,11 @@ Sema::ActOnMemberReferenceExpr(Scope *S, ExprArg Base, SourceLocation OpLoc,
<< IDecl->getDeclName() << &Member
<< BaseExpr->getSourceRange());
}
- // Handle properties on qualified "id" protocols.
- const ObjCObjectPointerType *QIdTy;
- if (OpKind == tok::period && (QIdTy = BaseType->getAsObjCQualifiedIdType())) {
+ // Handle properties on 'id' and qualified "id".
+ if (OpKind == tok::period && (BaseType->isObjCIdType() ||
+ BaseType->isObjCQualifiedIdType())) {
+ const ObjCObjectPointerType *QIdTy = BaseType->getAsObjCObjectPointerType();
+
// Check protocols on qualified interfaces.
Selector Sel = PP.getSelectorTable().getNullarySelector(&Member);
if (Decl *PMDecl = FindGetterNameDecl(QIdTy, Member, Sel, Context)) {
@@ -3531,6 +3533,8 @@ Sema::CheckAssignmentConstraints(QualType lhsType, QualType rhsType) {
return CheckPointeeTypesForAssignment(lhptee, rhptee);
}
if (rhsType->isObjCObjectPointerType()) {
+ if (lhsType->isObjCBuiltinType() || rhsType->isObjCBuiltinType())
+ return Compatible;
QualType lhptee = lhsType->getAsObjCObjectPointerType()->getPointeeType();
QualType rhptee = rhsType->getAsObjCObjectPointerType()->getPointeeType();
return CheckPointeeTypesForAssignment(lhptee, rhptee);
@@ -4279,11 +4283,6 @@ QualType Sema::CheckCompareOperands(Expr *&lex, Expr *&rex, SourceLocation Loc,
Diag(Loc, diag::ext_typecheck_comparison_of_distinct_pointers)
<< lType << rType << lex->getSourceRange() << rex->getSourceRange();
}
- if (lType->isObjCQualifiedIdType() && rType->isObjCQualifiedIdType()) {
- if (!ObjCQualifiedIdTypesAreCompatible(lType, rType, true))
- Diag(Loc, diag::warn_incompatible_qualified_id_operands)
- << lType << rType << lex->getSourceRange() << rex->getSourceRange();
- }
ImpCastExprToType(rex, lType);
return ResultTy;
}
diff --git a/lib/Sema/SemaOverload.cpp b/lib/Sema/SemaOverload.cpp
index bee3936048..35c5567503 100644
--- a/lib/Sema/SemaOverload.cpp
+++ b/lib/Sema/SemaOverload.cpp
@@ -1011,15 +1011,9 @@ bool Sema::isObjCPointerConversion(QualType FromType, QualType ToType,
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
+ // Objective C++: We're able to convert between "id" or "Class" and a
// pointer to any interface (in both directions).
- if (ToObjCPtr->isObjCClassType() || FromObjCPtr->isObjCClassType()) {
+ if (ToObjCPtr->isObjCBuiltinType() && FromObjCPtr->isObjCBuiltinType()) {
ConvertedType = ToType;
return true;
}
@@ -1169,8 +1163,7 @@ bool Sema::CheckPointerConversion(Expr *From, QualType ToType) {
// 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())
+ if (FromPtrType->isObjCBuiltinType() || ToPtrType->isObjCBuiltinType())
return false;
}
diff --git a/test/SemaObjC/comptypes-3.m b/test/SemaObjC/comptypes-3.m
index 2d8f19d806..0506bce7ad 100644
--- a/test/SemaObjC/comptypes-3.m
+++ b/test/SemaObjC/comptypes-3.m
@@ -42,8 +42,8 @@ int main()
obj_ac = obj_b; // expected-warning {{incompatible type assigning 'id<MyProtocolB>', expected 'id<MyProtocolAC>'}}
obj_ac = obj_ab; // expected-warning {{incompatible type assigning 'id<MyProtocolAB>', expected 'id<MyProtocolAC>'}}
- if (obj_a == obj_b) foo (); // expected-warning {{invalid operands to binary expression ('id<MyProtocolA>' and 'id<MyProtocolB>')}}
- if (obj_b == obj_a) foo (); // expected-warning {{invalid operands to binary expression ('id<MyProtocolB>' and 'id<MyProtocolA>')}}
+ if (obj_a == obj_b) foo (); // expected-warning {{comparison of distinct pointer types ('id<MyProtocolA>' and 'id<MyProtocolB>')}}
+ if (obj_b == obj_a) foo (); // expected-warning {{comparison of distinct pointer types ('id<MyProtocolB>' and 'id<MyProtocolA>')}}
if (obj_a == obj_ab) foo (); /* Ok */
if (obj_ab == obj_a) foo (); /* Ok */
@@ -54,11 +54,11 @@ int main()
if (obj_b == obj_ab) foo (); /* Ok */
if (obj_ab == obj_b) foo (); /* Ok */
- if (obj_b == obj_ac) foo (); // expected-warning {{invalid operands to binary expression ('id<MyProtocolB>' and 'id<MyProtocolAC>')}}
- if (obj_ac == obj_b) foo (); // expected-warning {{invalid operands to binary expression ('id<MyProtocolAC>' and 'id<MyProtocolB>')}}
+ if (obj_b == obj_ac) foo (); // expected-warning {{comparison of distinct pointer types ('id<MyProtocolB>' and 'id<MyProtocolAC>')}}
+ if (obj_ac == obj_b) foo (); // expected-warning {{comparison of distinct pointer types ('id<MyProtocolAC>' and 'id<MyProtocolB>')}}
- if (obj_ab == obj_ac) foo (); // expected-warning {{invalid operands to binary expression ('id<MyProtocolAB>' and 'id<MyProtocolAC>')}}
- if (obj_ac == obj_ab) foo (); // expected-warning {{invalid operands to binary expression ('id<MyProtocolAC>' and 'id<MyProtocolAB>')}}
+ if (obj_ab == obj_ac) foo (); // expected-warning {{comparison of distinct pointer types ('id<MyProtocolAB>' and 'id<MyProtocolAC>')}}
+ if (obj_ac == obj_ab) foo (); // expected-warning {{comparison of distinct pointer types ('id<MyProtocolAC>' and 'id<MyProtocolAB>')}}
return 0;
}
diff --git a/test/SemaObjC/conditional-expr-3.m b/test/SemaObjC/conditional-expr-3.m
index 0b392d4882..9f1ee68c6f 100644
--- a/test/SemaObjC/conditional-expr-3.m
+++ b/test/SemaObjC/conditional-expr-3.m
@@ -51,15 +51,15 @@ void f7(int cond, id x, A *a) {
}
void f8(int cond, id<P0,P1> x0, id<P0,P2> x1) {
- barP0(cond ? x0 : x1);
+ barP0(cond ? x0 : x1); // expected-warning {{incompatible operand types ('id<P0,P1>' and 'id<P0,P2>')}}
}
void f9(int cond, id<P0,P1> x0, id<P0,P2> x1) {
- barP1(cond ? x0 : x1);
+ barP1(cond ? x0 : x1); // expected-warning {{incompatible operand types ('id<P0,P1>' and 'id<P0,P2>')}}
}
void f10(int cond, id<P0,P1> x0, id<P0,P2> x1) {
- barP2(cond ? x0 : x1); // expected-warning {{incompatible type passing 'id<P0,P1>', expected 'id<P2>'}}
+ barP2(cond ? x0 : x1); // expected-warning {{incompatible operand types ('id<P0,P1>' and 'id<P0,P2>')}}
}
int f11(int cond, A* a, B* b) {