]> granicus.if.org Git - clang/commitdiff
Improve the correctness and accuracy of the message for -Wdynamic-class-memaccess
authorMatt Beaumont-Gay <matthewbg@google.com>
Fri, 19 Aug 2011 20:40:18 +0000 (20:40 +0000)
committerMatt Beaumont-Gay <matthewbg@google.com>
Fri, 19 Aug 2011 20:40:18 +0000 (20:40 +0000)
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@138074 91177308-0d34-0410-b5e6-96231b3b80d8

include/clang/Basic/DiagnosticSemaKinds.td
lib/Sema/SemaChecking.cpp
test/SemaCXX/warn-bad-memaccess.cpp

index 93521ed596d2ac7c0fca4968d6fa34e8eada90dc..c76dca0f7baf14591bceaa735fc194206c25f7fa 100644 (file)
@@ -264,8 +264,9 @@ def err_types_compatible_p_in_cplusplus : Error<
   "__builtin_types_compatible_p is not valid in C++">;
 def warn_builtin_unknown : Warning<"use of unknown builtin %0">, DefaultError;
 def warn_dyn_class_memaccess : Warning<
-  "%select{destination for|source of}0 this %1 call is a pointer to dynamic "
-  "class %2; vtable pointer will be overwritten">, 
+  "%select{destination for|source of|first operand of|second operand of}0 this "
+  "%1 call is a pointer to dynamic class %2; vtable pointer will be "
+  "%select{overwritten|copied|moved|compared}3">,
   InGroup<DiagGroup<"dynamic-class-memaccess">>;
 def note_bad_memaccess_silence : Note<
   "explicitly cast the pointer to silence this warning">;
index 82c97a63cdb14bce9b0adb1eec3963ff8f7713b8..530f81289a9a70666475cfde2d57b3bdc34d2426 100644 (file)
@@ -1971,22 +1971,25 @@ void Sema::CheckMemaccessArguments(const CallExpr *Call,
         }
       }
 
-      unsigned DiagID;
-
       // Always complain about dynamic classes.
       if (isDynamicClassType(PointeeTy))
-        DiagID = diag::warn_dyn_class_memaccess;
+        DiagRuntimeBehavior(
+          Dest->getExprLoc(), Dest,
+          PDiag(diag::warn_dyn_class_memaccess)
+            << (CMF == CMF_Memcmp ? ArgIdx + 2 : ArgIdx) << FnName << PointeeTy
+            // "overwritten" if we're warning about the destination for any call
+            // but memcmp; otherwise a verb appropriate to the call.
+            << (ArgIdx == 0 && CMF != CMF_Memcmp ? 0 : (unsigned)CMF)
+            << Call->getCallee()->getSourceRange());
       else if (PointeeTy.hasNonTrivialObjCLifetime() && CMF != CMF_Memset)
-        DiagID = diag::warn_arc_object_memaccess;
+        DiagRuntimeBehavior(
+          Dest->getExprLoc(), Dest,
+          PDiag(diag::warn_arc_object_memaccess)
+            << ArgIdx << FnName << PointeeTy
+            << Call->getCallee()->getSourceRange());
       else
         continue;
 
-      DiagRuntimeBehavior(
-        Dest->getExprLoc(), Dest,
-        PDiag(DiagID)
-          << ArgIdx << FnName << PointeeTy 
-          << Call->getCallee()->getSourceRange());
-
       DiagRuntimeBehavior(
         Dest->getExprLoc(), Dest,
         PDiag(diag::note_bad_memaccess_silence)
index 9a998f020cb4a5538a6356ddd4ae211512127eb8..3a02c84e9fc4bb743e0f46bb8cffbabeab57153e 100644 (file)
@@ -3,6 +3,7 @@
 extern "C" void *memset(void *, int, unsigned);
 extern "C" void *memmove(void *s1, const void *s2, unsigned n);
 extern "C" void *memcpy(void *s1, const void *s2, unsigned n);
+extern "C" void *memcmp(void *s1, const void *s2, unsigned n);
 
 // Several types that should not warn.
 struct S1 {} s1;
@@ -27,16 +28,22 @@ void test_warn() {
       // expected-note {{explicitly cast the pointer to silence this warning}}
 
   memmove(&x1, 0, sizeof x1); // \
-      // expected-warning{{destination for this 'memmove' call is a pointer to dynamic class}} \
+      // expected-warning{{destination for this 'memmove' call is a pointer to dynamic class 'struct X1'; vtable pointer will be overwritten}} \
       // expected-note {{explicitly cast the pointer to silence this warning}}
   memmove(0, &x1, sizeof x1); // \
-      // expected-warning{{source of this 'memmove' call is a pointer to dynamic class}} \
+      // expected-warning{{source of this 'memmove' call is a pointer to dynamic class 'struct X1'; vtable pointer will be moved}} \
       // expected-note {{explicitly cast the pointer to silence this warning}}
   memcpy(&x1, 0, sizeof x1); // \
-      // expected-warning{{destination for this 'memcpy' call is a pointer to dynamic class}} \
+      // expected-warning{{destination for this 'memcpy' call is a pointer to dynamic class 'struct X1'; vtable pointer will be overwritten}} \
       // expected-note {{explicitly cast the pointer to silence this warning}}
   memcpy(0, &x1, sizeof x1); // \
-      // expected-warning{{source of this 'memcpy' call is a pointer to dynamic class}} \
+      // expected-warning{{source of this 'memcpy' call is a pointer to dynamic class 'struct X1'; vtable pointer will be copied}} \
+      // expected-note {{explicitly cast the pointer to silence this warning}}
+  memcmp(&x1, 0, sizeof x1); // \
+      // expected-warning{{first operand of this 'memcmp' call is a pointer to dynamic class 'struct X1'; vtable pointer will be compared}} \
+      // expected-note {{explicitly cast the pointer to silence this warning}}
+  memcmp(0, &x1, sizeof x1); // \
+      // expected-warning{{second operand of this 'memcmp' call is a pointer to dynamic class 'struct X1'; vtable pointer will be compared}} \
       // expected-note {{explicitly cast the pointer to silence this warning}}
 
   __builtin_memset(&x1, 0, sizeof x1); // \
@@ -108,5 +115,3 @@ namespace N {
     N::memset(&x1, 0, sizeof x1);
   }
 }
-
-