r251496 - Refine r251469 to give better (and more localizable) diagnostics

John McCall via cfe-commits cfe-commits at lists.llvm.org
Tue Oct 27 22:03:19 PDT 2015


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 at arc-system-header.h:1 {{'test0' has been explicitly marked unavailable here}}
-// expected-note at 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 at arc-system-header.h:1 {{inline function performs a conversion which is forbidden in ARC}}
+// expected-note at 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 at arc-system-header.h:14 {{unsupported declaration here}}
+  p->field = 0; // expected-error {{'field' is unavailable in ARC}}
+                // expected-note at 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 at arc-system-header.h:19 {{unsupported declaration here}}
+  p->field1 = 0; // expected-error {{'field1' is unavailable in ARC}}
+                 // expected-note at 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 at arc-system-header.h:25 {{'field' has been explicitly marked unavailable here}}
+  p->field = 0; // expected-error {{'field' is unavailable in ARC}}
+                // expected-note at 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 at 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 at arc-system-header.h:41 4 {{declaration uses type that is ill-formed in ARC}}
 // expected-note at 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 at arc-system-header.h:10{{'a_b' has been explicitly marked unavailable here}}
+// expected-note at arc-system-header.h:10{{field has non-trivial ownership qualification}}




More information about the cfe-commits mailing list