Use Builtin ID as the return value

for FunctionDecl::getMemoryFunctionKind().

This is a follow up on the Chris's review for r148142: We don't want to
pollute FunctionDecl with an extra enum. (To make this work, added
memcmp and family to the library builtins.)

llvm-svn: 148267
This commit is contained in:
Anna Zaks 2012-01-17 00:37:07 +00:00
parent 3666d2c160
commit 2212270e71
5 changed files with 67 additions and 62 deletions

View File

@ -1986,26 +1986,11 @@ public:
/// definition of a member function.
virtual bool isOutOfLine() const;
/// \brief Enumeration used to identify memory setting or copying functions
/// identified by getMemoryFunctionKind().
enum MemoryFunctionKind {
MFK_Memset,
MFK_Memcpy,
MFK_Memmove,
MFK_Memcmp,
MFK_Strncpy,
MFK_Strncmp,
MFK_Strncasecmp,
MFK_Strncat,
MFK_Strndup,
MFK_Strlcpy,
MFK_Strlcat,
MFK_Invalid
};
/// \brief If the given function is a memory copy or setting function, return
/// it's kind. If the function is not a memory function, returns MFK_Invalid.
MemoryFunctionKind getMemoryFunctionKind();
/// \brief Identify a memory copying or setting function.
/// If the given function is a memory copy or setting function, returns
/// the corresponding Builtin ID. If the function is not a memory function,
/// returns 0.
unsigned getMemoryFunctionKind();
// Implement isa/cast/dyncast/etc.
static bool classof(const Decl *D) { return classofKind(D->getKind()); }

View File

@ -631,9 +631,12 @@ LIBBUILTIN(malloc, "v*z", "f", "stdlib.h", ALL_LANGUAGES)
LIBBUILTIN(realloc, "v*v*z", "f", "stdlib.h", ALL_LANGUAGES)
// C99 string.h
LIBBUILTIN(memcpy, "v*v*vC*z", "f", "string.h", ALL_LANGUAGES)
LIBBUILTIN(memcmp, "ivC*vC*z", "f", "string.h", ALL_LANGUAGES)
LIBBUILTIN(memmove, "v*v*vC*z", "f", "string.h", ALL_LANGUAGES)
LIBBUILTIN(strcpy, "c*c*cC*", "f", "string.h", ALL_LANGUAGES)
LIBBUILTIN(strncpy, "c*c*cC*z", "f", "string.h", ALL_LANGUAGES)
LIBBUILTIN(strcmp, "icC*cC*", "f", "string.h", ALL_LANGUAGES)
LIBBUILTIN(strncmp, "icC*cC*z", "f", "string.h", ALL_LANGUAGES)
LIBBUILTIN(strcat, "c*c*cC*", "f", "string.h", ALL_LANGUAGES)
LIBBUILTIN(strncat, "c*c*cC*z", "f", "string.h", ALL_LANGUAGES)
LIBBUILTIN(strxfrm, "zc*cC*z", "f", "string.h", ALL_LANGUAGES)
@ -678,6 +681,8 @@ LIBBUILTIN(strndup, "c*cC*z", "f", "string.h", ALL_LANGUAGES)
LIBBUILTIN(index, "c*cC*i", "f", "strings.h", ALL_LANGUAGES)
LIBBUILTIN(rindex, "c*cC*i", "f", "strings.h", ALL_LANGUAGES)
LIBBUILTIN(bzero, "vv*z", "f", "strings.h", ALL_LANGUAGES)
LIBBUILTIN(strcasecmp, "icC*cC*", "f", "strings.h", ALL_LANGUAGES)
LIBBUILTIN(strncasecmp, "icC*cC*z", "f", "strings.h", ALL_LANGUAGES)
// POSIX unistd.h
LIBBUILTIN(_exit, "vi", "fr", "unistd.h", ALL_LANGUAGES)
LIBBUILTIN(vfork, "i", "fj", "unistd.h", ALL_LANGUAGES)

View File

