forked from OSchip/llvm-project
Refine r251469 to give better (and more localizable) diagnostics
for all the reasons that ARC makes things implicitly unavailable. llvm-svn: 251496
This commit is contained in:
parent
9b1534df9d
commit
c6af8c606d
|
@ -132,6 +132,9 @@ def HasFunctionProto : SubsetSubject<DeclBase,
|
|||
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];
|
||||
}
|
||||
|
||||
|
|
|
@ -3992,8 +3992,6 @@ def err_unavailable_message : Error<"%0 is unavailable: %1">;
|
|||
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_unavailable : Error<
|
|||
|
||||
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<
|
||||
|
|
|
@ -3498,7 +3498,7 @@ public:
|
|||
bool ObjCPropertyAccess);
|
||||
|
||||
bool makeUnavailableInSystemHeader(SourceLocation loc,
|
||||
StringRef message);
|
||||
UnavailableAttr::ImplicitReason reason);
|
||||
|
||||
//===--------------------------------------------------------------------===//
|
||||
// Expression Parsing Callbacks: SemaExpr.cpp.
|
||||
|
|
|
@ -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(SourceLocation loc,
|
|||
// 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;
|
||||
}
|
||||
|
||||
|
|
|
@ -13076,9 +13076,8 @@ bool Sema::CheckNontrivialField(FieldDecl *FD) {
|
|||
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, SourceLocation RecLoc, Decl *EnclosingDecl,
|
|||
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)
|
||||
|
|
|
@ -5336,7 +5336,7 @@ void Sema::ProcessDeclAttributes(Scope *S, Decl *D, const Declarator &PD) {
|
|||
/// 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,29 +5344,25 @@ static bool isForbiddenTypeAllowed(Sema &S, Decl *decl,
|
|||
!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;
|
||||
// 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))) {
|
||||
if (diag.getForbiddenTypeDiagnostic() == diag::err_arc_weak_disabled ||
|
||||
diag.getForbiddenTypeDiagnostic() == diag::err_arc_weak_no_runtime) {
|
||||
reason = UnavailableAttr::IR_ForbiddenWeak;
|
||||
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.
|
||||
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";
|
||||
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;
|
||||
|
@ -5375,10 +5371,11 @@ static bool isForbiddenTypeAllowed(Sema &S, Decl *decl,
|
|||
/// 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(Sema &S, Sema::AvailabilityDiagnostic K,
|
|||
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;
|
||||
|
|
|
@ -100,9 +100,8 @@ bool Sema::checkInitMethod(ObjCMethodDecl *method,
|
|||
// 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;
|
||||
}
|
||||
|
||||
|
|
|
@ -3472,7 +3472,7 @@ diagnoseObjCARCConversion(Sema &S, SourceRange castRange,
|
|||
(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();
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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}}
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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}}
|
||||
|
|
Loading…
Reference in New Issue