[cfe-commits] r101016 - in /cfe/trunk: include/clang/Parse/Scope.h lib/Parse/ParseObjc.cpp lib/Sema/SemaExprObjC.cpp test/SemaObjC/super.m

Chris Lattner sabre at nondot.org
Sun Apr 11 22:38:43 PDT 2010


Author: lattner
Date: Mon Apr 12 00:38:43 2010
New Revision: 101016

URL: http://llvm.org/viewvc/llvm-project?rev=101016&view=rev
Log:
Have the parser decide whether a message to super is a variable or
type, instead of having sema do it.

Modified:
    cfe/trunk/include/clang/Parse/Scope.h
    cfe/trunk/lib/Parse/ParseObjc.cpp
    cfe/trunk/lib/Sema/SemaExprObjC.cpp
    cfe/trunk/test/SemaObjC/super.m

Modified: cfe/trunk/include/clang/Parse/Scope.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Parse/Scope.h?rev=101016&r1=101015&r2=101016&view=diff
==============================================================================
--- cfe/trunk/include/clang/Parse/Scope.h (original)
+++ cfe/trunk/include/clang/Parse/Scope.h Mon Apr 12 00:38:43 2010
@@ -52,8 +52,8 @@
 
     /// BlockScope - This is a scope that corresponds to a block object.
     /// Blocks serve as top-level scopes for some objects like labels, they
-    /// also prevent things like break and continue.  BlockScopes have the
-    /// other flags set as well.
+    /// also prevent things like break and continue.  BlockScopes always have
+    /// the FnScope, BreakScope, ContinueScope, and DeclScope flags set as well.
     BlockScope = 0x40,
 
     /// TemplateParamScope - This is a scope that corresponds to the
@@ -68,7 +68,11 @@
 
     /// AtCatchScope - This is a scope that corresponds to the Objective-C
     /// @catch statement.
-    AtCatchScope = 0x200
+    AtCatchScope = 0x200,
+    
+    /// ObjCMethodScope - This scope corresponds to an Objective-C method body.
+    /// It always has FnScope and DeclScope set as well.
+    ObjCMethodScope = 0x400
   };
 private:
   /// The parent scope for this scope.  This is null for the translation-unit
@@ -81,7 +85,7 @@
 
   /// Flags - This contains a set of ScopeFlags, which indicates how the scope
   /// interrelates with other control flow statements.
-  unsigned Flags : 10;
+  unsigned Flags : 11;
 
   /// WithinElse - Whether this scope is part of the "else" branch in
   /// its parent ControlScope.
@@ -233,6 +237,23 @@
     }
     return false;
   }
+  
+  /// isInObjcMethodScope - Return true if this scope is, or is contained in, an
+  /// Objective-C method body.  Note that this method is not constant time.
+  bool isInObjcMethodScope() const {
+    for (const Scope *S = this; S; S = S->getParent()) {
+      // If this scope is an objc method scope, then we succeed.
+      if (S->getFlags() & ObjCMethodScope)
+        return true;
+      
+      // If we've scanned up the scope chain and find out that we're in some
+      // other body scope (e.g. a block), we fail even if it is ultimately
+      // contained in an ObjC method body.
+      if (S->getFlags() & FnScope)
+        return false;
+    }
+    return false;
+  }
 
   /// isTemplateParamScope - Return true if this scope is a C++
   /// template parameter scope.

Modified: cfe/trunk/lib/Parse/ParseObjc.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Parse/ParseObjc.cpp?rev=101016&r1=101015&r2=101016&view=diff
==============================================================================
--- cfe/trunk/lib/Parse/ParseObjc.cpp (original)
+++ cfe/trunk/lib/Parse/ParseObjc.cpp Mon Apr 12 00:38:43 2010
@@ -1626,7 +1626,8 @@
   SourceLocation BraceLoc = Tok.getLocation();
 
   // Enter a scope for the method body.
-  ParseScope BodyScope(this, Scope::FnScope|Scope::DeclScope);
+  ParseScope BodyScope(this,
+                       Scope::ObjCMethodScope|Scope::FnScope|Scope::DeclScope);
 
   // Tell the actions module that we have entered a method definition with the
   // specified Declarator for the method.
@@ -1723,7 +1724,8 @@
     // If this is '[' 'super', then this is a magic superclass message.
     // We parse '[' 'super' '.' 'foo'  as an expression?
     // FIXME: Not in ParseInit.cpp?
