From be6c7737f30c010cc76bea7ef544eb204acc68aa Mon Sep 17 00:00:00 2001 From: Manman Ren Date: Tue, 13 Sep 2016 17:03:12 +0000 Subject: [PATCH] ObjectiveC: Refactor applyObjCProtocolQualifiers. To construct the canonical type of ObjCTypeParamType, we need to apply qualifiers on ObjCObjectPointerType. The updated applyObjCProtocolQualifiers handles this case by merging the protocol lists, constructing a new ObjCObjectType, then a new ObjCObjectPointerType. rdar://24619481 rdar://25060179 Differential Revision: http://reviews.llvm.org/D24059 git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@281353 91177308-0d34-0410-b5e6-96231b3b80d8 --- include/clang/AST/ASTContext.h | 8 ++++ lib/AST/ASTContext.cpp | 70 ++++++++++++++++++++++++++++++++++ lib/Sema/SemaType.cpp | 65 ++++--------------------------- 3 files changed, 86 insertions(+), 57 deletions(-) diff --git a/include/clang/AST/ASTContext.h b/include/clang/AST/ASTContext.h index 45127acba4..86a014fd43 100644 --- a/include/clang/AST/ASTContext.h +++ b/include/clang/AST/ASTContext.h @@ -1030,6 +1030,14 @@ public: /// replaced. QualType getAddrSpaceQualType(QualType T, unsigned AddressSpace) const; + /// \brief Apply Objective-C protocol qualifiers to the given type. + /// \param allowOnPointerType specifies if we can apply protocol + /// qualifiers on ObjCObjectPointerType. It can be set to true when + /// contructing the canonical type of a Objective-C type parameter. + QualType applyObjCProtocolQualifiers(QualType type, + ArrayRef protocols, bool &hasError, + bool allowOnPointerType = false) const; + /// \brief Return the uniqued reference to the type for an Objective-C /// gc-qualified type. /// diff --git a/lib/AST/ASTContext.cpp b/lib/AST/ASTContext.cpp index c2de06b895..697d4c1a52 100644 --- a/lib/AST/ASTContext.cpp +++ b/lib/AST/ASTContext.cpp @@ -3871,6 +3871,76 @@ QualType ASTContext::getObjCObjectType( return QualType(T, 0); } +/// Apply Objective-C protocol qualifiers to the given type. +/// If this is for the canonical type of a type parameter, we can apply +/// protocol qualifiers on the ObjCObjectPointerType. +QualType +ASTContext::applyObjCProtocolQualifiers(QualType type, + ArrayRef protocols, bool &hasError, + bool allowOnPointerType) const { + hasError = false; + + // Apply protocol qualifiers to ObjCObjectPointerType. + if (allowOnPointerType) { + if (const ObjCObjectPointerType *objPtr = + dyn_cast(type.getTypePtr())) { + const ObjCObjectType *objT = objPtr->getObjectType(); + // Merge protocol lists and construct ObjCObjectType. + SmallVector protocolsVec; + protocolsVec.append(objT->qual_begin(), + objT->qual_end()); + protocolsVec.append(protocols.begin(), protocols.end()); + ArrayRef protocols = protocolsVec; + type = getObjCObjectType( + objT->getBaseType(), + objT->getTypeArgsAsWritten(), + protocols, + objT->isKindOfTypeAsWritten()); + return getObjCObjectPointerType(type); + } + } + + // Apply protocol qualifiers to ObjCObjectType. + if (const ObjCObjectType *objT = dyn_cast(type.getTypePtr())){ + // FIXME: Check for protocols to which the class type is already + // known to conform. + + return getObjCObjectType(objT->getBaseType(), + objT->getTypeArgsAsWritten(), + protocols, + objT->isKindOfTypeAsWritten()); + } + + // If the canonical type is ObjCObjectType, ... + if (type->isObjCObjectType()) { + // Silently overwrite any existing protocol qualifiers. + // TODO: determine whether that's the right thing to do. + + // FIXME: Check for protocols to which the class type is already + // known to conform. + return getObjCObjectType(type, { }, protocols, false); + } + + // id + if (type->isObjCIdType()) { + const ObjCObjectPointerType *objPtr = type->castAs(); + type = getObjCObjectType(ObjCBuiltinIdTy, { }, protocols, + objPtr->isKindOfType()); + return getObjCObjectPointerType(type); + } + + // Class + if (type->isObjCClassType()) { + const ObjCObjectPointerType *objPtr = type->castAs(); + type = getObjCObjectType(ObjCBuiltinClassTy, { }, protocols, + objPtr->isKindOfType()); + return getObjCObjectPointerType(type); + } + + hasError = true; + return type; +} + /// ObjCObjectAdoptsQTypeProtocols - Checks that protocols in IC's /// protocol list adopt all protocols in QT's qualified-id protocol /// list. diff --git a/lib/Sema/SemaType.cpp b/lib/Sema/SemaType.cpp index 8a49f6120c..696586af9a 100644 --- a/lib/Sema/SemaType.cpp +++ b/lib/Sema/SemaType.cpp @@ -1000,57 +1000,6 @@ static QualType applyObjCTypeArgs(Sema &S, SourceLocation loc, QualType type, return S.Context.getObjCObjectType(type, finalTypeArgs, { }, false); } -/// Apply Objective-C protocol qualifiers to the given type. -static QualType applyObjCProtocolQualifiers( - Sema &S, SourceLocation loc, SourceRange range, QualType type, - ArrayRef protocols, - const SourceLocation *protocolLocs, - bool failOnError = false) { - ASTContext &ctx = S.Context; - if (const ObjCObjectType *objT = dyn_cast(type.getTypePtr())){ - // FIXME: Check for protocols to which the class type is already - // known to conform. - - return ctx.getObjCObjectType(objT->getBaseType(), - objT->getTypeArgsAsWritten(), - protocols, - objT->isKindOfTypeAsWritten()); - } - - if (type->isObjCObjectType()) { - // Silently overwrite any existing protocol qualifiers. - // TODO: determine whether that's the right thing to do. - - // FIXME: Check for protocols to which the class type is already - // known to conform. - return ctx.getObjCObjectType(type, { }, protocols, false); - } - - // id - if (type->isObjCIdType()) { - const ObjCObjectPointerType *objPtr = type->castAs(); - type = ctx.getObjCObjectType(ctx.ObjCBuiltinIdTy, { }, protocols, - objPtr->isKindOfType()); - return ctx.getObjCObjectPointerType(type); - } - - // Class - if (type->isObjCClassType()) { - const ObjCObjectPointerType *objPtr = type->castAs(); - type = ctx.getObjCObjectType(ctx.ObjCBuiltinClassTy, { }, protocols, - objPtr->isKindOfType()); - return ctx.getObjCObjectPointerType(type); - } - - S.Diag(loc, diag::err_invalid_protocol_qualifiers) - << range; - - if (failOnError) - return QualType(); - - return type; -} - QualType Sema::BuildObjCObjectType(QualType BaseType, SourceLocation Loc, SourceLocation TypeArgsLAngleLoc, @@ -1072,12 +1021,14 @@ QualType Sema::BuildObjCObjectType(QualType BaseType, } if (!Protocols.empty()) { - Result = applyObjCProtocolQualifiers(*this, Loc, - SourceRange(ProtocolLAngleLoc, - ProtocolRAngleLoc), - Result, Protocols, - ProtocolLocs.data(), - FailOnError); + bool HasError; + Result = Context.applyObjCProtocolQualifiers(Result, Protocols, + HasError); + if (HasError) { + Diag(Loc, diag::err_invalid_protocol_qualifiers) + << SourceRange(ProtocolLAngleLoc, ProtocolRAngleLoc); + if (FailOnError) Result = QualType(); + } if (FailOnError && Result.isNull()) return QualType(); } -- 2.40.0