From eae373ea328c4bc1d5741b3b7d6e78268fa60e45 Mon Sep 17 00:00:00 2001 From: Fariborz Jahanian Date: Tue, 2 Dec 2008 18:39:49 +0000 Subject: [PATCH] More type-checking of setter/getter methods. This is still work in prgress. llvm-svn: 60430 --- clang/include/clang/Basic/DiagnosticKinds.def | 4 ++ clang/lib/Sema/Sema.h | 3 ++ clang/lib/Sema/SemaDeclObjC.cpp | 42 +++++++++++++++++-- 3 files changed, 46 insertions(+), 3 deletions(-) diff --git a/clang/include/clang/Basic/DiagnosticKinds.def b/clang/include/clang/Basic/DiagnosticKinds.def index 2e76df17ba13..e48de866d664 100644 --- a/clang/include/clang/Basic/DiagnosticKinds.def +++ b/clang/include/clang/Basic/DiagnosticKinds.def @@ -569,6 +569,10 @@ DIAG(err_use_continuation_class, ERROR, "use contination class to override 'readonly' property with 'readwrite'") DIAG(warn_property_attr_mismatch, WARNING, "property attribute in continuation class does not match the primary class") +DIAG(err_accessor_property_type_mismatch, ERROR, + "type of property %0 does not match type of accessor %1") +DIAG(err_setter_type_void, ERROR, + "type of setter must be void") /// C++ parser diagnostics DIAG(err_expected_unqualified_id, ERROR, diff --git a/clang/lib/Sema/Sema.h b/clang/lib/Sema/Sema.h index 7f3d0f4d2fff..cfb221bf4014 100644 --- a/clang/lib/Sema/Sema.h +++ b/clang/lib/Sema/Sema.h @@ -1032,6 +1032,9 @@ public: void CheckObjCPropertyAttributes(QualType PropertyTy, SourceLocation Loc, unsigned &Attributes); + void diagnosePropertySetterGetterMismatch(ObjCPropertyDecl *property, + const ObjCMethodDecl *GetterMethod, + const ObjCMethodDecl *SetterMethod); void DiagnosePropertyMismatch(ObjCPropertyDecl *Property, ObjCPropertyDecl *SuperProperty, const IdentifierInfo *Name); diff --git a/clang/lib/Sema/SemaDeclObjC.cpp b/clang/lib/Sema/SemaDeclObjC.cpp index 3a78024f90da..ed8751668782 100644 --- a/clang/lib/Sema/SemaDeclObjC.cpp +++ b/clang/lib/Sema/SemaDeclObjC.cpp @@ -855,6 +855,33 @@ void Sema::AddFactoryMethodToGlobalPool(ObjCMethodDecl *Method) { } } +/// diagnosePropertySetterGetterMismatch - Make sure that use-defined +/// setter/getter methods have the property type and issue diagnostics +/// if they don't. +/// +void +Sema::diagnosePropertySetterGetterMismatch(ObjCPropertyDecl *property, + const ObjCMethodDecl *GetterMethod, + const ObjCMethodDecl *SetterMethod) { + if (GetterMethod && + GetterMethod->getResultType() != property->getType()) + Diag(property->getLocation(), + diag::err_accessor_property_type_mismatch) + << property->getDeclName() + << GetterMethod->getSelector().getAsIdentifierInfo(); + + if (SetterMethod) { + if (SetterMethod->getResultType() != Context.VoidPtrTy) + Diag(SetterMethod->getLocation(), diag::err_setter_type_void); + if (SetterMethod->getNumParams() != 1 || + (SetterMethod->getParamDecl(0)->getType() != property->getType())) + Diag(property->getLocation(), + diag::err_accessor_property_type_mismatch) + << property->getDeclName() + << SetterMethod->getSelector().getAsIdentifierInfo(); + } +} + // Note: For class/category implemenations, allMethods/allProperties is // always null. void Sema::ActOnAtEnd(SourceLocation AtEndLoc, DeclTy *classDecl, @@ -940,15 +967,21 @@ void Sema::ActOnAtEnd(SourceLocation AtEndLoc, DeclTy *classDecl, ComparePropertiesInBaseAndSuper(I); MergeProtocolPropertiesIntoClass(I, I); for (ObjCInterfaceDecl::classprop_iterator i = I->classprop_begin(), - e = I->classprop_end(); i != e; ++i) + e = I->classprop_end(); i != e; ++i) { + diagnosePropertySetterGetterMismatch((*i), InsMap[(*i)->getGetterName()], + InsMap[(*i)->getSetterName()]); I->addPropertyMethods(Context, *i, insMethods, InsMap); + } I->addMethods(&insMethods[0], insMethods.size(), &clsMethods[0], clsMethods.size(), AtEndLoc); } else if (ObjCProtocolDecl *P = dyn_cast(ClassDecl)) { for (ObjCProtocolDecl::classprop_iterator i = P->classprop_begin(), - e = P->classprop_end(); i != e; ++i) + e = P->classprop_end(); i != e; ++i) { + diagnosePropertySetterGetterMismatch((*i), InsMap[(*i)->getGetterName()], + InsMap[(*i)->getSetterName()]); P->addPropertyMethods(Context, *i, insMethods, InsMap); + } P->addMethods(&insMethods[0], insMethods.size(), &clsMethods[0], clsMethods.size(), AtEndLoc); } @@ -958,8 +991,11 @@ void Sema::ActOnAtEnd(SourceLocation AtEndLoc, DeclTy *classDecl, // FIXME: If we merge properties into class we should probably // merge them into category as well? for (ObjCCategoryDecl::classprop_iterator i = C->classprop_begin(), - e = C->classprop_end(); i != e; ++i) + e = C->classprop_end(); i != e; ++i) { + diagnosePropertySetterGetterMismatch((*i), InsMap[(*i)->getGetterName()], + InsMap[(*i)->getSetterName()]); C->addPropertyMethods(Context, *i, insMethods, InsMap); + } C->addMethods(&insMethods[0], insMethods.size(), &clsMethods[0], clsMethods.size(), AtEndLoc); }