[cfe-commits] r132996 - in /cfe/trunk: include/clang/Basic/DiagnosticSemaKinds.td lib/Sema/SemaChecking.cpp test/SemaCXX/warn-memset-bad-sizeof.cpp

Nico Weber thakis at chromium.org
Tue Jun 14 09:31:38 PDT 2011


Forgot to say in the revision log: This is for pr9977.

On Tue, Jun 14, 2011 at 9:14 AM, Nico Weber <nicolasweber at gmx.de> wrote:
> Author: nico
> Date: Tue Jun 14 11:14:58 2011
> New Revision: 132996
>
> URL: http://llvm.org/viewvc/llvm-project?rev=132996&view=rev
> Log:
> Warn on memset(ptr, 0, sizeof(ptr)). Diagnostic wording by Jordy Rose.
>
>
> Added:
>    cfe/trunk/test/SemaCXX/warn-memset-bad-sizeof.cpp
> Modified:
>    cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td
>    cfe/trunk/lib/Sema/SemaChecking.cpp
>
> Modified: cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td
> URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td?rev=132996&r1=132995&r2=132996&view=diff
> ==============================================================================
> --- cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td (original)
> +++ cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td Tue Jun 14 11:14:58 2011
> @@ -269,6 +269,9 @@
>   InGroup<DiagGroup<"dynamic-class-memaccess">>;
>  def note_bad_memaccess_silence : Note<
>   "explicitly cast the pointer to silence this warning">;
> +def warn_sizeof_pointer : Warning<
> +  "the argument to sizeof is pointer type %0, expected %1 to match "
> +  "%select{first|second}2 argument to %3">;
>
>  /// main()
>  // static/inline main() are not errors in C, just in C++.
>
> Modified: cfe/trunk/lib/Sema/SemaChecking.cpp
> URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaChecking.cpp?rev=132996&r1=132995&r2=132996&view=diff
> ==============================================================================
> --- cfe/trunk/lib/Sema/SemaChecking.cpp (original)
> +++ cfe/trunk/lib/Sema/SemaChecking.cpp Tue Jun 14 11:14:58 2011
> @@ -1812,6 +1812,20 @@
>   return false;
>  }
>
> +/// \brief If E is a sizeof expression, returns the expression's type in
> +/// OutType.
> +static bool sizeofExprType(const Expr* E, QualType *OutType) {
> +  if (const UnaryExprOrTypeTraitExpr *SizeOf =
> +      dyn_cast<UnaryExprOrTypeTraitExpr>(E)) {
> +    if (SizeOf->getKind() != clang::UETT_SizeOf)
> +      return false;
> +
> +    *OutType = SizeOf->getTypeOfArgument();
> +    return true;
> +  }
> +  return false;
> +}
> +
>  /// \brief Check for dangerous or invalid arguments to memset().
>  ///
>  /// This issues warnings on known problematic, dangerous or unspecified
> @@ -1827,8 +1841,10 @@
>     return;
>
>   unsigned LastArg = FnName->isStr("memset")? 1 : 2;
> +  const Expr *LenExpr = Call->getArg(2)->IgnoreParenImpCasts();
>   for (unsigned ArgIdx = 0; ArgIdx != LastArg; ++ArgIdx) {
>     const Expr *Dest = Call->getArg(ArgIdx)->IgnoreParenImpCasts();
> +    SourceRange ArgRange = Call->getArg(ArgIdx)->getSourceRange();
>
>     QualType DestTy = Dest->getType();
>     if (const PointerType *DestPtrTy = DestTy->getAs<PointerType>()) {
> @@ -1836,6 +1852,17 @@
>       if (PointeeTy->isVoidType())
>         continue;
>
> +      // Catch "memset(p, 0, sizeof(p))" -- needs to be sizeof(*p).
> +      QualType SizeofTy;
> +      if (sizeofExprType(LenExpr, &SizeofTy) &&
> +          Context.typesAreCompatible(SizeofTy, DestTy)) {
> +        // Note: This complains about sizeof(typeof(p)) as well.
> +        SourceLocation loc = LenExpr->getSourceRange().getBegin();
> +        Diag(loc, diag::warn_sizeof_pointer)
> +            << SizeofTy <<  PointeeTy << ArgIdx << FnName;
> +        break;
> +      }
> +
>       // Always complain about dynamic classes.
>       if (isDynamicClassType(PointeeTy)) {
>         DiagRuntimeBehavior(
> @@ -1847,7 +1874,6 @@
>         continue;
>       }
>
> -      SourceRange ArgRange = Call->getArg(ArgIdx)->getSourceRange();
>       DiagRuntimeBehavior(
>         Dest->getExprLoc(), Dest,
>         PDiag(diag::note_bad_memaccess_silence)
>
> Added: cfe/trunk/test/SemaCXX/warn-memset-bad-sizeof.cpp
> URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/SemaCXX/warn-memset-bad-sizeof.cpp?rev=132996&view=auto
> ==============================================================================
> --- cfe/trunk/test/SemaCXX/warn-memset-bad-sizeof.cpp (added)
> +++ cfe/trunk/test/SemaCXX/warn-memset-bad-sizeof.cpp Tue Jun 14 11:14:58 2011
> @@ -0,0 +1,97 @@
> +// RUN: %clang_cc1 -fsyntax-only -verify %s
> +//
> +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);
> +
> +struct S {int a, b, c, d;};
> +typedef S* PS;
> +
> +struct Foo {};
> +typedef const Foo& CFooRef;
> +typedef const Foo CFoo;
> +typedef volatile Foo VFoo;
> +typedef const volatile Foo CVFoo;
> +
> +typedef double Mat[4][4];
> +
> +template <class Dest, class Source>
> +inline Dest bit_cast(const Source& source) {
> +  Dest dest;
> +  memcpy(&dest, &source, sizeof(dest));
> +  return dest;
> +}
> +
> +// http://www.lysator.liu.se/c/c-faq/c-2.html#2-6
> +void f(char fake_array[8], Mat m, const Foo& const_foo) {
> +  S s;
> +  S* ps = &s;
> +  PS ps2 = &s;
> +  char arr[5];
> +  char* parr[5];
> +  Foo foo;
> +
> +  /* Should warn */
> +  memset(&s, 0, sizeof(&s));  // \
> +      // expected-warning {{the argument to sizeof is pointer type 'S *', expected 'S' to match first argument to 'memset'}}
> +  memset(ps, 0, sizeof(ps));  // \
> +      // expected-warning {{the argument to sizeof is pointer type 'S *', expected 'S' to match first argument to 'memset'}}
> +  memset(ps2, 0, sizeof(ps2));  // \
> +      // expected-warning {{the argument to sizeof is pointer type 'PS' (aka 'S *'), expected 'S' to match first argument to 'memset'}}
> +  memset(ps2, 0, sizeof(typeof(ps2)));  // \
> +      // expected-warning {{the argument to sizeof is pointer type 'typeof (ps2)' (aka 'S *'), expected 'S' to match first argument to 'memset'}}
> +  memset(ps2, 0, sizeof(PS));  // \
> +      // expected-warning {{the argument to sizeof is pointer type 'PS' (aka 'S *'), expected 'S' to match first argument to 'memset'}}
> +  memset(fake_array, 0, sizeof(fake_array));  // \
> +      // expected-warning {{the argument to sizeof is pointer type 'char *', expected 'char' to match first argument to 'memset'}}
> +
> +  memcpy(&s, 0, sizeof(&s));  // \
> +      // expected-warning {{the argument to sizeof is pointer type 'S *', expected 'S' to match first argument to 'memcpy'}}
> +  memcpy(0, &s, sizeof(&s));  // \
> +      // expected-warning {{the argument to sizeof is pointer type 'S *', expected 'S' to match second argument to 'memcpy'}}
> +
> +  /* Shouldn't warn */
> +  memset((void*)&s, 0, sizeof(&s));
> +  memset(&s, 0, sizeof(s));
> +  memset(&s, 0, sizeof(S));
> +  memset(&s, 0, sizeof(const S));
> +  memset(&s, 0, sizeof(volatile S));
> +  memset(&s, 0, sizeof(volatile const S));
> +  memset(&foo, 0, sizeof(CFoo));
> +  memset(&foo, 0, sizeof(VFoo));
> +  memset(&foo, 0, sizeof(CVFoo));
> +  memset(ps, 0, sizeof(*ps));
> +  memset(ps2, 0, sizeof(*ps2));
> +  memset(ps2, 0, sizeof(typeof(*ps2)));
> +  memset(arr, 0, sizeof(arr));
> +  memset(parr, 0, sizeof(parr));
> +
> +  memcpy(&foo, &const_foo, sizeof(Foo));
> +  memcpy((void*)&s, 0, sizeof(&s));
> +  memcpy(0, (void*)&s, sizeof(&s));
> +
> +  CFooRef cfoo = foo;
> +  memcpy(&foo, &cfoo, sizeof(Foo));
> +
> +  memcpy(0, &arr, sizeof(arr));
> +  typedef char Buff[8];
> +  memcpy(0, &arr, sizeof(Buff));
> +
> +  unsigned char* puc;
> +  bit_cast<char*>(puc);
> +
> +  float* pf;
> +  bit_cast<int*>(pf);
> +
> +  int iarr[14];
> +  memset(&iarr[0], 0, sizeof iarr);
> +
> +  int* iparr[14];
> +  memset(&iparr[0], 0, sizeof iparr);
> +
> +  memset(m, 0, sizeof(Mat));
> +
> +  // Copy to raw buffer shouldn't warn either
> +  memcpy(&foo, &arr, sizeof(Foo));
> +  memcpy(&arr, &foo, sizeof(Foo));
> +}
>
>
> _______________________________________________
> cfe-commits mailing list
> cfe-commits at cs.uiuc.edu
> http://lists.cs.uiuc.edu/mailman/listinfo/cfe-commits
>




More information about the cfe-commits mailing list