10 #include "clang/AST/ASTContext.h"
11 #include "clang/ASTMatchers/ASTMatchFinder.h"
20 AST_MATCHER(CXXRecordDecl, isNotTriviallyCopyable) {
22 return Node.hasDefinition() ? !Node.isTriviallyCopyable() :
false;
26 void UndefinedMemoryManipulationCheck::registerMatchers(MatchFinder *Finder) {
27 const auto NotTriviallyCopyableObject =
28 hasType(ast_matchers::hasCanonicalType(
29 pointsTo(cxxRecordDecl(isNotTriviallyCopyable()))));
33 Finder->addMatcher(callExpr(callee(functionDecl(hasAnyName(
34 "::memset",
"::memcpy",
"::memmove"))),
35 hasArgument(0, NotTriviallyCopyableObject))
42 callExpr(callee(functionDecl(hasAnyName(
"::memcpy",
"::memmove"))),
43 hasArgument(1, NotTriviallyCopyableObject))
48 void UndefinedMemoryManipulationCheck::check(
49 const MatchFinder::MatchResult &Result) {
50 if (
const auto *Call = Result.Nodes.getNodeAs<CallExpr>(
"dest")) {
51 QualType DestType = Call->getArg(0)->IgnoreImplicit()->getType();
52 if (!DestType->getPointeeType().isNull())
53 DestType = DestType->getPointeeType();
54 diag(Call->getBeginLoc(),
"undefined behavior, destination object type %0 "
55 "is not TriviallyCopyable")
58 if (
const auto *Call = Result.Nodes.getNodeAs<CallExpr>(
"src")) {
59 QualType SourceType = Call->getArg(1)->IgnoreImplicit()->getType();
60 if (!SourceType->getPointeeType().isNull())
61 SourceType = SourceType->getPointeeType();
62 diag(Call->getBeginLoc(),
63 "undefined behavior, source object type %0 is not TriviallyCopyable")