diff options
author | John McCall <rjmccall@apple.com> | 2015-10-28 05:03:19 +0000 |
---|---|---|
committer | John McCall <rjmccall@apple.com> | 2015-10-28 05:03:19 +0000 |
commit | c6af8c606dae9a9b728d5099d5964ea6540dc22c (patch) | |
tree | 0a19128c0f58cc451454838159b232968eb359e5 /clang/lib/Sema | |
parent | 9b1534df9da6695fde3d639e8ee3b9a7cf36b0a4 (diff) | |
download | bcm5719-llvm-c6af8c606dae9a9b728d5099d5964ea6540dc22c.tar.gz bcm5719-llvm-c6af8c606dae9a9b728d5099d5964ea6540dc22c.zip |
Refine r251469 to give better (and more localizable) diagnostics
for all the reasons that ARC makes things implicitly unavailable.
llvm-svn: 251496
Diffstat (limited to 'clang/lib/Sema')
-rw-r--r-- | clang/lib/Sema/Sema.cpp | 4 | ||||
-rw-r--r-- | clang/lib/Sema/SemaDecl.cpp | 10 | ||||
-rw-r--r-- | clang/lib/Sema/SemaDeclAttr.cpp | 93 | ||||
-rw-r--r-- | clang/lib/Sema/SemaDeclObjC.cpp | 5 | ||||
-rw-r--r-- | clang/lib/Sema/SemaExprObjC.cpp | 2 |
5 files changed, 72 insertions, 42 deletions
diff --git a/clang/lib/Sema/Sema.cpp b/clang/lib/Sema/Sema.cpp index 300e2f040a2..f96430f1ecc 100644 --- a/clang/lib/Sema/Sema.cpp +++ b/clang/lib/Sema/Sema.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; } diff --git a/clang/lib/Sema/SemaDecl.cpp b/clang/lib/Sema/SemaDecl.cpp index f9e75893bf3..43fe9947840 100644 --- a/clang/lib/Sema/SemaDecl.cpp +++ b/clang/lib/Sema/SemaDecl.cpp @@ -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) diff --git a/clang/lib/Sema/SemaDeclAttr.cpp b/clang/lib/Sema/SemaDeclAttr.cpp index 1f90b75e57c..91e196d2358 100644 --- a/clang/lib/Sema/SemaDeclAttr.cpp +++ b/clang/lib/Sema/SemaDeclAttr.cpp @@ -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,41 +5344,38 @@ 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; - } - - // 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(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; diff --git a/clang/lib/Sema/SemaDeclObjC.cpp b/clang/lib/Sema/SemaDeclObjC.cpp index dbdb558ba42..90c829e740c 100644 --- a/clang/lib/Sema/SemaDeclObjC.cpp +++ b/clang/lib/Sema/SemaDeclObjC.cpp @@ -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; } diff --git a/clang/lib/Sema/SemaExprObjC.cpp b/clang/lib/Sema/SemaExprObjC.cpp index b663566ff70..227b322adb3 100644 --- a/clang/lib/Sema/SemaExprObjC.cpp +++ b/clang/lib/Sema/SemaExprObjC.cpp @@ -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(); |