[cfe-commits] r130786 - in /cfe/trunk: include/clang/Basic/DiagnosticSemaKinds.td include/clang/Sema/Sema.h lib/Sema/SemaChecking.cpp test/SemaCXX/warn-non-pod-memset.cpp
Douglas Gregor
dgregor at apple.com
Tue May 3 13:37:33 PDT 2011
Author: dgregor
Date: Tue May 3 15:37:33 2011
New Revision: 130786
URL: http://llvm.org/viewvc/llvm-project?rev=130786&view=rev
Log:
Extend -Wnon-pod-memset to also encompass memcpy() and memmove(),
checking both the source and the destination operands, renaming the
warning group to -Wnon-pod-memaccess and tweaking the diagnostic text
in the process.
Modified:
cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td
cfe/trunk/include/clang/Sema/Sema.h
cfe/trunk/lib/Sema/SemaChecking.cpp
cfe/trunk/test/SemaCXX/warn-non-pod-memset.cpp
Modified: cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td?rev=130786&r1=130785&r2=130786&view=diff
==============================================================================
--- cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td (original)
+++ cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td Tue May 3 15:37:33 2011
@@ -261,13 +261,15 @@
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_memset : Warning<
- "destination for this memset call is a pointer to a dynamic class %0">,
- InGroup<DiagGroup<"non-pod-memset">>;
-def warn_non_pod_memset : Warning<
- "destination for this memset call is a pointer to a non-POD type %0">,
- InGroup<DiagGroup<"non-pod-memset">>, DefaultIgnore;
-def note_non_pod_memset_silence : Note<
+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">,
+ InGroup<DiagGroup<"non-pod-memaccess">>;
+def warn_non_pod_memaccess : Warning<
+ "%select{destination for|source of}0 this %1 call is a pointer to non-POD "
+ "type %2">,
+ InGroup<DiagGroup<"non-pod-memaccess">>, DefaultIgnore;
+def note_non_pod_memaccess_silence : Note<
"explicitly cast the pointer to silence this warning">;
/// main()
Modified: cfe/trunk/include/clang/Sema/Sema.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Sema/Sema.h?rev=130786&r1=130785&r2=130786&view=diff
==============================================================================
--- cfe/trunk/include/clang/Sema/Sema.h (original)
+++ cfe/trunk/include/clang/Sema/Sema.h Tue May 3 15:37:33 2011
@@ -5552,7 +5552,8 @@
unsigned format_idx, unsigned firstDataArg,
bool isPrintf);
- void CheckMemsetArguments(const CallExpr *Call);
+ void CheckMemsetcpymoveArguments(const CallExpr *Call,
+ const 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=130786&r1=130785&r2=130786&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/SemaChecking.cpp (original)
+++ cfe/trunk/lib/Sema/SemaChecking.cpp Tue May 3 15:37:33 2011
@@ -318,11 +318,13 @@
TheCall->getCallee()->getLocStart());
}
- // Memset handling
- if (FnInfo->isStr("memset") &&
- FDecl->getLinkage() == ExternalLinkage &&
- (!getLangOptions().CPlusPlus || FDecl->isExternC()))
- CheckMemsetArguments(TheCall);
+ // 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);
+ }
return false;
}
@@ -1813,45 +1815,51 @@
/// \brief Check for dangerous or invalid arguments to memset().
///
/// This issues warnings on known problematic or dangerous or unspecified
-/// arguments to the standard 'memset' function call.
+/// arguments to the standard 'memset', 'memcpy', and 'memmove' function calls.
///
/// \param Call The call expression to diagnose.
-void Sema::CheckMemsetArguments(const CallExpr *Call) {
+void Sema::CheckMemsetcpymoveArguments(const CallExpr *Call,
+ const 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)
return;
- const Expr *Dest = Call->getArg(0)->IgnoreParenImpCasts();
-
- QualType DestTy = Dest->getType();
- if (const PointerType *DestPtrTy = DestTy->getAs<PointerType>()) {
- QualType PointeeTy = DestPtrTy->getPointeeType();
- if (PointeeTy->isVoidType())
- return;
-
- unsigned DiagID = 0;
- // Always complain about dynamic classes.
- if (isDynamicClassType(PointeeTy))
- DiagID = diag::warn_dyn_class_memset;
- // Check the C++11 POD definition regardless of language mode; it is more
- // relaxed than earlier definitions and we don't want spurious warnings.
- else if (!PointeeTy->isCXX11PODType())
- DiagID = diag::warn_non_pod_memset;
- else
- return;
+ unsigned LastArg = FnName->isStr("memset")? 1 : 2;
+ for (unsigned ArgIdx = 0; ArgIdx != LastArg; ++ArgIdx) {
+ const Expr *Dest = Call->getArg(ArgIdx)->IgnoreParenImpCasts();
+
+ QualType DestTy = Dest->getType();
+ if (const PointerType *DestPtrTy = DestTy->getAs<PointerType>()) {
+ QualType PointeeTy = DestPtrTy->getPointeeType();
+ if (PointeeTy->isVoidType())
+ continue;
+
+ unsigned DiagID = 0;
+ // Always complain about dynamic classes.
+ if (isDynamicClassType(PointeeTy))
+ DiagID = diag::warn_dyn_class_memaccess;
+ // Check the C++11 POD definition regardless of language mode; it is more
+ // relaxed than earlier definitions and we don't want spurious warnings.
+ else if (!PointeeTy->isCXX11PODType())
+ DiagID = diag::warn_non_pod_memaccess;
+ else
+ continue;
- DiagRuntimeBehavior(
- Dest->getExprLoc(), Dest,
- PDiag(DiagID)
- << PointeeTy << Call->getCallee()->getSourceRange());
-
- SourceRange ArgRange = Call->getArg(0)->getSourceRange();
- DiagRuntimeBehavior(
- Dest->getExprLoc(), Dest,
- PDiag(diag::note_non_pod_memset_silence)
- << FixItHint::CreateInsertion(ArgRange.getBegin(), "(void*)"));
+ DiagRuntimeBehavior(
+ Dest->getExprLoc(), Dest,
+ PDiag(DiagID)
+ << ArgIdx << FnName << PointeeTy
+ << Call->getCallee()->getSourceRange());
+
+ SourceRange ArgRange = Call->getArg(0)->getSourceRange();
+ DiagRuntimeBehavior(
+ Dest->getExprLoc(), Dest,
+ PDiag(diag::note_non_pod_memaccess_silence)
+ << FixItHint::CreateInsertion(ArgRange.getBegin(), "(void*)"));
+ break;
+ }
}
}
Modified: cfe/trunk/test/SemaCXX/warn-non-pod-memset.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/SemaCXX/warn-non-pod-memset.cpp?rev=130786&r1=130785&r2=130786&view=diff
==============================================================================
--- cfe/trunk/test/SemaCXX/warn-non-pod-memset.cpp (original)
+++ cfe/trunk/test/SemaCXX/warn-non-pod-memset.cpp Tue May 3 15:37:33 2011
@@ -1,6 +1,8 @@
-// RUN: %clang_cc1 -fsyntax-only -Wnon-pod-memset -verify %s
+// RUN: %clang_cc1 -fsyntax-only -Wnon-pod-memaccess -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);
// Several POD types that should not warn.
struct S1 {} s1;
@@ -24,19 +26,32 @@
void test_warn() {
memset(&x1, 0, sizeof x1); // \
- // expected-warning {{destination for this memset call is a pointer to a non-POD type}} \
+ // expected-warning {{destination for this 'memset' call is a pointer to non-POD type}} \
// expected-note {{explicitly cast the pointer to silence this warning}}
memset(&x2, 0, sizeof x2); // \
- // expected-warning {{destination for this memset call is a pointer to a non-POD type}} \
+ // expected-warning {{destination for this 'memset' call is a pointer to non-POD type}} \
// expected-note {{explicitly cast the pointer to silence this warning}}
memset(&x3, 0, sizeof x3); // \
- // expected-warning {{destination for this memset call is a pointer to a dynamic class}} \
+ // expected-warning {{destination for this 'memset' call is a pointer to dynamic class}} \
// expected-note {{explicitly cast the pointer to silence this warning}}
memset(&x4, 0, sizeof x4); // \
- // expected-warning {{destination for this memset call is a pointer to a non-POD type}} \
+ // expected-warning {{destination for this 'memset' call is a pointer to non-POD type}} \
// expected-note {{explicitly cast the pointer to silence this warning}}
memset(&x5, 0, sizeof x5); // \
- // expected-warning {{destination for this memset call is a pointer to a dynamic class}} \
+ // expected-warning {{destination for this 'memset' call is a pointer to dynamic class}} \
+ // 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 non-POD type 'struct X1'}} \
+ // 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 non-POD type 'struct X1'}} \
+ // 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 non-POD type 'struct X1'}} \
+ // 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 non-POD type 'struct X1'}} \
// expected-note {{explicitly cast the pointer to silence this warning}}
}
More information about the cfe-commits
mailing list