]> granicus.if.org Git - clang/commitdiff
Warn in ObjC++ when an 'auto' variable deduces type 'id'.
authorJordan Rose <jordan_rose@apple.com>
Fri, 8 Jun 2012 22:46:07 +0000 (22:46 +0000)
committerJordan Rose <jordan_rose@apple.com>
Fri, 8 Jun 2012 22:46:07 +0000 (22:46 +0000)
This could happen for cases like this:

- (NSArray *)getAllNames:(NSArray *)images {
  NSMutableArray *results = [NSMutableArray array];
  for (auto img in images) {
    [results addObject:img.name];
  }
  return results;
}

Here the property access will fail because 'img' has type 'id', rather than,
say, NSImage.

This warning will not fire in templated code, since the 'id' could have
come from a template parameter.

git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@158239 91177308-0d34-0410-b5e6-96231b3b80d8

include/clang/Basic/DiagnosticSemaKinds.td
lib/Sema/SemaDecl.cpp
test/SemaObjCXX/arc-0x.mm

index e50138dccf1ecbfa8e29c59441fd28602ff73f43..235c6abdaee349fdf01587b32f395f8f309a77b9 100644 (file)
@@ -1469,6 +1469,10 @@ def warn_cxx98_compat_unicode_type : Warning<
 // Objective-C++
 def err_objc_decls_may_only_appear_in_global_scope : Error<
   "Objective-C declarations may only appear in global scope">;
+def warn_auto_var_is_id : Warning<
+  "'auto' deduced as 'id' in declaration of %0">,
+  InGroup<DiagGroup<"auto-var-id">>;
+
 // Attributes
 def err_nsobject_attribute : Error<
   "__attribute ((NSObject)) is for pointer types only">;
index 68f74694577be369ac30705bd151bb9d49b24da8..40cc35117c8c835919819f588bacff4fd6adb207 100644 (file)
@@ -6303,6 +6303,17 @@ void Sema::AddInitializerToDecl(Decl *RealDecl, Expr *Init,
     if (getLangOpts().ObjCAutoRefCount && inferObjCARCLifetime(VDecl))
       VDecl->setInvalidDecl();
 
+    // Warn if we deduced 'id'. 'auto' usually implies type-safety, but using
+    // 'id' instead of a specific object type prevents most of our usual checks.
+    // We only want to warn outside of template instantiations, though:
+    // inside a template, the 'id' could have come from a parameter.
+    if (ActiveTemplateInstantiations.empty() &&
+        DeducedType->getType()->isObjCIdType()) {
+      SourceLocation Loc = DeducedType->getTypeLoc().getBeginLoc();
+      Diag(Loc, diag::warn_auto_var_is_id)
+        << VDecl->getDeclName() << DeduceInit->getSourceRange();
+    }
+
     // If this is a redeclaration, check that the type we just deduced matches
     // the previously declared type.
     if (VarDecl *Old = VDecl->getPreviousDecl())
index 28eec51775bd1e3a677b13c2db4d2e277b10acfc..88b3ab11786440862e2b407f25ef306a3afa8472 100644 (file)
@@ -22,7 +22,7 @@ void deduction(id obj) {
   __strong id *idp = new auto(obj);
 
   __strong id array[17];
-  for (auto x : array) {
+  for (auto x : array) { // expected-warning{{'auto' deduced as 'id' in declaration of 'x'}}
     __strong id *xPtr = &x;
   }
 
@@ -51,3 +51,24 @@ void test1c() {
   (void) ^{ (void) p; };
   (void) ^{ (void) v; }; // expected-error {{cannot capture __autoreleasing variable in a block}}
 }
+
+
+// <rdar://problem/11319689>
+// warn when initializing an 'auto' variable with an 'id' initializer expression
+
+void testAutoId(id obj) {
+  auto x = obj; // expected-warning{{'auto' deduced as 'id' in declaration of 'x'}}
+}
+
+// ...but don't warn if it's coming from a template parameter.
+template<typename T>
+void autoTemplateFunction(T param, id obj) {
+  auto x = param; // no-warning
+  auto y = obj; // expected-warning{{'auto' deduced as 'id' in declaration of 'y'}}
+}
+
+void testAutoIdTemplate(id obj) {
+  autoTemplateFunction(obj, obj); // no-warning
+}
+
+