-    if ((II == Ident_super && GetLookAheadToken(1).isNot(tok::period)) ||
+    if ((II == Ident_super && GetLookAheadToken(1).isNot(tok::period) &&
+         CurScope->isInObjcMethodScope()) ||
         // Check to see if this is a typename.  If so, it is a class message.
         Actions.getTypeName(*II, Tok.getLocation(), CurScope)) {
       SourceLocation NameLoc = ConsumeToken();

Modified: cfe/trunk/lib/Sema/SemaExprObjC.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaExprObjC.cpp?rev=101016&r1=101015&r2=101016&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/SemaExprObjC.cpp (original)
+++ cfe/trunk/lib/Sema/SemaExprObjC.cpp Mon Apr 12 00:38:43 2010
@@ -498,18 +498,18 @@
   assert(receiverName && "missing receiver class name");
 
   Expr **ArgExprs = reinterpret_cast<Expr **>(Args);
-  ObjCInterfaceDecl* ClassDecl = 0;
-  bool isSuper = false;
+  ObjCInterfaceDecl *ClassDecl = 0;
 
+  // Special case a message to super, which can be either a class message or an
+  // instance message, depending on what CurMethodDecl is.
   if (receiverName->isStr("super")) {
     if (ObjCMethodDecl *CurMethod = getCurMethodDecl()) {
-      isSuper = true;
       ObjCInterfaceDecl *OID = CurMethod->getClassInterface();
       if (!OID)
         return Diag(lbrac, diag::error_no_super_class_message)
                       << CurMethod->getDeclName();
       ClassDecl = OID->getSuperClass();
-      if (!ClassDecl)
+      if (ClassDecl == 0)
         return Diag(lbrac, diag::error_no_super_class) << OID->getDeclName();
       if (CurMethod->isInstanceMethod()) {
         QualType superTy = Context.getObjCInterfaceType(ClassDecl);
@@ -520,29 +520,13 @@
         return ActOnInstanceMessage(ReceiverExpr.get(), Sel, lbrac,
                                     selectorLoc, rbrac, Args, NumArgs);
       }
-      // We are sending a message to 'super' within a class method. Do nothing,
-      // the receiver will pass through as 'super' (how convenient:-).
-    } else {
-      // 'super' has been used outside a method context. If a variable named
-      // 'super' has been declared, redirect. If not, produce a diagnostic.
-      
-      // FIXME:
-      // FIXME: This should be handled in the parser!
-      // FIXME:
       
-      NamedDecl *SuperDecl
-        = LookupSingleName(S, receiverName, LookupOrdinaryName);
-      ValueDecl *VD = dyn_cast_or_null<ValueDecl>(SuperDecl);
-      if (VD) {
-        ExprResult ReceiverExpr = new (Context) DeclRefExpr(VD, VD->getType(),
-                                                            receiverLoc);
-        // We are really in an instance method, redirect.
-        return ActOnInstanceMessage(ReceiverExpr.get(), Sel, lbrac,
-                                    selectorLoc, rbrac, Args, NumArgs);
-      }
-      ClassDecl = getObjCInterfaceDecl(receiverName, receiverLoc);
+      // Otherwise, if this is a class method, try dispatching to our
+      // superclass, which is in ClassDecl.
     }
-  } else
+  }
+  
+  if (ClassDecl == 0)
     ClassDecl = getObjCInterfaceDecl(receiverName, receiverLoc);
 
   // The following code allows for the following GCC-ism:
@@ -602,17 +586,9 @@
   // If we have the ObjCInterfaceDecl* for the class that is receiving the
   // message, use that to construct the ObjCMessageExpr.  Otherwise pass on the
   // IdentifierInfo* for the class.
-  // FIXME: need to do a better job handling 'super' usage within a class.  For
-  // now, we simply pass the "super" identifier through (which isn't consistent
-  // with instance methods.
-  if (isSuper)
-    return new (Context) ObjCMessageExpr(Context, receiverName, receiverLoc,
-                                         Sel, returnType, Method, lbrac, rbrac, 
-                                         ArgExprs, NumArgs);
-  else
-    return new (Context) ObjCMessageExpr(Context, ClassDecl, receiverLoc,
-                                         Sel, returnType, Method, lbrac, rbrac, 
-                                         ArgExprs, NumArgs);
+  return new (Context) ObjCMessageExpr(Context, ClassDecl, receiverLoc,
+                                       Sel, returnType, Method, lbrac, rbrac, 
+                                       ArgExprs, NumArgs);
 }
 
 // ActOnInstanceMessage - used for both unary and keyword messages.

Modified: cfe/trunk/test/SemaObjC/super.m
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/SemaObjC/super.m?rev=101016&r1=101015&r2=101016&view=diff
==============================================================================
--- cfe/trunk/test/SemaObjC/super.m (original)
+++ cfe/trunk/test/SemaObjC/super.m Mon Apr 12 00:38:43 2010
@@ -36,8 +36,8 @@
   [super m]; // expected-warning{{receiver type 'int' is not 'id'}} \
                 expected-warning {{method '-m' not found (return type defaults to 'id')}}
 }
-void f1(int puper) {
-  [super m]; // expected-error{{'super' is only valid in a method body}}
+void f1(id puper) {  // expected-note {{'puper' declared here}}
+  [super m]; // expected-error{{use of undeclared identifier 'super'; did you mean 'puper'?}}
 }
 
 // radar 7400691





More information about the cfe-commits mailing list