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.)
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@148267 91177308-0d34-0410-b5e6-96231b3b80d8
diff --git a/include/clang/AST/Decl.h b/include/clang/AST/Decl.h
index 5c6b447..4016c20 100644
--- a/include/clang/AST/Decl.h
+++ b/include/clang/AST/Decl.h
@@ -1986,26 +1986,11 @@
/// 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()); }
diff --git a/include/clang/Basic/Builtins.def b/include/clang/Basic/Builtins.def
index 5942e53..e3e2d7c 100644
--- a/include/clang/Basic/Builtins.def
+++ b/include/clang/Basic/Builtins.def
@@ -631,9 +631,12 @@
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(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)
diff --git a/include/clang/Sema/Sema.h b/include/clang/Sema/Sema.h
index c4af625..242af88 100644
--- a/include/clang/Sema/Sema.h
+++ b/include/clang/Sema/Sema.h
@@ -6315,7 +6315,7 @@
bool isPrintf);
void CheckMemaccessArguments(const CallExpr *Call,
- FunctionDecl::MemoryFunctionKind CMF,
+ unsigned BId,
IdentifierInfo *FnName);
void CheckStrlcpycatArguments(const CallExpr *Call,
diff --git a/lib/AST/Decl.cpp b/lib/AST/Decl.cpp
index 96766dc..1951363 100644
--- a/lib/AST/Decl.cpp
+++ b/lib/AST/Decl.cpp
@@ -2290,80 +2290,83 @@
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;
}
//===----------------------------------------------------------------------===//
diff --git a/lib/Sema/SemaChecking.cpp b/lib/Sema/SemaChecking.cpp
index 77c5717..af0eedd 100644
--- a/lib/Sema/SemaChecking.cpp
+++ b/lib/Sema/SemaChecking.cpp
@@ -482,15 +482,15 @@
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 @@
///
/// \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 @@
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 @@
}
// 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)