From: Ted Kremenek Date: Mon, 14 Mar 2011 19:50:37 +0000 (+0000) Subject: Tweak VariadicMethodTypeChecker to only create one ExplodedNode when issuing multiple... X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=6fb5c1facaf36795a8c1050cd901e0e829ac1a64;p=clang Tweak VariadicMethodTypeChecker to only create one ExplodedNode when issuing multiple warnings for the same message expression. Also add a test case showing that we correctly report multiple warnings for the same message expression. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@127605 91177308-0d34-0410-b5e6-96231b3b80d8 --- diff --git a/lib/StaticAnalyzer/Checkers/BasicObjCFoundationChecks.cpp b/lib/StaticAnalyzer/Checkers/BasicObjCFoundationChecks.cpp index a6f980ad49..8677f08ab9 100644 --- a/lib/StaticAnalyzer/Checkers/BasicObjCFoundationChecks.cpp +++ b/lib/StaticAnalyzer/Checkers/BasicObjCFoundationChecks.cpp @@ -502,10 +502,7 @@ public: bool VariadicMethodTypeChecker::isVariadicMessage(const ObjCMessage &msg) const { const ObjCMethodDecl *MD = msg.getMethodDecl(); - if (!MD) - return false; - - if (!MD->isVariadic()) + if (!MD || !MD->isVariadic()) return false; Selector S = msg.getSelector(); @@ -586,13 +583,19 @@ void VariadicMethodTypeChecker::checkPreObjCMessage(ObjCMessage msg, return; // Verify that all arguments have Objective-C types. + llvm::Optional errorNode; + for (unsigned I = variadicArgsBegin; I != variadicArgsEnd; ++I) { QualType ArgTy = msg.getArgType(I); if (ArgTy->isObjCObjectPointerType()) continue; - ExplodedNode *N = C.generateNode(); - if (!N) + // Generate only one error node to use for all bug reports. + if (!errorNode.hasValue()) { + errorNode = C.generateNode(); + } + + if (!errorNode.getValue()) continue; llvm::SmallString<128> sbuf; @@ -607,7 +610,8 @@ void VariadicMethodTypeChecker::checkPreObjCMessage(ObjCMessage msg, << "' should be an Objective-C pointer type, not '" << ArgTy.getAsString() << "'"; - RangedBugReport *R = new RangedBugReport(*BT, os.str(), N); + RangedBugReport *R = new RangedBugReport(*BT, os.str(), + errorNode.getValue()); R->addRange(msg.getArgSourceRange(I)); C.EmitReport(R); } diff --git a/test/Analysis/variadic-method-types.m b/test/Analysis/variadic-method-types.m index 5b187edced..bd1b227f9f 100644 --- a/test/Analysis/variadic-method-types.m +++ b/test/Analysis/variadic-method-types.m @@ -63,7 +63,7 @@ typedef struct {} NSFastEnumerationState; void f(id a, id

b, C* c, C

*d) { [NSArray arrayWithObjects:@"Hello", a, b, c, d, nil]; - [NSArray arrayWithObjects:@"Foo", "Bar", nil]; // expected-warning {{Argument to 'NSArray' method 'arrayWithObjects:' should be an Objective-C pointer type, not 'char *'}} + [NSArray arrayWithObjects:@"Foo", "Bar", "Baz", nil]; // expected-warning 2 {{Argument to 'NSArray' method 'arrayWithObjects:' should be an Objective-C pointer type, not 'char *'}} [NSDictionary dictionaryWithObjectsAndKeys:@"Foo", "Bar", nil]; // expected-warning {{Argument to 'NSDictionary' method 'dictionaryWithObjectsAndKeys:' should be an Objective-C pointer type, not 'char *'}} [NSSet setWithObjects:@"Foo", "Bar", nil]; // expected-warning {{Argument to 'NSSet' method 'setWithObjects:' should be an Objective-C pointer type, not 'char *'}}