@ -6315,7 +6315,7 @@ private:
bool isPrintf);
void CheckMemaccessArguments(const CallExpr *Call,
FunctionDecl::MemoryFunctionKind CMF,
unsigned BId,
IdentifierInfo *FnName);
void CheckStrlcpycatArguments(const CallExpr *Call,

View File

@ -2290,80 +2290,83 @@ SourceRange FunctionDecl::getSourceRange() const {
return SourceRange(getOuterLocStart(), EndRangeLoc);
}
FunctionDecl::MemoryFunctionKind FunctionDecl::getMemoryFunctionKind() {
unsigned FunctionDecl::getMemoryFunctionKind() {
IdentifierInfo *FnInfo = getIdentifier();
if (!FnInfo)
return MFK_Invalid;
return 0;
// Builtin handling.
switch (getBuiltinID()) {
case Builtin::BI__builtin_memset:
case Builtin::BI__builtin___memset_chk:
case Builtin::BImemset:
return MFK_Memset;
return Builtin::BImemset;
case Builtin::BI__builtin_memcpy:
case Builtin::BI__builtin___memcpy_chk:
case Builtin::BImemcpy:
return MFK_Memcpy;
return Builtin::BImemcpy;
case Builtin::BI__builtin_memmove:
case Builtin::BI__builtin___memmove_chk:
case Builtin::BImemmove:
return MFK_Memmove;
return Builtin::BImemmove;
case Builtin::BIstrlcpy:
return MFK_Strlcpy;
return Builtin::BIstrlcpy;
case Builtin::BIstrlcat:
return MFK_Strlcat;
return Builtin::BIstrlcat;
case Builtin::BI__builtin_memcmp:
return MFK_Memcmp;
case Builtin::BImemcmp:
return Builtin::BImemcmp;
case Builtin::BI__builtin_strncpy:
case Builtin::BI__builtin___strncpy_chk:
case Builtin::BIstrncpy:
return MFK_Strncpy;
return Builtin::BIstrncpy;
case Builtin::BI__builtin_strncmp:
return MFK_Strncmp;
case Builtin::BIstrncmp:
return Builtin::BIstrncmp;
case Builtin::BI__builtin_strncasecmp:
return MFK_Strncasecmp;
case Builtin::BIstrncasecmp:
return Builtin::BIstrncasecmp;
case Builtin::BI__builtin_strncat:
case Builtin::BIstrncat:
return MFK_Strncat;
return Builtin::BIstrncat;
case Builtin::BI__builtin_strndup:
case Builtin::BIstrndup:
return MFK_Strndup;
return Builtin::BIstrndup;
default:
if (isExternC()) {
if (FnInfo->isStr("memset"))
return MFK_Memset;
return Builtin::BImemset;
else if (FnInfo->isStr("memcpy"))
return MFK_Memcpy;
return Builtin::BImemcpy;
else if (FnInfo->isStr("memmove"))
return MFK_Memmove;
return Builtin::BImemmove;
else if (FnInfo->isStr("memcmp"))
return MFK_Memcmp;
return Builtin::BImemcmp;
else if (FnInfo->isStr("strncpy"))
return MFK_Strncpy;
return Builtin::BIstrncpy;
else if (FnInfo->isStr("strncmp"))
return MFK_Strncmp;
return Builtin::BIstrncmp;
else if (FnInfo->isStr("strncasecmp"))
return MFK_Strncasecmp;
return Builtin::BIstrncasecmp;
else if (FnInfo->isStr("strncat"))
return MFK_Strncat;
return Builtin::BIstrncat;
else if (FnInfo->isStr("strndup"))
return MFK_Strndup;
return Builtin::BIstrndup;
}
break;
}
return MFK_Invalid;
return 0;
}
//===----------------------------------------------------------------------===//

View File

@ -482,15 +482,15 @@ bool Sema::CheckFunctionCall(FunctionDecl *FDecl, CallExpr *TheCall) {
TheCall->getCallee()->getLocStart());
}
FunctionDecl::MemoryFunctionKind CMF = FDecl->getMemoryFunctionKind();
if (CMF == FunctionDecl::MFK_Invalid)
unsigned CMId = FDecl->getMemoryFunctionKind();
if (CMId == 0)
return false;
// Handle memory setting and copying functions.
if (CMF == FunctionDecl::MFK_Strlcpy || CMF == FunctionDecl::MFK_Strlcat)
if (CMId == Builtin::BIstrlcpy || CMId == Builtin::BIstrlcat)
CheckStrlcpycatArguments(TheCall, FnInfo);
else
CheckMemaccessArguments(TheCall, CMF, FnInfo);
CheckMemaccessArguments(TheCall, CMId, FnInfo);
return false;
}
@ -2433,17 +2433,19 @@ static QualType getSizeOfArgType(const Expr* E) {
///
/// \param Call The call expression to diagnose.
void Sema::CheckMemaccessArguments(const CallExpr *Call,
FunctionDecl::MemoryFunctionKind CMF,
unsigned BId,
IdentifierInfo *FnName) {
assert(BId != 0);
// It is possible to have a non-standard definition of memset. Validate
// we have enough arguments, and if not, abort further checking.
unsigned ExpectedNumArgs = (CMF == FunctionDecl::MFK_Strndup ? 2 : 3);
unsigned ExpectedNumArgs = (BId == Builtin::BIstrndup ? 2 : 3);
if (Call->getNumArgs() < ExpectedNumArgs)
return;
unsigned LastArg = (CMF == FunctionDecl::MFK_Memset ||
CMF == FunctionDecl::MFK_Strndup ? 1 : 2);
unsigned LenArg = (CMF == FunctionDecl::MFK_Strndup ? 1 : 2);
unsigned LastArg = (BId == Builtin::BImemset ||
BId == Builtin::BIstrndup ? 1 : 2);
unsigned LenArg = (BId == Builtin::BIstrndup ? 1 : 2);
const Expr *LenExpr = Call->getArg(LenArg)->IgnoreParenImpCasts();
// We have special checking when the length is a sizeof expression.
@ -2488,7 +2490,7 @@ void Sema::CheckMemaccessArguments(const CallExpr *Call,
ActionIdx = 2; // If the pointee's size is sizeof(char),
// suggest an explicit length.
unsigned DestSrcSelect =
(CMF == FunctionDecl::MFK_Strndup ? 1 : ArgIdx);
(BId == Builtin::BIstrndup ? 1 : ArgIdx);
DiagRuntimeBehavior(SizeOfArg->getExprLoc(), Dest,
PDiag(diag::warn_sizeof_pointer_expr_memaccess)
<< FnName << DestSrcSelect << ActionIdx
@ -2514,19 +2516,29 @@ void Sema::CheckMemaccessArguments(const CallExpr *Call,
}
// Always complain about dynamic classes.
if (isDynamicClassType(PointeeTy))
if (isDynamicClassType(PointeeTy)) {
unsigned OperationType = 0;
// "overwritten" if we're warning about the destination for any call
// but memcmp; otherwise a verb appropriate to the call.
if (ArgIdx != 0 || BId == Builtin::BImemcmp) {
if (BId == Builtin::BImemcpy)
OperationType = 1;
else if(BId == Builtin::BImemmove)
OperationType = 2;
else if (BId == Builtin::BImemcmp)
OperationType = 3;
}
DiagRuntimeBehavior(
Dest->getExprLoc(), Dest,
PDiag(diag::warn_dyn_class_memaccess)
<< (CMF == FunctionDecl::MFK_Memcmp ? ArgIdx + 2 : ArgIdx)
<< (BId == Builtin::BImemcmp ? ArgIdx + 2 : ArgIdx)
<< FnName << PointeeTy
// "overwritten" if we're warning about the destination for any call
// but memcmp; otherwise a verb appropriate to the call.
<< (ArgIdx == 0 &&
CMF != FunctionDecl::MFK_Memcmp ? 0 : (unsigned)CMF)
<< OperationType
<< Call->getCallee()->getSourceRange());
else if (PointeeTy.hasNonTrivialObjCLifetime() &&
CMF != FunctionDecl::MFK_Memset)
} else if (PointeeTy.hasNonTrivialObjCLifetime() &&
BId != Builtin::BImemset)
DiagRuntimeBehavior(
Dest->getExprLoc(), Dest,
PDiag(diag::warn_arc_object_memaccess)