Author: mren Date: Tue Jun 28 18:01:49 2016 New Revision: 274076 URL: http://llvm.org/viewvc/llvm-project?rev=274076&view=rev Log: ObjC Class Property: diagnostics when accessing a class property using instance.
When a class property is accessed with an object instance, before this commit, we try to apply a typo correction of the same property: property 'c' not found on object of type 'A *'; did you mean 'c'? With this commit, we correctly emit a diagnostics: property 'c' is a class property; did you mean to access it with class 'A'? rdar://26866973 Modified: cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td cfe/trunk/lib/Sema/SemaExprObjC.cpp cfe/trunk/test/FixIt/fixit-objc.m cfe/trunk/test/SemaObjC/objc-class-property.m Modified: cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td?rev=274076&r1=274075&r2=274076&view=diff ============================================================================== --- cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td (original) +++ cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td Tue Jun 28 18:01:49 2016 @@ -7761,6 +7761,8 @@ def err_typecheck_member_reference_ivar_ "%0 does not have a member named %1; did you mean %2?">; def err_property_not_found_suggest : Error< "property %0 not found on object of type %1; did you mean %2?">; +def err_class_property_found : Error< + "property %0 is a class property; did you mean to access it with class '%1'?">; def err_ivar_access_using_property_syntax_suggest : Error< "property %0 not found on object of type %1; did you mean to access instance variable %2?">; def warn_property_access_suggest : Warning< Modified: cfe/trunk/lib/Sema/SemaExprObjC.cpp URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaExprObjC.cpp?rev=274076&r1=274075&r2=274076&view=diff ============================================================================== --- cfe/trunk/lib/Sema/SemaExprObjC.cpp (original) +++ cfe/trunk/lib/Sema/SemaExprObjC.cpp Tue Jun 28 18:01:49 2016 @@ -1817,7 +1817,7 @@ HandleExprPropertyRefExpr(const ObjCObje Selector Sel = PP.getSelectorTable().getNullarySelector(Member); ObjCMethodDecl *Getter = IFace->lookupInstanceMethod(Sel); - // May be founf in property's qualified list. + // May be found in property's qualified list. if (!Getter) Getter = LookupMethodInQualifiedType(Sel, OPT, true); @@ -1837,7 +1837,7 @@ HandleExprPropertyRefExpr(const ObjCObje PP.getSelectorTable(), Member); ObjCMethodDecl *Setter = IFace->lookupInstanceMethod(SetterSel); - // May be founf in property's qualified list. + // May be found in property's qualified list. if (!Setter) Setter = LookupMethodInQualifiedType(SetterSel, OPT, true); @@ -1885,12 +1885,29 @@ HandleExprPropertyRefExpr(const ObjCObje LookupOrdinaryName, nullptr, nullptr, llvm::make_unique<DeclFilterCCC<ObjCPropertyDecl>>(), CTK_ErrorRecovery, IFace, false, OPT)) { - diagnoseTypo(Corrected, PDiag(diag::err_property_not_found_suggest) - << MemberName << QualType(OPT, 0)); DeclarationName TypoResult = Corrected.getCorrection(); - return HandleExprPropertyRefExpr(OPT, BaseExpr, OpLoc, - TypoResult, MemberLoc, - SuperLoc, SuperType, Super); + if (TypoResult.isIdentifier() && + TypoResult.getAsIdentifierInfo() == Member) { + // There is no need to try the correction if it is the same. + NamedDecl *ChosenDecl = + Corrected.isKeyword() ? nullptr : Corrected.getFoundDecl(); + if (ChosenDecl && isa<ObjCPropertyDecl>(ChosenDecl)) + if (cast<ObjCPropertyDecl>(ChosenDecl)->isClassProperty()) { + // This is a class property, we should not use the instance to + // access it. + Diag(MemberLoc, diag::err_class_property_found) << MemberName + << OPT->getInterfaceDecl()->getName() + << FixItHint::CreateReplacement(BaseExpr->getSourceRange(), + OPT->getInterfaceDecl()->getName()); + return ExprError(); + } + } else { + diagnoseTypo(Corrected, PDiag(diag::err_property_not_found_suggest) + << MemberName << QualType(OPT, 0)); + return HandleExprPropertyRefExpr(OPT, BaseExpr, OpLoc, + TypoResult, MemberLoc, + SuperLoc, SuperType, Super); + } } ObjCInterfaceDecl *ClassDeclared; if (ObjCIvarDecl *Ivar = Modified: cfe/trunk/test/FixIt/fixit-objc.m URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/FixIt/fixit-objc.m?rev=274076&r1=274075&r2=274076&view=diff ============================================================================== --- cfe/trunk/test/FixIt/fixit-objc.m (original) +++ cfe/trunk/test/FixIt/fixit-objc.m Tue Jun 28 18:01:49 2016 @@ -67,3 +67,11 @@ void sentinel_test(Sentinel *a) { sentinel(1, 2, 3); // expected-warning{{missing sentinel in function call}} [a sentinel:1, 2, 3]; // expected-warning{{missing sentinel in method dispatch}} } + +@interface A +@property (class) int c; +@end + +int test(A *a) { + return a.c; // expected-error {{property 'c' is a class property; did you mean to access it with class 'A'}} +} Modified: cfe/trunk/test/SemaObjC/objc-class-property.m URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/SemaObjC/objc-class-property.m?rev=274076&r1=274075&r2=274076&view=diff ============================================================================== --- cfe/trunk/test/SemaObjC/objc-class-property.m (original) +++ cfe/trunk/test/SemaObjC/objc-class-property.m Tue Jun 28 18:01:49 2016 @@ -33,6 +33,7 @@ int test() { A *a = [[A alloc] init]; + a.c; // expected-error {{property 'c' is a class property; did you mean to access it with class 'A'}} return a.x + A.c; } _______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits