fix PR6811 by not parsing 'super' as a magic expression in
LookupInObjCMethod.  Doing so allows all sorts of invalid code
to slip through to codegen.  This patch does not change the 
AST representation of super, though that would now be a natural
thing to do since it can only be in the receiver position and
in the base of a ObjCPropertyRefExpr.

There are still several ugly areas handling super in the parser,
but this is definitely a step in the right direction.



git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@100959 91177308-0d34-0410-b5e6-96231b3b80d8
diff --git a/lib/Parse/ParseExpr.cpp b/lib/Parse/ParseExpr.cpp
index 965f764..ad42264 100644
--- a/lib/Parse/ParseExpr.cpp
+++ b/lib/Parse/ParseExpr.cpp
@@ -637,11 +637,9 @@
     IdentifierInfo &II = *Tok.getIdentifierInfo();
     SourceLocation ILoc = ConsumeToken();
     
-    // Support 'Class.property' notation.  We don't use
-    // isTokObjCMessageIdentifierReceiver(), since it allows 'super' (which is
-    // inappropriate here).
+    // Support 'Class.property' and 'super.property' notation.
     if (getLang().ObjC1 && Tok.is(tok::period) &&
-        Actions.getTypeName(II, ILoc, CurScope)) {
+        (Actions.getTypeName(II, ILoc, CurScope) || II.isStr("super"))) {
       SourceLocation DotLoc = ConsumeToken();
       
       if (Tok.isNot(tok::identifier)) {
@@ -1441,6 +1439,15 @@
         // returns the parsed type to the callee.
         return OwningExprResult(Actions);
       }
+      
+      
+      // Reject the cast of super idiom in ObjC.
+      if (Tok.is(tok::identifier) && getLang().ObjC1 &&
+          Tok.getIdentifierInfo()->isStr("super")) {
+        Diag(Tok.getLocation(), diag::err_illegal_super_cast)
+          << SourceRange(OpenLoc, RParenLoc);
+        return ExprError();
+      }
 
       // Parse the cast-expression that follows it next.
       // TODO: For cast expression with CastTy.
diff --git a/lib/Parse/ParseInit.cpp b/lib/Parse/ParseInit.cpp
index 9154d8d..57751c9 100644
--- a/lib/Parse/ParseInit.cpp
+++ b/lib/Parse/ParseInit.cpp
@@ -124,23 +124,27 @@
     //
     SourceLocation StartLoc = ConsumeBracket();
 
-    // If Objective-C is enabled and this is a typename or other identifier
-    // receiver, parse this as a message send expression.
-    if (getLang().ObjC1 && isTokObjCMessageIdentifierReceiver()) {
-      // If we have exactly one array designator, this used the GNU
-      // 'designation: array-designator' extension, otherwise there should be no
-      // designators at all!
-      if (Desig.getNumDesignators() == 1 &&
-          (Desig.getDesignator(0).isArrayDesignator() ||
-           Desig.getDesignator(0).isArrayRangeDesignator()))
-        Diag(StartLoc, diag::ext_gnu_missing_equal_designator);
-      else if (Desig.getNumDesignators() > 0)
-        Diag(Tok, diag::err_expected_equal_designator);
+    // If Objective-C is enabled and this is a typename (class message send) or
+    // 'super', parse this as a message send expression.
+    if (getLang().ObjC1 && Tok.is(tok::identifier)) {
+      IdentifierInfo *II = Tok.getIdentifierInfo();
 
-      IdentifierInfo *Name = Tok.getIdentifierInfo();
-      SourceLocation NameLoc = ConsumeToken();
-      return ParseAssignmentExprWithObjCMessageExprStart(
-                       StartLoc, NameLoc, Name, ExprArg(Actions));
+      if (II == Ident_super || Actions.getTypeName(*II, Tok.getLocation(),
+                                                   CurScope)) {
+        // If we have exactly one array designator, this used the GNU
+        // 'designation: array-designator' extension, otherwise there should be no
+        // designators at all!
+        if (Desig.getNumDesignators() == 1 &&
+            (Desig.getDesignator(0).isArrayDesignator() ||
+             Desig.getDesignator(0).isArrayRangeDesignator()))
+          Diag(StartLoc, diag::ext_gnu_missing_equal_designator);
+        else if (Desig.getNumDesignators() > 0)
+          Diag(Tok, diag::err_expected_equal_designator);
+
+        SourceLocation NameLoc = ConsumeToken();
+        return ParseAssignmentExprWithObjCMessageExprStart(
+                                       StartLoc, NameLoc, II, ExprArg(Actions));
+      }
     }
 
     // Note that we parse this as an assignment expression, not a constant
diff --git a/lib/Parse/ParseObjc.cpp b/lib/Parse/ParseObjc.cpp
index cd42aee..6e31f0f 100644
--- a/lib/Parse/ParseObjc.cpp
+++ b/lib/Parse/ParseObjc.cpp
@@ -1709,6 +1709,7 @@
 ///     '[' objc-receiver objc-message-args ']'
 ///
 ///   objc-receiver:
+///     'super'
 ///     expression
 ///     class-name
 ///     type-name
@@ -1716,16 +1717,22 @@
   assert(Tok.is(tok::l_square) && "'[' expected");
   SourceLocation LBracLoc = ConsumeBracket(); // consume '['
 
-  // Parse receiver
-  if (isTokObjCMessageIdentifierReceiver()) {
-    IdentifierInfo *ReceiverName = Tok.getIdentifierInfo();
-    if (ReceiverName != Ident_super || GetLookAheadToken(1).isNot(tok::period)) {
+  if (Tok.is(tok::identifier)) {
+    IdentifierInfo *II = Tok.getIdentifierInfo();
+
+    // 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)) ||
+        // Check to see if this is a typename.  If so, it is a class message.
+        Actions.getTypeName(*II, Tok.getLocation(), CurScope)) {
       SourceLocation NameLoc = ConsumeToken();
-      return ParseObjCMessageExpressionBody(LBracLoc, NameLoc, ReceiverName,
+      return ParseObjCMessageExpressionBody(LBracLoc, NameLoc, II,
                                             ExprArg(Actions));
     }
   }
-
+  
+  // Otherwise, an arbitrary expression can be the receiver of a send.
   OwningExprResult Res(ParseExpression());
   if (Res.isInvalid()) {
     SkipUntil(tok::r_square);
diff --git a/lib/Sema/Sema.h b/lib/Sema/Sema.h
index d6476be..822e959 100644
--- a/lib/Sema/Sema.h
+++ b/lib/Sema/Sema.h
@@ -3845,17 +3845,17 @@
   ObjCMethodDecl *LookupPrivateInstanceMethod(Selector Sel,
                                               ObjCInterfaceDecl *ClassDecl);
 
-  Action::OwningExprResult
+  OwningExprResult
   HandleExprPropertyRefExpr(const ObjCObjectPointerType *OPT,
                             Expr *BaseExpr,
                             DeclarationName MemberName,
                             SourceLocation MemberLoc);
   
-  virtual OwningExprResult ActOnClassPropertyRefExpr(
-    IdentifierInfo &receiverName,
-    IdentifierInfo &propertyName,
-    SourceLocation &receiverNameLoc,
-    SourceLocation &propertyNameLoc);
+  virtual OwningExprResult
+  ActOnClassPropertyRefExpr(IdentifierInfo &receiverName,
+                            IdentifierInfo &propertyName,
+                            SourceLocation receiverNameLoc,
+                            SourceLocation propertyNameLoc);
 
   // ActOnClassMessage - used for both unary and keyword messages.
   // ArgExprs is optional - if it is present, the number of expressions
diff --git a/lib/Sema/SemaExpr.cpp b/lib/Sema/SemaExpr.cpp
index c173705..54f74d5 100644
--- a/lib/Sema/SemaExpr.cpp
+++ b/lib/Sema/SemaExpr.cpp
@@ -1233,10 +1233,11 @@
 /// Returns a null sentinel to indicate trivial success.
 Sema::OwningExprResult
 Sema::LookupInObjCMethod(LookupResult &Lookup, Scope *S,
-                         IdentifierInfo *II,
-                         bool AllowBuiltinCreation) {
+                         IdentifierInfo *II, bool AllowBuiltinCreation) {
   SourceLocation Loc = Lookup.getNameLoc();
 
+  // FIXME: Stop re-evaluating "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 instance method (i.e.
@@ -1304,17 +1305,6 @@
     }
   }
 
-  // Needed to implement property "super.method" notation.
-  if (Lookup.empty() && II->isStr("super")) {
-    QualType T;
-
-    if (getCurMethodDecl()->isInstanceMethod())
-      T = Context.getObjCObjectPointerType(Context.getObjCInterfaceType(
-                                    getCurMethodDecl()->getClassInterface()));
-    else
-      T = Context.getObjCClassType();
-    return Owned(new (Context) ObjCSuperExpr(Loc, T));
-  }
   if (Lookup.empty() && II && AllowBuiltinCreation) {
     // FIXME. Consolidate this with similar code in LookupName.
     if (unsigned BuiltinID = II->getBuiltinID()) {
@@ -3138,6 +3128,7 @@
     return ExprError(Diag(MemberLoc, diag::err_property_not_found)
                        << MemberName << BaseType);
   }
+  
   // Handle Objective-C property access, which is "Obj.property" where Obj is a
   // pointer to a (potentially qualified) interface type.
   if (!IsArrow)
@@ -3850,9 +3841,6 @@
   if (castExpr->getType()->isVectorType())
     return CheckVectorCast(TyR, castExpr->getType(), castType, Kind);
 
-  if (getLangOptions().ObjC1 && isa<ObjCSuperExpr>(castExpr))
-    return Diag(castExpr->getLocStart(), diag::err_illegal_super_cast) << TyR;
-
   if (isa<ObjCSelectorExpr>(castExpr))
     return Diag(castExpr->getLocStart(), diag::err_cast_selector_expr);
 
diff --git a/lib/Sema/SemaExprObjC.cpp b/lib/Sema/SemaExprObjC.cpp
index 327e294..9ada985 100644
--- a/lib/Sema/SemaExprObjC.cpp
+++ b/lib/Sema/SemaExprObjC.cpp
@@ -394,20 +394,42 @@
 
 
 
-Action::OwningExprResult Sema::ActOnClassPropertyRefExpr(
-  IdentifierInfo &receiverName,
-  IdentifierInfo &propertyName,
-  SourceLocation &receiverNameLoc,
-  SourceLocation &propertyNameLoc) {
+Action::OwningExprResult Sema::
+ActOnClassPropertyRefExpr(IdentifierInfo &receiverName,
+                          IdentifierInfo &propertyName,
+                          SourceLocation receiverNameLoc,
+                          SourceLocation propertyNameLoc) {
 
   IdentifierInfo *receiverNamePtr = &receiverName;
   ObjCInterfaceDecl *IFace = getObjCInterfaceDecl(receiverNamePtr);
-  if (!IFace) {
-    Diag(receiverNameLoc, diag::err_expected_ident_or_lparen);
-    return ExprError();
-  }
-  // Search for a declared property first.
+  if (IFace == 0) {
+    // If the "receiver" is 'super' in a method, handle it as an expression-like
+    // property reference.
+    if (ObjCMethodDecl *CurMethod = getCurMethodDecl())
+      if (receiverNamePtr->isStr("super")) {
+        if (CurMethod->isInstanceMethod()) {
+          QualType T = 
+            Context.getObjCInterfaceType(CurMethod->getClassInterface());
+          T = Context.getObjCObjectPointerType(T);
+          Expr *SuperExpr = new (Context) ObjCSuperExpr(receiverNameLoc, T);
+        
+          return HandleExprPropertyRefExpr(T->getAsObjCInterfacePointerType(),
+                                           SuperExpr, &propertyName,
+                                           propertyNameLoc);
+        }
 
+        // Otherwise, if this is a class method, try dispatching to our
+        // superclass.
+        IFace = CurMethod->getClassInterface()->getSuperClass();
+      }
+    
+    if (IFace == 0) {
+      Diag(receiverNameLoc, diag::err_expected_ident_or_lparen);
+      return ExprError();
+    }
+  }
+
+  // Search for a declared property first.
   Selector Sel = PP.getSelectorTable().getNullarySelector(&propertyName);
   ObjCMethodDecl *Getter = IFace->lookupClassMethod(Sel);
 
@@ -468,12 +490,11 @@
 // ActOnClassMessage - used for both unary and keyword messages.
 // ArgExprs is optional - if it is present, the number of expressions
 // is obtained from Sel.getNumArgs().
-Sema::ExprResult Sema::ActOnClassMessage(
-  Scope *S,
-  IdentifierInfo *receiverName, Selector Sel,
-  SourceLocation lbrac, SourceLocation receiverLoc,
-  SourceLocation selectorLoc, SourceLocation rbrac,
-  ExprTy **Args, unsigned NumArgs) {
+Sema::ExprResult Sema::
+ActOnClassMessage(Scope *S, IdentifierInfo *receiverName, Selector Sel,
+                  SourceLocation lbrac, SourceLocation receiverLoc,
+                  SourceLocation selectorLoc, SourceLocation rbrac,
+                  ExprTy **Args, unsigned NumArgs) {
   assert(receiverName && "missing receiver class name");
 
   Expr **ArgExprs = reinterpret_cast<Expr **>(Args);
@@ -481,16 +502,16 @@
   bool isSuper = false;
 
   if (receiverName->isStr("super")) {
-    if (getCurMethodDecl()) {
+    if (ObjCMethodDecl *CurMethod = getCurMethodDecl()) {
       isSuper = true;
-      ObjCInterfaceDecl *OID = getCurMethodDecl()->getClassInterface();
+      ObjCInterfaceDecl *OID = CurMethod->getClassInterface();
       if (!OID)
         return Diag(lbrac, diag::error_no_super_class_message)
-                      << getCurMethodDecl()->getDeclName();
+                      << CurMethod->getDeclName();
       ClassDecl = OID->getSuperClass();
       if (!ClassDecl)
         return Diag(lbrac, diag::error_no_super_class) << OID->getDeclName();
-      if (getCurMethodDecl()->isInstanceMethod()) {
+      if (CurMethod->isInstanceMethod()) {
         QualType superTy = Context.getObjCInterfaceType(ClassDecl);
         superTy = Context.getObjCObjectPointerType(superTy);
         ExprResult ReceiverExpr = new (Context) ObjCSuperExpr(SourceLocation(),
@@ -504,6 +525,11 @@
     } 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);
@@ -514,17 +540,7 @@
         return ActOnInstanceMessage(ReceiverExpr.get(), Sel, lbrac,
                                     selectorLoc, rbrac, Args, NumArgs);
       }
-      else if (TypedefDecl *OCTD = dyn_cast_or_null<TypedefDecl>(SuperDecl)) {
-        const ObjCInterfaceType *OCIT;
-        OCIT = OCTD->getUnderlyingType()->getAs<ObjCInterfaceType>();
-        if (!OCIT) {
-          Diag(receiverLoc, diag::err_invalid_receiver_to_message);
-          return true;
-        }
-        ClassDecl = OCIT->getDecl();
-      }
-      else      
-        return Diag(receiverLoc, diag::err_undeclared_var_use) << receiverName;
+      ClassDecl = getObjCInterfaceDecl(receiverName, receiverLoc);
     }
   } else
     ClassDecl = getObjCInterfaceDecl(receiverName, receiverLoc);
@@ -548,7 +564,11 @@
         ClassDecl = OCIT->getDecl();
 
     if (!ClassDecl) {
-      Diag(receiverLoc, diag::err_invalid_receiver_to_message);
+      // Give a better error message for invalid use of super.
+      if (receiverName->isStr("super"))
+        Diag(receiverLoc, diag::err_invalid_receiver_to_message_super);
+      else
+        Diag(receiverLoc, diag::err_invalid_receiver_to_message);
       return true;
     }
   }
@@ -616,6 +636,7 @@
   QualType ReceiverCType =
     Context.getCanonicalType(RExpr->getType()).getUnqualifiedType();
 
+#if 0
   // Handle messages to 'super'.
   if (isa<ObjCSuperExpr>(RExpr)) {
     ObjCMethodDecl *Method = 0;
@@ -643,6 +664,7 @@
                                          Method, lbrac, rbrac,
                                          ArgExprs, NumArgs);
   }
+#endif
 
   // Handle messages to id.
   if (ReceiverCType->isObjCIdType() || ReceiverCType->isBlockPointerType() ||