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;
}
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];
}
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">;
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<
bool ObjCPropertyAccess);
bool makeUnavailableInSystemHeader(SourceLocation loc,
- StringRef message);
+ UnavailableAttr::ImplicitReason reason);
//===--------------------------------------------------------------------===//
// Expression Parsing Callbacks: SemaExpr.cpp.
/// 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;
// 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;
}
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;
}
}
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)
/// 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.
!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)
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;
// 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;
}
(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();
#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() {
}
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
# 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}}
}
@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
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}}