diff options
Diffstat (limited to 'lib/Sema/SemaExprObjC.cpp')
| -rw-r--r-- | lib/Sema/SemaExprObjC.cpp | 183 | 
1 files changed, 66 insertions, 117 deletions
diff --git a/lib/Sema/SemaExprObjC.cpp b/lib/Sema/SemaExprObjC.cpp index 9c3b51c623d3..63b7485c8764 100644 --- a/lib/Sema/SemaExprObjC.cpp +++ b/lib/Sema/SemaExprObjC.cpp @@ -218,7 +218,9 @@ static ObjCMethodDecl *getNSNumberFactoryMethod(Sema &S, SourceLocation Loc,        S.Diag(Loc, diag::err_undeclared_nsnumber);        return nullptr;      } -     +  } + +  if (S.NSNumberPointer.isNull()) {      // generate the pointer to NSNumber type.      QualType NSNumberObject = CX.getObjCInterfaceType(S.NSNumberDecl);      S.NSNumberPointer = CX.getObjCObjectPointerType(NSNumberObject); @@ -1041,7 +1043,7 @@ ExprResult Sema::ParseObjCSelectorExpression(Selector Sel,                                               SourceLocation RParenLoc,                                               bool WarnMultipleSelectors) {    ObjCMethodDecl *Method = LookupInstanceMethodInGlobalPool(Sel, -                             SourceRange(LParenLoc, RParenLoc), false, false); +                             SourceRange(LParenLoc, RParenLoc));    if (!Method)      Method = LookupFactoryMethodInGlobalPool(Sel,                                            SourceRange(LParenLoc, RParenLoc)); @@ -1059,15 +1061,11 @@ ExprResult Sema::ParseObjCSelectorExpression(Selector Sel,    } else      DiagnoseMismatchedSelectors(*this, AtLoc, Method, LParenLoc, RParenLoc,                                  WarnMultipleSelectors); -   +    if (Method &&        Method->getImplementationControl() != ObjCMethodDecl::Optional && -      !getSourceManager().isInSystemHeader(Method->getLocation())) { -    llvm::DenseMap<Selector, SourceLocation>::iterator Pos -      = ReferencedSelectors.find(Sel); -    if (Pos == ReferencedSelectors.end()) -      ReferencedSelectors.insert(std::make_pair(Sel, AtLoc)); -  } +      !getSourceManager().isInSystemHeader(Method->getLocation())) +    ReferencedSelectors.insert(std::make_pair(Sel, AtLoc));    // In ARC, forbid the user from using @selector for     // retain/release/autorelease/dealloc/retainCount. @@ -1507,64 +1505,6 @@ ObjCMethodDecl *Sema::LookupMethodInQualifiedType(Selector Sel,    return nullptr;  } -static void DiagnoseARCUseOfWeakReceiver(Sema &S, Expr *Receiver) { -  if (!Receiver) -    return; -   -  if (OpaqueValueExpr *OVE = dyn_cast<OpaqueValueExpr>(Receiver)) -    Receiver = OVE->getSourceExpr(); -   -  Expr *RExpr = Receiver->IgnoreParenImpCasts(); -  SourceLocation Loc = RExpr->getLocStart(); -  QualType T = RExpr->getType(); -  const ObjCPropertyDecl *PDecl = nullptr; -  const ObjCMethodDecl *GDecl = nullptr; -  if (PseudoObjectExpr *POE = dyn_cast<PseudoObjectExpr>(RExpr)) { -    RExpr = POE->getSyntacticForm(); -    if (ObjCPropertyRefExpr *PRE = dyn_cast<ObjCPropertyRefExpr>(RExpr)) { -      if (PRE->isImplicitProperty()) { -        GDecl = PRE->getImplicitPropertyGetter(); -        if (GDecl) { -          T = GDecl->getReturnType(); -        } -      } -      else { -        PDecl = PRE->getExplicitProperty(); -        if (PDecl) { -          T = PDecl->getType(); -        } -      } -    } -  } -  else if (ObjCMessageExpr *ME = dyn_cast<ObjCMessageExpr>(RExpr)) { -    // See if receiver is a method which envokes a synthesized getter -    // backing a 'weak' property. -    ObjCMethodDecl *Method = ME->getMethodDecl(); -    if (Method && Method->getSelector().getNumArgs() == 0) { -      PDecl = Method->findPropertyDecl(); -      if (PDecl) -        T = PDecl->getType(); -    } -  } -   -  if (T.getObjCLifetime() != Qualifiers::OCL_Weak) { -    if (!PDecl) -      return; -    if (!(PDecl->getPropertyAttributes() & ObjCPropertyDecl::OBJC_PR_weak)) -      return; -  } - -  S.Diag(Loc, diag::warn_receiver_is_weak) -    << ((!PDecl && !GDecl) ? 0 : (PDecl ? 1 : 2)); - -  if (PDecl) -    S.Diag(PDecl->getLocation(), diag::note_property_declare); -  else if (GDecl) -    S.Diag(GDecl->getLocation(), diag::note_method_declared_at) << GDecl; - -  S.Diag(Loc, diag::note_arc_assign_to_strong); -} -  /// HandleExprPropertyRefExpr - Handle foo.bar where foo is a pointer to an  /// objective C interface.  This is a property reference expression.  ExprResult Sema:: @@ -1751,29 +1691,30 @@ ActOnClassPropertyRefExpr(IdentifierInfo &receiverName,        IsSuper = true;        if (ObjCMethodDecl *CurMethod = tryCaptureObjCSelf(receiverNameLoc)) { -        if (CurMethod->isInstanceMethod()) { -          ObjCInterfaceDecl *Super = -            CurMethod->getClassInterface()->getSuperClass(); -          if (!Super) { -            // The current class does not have a superclass. -            Diag(receiverNameLoc, diag::error_root_class_cannot_use_super) -            << CurMethod->getClassInterface()->getIdentifier(); -            return ExprError(); +        if (ObjCInterfaceDecl *Class = CurMethod->getClassInterface()) { +          if (CurMethod->isInstanceMethod()) { +            ObjCInterfaceDecl *Super = Class->getSuperClass(); +            if (!Super) { +              // The current class does not have a superclass. +              Diag(receiverNameLoc, diag::error_root_class_cannot_use_super) +              << Class->getIdentifier(); +              return ExprError(); +            } +            QualType T = Context.getObjCInterfaceType(Super); +            T = Context.getObjCObjectPointerType(T); + +            return HandleExprPropertyRefExpr(T->getAsObjCInterfacePointerType(), +                                             /*BaseExpr*/nullptr, +                                             SourceLocation()/*OpLoc*/, +                                             &propertyName, +                                             propertyNameLoc, +                                             receiverNameLoc, T, true);            } -          QualType T = Context.getObjCInterfaceType(Super); -          T = Context.getObjCObjectPointerType(T); - -          return HandleExprPropertyRefExpr(T->getAsObjCInterfacePointerType(), -                                           /*BaseExpr*/nullptr, -                                           SourceLocation()/*OpLoc*/,  -                                           &propertyName, -                                           propertyNameLoc, -                                           receiverNameLoc, T, true); -        } -        // Otherwise, if this is a class method, try dispatching to our -        // superclass. -        IFace = CurMethod->getClassInterface()->getSuperClass(); +          // Otherwise, if this is a class method, try dispatching to our +          // superclass. +          IFace = Class->getSuperClass(); +        }        }      } @@ -2452,8 +2393,11 @@ ExprResult Sema::BuildInstanceMessage(Expr *Receiver,          if (ObjCMethodDecl *BestMethod =                SelectBestMethod(Sel, ArgsIn, Method->isInstanceMethod()))            Method = BestMethod; -        if (!AreMultipleMethodsInGlobalPool(Sel, Method->isInstanceMethod())) +        if (!AreMultipleMethodsInGlobalPool(Sel, Method, +                                            SourceRange(LBracLoc, RBracLoc), +                                            receiverIsId)) {            DiagnoseUseOfDecl(Method, SelLoc); +        }        }      } else if (ReceiverType->isObjCClassType() ||                 ReceiverType->isObjCQualifiedClassType()) { @@ -2491,14 +2435,12 @@ ExprResult Sema::BuildInstanceMessage(Expr *Receiver,            // If not messaging 'self', look for any factory method named 'Sel'.            if (!Receiver || !isSelfExpr(Receiver)) {              Method = LookupFactoryMethodInGlobalPool(Sel,  -                                                SourceRange(LBracLoc, RBracLoc), -                                                     true); +                                                SourceRange(LBracLoc, RBracLoc));              if (!Method) {                // If no class (factory) method was found, check if an _instance_                // method of the same name exists in the root class only.                Method = LookupInstanceMethodInGlobalPool(Sel, -                                               SourceRange(LBracLoc, RBracLoc), -                                                        true); +                                               SourceRange(LBracLoc, RBracLoc));                if (Method)                    if (const ObjCInterfaceDecl *ID =                        dyn_cast<ObjCInterfaceDecl>(Method->getDeclContext())) { @@ -2575,6 +2517,14 @@ ExprResult Sema::BuildInstanceMessage(Expr *Receiver,              if (OCIType->qual_empty()) {                Method = LookupInstanceMethodInGlobalPool(Sel,                                                SourceRange(LBracLoc, RBracLoc)); +              if (Method) { +                if (auto BestMethod = +                      SelectBestMethod(Sel, ArgsIn, Method->isInstanceMethod())) +                  Method = BestMethod; +                AreMultipleMethodsInGlobalPool(Sel, Method, +                                               SourceRange(LBracLoc, RBracLoc), +                                               true); +              }                if (Method && !forwardClass)                  Diag(SelLoc, diag::warn_maynot_respond)                    << OCIType->getInterfaceDecl()->getIdentifier() @@ -2757,15 +2707,6 @@ ExprResult Sema::BuildInstanceMessage(Expr *Receiver,    }    if (getLangOpts().ObjCAutoRefCount) { -    // Do not warn about IBOutlet weak property receivers being set to null -    // as this cannot asynchronously happen. -    bool WarnWeakReceiver = true; -    if (isImplicit && Method) -      if (const ObjCPropertyDecl *PropertyDecl = Method->findPropertyDecl()) -        WarnWeakReceiver = !PropertyDecl->hasAttr<IBOutletAttr>(); -    if (WarnWeakReceiver) -      DiagnoseARCUseOfWeakReceiver(*this, Receiver); -          // In ARC, annotate delegate init calls.      if (Result->getMethodFamily() == OMF_init &&          (SuperLoc.isValid() || isSelfExpr(Receiver))) { @@ -2796,7 +2737,9 @@ ExprResult Sema::BuildInstanceMessage(Expr *Receiver,        }      }    } -   + +  CheckObjCCircularContainer(Result); +    return MaybeBindToTemporary(Result);  } @@ -2805,8 +2748,7 @@ static void RemoveSelectorFromWarningCache(Sema &S, Expr* Arg) {        dyn_cast<ObjCSelectorExpr>(Arg->IgnoreParenCasts())) {      Selector Sel = OSE->getSelector();      SourceLocation Loc = OSE->getAtLoc(); -    llvm::DenseMap<Selector, SourceLocation>::iterator Pos -    = S.ReferencedSelectors.find(Sel); +    auto Pos = S.ReferencedSelectors.find(Sel);      if (Pos != S.ReferencedSelectors.end() && Pos->second == Loc)        S.ReferencedSelectors.erase(Pos);    } @@ -3028,17 +2970,20 @@ namespace {      /// Some declaration references are okay.      ACCResult VisitDeclRefExpr(DeclRefExpr *e) { -      // References to global constants from system headers are okay. -      // These are things like 'kCFStringTransformToLatin'.  They are -      // can also be assumed to be immune to retains.        VarDecl *var = dyn_cast<VarDecl>(e->getDecl()); +      // References to global constants are okay.        if (isAnyRetainable(TargetClass) &&            isAnyRetainable(SourceClass) &&            var &&            var->getStorageClass() == SC_Extern && -          var->getType().isConstQualified() && -          Context.getSourceManager().isInSystemHeader(var->getLocation())) { -        return ACC_bottom; +          var->getType().isConstQualified()) { + +        // In system headers, they can also be assumed to be immune to retains. +        // These are things like 'kCFStringTransformToLatin'. +        if (Context.getSourceManager().isInSystemHeader(var->getLocation())) +          return ACC_bottom; + +        return ACC_plusZero;        }        // Nothing else. @@ -3421,7 +3366,7 @@ static bool CheckObjCBridgeNSCast(Sema &S, QualType castType, Expr *castExpr,                ObjCInterfaceDecl *CastClass                  = InterfacePointerType->getObjectType()->getInterface();                if ((CastClass == ExprClass) || -                  (CastClass && ExprClass->isSuperClassOf(CastClass))) +                  (CastClass && CastClass->isSuperClassOf(ExprClass)))                  return true;                if (warn)                  S.Diag(castExpr->getLocStart(), diag::warn_objc_invalid_bridge) @@ -3444,12 +3389,13 @@ static bool CheckObjCBridgeNSCast(Sema &S, QualType castType, Expr *castExpr,                return false;             }            } +        } else if (!castType->isObjCIdType()) { +          S.Diag(castExpr->getLocStart(), diag::err_objc_cf_bridged_not_interface) +            << castExpr->getType() << Parm; +          S.Diag(TDNDecl->getLocStart(), diag::note_declared_at); +          if (Target) +            S.Diag(Target->getLocStart(), diag::note_declared_at);          } -        S.Diag(castExpr->getLocStart(), diag::err_objc_cf_bridged_not_interface) -          << castExpr->getType() << Parm; -        S.Diag(TDNDecl->getLocStart(), diag::note_declared_at); -        if (Target) -          S.Diag(Target->getLocStart(), diag::note_declared_at);          return true;        }        return false; @@ -3469,6 +3415,9 @@ static bool CheckObjCBridgeCFCast(Sema &S, QualType castType, Expr *castExpr,      if (TB *ObjCBAttr = getObjCBridgeAttr<TB>(TD)) {        if (IdentifierInfo *Parm = ObjCBAttr->getBridgedType()) {          HadTheAttribute = true; +        if (Parm->isStr("id")) +          return true; +          NamedDecl *Target = nullptr;          // Check for an existing type with this name.          LookupResult R(S, DeclarationName(Parm), SourceLocation(),  | 
