diff options
author | Steve Naroff <snaroff@apple.com> | 2009-07-10 23:34:53 +0000 |
---|---|---|
committer | Steve Naroff <snaroff@apple.com> | 2009-07-10 23:34:53 +0000 |
commit | 14108da7f7fc059772711e4ffee1322a27b152a7 (patch) | |
tree | 5461a189505985c1c245c3f63a48030f0cd5e929 /lib | |
parent | 7ecbfbcddd278eede10bd38fa03a95a2110b191a (diff) |
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.
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@75314 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'lib')
30 files changed, 764 insertions, 671 deletions
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 && 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 @@ QualType ASTContext::mergeTypes(QualType LHS, QualType RHS) { 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 @@ QualType ASTContext::mergeTypes(QualType LHS, QualType RHS) { 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 @@ QualType ASTContext::mergeTypes(QualType LHS, QualType RHS) { 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(); diff --git a/lib/AST/DeclObjC.cpp b/lib/AST/DeclObjC.cpp index 54f13e14ba..613dc58a57 100644 --- a/lib/AST/DeclObjC.cpp +++ b/lib/AST/DeclObjC.cpp @@ -280,7 +280,7 @@ void ObjCMethodDecl::createImplicitParams(ASTContext &Context, // 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(); } diff --git a/lib/AST/Expr.cpp b/lib/AST/Expr.cpp index 970e8bc6c7..2c65179f95 100644 --- a/lib/AST/Expr.cpp +++ b/lib/AST/Expr.cpp @@ -1095,6 +1095,7 @@ bool Expr::isConstantInitializer(ASTContext &Ctx) const { switch (getStmtClass()) { default: break; case StringLiteralClass: + case ObjCStringLiteralClass: case ObjCEncodeExprClass: return true; case CompoundLiteralExprClass: { @@ -1136,7 +1137,6 @@ bool Expr::isConstantInitializer(ASTContext &Ctx) const { return cast<CastExpr>(this)->getSubExpr()->isConstantInitializer(Ctx); break; } - return isEvaluatable(Ctx); } diff --git a/lib/AST/ExprConstant.cpp b/lib/AST/ExprConstant.cpp index eb6b5b725f..c3d0402152 100644 --- a/lib/AST/ExprConstant.cpp +++ b/lib/AST/ExprConstant.cpp @@ -382,7 +382,8 @@ APValue PointerExprEvaluator::VisitCastExpr(const CastExpr* E) { 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; diff --git a/lib/AST/Type.cpp b/lib/AST/Type.cpp index 78c3b78977..fd368c4815 100644 --- a/lib/AST/Type.cpp +++ b/lib/AST/Type.cpp @@ -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 @@ const FunctionProtoType *Type::getAsFunctionProtoType() const { 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 @@ const ObjCObjectPointerType *Type::getAsObjCQualifiedIdType() const { 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 FunctionProtoType::Profile(llvm::FoldingSetNodeID &ID) { } 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 @@ 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; @@ -1671,15 +1701,7 @@ void ObjCInterfaceType::getAsStringInternal(std::string &InnerString, const Prin 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 @@ void ObjCObjectPointerType::getAsStringInternal(std::string &InnerString, } 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; } diff --git a/lib/Analysis/BasicObjCFoundationChecks.cpp b/lib/Analysis/BasicObjCFoundationChecks.cpp index aa85769157..b454a3605c 100644 --- a/lib/Analysis/BasicObjCFoundationChecks.cpp +++ b/lib/Analysis/BasicObjCFoundationChecks.cpp @@ -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 @@ class VISIBILITY_HIDDEN BasicObjCFoundationChecks : public GRSimpleAPICheck { 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 @@ bool BasicObjCFoundationChecks::Audit(ExplodedNode<GRState>* N, 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 @@ bool BasicObjCFoundationChecks::Audit(ExplodedNode<GRState>* N, 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 @@ bool BasicObjCFoundationChecks::CheckNilArg(NodeTy* N, unsigned Arg) { // 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); } diff --git a/lib/Analysis/CFRefCount.cpp b/lib/Analysis/CFRefCount.cpp index c74668cf0f..1cfd783492 100644 --- a/lib/Analysis/CFRefCount.cpp +++ b/lib/Analysis/CFRefCount.cpp @@ -547,14 +547,12 @@ public: 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 @@ public: 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 @@ bool RetainSummaryManager::isTrack |