r274076 - ObjC Class Property: diagnostics when accessing a class property using instance.

Manman Ren via cfe-commits cfe-commits at lists.llvm.org
Tue Jun 28 16:01:49 PDT 2016


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}}
 }
+
+ at interface A
+ at property (class) int c;
+ at 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;
 }
 




More information about the cfe-commits mailing list