diff options
author | Douglas Gregor <dgregor@apple.com> | 2011-06-16 17:56:04 +0000 |
---|---|---|
committer | Douglas Gregor <dgregor@apple.com> | 2011-06-16 17:56:04 +0000 |
commit | 707a23e8b87410332b55bb4534fa1c799edef38a (patch) | |
tree | 456b272b77e0288d0e3618beaf9463959e53e62c /lib/Sema/SemaChecking.cpp | |
parent | b1f7d2496a2916cfad17633e403151dd09118821 (diff) |
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>.
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@133173 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'lib/Sema/SemaChecking.cpp')
-rw-r--r-- | lib/Sema/SemaChecking.cpp | 52 |
1 files changed, 40 insertions, 12 deletions
diff --git a/lib/Sema/SemaChecking.cpp b/lib/Sema/SemaChecking.cpp index 81506bf571..54900e0cf1 100644 --- a/lib/Sema/SemaChecking.cpp +++ b/lib/Sema/SemaChecking.cpp @@ -320,12 +320,41 @@ bool Sema::CheckFunctionCall(FunctionDecl *FDecl, CallExpr *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); + 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 @@ static QualType getSizeOfArgType(const Expr* E) { /// /// \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 @@ void Sema::CheckMemsetcpymoveArguments(const CallExpr *Call, // 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; |