Some code refactoring. Be more generous in issuance of warning
on method type mismatches per Chris's comment. llvm-svn: 78075
This commit is contained in:
parent
206ee96bd6
commit
b61af4c566
|
@ -1464,35 +1464,41 @@ void Sema::ProcessPropertyDecl(ObjCPropertyDecl *property,
|
|||
AddInstanceMethodToGlobalPool(SetterMethod);
|
||||
}
|
||||
|
||||
/// CompareMethodParamsInBaseAndSuper - This routine compares methods with
|
||||
/// identical selector names in current and its super classes and issues
|
||||
/// a warning if any of their argument types are incompatible.
|
||||
void Sema::CompareMethodParamsInBaseAndSuper(Decl *ClassDecl,
|
||||
ObjCMethodDecl *Method,
|
||||
bool IsInstance) {
|
||||
if (ObjCInterfaceDecl *ID = dyn_cast<ObjCInterfaceDecl>(ClassDecl))
|
||||
while (ObjCInterfaceDecl *SD = ID->getSuperClass()) {
|
||||
if (ObjCMethodDecl *SuperMethodDecl =
|
||||
SD->lookupMethod(Method->getSelector(), IsInstance)) {
|
||||
ObjCMethodDecl::param_iterator ParamI = Method->param_begin(),
|
||||
E = Method->param_end();
|
||||
ObjCMethodDecl::param_iterator PrevI =
|
||||
SuperMethodDecl->param_begin();
|
||||
for (; ParamI != E; ++ParamI, ++PrevI) {
|
||||
assert(PrevI != SuperMethodDecl->param_end() && "Param mismatch");
|
||||
QualType T1 = Context.getCanonicalType((*ParamI)->getType());
|
||||
QualType T2 = Context.getCanonicalType((*PrevI)->getType());
|
||||
if (T1 != T2) {
|
||||
AssignConvertType ConvTy = CheckAssignmentConstraints(T1, T2);
|
||||
if (ConvTy == Incompatible || ConvTy == IncompatiblePointer) {
|
||||
Diag((*ParamI)->getLocation(), diag::ext_typecheck_base_super)
|
||||
<< T1 << T2;
|
||||
Diag(SuperMethodDecl->getLocation(),
|
||||
diag::note_previous_declaration);
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
ObjCInterfaceDecl *ID = dyn_cast<ObjCInterfaceDecl>(ClassDecl);
|
||||
if (ID == 0) return;
|
||||
|
||||
while (ObjCInterfaceDecl *SD = ID->getSuperClass()) {
|
||||
ObjCMethodDecl *SuperMethodDecl =
|
||||
SD->lookupMethod(Method->getSelector(), IsInstance);
|
||||
if (SuperMethodDecl == 0) {
|
||||
ID = SD;
|
||||
continue;
|
||||
}
|
||||
ObjCMethodDecl::param_iterator ParamI = Method->param_begin(),
|
||||
E = Method->param_end();
|
||||
ObjCMethodDecl::param_iterator PrevI = SuperMethodDecl->param_begin();
|
||||
for (; ParamI != E; ++ParamI, ++PrevI) {
|
||||
// Number of parameters are the same and is guaranteed by selector match.
|
||||
assert(PrevI != SuperMethodDecl->param_end() && "Param mismatch");
|
||||
QualType T1 = Context.getCanonicalType((*ParamI)->getType());
|
||||
QualType T2 = Context.getCanonicalType((*PrevI)->getType());
|
||||
// If type of arguement of method in this class does not match its
|
||||
// respective argument type in the super class method, issue warning;
|
||||
if (!Context.typesAreCompatible(T1, T2)) {
|
||||
Diag((*ParamI)->getLocation(), diag::ext_typecheck_base_super)
|
||||
<< T1 << T2;
|
||||
Diag(SuperMethodDecl->getLocation(), diag::note_previous_declaration);
|
||||
return;
|
||||
}
|
||||
}
|
||||
ID = SD;
|
||||
}
|
||||
}
|
||||
|
||||
// Note: For class/category implemenations, allMethods/allProperties is
|
||||
|
@ -1540,6 +1546,8 @@ void Sema::ActOnAtEnd(SourceLocation AtEndLoc, DeclPtrTy classDecl,
|
|||
InsMap[Method->getSelector()] = Method;
|
||||
/// The following allows us to typecheck messages to "id".
|
||||
AddInstanceMethodToGlobalPool(Method);
|
||||
// verify that the instance method conforms to the same definition of
|
||||
// parent methods if it shadows one.
|
||||
CompareMethodParamsInBaseAndSuper(ClassDecl, Method, true);
|
||||
}
|
||||
}
|
||||
|
@ -1558,6 +1566,8 @@ void Sema::ActOnAtEnd(SourceLocation AtEndLoc, DeclPtrTy classDecl,
|
|||
ClsMap[Method->getSelector()] = Method;
|
||||
/// The following allows us to typecheck messages to "Class".
|
||||
AddFactoryMethodToGlobalPool(Method);
|
||||
// verify that the class method conforms to the same definition of
|
||||
// parent methods if it shadows one.
|
||||
CompareMethodParamsInBaseAndSuper(ClassDecl, Method, false);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -12,6 +12,8 @@
|
|||
-(void) method2: (Sub*) x;
|
||||
+ method3: (int)x1 : (Base *)x2 : (float)x3; // expected-note {{previous declaration is here}}
|
||||
+ mathod4: (id)x1;
|
||||
- method5: (int) x : (double) d; // expected-note {{previous declaration is here}}
|
||||
- method6: (int) x : (float) d; // expected-note {{previous declaration is here}}
|
||||
@end
|
||||
|
||||
struct A {
|
||||
|
@ -25,6 +27,8 @@ struct A {
|
|||
+ method3: (int)x1 : (Sub *)x2 : (float)x3; // expected-warning {{method parameter type 'Sub *' does not match super class method parameter type 'Base *'}}
|
||||
+ mathod4: (Base*)x1;
|
||||
-(void) method_r: (char)ch : (float*)f1 : (Sub*) x; // expected-warning {{method parameter type 'Sub *' does not match super class method parameter type 'int *'}}
|
||||
- method5: (int) x : (float) d; // expected-warning {{method parameter type 'float' does not match super class method parameter type 'double'}}
|
||||
- method6: (int) x : (double) d; // expected-warning {{method parameter type 'double' does not match super class method parameter type 'float'}}
|
||||
@end
|
||||
|
||||
void f(Base *base, Sub *sub) {
|
||||
|
|
Loading…
Reference in New Issue