[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