[PATCH] D15636: Reduce false positives in printf/scanf format checker

Andy Gibbs via cfe-commits cfe-commits at lists.llvm.org
Mon Feb 22 07:44:10 PST 2016


AndyG marked 11 inline comments as done.
AndyG added a comment.

Revised patch coming shortly...


================
Comment at: lib/Sema/SemaChecking.cpp:3603
@@ -3554,3 +3602,3 @@
 
-  void DoneProcessing();
+  void DoneProcessing(signed &FirstUncoveredArg);
 
----------------
rtrieu wrote:
> Don't change the call signature here, leave it as a zero argument call.  Have another function return the first uncovered argument.
DoneProcessing is that function!  To move the logic into another function would leave nothing behind :o)

Passing UncoveredArgHandler& into CheckFormatHandler allows this to be worked around.

================
Comment at: lib/Sema/SemaChecking.cpp:3840-3892
@@ -3796,5 +3839,55 @@
+
+void UncoveredArgHandler::Update(signed NewFirstUncoveredArg,
+                                 const Expr *StrExpr) {
+  // Don't update if a previous string covers all arguments.
+  if (FirstUncoveredArg == AllCovered)
+    return;
+
+  switch (NewFirstUncoveredArg) {
+    case Unknown:
+      // The string was not fully analysed.  Do nothing.
+      break;
+
+    case UncoveredArgHandler::AllCovered:
+      // A string has been found with all arguments covered, so clear out
+      // the diagnostics.
+      FirstUncoveredArg = AllCovered;
+      DiagnosticExprs.clear();
+      break;
+
+    default:
+      // UncoveredArgHandler tracks the highest uncovered argument index
+      // and with it all the strings that match this index.
+      if (NewFirstUncoveredArg == FirstUncoveredArg)
+        DiagnosticExprs.push_back(StrExpr);
+      else if (NewFirstUncoveredArg > FirstUncoveredArg) {
+        DiagnosticExprs.clear();
+        DiagnosticExprs.push_back(StrExpr);
+        FirstUncoveredArg = NewFirstUncoveredArg;
       }
-    }
+      break;
   }
 }
 
+void UncoveredArgHandler::Diagnose(Sema &S, bool IsFunctionCall,
+                                   const Expr *ArgExpr) {
+  assert(FirstUncoveredArg >= 0 && DiagnosticExprs.size() > 0 &&
+         "Invalid state");
+
+  if (!ArgExpr)
+    return;
+
+  SourceLocation Loc = ArgExpr->getLocStart();
+
+  if (S.getSourceManager().isInSystemMacro(Loc))
+    return;
+
+  PartialDiagnostic PDiag = S.PDiag(diag::warn_printf_data_arg_not_used);
+  for (unsigned i = 1; i < DiagnosticExprs.size(); ++i)
+    PDiag << DiagnosticExprs[i]->getSourceRange();
+
+  CheckFormatHandler::EmitFormatDiagnostic(
+                                  S, IsFunctionCall, DiagnosticExprs[0],
+                                  PDiag, Loc, /*IsStringLocation*/false,
+                                  DiagnosticExprs[0]->getSourceRange());
+}
----------------
rtrieu wrote:
> Move these two functions up to where the class is defined.
UncoveredArgHandler::Update has been moved up, but UncoveredArgHandler::Diagnose has been left since it has a dependency on CheckFormatHandler.

================
Comment at: lib/Sema/SemaChecking.cpp:3886-3887
@@ +3885,4 @@
+  PartialDiagnostic PDiag = S.PDiag(diag::warn_printf_data_arg_not_used);
+  for (unsigned i = 1; i < DiagnosticExprs.size(); ++i)
+    PDiag << DiagnosticExprs[i]->getSourceRange();
+
----------------
rtrieu wrote:
> Use a range-based for-loop here.
Except that it is iterating from the second item in the list.  I don't think there is an easier way to do it.


http://reviews.llvm.org/D15636





More information about the cfe-commits mailing list