//===--- UndefinedMemoryManipulationCheck.cpp - clang-tidy-----------------===// // // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. // See https://llvm.org/LICENSE.txt for license information. // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception // //===----------------------------------------------------------------------===// #include "UndefinedMemoryManipulationCheck.h" #include "clang/AST/ASTContext.h" #include "clang/ASTMatchers/ASTMatchFinder.h" using namespace clang::ast_matchers; namespace clang { namespace tidy { namespace bugprone { namespace { AST_MATCHER(CXXRecordDecl, isNotTriviallyCopyable) { // For incomplete types, assume they are TriviallyCopyable. return Node.hasDefinition() ? !Node.isTriviallyCopyable() : false; } } // namespace void UndefinedMemoryManipulationCheck::registerMatchers(MatchFinder *Finder) { const auto NotTriviallyCopyableObject = hasType(ast_matchers::hasCanonicalType( pointsTo(cxxRecordDecl(isNotTriviallyCopyable())))); // Check whether destination object is not TriviallyCopyable. // Applicable to all three memory manipulation functions. Finder->addMatcher(callExpr(callee(functionDecl(hasAnyName( "::memset", "::memcpy", "::memmove"))), hasArgument(0, NotTriviallyCopyableObject)) .bind("dest"), this); // Check whether source object is not TriviallyCopyable. // Only applicable to memcpy() and memmove(). Finder->addMatcher( callExpr(callee(functionDecl(hasAnyName("::memcpy", "::memmove"))), hasArgument(1, NotTriviallyCopyableObject)) .bind("src"), this); } void UndefinedMemoryManipulationCheck::check( const MatchFinder::MatchResult &Result) { if (const auto *Call = Result.Nodes.getNodeAs("dest")) { QualType DestType = Call->getArg(0)->IgnoreImplicit()->getType(); if (!DestType->getPointeeType().isNull()) DestType = DestType->getPointeeType(); diag(Call->getBeginLoc(), "undefined behavior, destination object type %0 " "is not TriviallyCopyable") << DestType; } if (const auto *Call = Result.Nodes.getNodeAs("src")) { QualType SourceType = Call->getArg(1)->IgnoreImplicit()->getType(); if (!SourceType->getPointeeType().isNull()) SourceType = SourceType->getPointeeType(); diag(Call->getBeginLoc(), "undefined behavior, source object type %0 is not TriviallyCopyable") << SourceType; } } } // namespace bugprone } // namespace tidy } // namespace clang