forked from OSchip/llvm-project
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 llvm-svn: 281353
This commit is contained in:
parent
662b51f606
commit
3569eb5267
|
@ -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<ObjCProtocolDecl *> protocols, bool &hasError,
|
||||
bool allowOnPointerType = false) const;
|
||||
|
||||
/// \brief Return the uniqued reference to the type for an Objective-C
|
||||
/// gc-qualified type.
|
||||
///
|
||||
|
|
|
@ -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<ObjCProtocolDecl *> protocols, bool &hasError,
|
||||
bool allowOnPointerType) const {
|
||||
hasError = false;
|
||||
|
||||
// Apply protocol qualifiers to ObjCObjectPointerType.
|
||||
if (allowOnPointerType) {
|
||||
if (const ObjCObjectPointerType *objPtr =
|
||||
dyn_cast<ObjCObjectPointerType>(type.getTypePtr())) {
|
||||
const ObjCObjectType *objT = objPtr->getObjectType();
|
||||
// Merge protocol lists and construct ObjCObjectType.
|
||||
SmallVector<ObjCProtocolDecl*, 8> protocolsVec;
|
||||
protocolsVec.append(objT->qual_begin(),
|
||||
objT->qual_end());
|
||||
protocolsVec.append(protocols.begin(), protocols.end());
|
||||
ArrayRef<ObjCProtocolDecl *> 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<ObjCObjectType>(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<protocol-list>
|
||||
if (type->isObjCIdType()) {
|
||||
const ObjCObjectPointerType *objPtr = type->castAs<ObjCObjectPointerType>();
|
||||
type = getObjCObjectType(ObjCBuiltinIdTy, { }, protocols,
|
||||
objPtr->isKindOfType());
|
||||
return getObjCObjectPointerType(type);
|
||||
}
|
||||
|
||||
// Class<protocol-list>
|
||||
if (type->isObjCClassType()) {
|
||||
const ObjCObjectPointerType *objPtr = type->castAs<ObjCObjectPointerType>();
|
||||
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.
|
||||
|
|
|
@ -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<ObjCProtocolDecl *> protocols,
|
||||
const SourceLocation *protocolLocs,
|
||||
bool failOnError = false) {
|
||||
ASTContext &ctx = S.Context;
|
||||
if (const ObjCObjectType *objT = dyn_cast<ObjCObjectType>(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<protocol-list>
|
||||
if (type->isObjCIdType()) {
|
||||
const ObjCObjectPointerType *objPtr = type->castAs<ObjCObjectPointerType>();
|
||||
type = ctx.getObjCObjectType(ctx.ObjCBuiltinIdTy, { }, protocols,
|
||||
objPtr->isKindOfType());
|
||||
return ctx.getObjCObjectPointerType(type);
|
||||
}
|
||||
|
||||
// Class<protocol-list>
|
||||
if (type->isObjCClassType()) {
|
||||
const ObjCObjectPointerType *objPtr = type->castAs<ObjCObjectPointerType>();
|
||||
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();
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue