From: Jordan Rose Date: Fri, 8 Jun 2012 22:46:07 +0000 (+0000) Subject: Warn in ObjC++ when an 'auto' variable deduces type 'id'. X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=0abbdfe561377b7af8eba6fc87757a46342f7a10;p=clang Warn in ObjC++ when an 'auto' variable deduces type 'id'. 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 --- diff --git a/include/clang/Basic/DiagnosticSemaKinds.td b/include/clang/Basic/DiagnosticSemaKinds.td index e50138dccf..235c6abdae 100644 --- a/include/clang/Basic/DiagnosticSemaKinds.td +++ b/include/clang/Basic/DiagnosticSemaKinds.td @@ -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>; + // Attributes def err_nsobject_attribute : Error< "__attribute ((NSObject)) is for pointer types only">; diff --git a/lib/Sema/SemaDecl.cpp b/lib/Sema/SemaDecl.cpp index 68f7469457..40cc35117c 100644 --- a/lib/Sema/SemaDecl.cpp +++ b/lib/Sema/SemaDecl.cpp @@ -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()) diff --git a/test/SemaObjCXX/arc-0x.mm b/test/SemaObjCXX/arc-0x.mm index 28eec51775..88b3ab1178 100644 --- a/test/SemaObjCXX/arc-0x.mm +++ b/test/SemaObjCXX/arc-0x.mm @@ -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}} } + + +// +// 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 +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 +} + +