Author: rjmccall Date: Wed Oct 28 00:03:19 2015 New Revision: 251496 URL: http://llvm.org/viewvc/llvm-project?rev=251496&view=rev Log: Refine r251469 to give better (and more localizable) diagnostics for all the reasons that ARC makes things implicitly unavailable.
Modified: cfe/trunk/include/clang/Basic/Attr.td cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td cfe/trunk/include/clang/Sema/Sema.h cfe/trunk/lib/Sema/Sema.cpp cfe/trunk/lib/Sema/SemaDecl.cpp cfe/trunk/lib/Sema/SemaDeclAttr.cpp cfe/trunk/lib/Sema/SemaDeclObjC.cpp cfe/trunk/lib/Sema/SemaExprObjC.cpp cfe/trunk/test/SemaObjC/arc-system-header.m cfe/trunk/test/SemaObjC/arc-unavailable-system-function.m cfe/trunk/test/SemaObjC/mrc-no-weak.m cfe/trunk/test/SemaObjCXX/arc-system-header.mm Modified: cfe/trunk/include/clang/Basic/Attr.td URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Basic/Attr.td?rev=251496&r1=251495&r2=251496&view=diff ============================================================================== --- cfe/trunk/include/clang/Basic/Attr.td (original) +++ cfe/trunk/include/clang/Basic/Attr.td Wed Oct 28 00:03:19 2015 @@ -132,6 +132,9 @@ def HasFunctionProto : SubsetSubject<Dec class Argument<string name, bit optional, bit fake = 0> { string Name = name; bit Optional = optional; + + /// A fake argument is used to store and serialize additional information + /// in an attribute without actually changing its parsing or pretty-printing. bit Fake = fake; } @@ -1353,9 +1356,14 @@ def TransparentUnion : InheritableAttr { def Unavailable : InheritableAttr { let Spellings = [GNU<"unavailable">]; let Args = [StringArgument<"Message", 1>, - EnumArgument<"ImplicitSource", "ImplicitSourceKind", - ["none", "forbiddenType"], - ["ISK_None", "ISK_ForbiddenType"], 1, /*fake*/ 1>]; + EnumArgument<"ImplicitReason", "ImplicitReason", + ["", "", "", ""], + ["IR_None", + "IR_ARCForbiddenType", + "IR_ForbiddenWeak", + "IR_ARCForbiddenConversion", + "IR_ARCInitReturnsUnrelated", + "IR_ARCFieldWithOwnership"], 1, /*fake*/ 1>]; let Documentation = [Undocumented]; } Modified: cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td?rev=251496&r1=251495&r2=251496&view=diff ============================================================================== --- cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td (original) +++ cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td Wed Oct 28 00:03:19 2015 @@ -3992,8 +3992,6 @@ def err_unavailable_message : Error<"%0 def warn_unavailable_fwdclass_message : Warning< "%0 may be unavailable because the receiver type is unknown">, InGroup<UnavailableDeclarations>; -def note_unavailability_inferred_here : Note< - "unsupported declaration here">; def note_availability_specified_here : Note< "%0 has been explicitly marked " "%select{unavailable|deleted|deprecated|partial}1 here">; @@ -4555,6 +4553,21 @@ def err_arc_convesion_of_weak_unavailabl let CategoryName = "ARC Restrictions" in { +def err_unavailable_in_arc : Error< + "%0 is unavailable in ARC">; +def note_arc_forbidden_type : Note< + "declaration uses type that is ill-formed in ARC">; +def note_performs_forbidden_arc_conversion : Note< + "inline function performs a conversion which is forbidden in ARC">; +def note_arc_init_returns_unrelated : Note< + "init method must return a type related to its receiver type">; +def note_arc_weak_disabled : Note< + "declaration uses __weak, but ARC is disabled">; +def note_arc_weak_no_runtime : Note<"declaration uses __weak, which " + "the current deployment target does not support">; +def note_arc_field_with_ownership : Note< + "field has non-trivial ownership qualification">; + def err_arc_illegal_explicit_message : Error< "ARC forbids explicit message send of %0">; def err_arc_unused_init_message : Error< Modified: cfe/trunk/include/clang/Sema/Sema.h URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Sema/Sema.h?rev=251496&r1=251495&r2=251496&view=diff ============================================================================== --- cfe/trunk/include/clang/Sema/Sema.h (original) +++ cfe/trunk/include/clang/Sema/Sema.h Wed Oct 28 00:03:19 2015 @@ -3498,7 +3498,7 @@ public: bool ObjCPropertyAccess); bool makeUnavailableInSystemHeader(SourceLocation loc, - StringRef message); + UnavailableAttr::ImplicitReason reason); //===--------------------------------------------------------------------===// // Expression Parsing Callbacks: SemaExpr.cpp. Modified: cfe/trunk/lib/Sema/Sema.cpp URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/Sema.cpp?rev=251496&r1=251495&r2=251496&view=diff ============================================================================== --- cfe/trunk/lib/Sema/Sema.cpp (original) +++ cfe/trunk/lib/Sema/Sema.cpp Wed Oct 28 00:03:19 2015 @@ -296,7 +296,7 @@ Sema::~Sema() { /// make the relevant declaration unavailable instead of erroring, do /// so and return true. bool Sema::makeUnavailableInSystemHeader(SourceLocation loc, - StringRef msg) { + UnavailableAttr::ImplicitReason reason) { // If we're not in a function, it's an error. FunctionDecl *fn = dyn_cast<FunctionDecl>(CurContext); if (!fn) return false; @@ -312,7 +312,7 @@ bool Sema::makeUnavailableInSystemHeader // If the function is already unavailable, it's not an error. if (fn->hasAttr<UnavailableAttr>()) return true; - fn->addAttr(UnavailableAttr::CreateImplicit(Context, msg, loc)); + fn->addAttr(UnavailableAttr::CreateImplicit(Context, "", reason, loc)); return true; } Modified: cfe/trunk/lib/Sema/SemaDecl.cpp URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaDecl.cpp?rev=251496&r1=251495&r2=251496&view=diff ============================================================================== --- cfe/trunk/lib/Sema/SemaDecl.cpp (original) +++ cfe/trunk/lib/Sema/SemaDecl.cpp Wed Oct 28 00:03:19 2015 @@ -13076,9 +13076,8 @@ bool Sema::CheckNontrivialField(FieldDec SourceLocation Loc = FD->getLocation(); if (getSourceManager().isInSystemHeader(Loc)) { if (!FD->hasAttr<UnavailableAttr>()) - FD->addAttr(UnavailableAttr::CreateImplicit(Context, - "this system field has retaining ownership", - Loc)); + FD->addAttr(UnavailableAttr::CreateImplicit(Context, "", + UnavailableAttr::IR_ARCFieldWithOwnership, Loc)); return false; } } @@ -13447,9 +13446,8 @@ void Sema::ActOnFields(Scope *S, SourceL SourceLocation loc = FD->getLocation(); if (getSourceManager().isInSystemHeader(loc)) { if (!FD->hasAttr<UnavailableAttr>()) { - FD->addAttr(UnavailableAttr::CreateImplicit(Context, - "this system field has retaining ownership", - loc)); + FD->addAttr(UnavailableAttr::CreateImplicit(Context, "", + UnavailableAttr::IR_ARCFieldWithOwnership, loc)); } } else { Diag(FD->getLocation(), diag::err_arc_objc_object_in_tag) Modified: cfe/trunk/lib/Sema/SemaDeclAttr.cpp URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaDeclAttr.cpp?rev=251496&r1=251495&r2=251496&view=diff ============================================================================== --- cfe/trunk/lib/Sema/SemaDeclAttr.cpp (original) +++ cfe/trunk/lib/Sema/SemaDeclAttr.cpp Wed Oct 28 00:03:19 2015 @@ -5336,7 +5336,7 @@ void Sema::ProcessDeclAttributes(Scope * /// illegal to actually use. static bool isForbiddenTypeAllowed(Sema &S, Decl *decl, const DelayedDiagnostic &diag, - llvm::StringRef &explanation) { + UnavailableAttr::ImplicitReason &reason) { // Private ivars are always okay. Unfortunately, people don't // always properly make their ivars private, even in system headers. // Plus we need to make fields okay, too. @@ -5344,41 +5344,38 @@ static bool isForbiddenTypeAllowed(Sema !isa<FunctionDecl>(decl)) return false; - // All of these declarations are allowed in all system headers. which - // we assume to not be defined in user code. - if (S.Context.getSourceManager().isInSystemHeader(decl->getLocation())) { - explanation = "this system declaration uses an unsupported type"; - return true; - } - - // We do also need to allow __weak in user declarations when it's been - // disabled, for ease of integration with -fno-objc-arc files, but we - // have to take some care against attempts to define such things. - // For now, that care only extends to ivars and properties. + // Silently accept unsupported uses of __weak in both user and system + // declarations when it's been disabled, for ease of integration with + // -fno-objc-arc files. We do have to take some care against attempts + // to define such things; for now, we've only done that for ivars + // and properties. if ((isa<ObjCIvarDecl>(decl) || isa<ObjCPropertyDecl>(decl))) { - // TODO: find a way to localize these. - if (diag.getForbiddenTypeDiagnostic() == diag::err_arc_weak_disabled) { - explanation = "cannot use weak references in file using manual " - "reference counting"; - return true; - } - if (diag.getForbiddenTypeDiagnostic() == diag::err_arc_weak_no_runtime) { - explanation = "cannot use weak references because the current " - "deployment target does not support them"; + if (diag.getForbiddenTypeDiagnostic() == diag::err_arc_weak_disabled || + diag.getForbiddenTypeDiagnostic() == diag::err_arc_weak_no_runtime) { + reason = UnavailableAttr::IR_ForbiddenWeak; return true; } } + // Allow all sorts of things in system headers. + if (S.Context.getSourceManager().isInSystemHeader(decl->getLocation())) { + // Currently, all the failures dealt with this way are due to ARC + // restrictions. + reason = UnavailableAttr::IR_ARCForbiddenType; + return true; + } + return false; } /// Handle a delayed forbidden-type diagnostic. static void handleDelayedForbiddenType(Sema &S, DelayedDiagnostic &diag, Decl *decl) { - llvm::StringRef explanation; - if (decl && isForbiddenTypeAllowed(S, decl, diag, explanation)) { - decl->addAttr(UnavailableAttr::CreateImplicit(S.Context, explanation, - UnavailableAttr::ISK_ForbiddenType, diag.Loc)); + auto reason = UnavailableAttr::IR_None; + if (decl && isForbiddenTypeAllowed(S, decl, diag, reason)) { + assert(reason && "didn't set reason?"); + decl->addAttr(UnavailableAttr::CreateImplicit(S.Context, "", reason, + diag.Loc)); return; } if (S.getLangOpts().ObjCAutoRefCount) @@ -5462,11 +5459,47 @@ static void DoEmitAvailabilityWarning(Se property_note_select = /* unavailable */ 1; available_here_select_kind = /* unavailable */ 0; - if (!Message.empty()) { - if (auto attr = D->getAttr<UnavailableAttr>()) - if (attr->isImplicit() && - attr->getImplicitSource() == UnavailableAttr::ISK_ForbiddenType) - diag_available_here = diag::note_unavailability_inferred_here; + if (auto attr = D->getAttr<UnavailableAttr>()) { + if (attr->isImplicit() && attr->getImplicitReason()) { + // Most of these failures are due to extra restrictions in ARC; + // reflect that in the primary diagnostic when applicable. + auto flagARCError = [&] { + if (S.getLangOpts().ObjCAutoRefCount && + S.getSourceManager().isInSystemHeader(D->getLocation())) + diag = diag::err_unavailable_in_arc; + }; + + switch (attr->getImplicitReason()) { + case UnavailableAttr::IR_None: break; + + case UnavailableAttr::IR_ARCForbiddenType: + flagARCError(); + diag_available_here = diag::note_arc_forbidden_type; + break; + + case UnavailableAttr::IR_ForbiddenWeak: + if (S.getLangOpts().ObjCWeakRuntime) + diag_available_here = diag::note_arc_weak_disabled; + else + diag_available_here = diag::note_arc_weak_no_runtime; + break; + + case UnavailableAttr::IR_ARCForbiddenConversion: + flagARCError(); + diag_available_here = diag::note_performs_forbidden_arc_conversion; + break; + + case UnavailableAttr::IR_ARCInitReturnsUnrelated: + flagARCError(); + diag_available_here = diag::note_arc_init_returns_unrelated; + break; + + case UnavailableAttr::IR_ARCFieldWithOwnership: + flagARCError(); + diag_available_here = diag::note_arc_field_with_ownership; + break; + } + } } break; Modified: cfe/trunk/lib/Sema/SemaDeclObjC.cpp URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaDeclObjC.cpp?rev=251496&r1=251495&r2=251496&view=diff ============================================================================== --- cfe/trunk/lib/Sema/SemaDeclObjC.cpp (original) +++ cfe/trunk/lib/Sema/SemaDeclObjC.cpp Wed Oct 28 00:03:19 2015 @@ -100,9 +100,8 @@ bool Sema::checkInitMethod(ObjCMethodDec // If we're in a system header, and this is not a call, just make // the method unusable. if (receiverTypeIfCall.isNull() && getSourceManager().isInSystemHeader(loc)) { - method->addAttr(UnavailableAttr::CreateImplicit(Context, - "init method returns a type unrelated to its receiver type", - loc)); + method->addAttr(UnavailableAttr::CreateImplicit(Context, "", + UnavailableAttr::IR_ARCInitReturnsUnrelated, loc)); return true; } Modified: cfe/trunk/lib/Sema/SemaExprObjC.cpp URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaExprObjC.cpp?rev=251496&r1=251495&r2=251496&view=diff ============================================================================== --- cfe/trunk/lib/Sema/SemaExprObjC.cpp (original) +++ cfe/trunk/lib/Sema/SemaExprObjC.cpp Wed Oct 28 00:03:19 2015 @@ -3472,7 +3472,7 @@ diagnoseObjCARCConversion(Sema &S, Sourc (castRange.isValid() ? castRange.getBegin() : castExpr->getExprLoc()); if (S.makeUnavailableInSystemHeader(loc, - "converts between Objective-C and C pointers in -fobjc-arc")) + UnavailableAttr::IR_ARCForbiddenConversion)) return; QualType castExprType = castExpr->getType(); Modified: cfe/trunk/test/SemaObjC/arc-system-header.m URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/SemaObjC/arc-system-header.m?rev=251496&r1=251495&r2=251496&view=diff ============================================================================== --- cfe/trunk/test/SemaObjC/arc-system-header.m (original) +++ cfe/trunk/test/SemaObjC/arc-system-header.m Wed Oct 28 00:03:19 2015 @@ -5,26 +5,26 @@ #ifndef NO_USE void test(id op, void *cp) { - cp = test0(op); // expected-error {{'test0' is unavailable: converts between Objective-C and C pointers in -fobjc-arc}} - cp = *test1(&op); // expected-error {{'test1' is unavailable: converts between Objective-C and C pointers in -fobjc-arc}} -// expected-note@arc-system-header.h:1 {{'test0' has been explicitly marked unavailable here}} -// expected-note@arc-system-header.h:5 {{'test1' has been explicitly marked unavailable here}} + cp = test0(op); // expected-error {{'test0' is unavailable in ARC}} + cp = *test1(&op); // expected-error {{'test1' is unavailable in ARC}} +// expected-note@arc-system-header.h:1 {{inline function performs a conversion which is forbidden in ARC}} +// expected-note@arc-system-header.h:5 {{inline function performs a conversion which is forbidden in ARC}} } void test3(struct Test3 *p) { - p->field = 0; // expected-error {{'field' is unavailable: this system declaration uses an unsupported type}} - // expected-note@arc-system-header.h:14 {{unsupported declaration here}} + p->field = 0; // expected-error {{'field' is unavailable in ARC}} + // expected-note@arc-system-header.h:14 {{declaration uses type that is ill-formed in ARC}} } void test4(Test4 *p) { - p->field1 = 0; // expected-error {{'field1' is unavailable: this system declaration uses an unsupported type}} - // expected-note@arc-system-header.h:19 {{unsupported declaration here}} + p->field1 = 0; // expected-error {{'field1' is unavailable in ARC}} + // expected-note@arc-system-header.h:19 {{declaration uses type that is ill-formed in ARC}} p->field2 = 0; } void test5(struct Test5 *p) { - p->field = 0; // expected-error {{'field' is unavailable: this system field has retaining ownership}} - // expected-note@arc-system-header.h:25 {{'field' has been explicitly marked unavailable here}} + p->field = 0; // expected-error {{'field' is unavailable in ARC}} + // expected-note@arc-system-header.h:25 {{field has non-trivial ownership qualification}} } id test6() { @@ -39,11 +39,11 @@ id test6() { } void test7(Test7 *p) { - *p.prop = 0; // expected-error {{'prop' is unavailable: this system declaration uses an unsupported type}} - p.prop = 0; // expected-error {{'prop' is unavailable: this system declaration uses an unsupported type}} - *[p prop] = 0; // expected-error {{'prop' is unavailable: this system declaration uses an unsupported type}} - [p setProp: 0]; // expected-error {{'setProp:' is unavailable: this system declaration uses an unsupported type}} -// expected-note@arc-system-header.h:41 4 {{unsupported declaration here}} + *p.prop = 0; // expected-error {{'prop' is unavailable in ARC}} + p.prop = 0; // expected-error {{'prop' is unavailable in ARC}} + *[p prop] = 0; // expected-error {{'prop' is unavailable in ARC}} + [p setProp: 0]; // expected-error {{'setProp:' is unavailable in ARC}} +// expected-note@arc-system-header.h:41 4 {{declaration uses type that is ill-formed in ARC}} // expected-note@arc-system-header.h:41 2 {{property 'prop' is declared unavailable here}} } #endif Modified: cfe/trunk/test/SemaObjC/arc-unavailable-system-function.m URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/SemaObjC/arc-unavailable-system-function.m?rev=251496&r1=251495&r2=251496&view=diff ============================================================================== --- cfe/trunk/test/SemaObjC/arc-unavailable-system-function.m (original) +++ cfe/trunk/test/SemaObjC/arc-unavailable-system-function.m Wed Oct 28 00:03:19 2015 @@ -3,11 +3,11 @@ # 1 "<command line>" # 1 "/System/Library/Frameworks/Foundation.framework/Headers/Foundation.h" 1 3 -id * foo(); // expected-note {{unsupported declaration here}} +id * foo(); // expected-note {{declaration uses type that is ill-formed in ARC}} # 1 "arc-unavailable-system-function.m" 2 void ret() { - foo(); // expected-error {{'foo' is unavailable: this system declaration uses an unsupported type}} + foo(); // expected-error {{'foo' is unavailable in ARC}} } Modified: cfe/trunk/test/SemaObjC/mrc-no-weak.m URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/SemaObjC/mrc-no-weak.m?rev=251496&r1=251495&r2=251496&view=diff ============================================================================== --- cfe/trunk/test/SemaObjC/mrc-no-weak.m (original) +++ cfe/trunk/test/SemaObjC/mrc-no-weak.m Wed Oct 28 00:03:19 2015 @@ -36,13 +36,13 @@ __attribute__((objc_root_class)) @interface E : Root { @public - __weak id x; // expected-note 2 {{unsupported declaration here}} + __weak id x; // expected-note 2 {{declaration uses __weak, but ARC is disabled}} } @end void testE(E *e) { - id x = e->x; // expected-error {{'x' is unavailable: cannot use weak references in file using manual reference counting}} - e->x = x; // expected-error {{'x' is unavailable: cannot use weak references in file using manual reference counting}} + id x = e->x; // expected-error {{'x' is unavailable}} + e->x = x; // expected-error {{'x' is unavailable}} } @interface F : Root Modified: cfe/trunk/test/SemaObjCXX/arc-system-header.mm URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/SemaObjCXX/arc-system-header.mm?rev=251496&r1=251495&r2=251496&view=diff ============================================================================== --- cfe/trunk/test/SemaObjCXX/arc-system-header.mm (original) +++ cfe/trunk/test/SemaObjCXX/arc-system-header.mm Wed Oct 28 00:03:19 2015 @@ -4,6 +4,6 @@ void f(A* a) { a->data.void_ptr = 0; - a->data.a_b.b = 0; // expected-error{{'a_b' is unavailable: this system field has retaining ownership}} + a->data.a_b.b = 0; // expected-error{{'a_b' is unavailable in ARC}} } -// expected-note@arc-system-header.h:10{{'a_b' has been explicitly marked unavailable here}} +// expected-note@arc-system-header.h:10{{field has non-trivial ownership qualification}} _______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits