summaryrefslogtreecommitdiffstats
path: root/contrib/llvm/tools/clang/lib/Sema/SemaChecking.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'contrib/llvm/tools/clang/lib/Sema/SemaChecking.cpp')
-rw-r--r--contrib/llvm/tools/clang/lib/Sema/SemaChecking.cpp96
1 files changed, 59 insertions, 37 deletions
diff --git a/contrib/llvm/tools/clang/lib/Sema/SemaChecking.cpp b/contrib/llvm/tools/clang/lib/Sema/SemaChecking.cpp
index 5b645df..7e22b33 100644
--- a/contrib/llvm/tools/clang/lib/Sema/SemaChecking.cpp
+++ b/contrib/llvm/tools/clang/lib/Sema/SemaChecking.cpp
@@ -318,9 +318,13 @@ bool Sema::CheckFunctionCall(FunctionDecl *FDecl, CallExpr *TheCall) {
TheCall->getCallee()->getLocStart());
}
- // Memset handling
- if (FnInfo->isStr("memset"))
- 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;
}
@@ -1832,49 +1836,59 @@ void Sema::CheckFormatString(const StringLiteral *FExpr,
//===--- CHECK: Standard memory functions ---------------------------------===//
+/// \brief Determine whether the given type is a dynamic class type (e.g.,
+/// whether it has a vtable).
+static bool isDynamicClassType(QualType T) {
+ if (CXXRecordDecl *Record = T->getAsCXXRecordDecl())
+ if (CXXRecordDecl *Definition = Record->getDefinition())
+ if (Definition->isDynamicClass())
+ return true;
+
+ return false;
+}
+
/// \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.
+/// This issues warnings on known problematic, dangerous or unspecified
+/// 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();
-
- // The type checking for this warning is moderately expensive, only do it
- // when enabled.
- if (getDiagnostics().getDiagnosticLevel(diag::warn_non_pod_memset,
- Dest->getExprLoc()) ==
- Diagnostic::Ignored)
- return;
-
- QualType DestTy = Dest->getType();
- if (const PointerType *DestPtrTy = DestTy->getAs<PointerType>()) {
- QualType PointeeTy = DestPtrTy->getPointeeType();
- if (PointeeTy->isVoidType())
- return;
-
- // Check the C++11 POD definition regardless of language mode; it is more
- // relaxed than earlier definitions and we don't want spurrious warnings.
- if (PointeeTy->isCXX11PODType())
- return;
-
- DiagRuntimeBehavior(
- Dest->getExprLoc(), Dest,
- PDiag(diag::warn_non_pod_memset)
- << PointeeTy << Call->getCallee()->getSourceRange());
+ 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;
+
+ // Always complain about dynamic classes.
+ if (isDynamicClassType(PointeeTy)) {
+ DiagRuntimeBehavior(
+ Dest->getExprLoc(), Dest,
+ PDiag(diag::warn_dyn_class_memaccess)
+ << ArgIdx << FnName << PointeeTy
+ << Call->getCallee()->getSourceRange());
+ } else {
+ continue;
+ }
- SourceRange ArgRange = Call->getArg(0)->getSourceRange();
- DiagRuntimeBehavior(
- Dest->getExprLoc(), Dest,
- PDiag(diag::note_non_pod_memset_silence)
- << FixItHint::CreateInsertion(ArgRange.getBegin(), "(void*)"));
+ SourceRange ArgRange = Call->getArg(0)->getSourceRange();
+ DiagRuntimeBehavior(
+ Dest->getExprLoc(), Dest,
+ PDiag(diag::note_bad_memaccess_silence)
+ << FixItHint::CreateInsertion(ArgRange.getBegin(), "(void*)"));
+ break;
+ }
}
}
@@ -2391,7 +2405,7 @@ IntRange GetValueRange(ASTContext &C, APValue &result, QualType Ty,
// the sign right on this one case. It would be nice if APValue
// preserved this.
assert(result.isLValue());
- return IntRange(MaxWidth, Ty->isUnsignedIntegerType());
+ return IntRange(MaxWidth, Ty->isUnsignedIntegerOrEnumerationType());
}
/// Pseudo-evaluate the given integer expression, estimating the
@@ -2565,7 +2579,8 @@ IntRange GetExprRange(ASTContext &C, Expr *E, unsigned MaxWidth) {
llvm::APSInt BitWidthAP = BitField->getBitWidth()->EvaluateAsInt(C);
unsigned BitWidth = BitWidthAP.getZExtValue();
- return IntRange(BitWidth, BitField->getType()->isUnsignedIntegerType());
+ return IntRange(BitWidth,
+ BitField->getType()->isUnsignedIntegerOrEnumerationType());
}
return IntRange::forValueOfType(C, E->getType());
@@ -2982,6 +2997,13 @@ void CheckImplicitConversion(Sema &S, Expr *E, QualType T,
if (!Source->isIntegerType() || !Target->isIntegerType())
return;
+ if ((E->isNullPointerConstant(S.Context, Expr::NPC_ValueDependentIsNotNull)
+ == Expr::NPCK_GNUNull) && Target->isIntegerType()) {
+ S.Diag(E->getExprLoc(), diag::warn_impcast_null_pointer_to_integer)
+ << E->getSourceRange() << clang::SourceRange(CC);
+ return;
+ }
+
IntRange SourceRange = GetExprRange(S.Context, E);
IntRange TargetRange = IntRange::forTargetOfCanonicalType(S.Context, Target);
OpenPOWER on IntegriCloud