[cfe-commits] r133173 - in /cfe/trunk: include/clang/Sema/Sema.h lib/Sema/SemaChecking.cpp test/SemaCXX/warn-bad-memaccess.cpp

Douglas Gregor dgregor at apple.com
Thu Jun 16 10:56:04 PDT 2011


Author: dgregor
Date: Thu Jun 16 12:56:04 2011
New Revision: 133173

URL: http://llvm.org/viewvc/llvm-project?rev=133173&view=rev
Log:
Teach the warning about non-POD memset/memcpy/memmove to deal with the
__builtin_ versions of these functions as well as the normal function
versions, so that it works on platforms where memset/memcpy/memmove
are macros that map down to the builtins (e.g., Darwin). Fixes
<rdar://problem/9372688>.

Modified:
    cfe/trunk/include/clang/Sema/Sema.h
    cfe/trunk/lib/Sema/SemaChecking.cpp
    cfe/trunk/test/SemaCXX/warn-bad-memaccess.cpp

Modified: cfe/trunk/include/clang/Sema/Sema.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Sema/Sema.h?rev=133173&r1=133172&r2=133173&view=diff
==============================================================================
--- cfe/trunk/include/clang/Sema/Sema.h (original)
+++ cfe/trunk/include/clang/Sema/Sema.h Thu Jun 16 12:56:04 2011
@@ -5901,8 +5901,17 @@
                                  unsigned format_idx, unsigned firstDataArg,
                                  bool isPrintf);
 
-  void CheckMemsetcpymoveArguments(const CallExpr *Call,
-                                   const IdentifierInfo *FnName);
+  /// \brief Enumeration used to describe which of the memory setting or copying
+  /// functions is being checked by \c CheckMemsetcpymoveArguments().
+  enum CheckedMemoryFunction {
+    CMF_Memset,
+    CMF_Memcpy,
+    CMF_Memmove
+  };
+  
+  void CheckMemsetcpymoveArguments(const CallExpr *Call, 
+                                   CheckedMemoryFunction CMF,
+                                   IdentifierInfo *FnName);
 
   void CheckReturnStackAddr(Expr *RetValExp, QualType lhsType,
                             SourceLocation ReturnLoc);

Modified: cfe/trunk/lib/Sema/SemaChecking.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaChecking.cpp?rev=133173&r1=133172&r2=133173&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/SemaChecking.cpp (original)
+++ cfe/trunk/lib/Sema/SemaChecking.cpp Thu Jun 16 12:56:04 2011
@@ -320,12 +320,41 @@
   }
 
   // Memset/memcpy/memmove handling
-  if (FDecl->getLinkage() == ExternalLinkage &&
-      (!getLangOptions().CPlusPlus || FDecl->isExternC())) {
-    if (FnInfo->isStr("memset") || FnInfo->isStr("memcpy") || 
-        FnInfo->isStr("memmove"))
-      CheckMemsetcpymoveArguments(TheCall, FnInfo);
+  int CMF = -1;
+  switch (FDecl->getBuiltinID()) {
+  case Builtin::BI__builtin_memset:
+  case Builtin::BI__builtin___memset_chk:
+  case Builtin::BImemset:
+    CMF = CMF_Memset;
+    break;
+    
+  case Builtin::BI__builtin_memcpy:
+  case Builtin::BI__builtin___memcpy_chk:
+  case Builtin::BImemcpy:
+    CMF = CMF_Memcpy;
+    break;
+    
+  case Builtin::BI__builtin_memmove:
+  case Builtin::BI__builtin___memmove_chk:
+  case Builtin::BImemmove:
+    CMF = CMF_Memmove;
+    break;
+    
+  default:
+    if (FDecl->getLinkage() == ExternalLinkage &&
+        (!getLangOptions().CPlusPlus || FDecl->isExternC())) {
+      if (FnInfo->isStr("memset"))
+        CMF = CMF_Memset;
+      else if (FnInfo->isStr("memcpy"))
+        CMF = CMF_Memcpy;
+      else if (FnInfo->isStr("memmove"))
+        CMF = CMF_Memmove;
+    }
+    break;
   }
+   
+  if (CMF != -1)
+    CheckMemsetcpymoveArguments(TheCall, CheckedMemoryFunction(CMF), FnInfo);
 
   return false;
 }
