[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