[cfe-commits] r65879 - in /cfe/trunk: include/clang/Basic/DiagnosticSemaKinds.def lib/Sema/SemaExpr.cpp test/SemaObjC/ivar-ref-misuse.m

Fariborz Jahanian fjahanian at apple.com
Mon Mar 2 13:55:29 PST 2009


Author: fjahanian
Date: Mon Mar  2 15:55:29 2009
New Revision: 65879

URL: http://llvm.org/viewvc/llvm-project?rev=65879&view=rev
Log:
Diagnose a variety of access of ivars when they conflict with 
local or global variables in instance/class methods.

Added:
    cfe/trunk/test/SemaObjC/ivar-ref-misuse.m
Modified:
    cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.def
    cfe/trunk/lib/Sema/SemaExpr.cpp

Modified: cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.def
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.def?rev=65879&r1=65878&r2=65879&view=diff

==============================================================================
--- cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.def (original)
+++ cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.def Mon Mar  2 15:55:29 2009
@@ -1436,4 +1436,8 @@
      "invalid protocol qualifiers on non-ObjC type")
 DIAG(err_qualified_class_unsupported, ERROR,
      "protocol qualified 'Class' is unsupported")
+DIAG(warn_ivar_use_hidden, WARNING,
+     "local declaration of %0 hides instance variable")
+DIAG(error_ivar_use_in_class_method, ERROR,
+     "instance variable %0 accessed in class method")
 

Modified: cfe/trunk/lib/Sema/SemaExpr.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaExpr.cpp?rev=65879&r1=65878&r2=65879&view=diff

==============================================================================
--- cfe/trunk/lib/Sema/SemaExpr.cpp (original)
+++ cfe/trunk/lib/Sema/SemaExpr.cpp Mon Mar  2 15:55:29 2009
@@ -627,27 +627,42 @@
   if (II && getCurMethodDecl()) {
     // There are two cases to handle here.  1) scoped lookup could have failed,
     // in which case we should look for an ivar.  2) scoped lookup could have
-    // found a decl, but that decl is outside the current method (i.e. a global
-    // variable).  In these two cases, we do a lookup for an ivar with this
-    // name, if the lookup suceeds, we replace it our current decl.
+    // found a decl, but that decl is outside the current instance method (i.e. 
+    // a global variable).  In these two cases, we do a lookup for an ivar with 
+    // this name, if the lookup sucedes, we replace it our current decl.
     if (D == 0 || D->isDefinedOutsideFunctionOrMethod()) {
       ObjCInterfaceDecl *IFace = getCurMethodDecl()->getClassInterface();
       if (ObjCIvarDecl *IV = IFace->lookupInstanceVariable(II)) {
         // Check if referencing a field with __attribute__((deprecated)).
         if (DiagnoseUseOfDecl(IV, Loc))
           return ExprError();
-
-        // FIXME: This should use a new expr for a direct reference, don't turn
-        // this into Self->ivar, just return a BareIVarExpr or something.
-        IdentifierInfo &II = Context.Idents.get("self");
-        OwningExprResult SelfExpr = ActOnIdentifierExpr(S, Loc, II, false);
-        ObjCIvarRefExpr *MRef = new (Context) ObjCIvarRefExpr(IV, IV->getType(),
-                                  Loc, static_cast<Expr*>(SelfExpr.release()),
-                                  true, true);
-        Context.setFieldDecl(IFace, IV, MRef);
-        return Owned(MRef);
+        bool IsClsMethod = getCurMethodDecl()->isClassMethod();
+        // If a class method attemps to use a free standing ivar, this is
+        // an error.
+        if (IsClsMethod && D && !D->isDefinedOutsideFunctionOrMethod())
+           return ExprError(Diag(Loc, diag::error_ivar_use_in_class_method)
+                           << IV->getDeclName());
+        // If a class method uses a global variable, even if an ivar with
+        // same name exists, use the global.
+        if (!IsClsMethod) {
+          // FIXME: This should use a new expr for a direct reference, don't turn
+          // this into Self->ivar, just return a BareIVarExpr or something.
+          IdentifierInfo &II = Context.Idents.get("self");
+          OwningExprResult SelfExpr = ActOnIdentifierExpr(S, Loc, II, false);
+          ObjCIvarRefExpr *MRef = new (Context) ObjCIvarRefExpr(IV, IV->getType(),
+                                    Loc, static_cast<Expr*>(SelfExpr.release()),
+                                    true, true);
+          Context.setFieldDecl(IFace, IV, MRef);
+          return Owned(MRef);
+        }
       }
     }
+    else if (getCurMethodDecl()->isInstanceMethod()) {
+      // We should warn if a local variable hides an ivar.
+      ObjCInterfaceDecl *IFace = getCurMethodDecl()->getClassInterface();
+      if (ObjCIvarDecl *IV = IFace->lookupInstanceVariable(II))
+        Diag(Loc, diag::warn_ivar_use_hidden)<<IV->getDeclName();
+    }
     // Needed to implement property "super.method" notation.
     if (D == 0 && II->isStr("super")) {
       QualType T = Context.getPointerType(Context.getObjCInterfaceType(

Added: cfe/trunk/test/SemaObjC/ivar-ref-misuse.m
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/SemaObjC/ivar-ref-misuse.m?rev=65879&view=auto

==============================================================================
--- cfe/trunk/test/SemaObjC/ivar-ref-misuse.m (added)
+++ cfe/trunk/test/SemaObjC/ivar-ref-misuse.m Mon Mar  2 15:55:29 2009
@@ -0,0 +1,41 @@
+// RUN: clang -fsyntax-only -verify %s
+
+ at interface Sprite {
+  int sprite, spree;
+  int UseGlobalBar;
+}
++ (void)setFoo:(int)foo;
++ (void)setSprite:(int)sprite;
+- (void)setFoo:(int)foo;
+- (void)setSprite:(int)sprite;
+ at end
+
+int spree = 23;
+int UseGlobalBar;
+
+ at implementation Sprite
++ (void)setFoo:(int)foo {
+  sprite = foo;   // expected-error {{use of undeclared identifier 'sprite'}}
+  spree = foo;
+  Xsprite = foo; // expected-error {{use of undeclared identifier 'Xsprite'}} 
+  UseGlobalBar = 10;
+}
++ (void)setSprite:(int)sprite {
+  int spree;
+  sprite = 15;
+  spree = 17;
+  ((Sprite *)self)->sprite = 16;   /* NB: This is how one _should_ access */
+  ((Sprite *)self)->spree = 18;    /* ivars from within class methods!    */
+}
+- (void)setFoo:(int)foo {
+  sprite = foo;
+  spree = foo;
+}
+- (void)setSprite:(int)sprite {
+  int spree;
+  sprite = 15;  // expected-warning {{local declaration of 'sprite' hides instance variable}}
+  self->sprite = 16;
+  spree = 17;  // expected-warning {{local declaration of 'spree' hides instance variable}}
+  self->spree = 18;
+}   
+ at end





More information about the cfe-commits mailing list