forked from OSchip/llvm-project
ObjC migrator: finding conforming protocol
candidates for each class. wip. llvm-svn: 186349
This commit is contained in:
parent
786928dbd2
commit
d36150d7ca
|
@ -1717,6 +1717,9 @@ public:
|
||||||
getCanonicalType(T2).getTypePtr();
|
getCanonicalType(T2).getTypePtr();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool ObjCMethodsAreEqual(const ObjCMethodDecl *MethodDecl,
|
||||||
|
const ObjCMethodDecl *MethodImp);
|
||||||
|
|
||||||
bool UnwrapSimilarPointerTypes(QualType &T1, QualType &T2);
|
bool UnwrapSimilarPointerTypes(QualType &T1, QualType &T2);
|
||||||
|
|
||||||
/// \brief Retrieves the "canonical" nested name specifier for a
|
/// \brief Retrieves the "canonical" nested name specifier for a
|
||||||
|
|
|
@ -238,8 +238,50 @@ void ObjCMigrateASTConsumer::migrateObjCInterfaceDecl(ASTContext &Ctx,
|
||||||
static bool
|
static bool
|
||||||
ClassImplementsAllMethodsAndProperties(ASTContext &Ctx,
|
ClassImplementsAllMethodsAndProperties(ASTContext &Ctx,
|
||||||
const ObjCImplementationDecl *ImpDecl,
|
const ObjCImplementationDecl *ImpDecl,
|
||||||
|
const ObjCInterfaceDecl *IDecl,
|
||||||
ObjCProtocolDecl *Protocol) {
|
ObjCProtocolDecl *Protocol) {
|
||||||
return false;
|
// In auto-synthesis, protocol properties are not synthesized. So,
|
||||||
|
// a conforming protocol must have its required properties declared
|
||||||
|
// in class interface.
|
||||||
|
if (const ObjCProtocolDecl *PDecl = Protocol->getDefinition())
|
||||||
|
for (ObjCProtocolDecl::prop_iterator P = PDecl->prop_begin(),
|
||||||
|
E = PDecl->prop_end(); P != E; ++P) {
|
||||||
|
ObjCPropertyDecl *Property = *P;
|
||||||
|
if (Property->getPropertyImplementation() == ObjCPropertyDecl::Optional)
|
||||||
|
continue;
|
||||||
|
DeclContext::lookup_const_result R = IDecl->lookup(Property->getDeclName());
|
||||||
|
for (unsigned I = 0, N = R.size(); I != N; ++I) {
|
||||||
|
if (ObjCPropertyDecl *ClassProperty = dyn_cast<ObjCPropertyDecl>(R[0])) {
|
||||||
|
if (ClassProperty->getPropertyAttributes()
|
||||||
|
!= Property->getPropertyAttributes())
|
||||||
|
return false;
|
||||||
|
if (!Ctx.hasSameType(ClassProperty->getType(), Property->getType()))
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// At this point, all required properties in this protocol conform to those
|
||||||
|
// declared in the class.
|
||||||
|
// Check that class implements the required methods of the protocol too.
|
||||||
|
if (const ObjCProtocolDecl *PDecl = Protocol->getDefinition())
|
||||||
|
for (ObjCContainerDecl::method_iterator M = PDecl->meth_begin(),
|
||||||
|
MEnd = PDecl->meth_end(); M != MEnd; ++M) {
|
||||||
|
ObjCMethodDecl *MD = (*M);
|
||||||
|
if (MD->getImplementationControl() == ObjCMethodDecl::Optional)
|
||||||
|
continue;
|
||||||
|
bool match = false;
|
||||||
|
DeclContext::lookup_const_result R = ImpDecl->lookup(MD->getDeclName());
|
||||||
|
for (unsigned I = 0, N = R.size(); I != N; ++I)
|
||||||
|
if (ObjCMethodDecl *ImpMD = dyn_cast<ObjCMethodDecl>(R[0]))
|
||||||
|
if (Ctx.ObjCMethodsAreEqual(MD, ImpMD)) {
|
||||||
|
match = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
if (!match)
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
void ObjCMigrateASTConsumer::migrateProtocolConformance(ASTContext &Ctx,
|
void ObjCMigrateASTConsumer::migrateProtocolConformance(ASTContext &Ctx,
|
||||||
|
@ -267,7 +309,7 @@ void ObjCMigrateASTConsumer::migrateProtocolConformance(ASTContext &Ctx,
|
||||||
// methods and properties, then this class conforms to this protocol.
|
// methods and properties, then this class conforms to this protocol.
|
||||||
llvm::SmallVector<ObjCProtocolDecl*, 8> ConformingProtocols;
|
llvm::SmallVector<ObjCProtocolDecl*, 8> ConformingProtocols;
|
||||||
for (unsigned i = 0, e = PotentialImplicitProtocols.size(); i != e; i++)
|
for (unsigned i = 0, e = PotentialImplicitProtocols.size(); i != e; i++)
|
||||||
if (ClassImplementsAllMethodsAndProperties(Ctx, ImpDecl,
|
if (ClassImplementsAllMethodsAndProperties(Ctx, ImpDecl, IDecl,
|
||||||
PotentialImplicitProtocols[i]))
|
PotentialImplicitProtocols[i]))
|
||||||
ConformingProtocols.push_back(PotentialImplicitProtocols[i]);
|
ConformingProtocols.push_back(PotentialImplicitProtocols[i]);
|
||||||
}
|
}
|
||||||
|
|
|
@ -8129,3 +8129,35 @@ ASTContext::getParents(const ast_type_traits::DynTypedNode &Node) {
|
||||||
}
|
}
|
||||||
return I->second;
|
return I->second;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool
|
||||||
|
ASTContext::ObjCMethodsAreEqual(const ObjCMethodDecl *MethodDecl,
|
||||||
|
const ObjCMethodDecl *MethodImpl) {
|
||||||
|
// No point trying to match an unavailable/deprecated mothod.
|
||||||
|
if (MethodDecl->hasAttr<UnavailableAttr>()
|
||||||
|
|| MethodDecl->hasAttr<DeprecatedAttr>())
|
||||||
|
return false;
|
||||||
|
if (MethodDecl->getObjCDeclQualifier() !=
|
||||||
|
MethodImpl->getObjCDeclQualifier())
|
||||||
|
return false;
|
||||||
|
if (!hasSameType(MethodDecl->getResultType(),
|
||||||
|
MethodImpl->getResultType()))
|
||||||
|
return false;
|
||||||
|
|
||||||
|
if (MethodDecl->param_size() != MethodImpl->param_size())
|
||||||
|
return false;
|
||||||
|
|
||||||
|
for (ObjCMethodDecl::param_const_iterator IM = MethodImpl->param_begin(),
|
||||||
|
IF = MethodDecl->param_begin(), EM = MethodImpl->param_end(),
|
||||||
|
EF = MethodDecl->param_end();
|
||||||
|
IM != EM && IF != EF; ++IM, ++IF) {
|
||||||
|
const ParmVarDecl *DeclVar = (*IF);
|
||||||
|
const ParmVarDecl *ImplVar = (*IM);
|
||||||
|
if (ImplVar->getObjCDeclQualifier() != DeclVar->getObjCDeclQualifier())
|
||||||
|
return false;
|
||||||
|
if (!hasSameType(DeclVar->getType(), ImplVar->getType()))
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return (MethodDecl->isVariadic() == MethodImpl->isVariadic());
|
||||||
|
|
||||||
|
}
|
||||||
|
|
Loading…
Reference in New Issue