]> granicus.if.org Git - clang/commitdiff
[analyzer] Do not report uninitialized value warnings inside swap functions.
authorAnna Zaks <ganna@apple.com>
Tue, 18 Jun 2013 23:16:15 +0000 (23:16 +0000)
committerAnna Zaks <ganna@apple.com>
Tue, 18 Jun 2013 23:16:15 +0000 (23:16 +0000)
This silences warnings that could occur when one is swapping partially initialized structs. We suppress
not only the assignments of uninitialized members, but any values inside swap because swap could
potentially be used as a subroutine to swap class members.

This silences a warning from std::try::function::swap() on partially initialized objects.

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

lib/StaticAnalyzer/Checkers/UndefResultChecker.cpp
lib/StaticAnalyzer/Checkers/UndefinedAssignmentChecker.cpp
test/Analysis/uninit-vals-ps-region.m

index 673356319833fa2f62873b14ac390131cfc330fa..3f6549de56b0a53ebd3b5eb84c2823071a4d97ca 100644 (file)
@@ -40,6 +40,15 @@ void UndefResultChecker::checkPostStmt(const BinaryOperator *B,
   ProgramStateRef state = C.getState();
   const LocationContext *LCtx = C.getLocationContext();
   if (state->getSVal(B, LCtx).isUndef()) {
+
+    // Do not report assignments of uninitialized values inside swap functions.
+    // This should allow to swap partially uninitialized structs
+    // (radar://14129997)
+    if (const FunctionDecl *EnclosingFunctionDecl =
+        dyn_cast<FunctionDecl>(C.getStackFrame()->getDecl()))
+      if (C.getCalleeName(EnclosingFunctionDecl) == "swap")
+        return;
+
     // Generate an error node.
     ExplodedNode *N = C.generateSink();
     if (!N)
index e04f49c3746df1f25a0dde834894636819794249..016e3c80459246882253708fdc294e503d2cdd0a 100644 (file)
@@ -38,6 +38,14 @@ void UndefinedAssignmentChecker::checkBind(SVal location, SVal val,
   if (!val.isUndef())
     return;
 
+  // Do not report assignments of uninitialized values inside swap functions.
+  // This should allow to swap partially uninitialized structs
+  // (radar://14129997)
+  if (const FunctionDecl *EnclosingFunctionDecl =
+      dyn_cast<FunctionDecl>(C.getStackFrame()->getDecl()))
+    if (C.getCalleeName(EnclosingFunctionDecl) == "swap")
+      return;
+
   ExplodedNode *N = C.generateSink();
 
   if (!N)
index 614ce2fc33543bf75377550f3810a5342d0d5cdc..a4aa5a114aeb1d61d29ee422c77026327abab3e5 100644 (file)
@@ -76,3 +76,18 @@ void PR10163 (void) {
   test_PR10163(x[1]); // expected-warning{{uninitialized value}}
 }
 
+struct MyStr {
+  int x;
+  int y;
+};
+void swap(struct MyStr *To, struct MyStr *From) {
+  // This is not really a swap but close enough for our test.
+  To->x = From->x;
+  To->y = From->y; // no warning
+}
+int test_undefined_member_assignment_in_swap(struct MyStr *s2) {
+  struct MyStr s1;
+  s1.x = 5;
+  swap(s2, &s1);
+  return s2->y; // expected-warning{{Undefined or garbage value returned to caller}}
+}