@@ -1856,14 +1885,14 @@
 ///
 /// \param Call The call expression to diagnose.
 void Sema::CheckMemsetcpymoveArguments(const CallExpr *Call,
-                                       const IdentifierInfo *FnName) {
+                                       CheckedMemoryFunction CMF,
+                                       IdentifierInfo *FnName) {
   // It is possible to have a non-standard definition of memset.  Validate
-  // we have the proper number of arguments, and if not, abort further
-  // checking.
-  if (Call->getNumArgs() != 3)
+  // we have enough arguments, and if not, abort further checking.
+  if (Call->getNumArgs() < 3)
     return;
 
-  unsigned LastArg = FnName->isStr("memset")? 1 : 2;
+  unsigned LastArg = (CMF == CMF_Memset? 1 : 2);
   const Expr *LenExpr = Call->getArg(2)->IgnoreParenImpCasts();
 
   // We have special checking when the length is a sizeof expression.
@@ -1934,8 +1963,7 @@
       // Always complain about dynamic classes.
       if (isDynamicClassType(PointeeTy))
         DiagID = diag::warn_dyn_class_memaccess;
-      else if (PointeeTy.hasNonTrivialObjCLifetime() && 
-               !FnName->isStr("memset"))
+      else if (PointeeTy.hasNonTrivialObjCLifetime() && CMF != CMF_Memset)
         DiagID = diag::warn_arc_object_memaccess;
       else
         continue;

Modified: cfe/trunk/test/SemaCXX/warn-bad-memaccess.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/SemaCXX/warn-bad-memaccess.cpp?rev=133173&r1=133172&r2=133173&view=diff
==============================================================================
--- cfe/trunk/test/SemaCXX/warn-bad-memaccess.cpp (original)
+++ cfe/trunk/test/SemaCXX/warn-bad-memaccess.cpp Thu Jun 16 12:56:04 2011
@@ -38,6 +38,46 @@
   memcpy(0, &x1, sizeof x1); // \
       // expected-warning{{source of this 'memcpy' call is a pointer to dynamic class}} \
       // expected-note {{explicitly cast the pointer to silence this warning}}
+
+  __builtin_memset(&x1, 0, sizeof x1); // \
+      // expected-warning {{destination for this '__builtin_memset' call is a pointer to dynamic class}} \
+      // expected-note {{explicitly cast the pointer to silence this warning}}
+  __builtin_memset(&x2, 0, sizeof x2); // \
+      // expected-warning {{destination for this '__builtin_memset' call is a pointer to dynamic class}} \
+      // expected-note {{explicitly cast the pointer to silence this warning}}
+
+  __builtin_memmove(&x1, 0, sizeof x1); // \
+      // expected-warning{{destination for this '__builtin_memmove' call is a pointer to dynamic class}} \
+      // expected-note {{explicitly cast the pointer to silence this warning}}
+  __builtin_memmove(0, &x1, sizeof x1); // \
+      // expected-warning{{source of this '__builtin_memmove' call is a pointer to dynamic class}} \
+      // expected-note {{explicitly cast the pointer to silence this warning}}
+  __builtin_memcpy(&x1, 0, sizeof x1); // \
+      // expected-warning{{destination for this '__builtin_memcpy' call is a pointer to dynamic class}} \
+      // expected-note {{explicitly cast the pointer to silence this warning}}
+  __builtin_memcpy(0, &x1, sizeof x1); // \
+      // expected-warning{{source of this '__builtin_memcpy' call is a pointer to dynamic class}} \
+      // expected-note {{explicitly cast the pointer to silence this warning}}
+
+  __builtin___memset_chk(&x1, 0, sizeof x1, sizeof x1); //                    \
+      // expected-warning {{destination for this '__builtin___memset_chk' call is a pointer to dynamic class}} \
+      // expected-note {{explicitly cast the pointer to silence this warning}}
+  __builtin___memset_chk(&x2, 0, sizeof x2, sizeof x2); //                    \
+      // expected-warning {{destination for this '__builtin___memset_chk' call is a pointer to dynamic class}} \
+      // expected-note {{explicitly cast the pointer to silence this warning}}
+
+  __builtin___memmove_chk(&x1, 0, sizeof x1, sizeof x1); //                   \
+      // expected-warning{{destination for this '__builtin___memmove_chk' call is a pointer to dynamic class}} \
+      // expected-note {{explicitly cast the pointer to silence this warning}}
+  __builtin___memmove_chk(0, &x1, sizeof x1, sizeof x1); //                   \
+      // expected-warning{{source of this '__builtin___memmove_chk' call is a pointer to dynamic class}} \
+      // expected-note {{explicitly cast the pointer to silence this warning}}
+  __builtin___memcpy_chk(&x1, 0, sizeof x1, sizeof x1); //                    \
+      // expected-warning{{destination for this '__builtin___memcpy_chk' call is a pointer to dynamic class}} \
+      // expected-note {{explicitly cast the pointer to silence this warning}}
+  __builtin___memcpy_chk(0, &x1, sizeof x1, sizeof x1); //                    \
+      // expected-warning{{source of this '__builtin___memcpy_chk' call is a pointer to dynamic class}} \
+      // expected-note {{explicitly cast the pointer to silence this warning}}
 }
 
 void test_nowarn(void *void_ptr) {
@@ -68,3 +108,5 @@
     N::memset(&x1, 0, sizeof x1);
   }
 }
+
+





More information about the cfe-commits mailing list