diff options
Diffstat (limited to 'clang/lib/Sema')
-rw-r--r-- | clang/lib/Sema/SemaDeclAttr.cpp | 30 | ||||
-rw-r--r-- | clang/lib/Sema/SemaDeclObjC.cpp | 41 | ||||
-rw-r--r-- | clang/lib/Sema/SemaExprObjC.cpp | 67 | ||||
-rw-r--r-- | clang/lib/Sema/SemaObjCProperty.cpp | 22 |
4 files changed, 154 insertions, 6 deletions
diff --git a/clang/lib/Sema/SemaDeclAttr.cpp b/clang/lib/Sema/SemaDeclAttr.cpp index 5728df428a3..d16913e2d0e 100644 --- a/clang/lib/Sema/SemaDeclAttr.cpp +++ b/clang/lib/Sema/SemaDeclAttr.cpp @@ -2600,6 +2600,29 @@ static void handleVisibilityAttr(Sema &S, Decl *D, const ParsedAttr &AL, D->addAttr(newAttr); } +static void handleObjCDirectAttr(Sema &S, Decl *D, const ParsedAttr &AL) { + // objc_direct cannot be set on methods declared in the context of a protocol + if (isa<ObjCProtocolDecl>(D->getDeclContext())) { + S.Diag(AL.getLoc(), diag::err_objc_direct_on_protocol) << false; + return; + } + + if (S.getLangOpts().ObjCRuntime.allowsDirectDispatch()) { + handleSimpleAttribute<ObjCDirectAttr>(S, D, AL); + } else { + S.Diag(AL.getLoc(), diag::warn_objc_direct_ignored) << AL; + } +} + +static void handleObjCDirectMembersAttr(Sema &S, Decl *D, + const ParsedAttr &AL) { + if (S.getLangOpts().ObjCRuntime.allowsDirectDispatch()) { + handleSimpleAttribute<ObjCDirectMembersAttr>(S, D, AL); + } else { + S.Diag(AL.getLoc(), diag::warn_objc_direct_ignored) << AL; + } +} + static void handleObjCMethodFamilyAttr(Sema &S, Decl *D, const ParsedAttr &AL) { const auto *M = cast<ObjCMethodDecl>(D); if (!AL.isArgIdent(0)) { @@ -6944,6 +6967,13 @@ static void ProcessDeclAttribute(Sema &S, Scope *scope, Decl *D, case ParsedAttr::AT_ObjCRootClass: handleSimpleAttribute<ObjCRootClassAttr>(S, D, AL); break; + case ParsedAttr::AT_ObjCDirect: + handleObjCDirectAttr(S, D, AL); + break; + case ParsedAttr::AT_ObjCDirectMembers: + handleObjCDirectMembersAttr(S, D, AL); + handleSimpleAttribute<ObjCDirectMembersAttr>(S, D, AL); + break; case ParsedAttr::AT_ObjCNonLazyClass: handleSimpleAttribute<ObjCNonLazyClassAttr>(S, D, AL); break; diff --git a/clang/lib/Sema/SemaDeclObjC.cpp b/clang/lib/Sema/SemaDeclObjC.cpp index 30a1b95d424..e84dc47a1ee 100644 --- a/clang/lib/Sema/SemaDeclObjC.cpp +++ b/clang/lib/Sema/SemaDeclObjC.cpp @@ -3239,6 +3239,9 @@ bool Sema::MatchTwoMethodDeclarations(const ObjCMethodDecl *left, if (left->isHidden() || right->isHidden()) return false; + if (left->isDirectMethod() != right->isDirectMethod()) + return false; + if (getLangOpts().ObjCAutoRefCount && (left->hasAttr<NSReturnsRetainedAttr>() != right->hasAttr<NSReturnsRetainedAttr>() || @@ -3430,6 +3433,9 @@ static bool isAcceptableMethodMismatch(ObjCMethodDecl *chosen, if (!chosen->isInstanceMethod()) return false; + if (chosen->isDirectMethod() != other->isDirectMethod()) + return false; + Selector sel = chosen->getSelector(); if (!sel.isUnarySelector() || sel.getNameForSlot(0) != "length") return false; @@ -4339,6 +4345,18 @@ private: }; } // end anonymous namespace +void Sema::CheckObjCMethodDirectOverrides(ObjCMethodDecl *method, + ObjCMethodDecl *overridden) { + if (const auto *attr = overridden->getAttr<ObjCDirectAttr>()) { + Diag(method->getLocation(), diag::err_objc_override_direct_method); + Diag(attr->getLocation(), diag::note_previous_declaration); + } else if (const auto *attr = method->getAttr<ObjCDirectAttr>()) { + Diag(attr->getLocation(), diag::err_objc_direct_on_override) + << isa<ObjCProtocolDecl>(overridden->getDeclContext()); + Diag(overridden->getLocation(), diag::note_previous_declaration); + } +} + void Sema::CheckObjCMethodOverrides(ObjCMethodDecl *ObjCMethod, ObjCInterfaceDecl *CurrentClass, ResultTypeCompatibilityKind RTC) { @@ -4357,8 +4375,8 @@ void Sema::CheckObjCMethodOverrides(ObjCMethodDecl *ObjCMethod, if (isa<ObjCProtocolDecl>(overridden->getDeclContext()) || CurrentClass != overridden->getClassInterface() || overridden->isOverriding()) { + CheckObjCMethodDirectOverrides(ObjCMethod, overridden); hasOverriddenMethodsInBaseOrProtocol = true; - } else if (isa<ObjCImplDecl>(ObjCMethod->getDeclContext())) { // OverrideSearch will return as "overridden" the same method in the // interface. For hasOverriddenMethodsInBaseOrProtocol, we need to @@ -4382,6 +4400,7 @@ void Sema::CheckObjCMethodOverrides(ObjCMethodDecl *ObjCMethod, for (ObjCMethodDecl *SuperOverridden : overrides) { if (isa<ObjCProtocolDecl>(SuperOverridden->getDeclContext()) || CurrentClass != SuperOverridden->getClassInterface()) { + CheckObjCMethodDirectOverrides(ObjCMethod, SuperOverridden); hasOverriddenMethodsInBaseOrProtocol = true; overridden->setOverriding(true); break; @@ -4489,6 +4508,12 @@ static void mergeInterfaceMethodToImpl(Sema &S, method->getLocation())); } + if (!method->isDirectMethod()) + if (const auto *attr = prevMethod->getAttr<ObjCDirectAttr>()) { + method->addAttr( + ObjCDirectAttr::CreateImplicit(S.Context, attr->getLocation())); + } + // Merge nullability of the result type. QualType newReturnType = mergeTypeNullabilityForRedecl( @@ -4719,6 +4744,12 @@ Decl *Sema::ActOnMethodDeclaration( if (auto *IMD = IDecl->lookupMethod(ObjCMethod->getSelector(), ObjCMethod->isInstanceMethod())) { mergeInterfaceMethodToImpl(*this, ObjCMethod, IMD); + if (const auto *attr = ObjCMethod->getAttr<ObjCDirectAttr>()) { + if (!IMD->isDirectMethod()) { + Diag(attr->getLocation(), diag::err_objc_direct_missing_on_decl); + Diag(IMD->getLocation(), diag::note_previous_declaration); + } + } // Warn about defining -dealloc in a category. if (isa<ObjCCategoryImplDecl>(ImpDecl) && IMD->isOverriding() && @@ -4726,6 +4757,9 @@ Decl *Sema::ActOnMethodDeclaration( Diag(ObjCMethod->getLocation(), diag::warn_dealloc_in_category) << ObjCMethod->getDeclName(); } + } else if (ImpDecl->hasAttr<ObjCDirectMembersAttr>()) { + ObjCMethod->addAttr( + ObjCDirectAttr::CreateImplicit(Context, ObjCMethod->getLocation())); } // Warn if a method declared in a protocol to which a category or @@ -4745,6 +4779,11 @@ Decl *Sema::ActOnMethodDeclaration( } } } else { + if (!ObjCMethod->isDirectMethod() && + ClassDecl->hasAttr<ObjCDirectMembersAttr>()) { + ObjCMethod->addAttr( + ObjCDirectAttr::CreateImplicit(Context, ObjCMethod->getLocation())); + } cast<DeclContext>(ClassDecl)->addDecl(ObjCMethod); } diff --git a/clang/lib/Sema/SemaExprObjC.cpp b/clang/lib/Sema/SemaExprObjC.cpp index 8db4e0ba74a..687348c90a8 100644 --- a/clang/lib/Sema/SemaExprObjC.cpp +++ b/clang/lib/Sema/SemaExprObjC.cpp @@ -1170,6 +1170,35 @@ static void DiagnoseMismatchedSelectors(Sema &S, SourceLocation AtLoc, } } +static void HelperToDiagnoseDirectSelectorsExpr(Sema &S, SourceLocation AtLoc, + Selector Sel, + ObjCMethodList &MethList, + bool &onlyDirect) { + ObjCMethodList *M = &MethList; + for (M = M->getNext(); M; M = M->getNext()) { + ObjCMethodDecl *Method = M->getMethod(); + if (Method->getSelector() != Sel) + continue; + if (!Method->isDirectMethod()) + onlyDirect = false; + } +} + +static void DiagnoseDirectSelectorsExpr(Sema &S, SourceLocation AtLoc, + Selector Sel, bool &onlyDirect) { + for (Sema::GlobalMethodPool::iterator b = S.MethodPool.begin(), + e = S.MethodPool.end(); b != e; b++) { + // first, instance methods + ObjCMethodList &InstMethList = b->second.first; + HelperToDiagnoseDirectSelectorsExpr(S, AtLoc, Sel, InstMethList, + onlyDirect); + + // second, class methods + ObjCMethodList &ClsMethList = b->second.second; + HelperToDiagnoseDirectSelectorsExpr(S, AtLoc, Sel, ClsMethList, onlyDirect); + } +} + ExprResult Sema::ParseObjCSelectorExpression(Selector Sel, SourceLocation AtLoc, SourceLocation SelLoc, @@ -1192,9 +1221,18 @@ ExprResult Sema::ParseObjCSelectorExpression(Selector Sel, } else Diag(SelLoc, diag::warn_undeclared_selector) << Sel; - } else + } else { + bool onlyDirect = Method->isDirectMethod(); + DiagnoseDirectSelectorsExpr(*this, AtLoc, Sel, onlyDirect); DiagnoseMismatchedSelectors(*this, AtLoc, Method, LParenLoc, RParenLoc, WarnMultipleSelectors); + if (onlyDirect) { + Diag(AtLoc, diag::err_direct_selector_expression) + << Method->getSelector(); + Diag(Method->getLocation(), diag::note_direct_method_declared_at) + << Method->getDeclName(); + } + } if (Method && Method->getImplementationControl() != ObjCMethodDecl::Optional && @@ -2767,9 +2805,6 @@ ExprResult Sema::BuildInstanceMessage(Expr *Receiver, } } - if (ReceiverType->isObjCIdType() && !isImplicit) - Diag(Receiver->getExprLoc(), diag::warn_messaging_unqualified_id); - // There's a somewhat weird interaction here where we assume that we // won't actually have a method unless we also don't need to do some // of the more detailed type-checking on the receiver. @@ -2971,6 +3006,30 @@ ExprResult Sema::BuildInstanceMessage(Expr *Receiver, (Method && Method->getMethodFamily() == OMF_init) ? getEnclosingFunction() : nullptr; + if (Method && Method->isDirectMethod()) { + if (ReceiverType->isObjCIdType() && !isImplicit) { + Diag(Receiver->getExprLoc(), + diag::err_messaging_unqualified_id_with_direct_method); + Diag(Method->getLocation(), diag::note_direct_method_declared_at) + << Method->getDeclName(); + } + + if (ReceiverType->isObjCClassType() && !isImplicit) { + Diag(Receiver->getExprLoc(), + diag::err_messaging_class_with_direct_method); + Diag(Method->getLocation(), diag::note_direct_method_declared_at) + << Method->getDeclName(); + } + + if (SuperLoc.isValid()) { + Diag(SuperLoc, diag::err_messaging_super_with_direct_method); + Diag(Method->getLocation(), diag::note_direct_method_declared_at) + << Method->getDeclName(); + } + } else if (ReceiverType->isObjCIdType() && !isImplicit) { + Diag(Receiver->getExprLoc(), diag::warn_messaging_unqualified_id); + } + if (DIFunctionScopeInfo && DIFunctionScopeInfo->ObjCIsDesignatedInit && (SuperLoc.isValid() || isSelfExpr(Receiver))) { diff --git a/clang/lib/Sema/SemaObjCProperty.cpp b/clang/lib/Sema/SemaObjCProperty.cpp index 558a754a445..87f7baaf568 100644 --- a/clang/lib/Sema/SemaObjCProperty.cpp +++ b/clang/lib/Sema/SemaObjCProperty.cpp @@ -306,6 +306,8 @@ makePropertyAttributesAsWritten(unsigned Attributes) { attributesAsWritten |= ObjCPropertyDecl::OBJC_PR_atomic; if (Attributes & ObjCDeclSpec::DQ_PR_class) attributesAsWritten |= ObjCPropertyDecl::OBJC_PR_class; + if (Attributes & ObjCDeclSpec::DQ_PR_direct) + attributesAsWritten |= ObjCPropertyDecl::OBJC_PR_direct; return (ObjCPropertyDecl::PropertyAttributeKind)attributesAsWritten; } @@ -705,9 +707,21 @@ ObjCPropertyDecl *Sema::CreatePropertyDecl(Scope *S, if (Attributes & ObjCDeclSpec::DQ_PR_null_resettable) PDecl->setPropertyAttributes(ObjCPropertyDecl::OBJC_PR_null_resettable); - if (Attributes & ObjCDeclSpec::DQ_PR_class) + if (Attributes & ObjCDeclSpec::DQ_PR_class) PDecl->setPropertyAttributes(ObjCPropertyDecl::OBJC_PR_class); + if ((Attributes & ObjCDeclSpec::DQ_PR_direct) || + CDecl->hasAttr<ObjCDirectMembersAttr>()) { + if (isa<ObjCProtocolDecl>(CDecl)) { + Diag(PDecl->getLocation(), diag::err_objc_direct_on_protocol) << true; + } else if (getLangOpts().ObjCRuntime.allowsDirectDispatch()) { + PDecl->setPropertyAttributes(ObjCPropertyDecl::OBJC_PR_direct); + } else { + Diag(PDecl->getLocation(), diag::warn_objc_direct_property_ignored) + << PDecl->getDeclName(); + } + } + return PDecl; } @@ -2460,6 +2474,9 @@ void Sema::ProcessPropertyDecl(ObjCPropertyDecl *property) { AddPropertyAttrs(*this, GetterMethod, property); + if (property->isDirectProperty()) + GetterMethod->addAttr(ObjCDirectAttr::CreateImplicit(Context, Loc)); + if (property->hasAttr<NSReturnsNotRetainedAttr>()) GetterMethod->addAttr(NSReturnsNotRetainedAttr::CreateImplicit(Context, Loc)); @@ -2534,6 +2551,9 @@ void Sema::ProcessPropertyDecl(ObjCPropertyDecl *property) { AddPropertyAttrs(*this, SetterMethod, property); + if (property->isDirectProperty()) + SetterMethod->addAttr(ObjCDirectAttr::CreateImplicit(Context, Loc)); + CD->addDecl(SetterMethod); if (const SectionAttr *SA = property->getAttr<SectionAttr>()) SetterMethod->addAttr(SectionAttr::CreateImplicit( |