10#include "../utils/ASTUtils.h"
11#include "clang/ASTMatchers/ASTMatchFinder.h"
12#include "clang/Lex/Lexer.h"
20constexpr char ConstructExprN[] =
"found_construct_expr";
21constexpr char NewExprN[] =
"found_new_expr";
22constexpr char ConstructorN[] =
"found_constructor";
24bool isInSingleDeclStmt(
const DeclaratorDecl *D) {
25 const DynTypedNodeList
Parents =
26 D->getASTContext().getParentMapContext().getParents(*D);
27 for (
const DynTypedNode &PNode : Parents)
28 if (
const auto *PDecl = PNode.get<DeclStmt>())
29 return PDecl->isSingleDecl();
33const DeclaratorDecl *getConstructedVarOrField(
const Expr *FoundConstructExpr,
35 const DynTypedNodeList ConstructParents =
36 Ctx.getParentMapContext().getParents(*FoundConstructExpr);
37 if (ConstructParents.size() != 1)
39 const auto *ParentDecl = ConstructParents.begin()->get<DeclaratorDecl>();
40 if (isa_and_nonnull<VarDecl, FieldDecl>(ParentDecl))
61 auto FindConstructor =
63 parameterCountIs(1), isExplicit())
65 auto FindConstructExpr =
67 hasDeclaration(FindConstructor), argumentCountIs(1),
70 hasType(hasCanonicalType(pointerType(
73 .bind(ConstructExprN);
74 Finder->addMatcher(FindConstructExpr,
this);
78 const auto *FoundNewExpr = Result.Nodes.getNodeAs<CXXNewExpr>(NewExprN);
79 const auto *FoundConstructExpr =
80 Result.Nodes.getNodeAs<CXXConstructExpr>(ConstructExprN);
81 const auto *FoundConstructorDecl =
82 Result.Nodes.getNodeAs<CXXConstructorDecl>(ConstructorN);
84 ASTContext &Ctx = FoundConstructorDecl->getASTContext();
85 const DeclaratorDecl *VarOrField =
86 getConstructedVarOrField(FoundConstructExpr, Ctx);
88 auto D =
diag(FoundNewExpr->getBeginLoc(),
89 "%0 pointer to non-array is initialized with array")
91 D << FoundNewExpr->getSourceRange();
94 auto TSTypeLoc = VarOrField->getTypeSourceInfo()
96 .getAsAdjusted<clang::TemplateSpecializationTypeLoc>();
97 assert(TSTypeLoc.getNumArgs() >= 1 &&
98 "Matched type should have at least 1 template argument.");
100 SourceRange TemplateArgumentRange = TSTypeLoc.getArgLoc(0)
104 D << TemplateArgumentRange;
106 if (isInSingleDeclStmt(VarOrField)) {
107 const SourceManager &SM = Ctx.getSourceManager();
111 SourceLocation InsertLoc = Lexer::getLocForEndOfToken(
112 TemplateArgumentRange.getEnd(), 0, SM, Ctx.getLangOpts());
113 D << FixItHint::CreateInsertion(InsertLoc,
"[]");
llvm::SmallString< 256U > Name
Base class for all clang-tidy checks.
DiagnosticBuilder diag(SourceLocation Loc, StringRef Description, DiagnosticIDs::Level Level=DiagnosticIDs::Warning)
Add a diagnostic with the check's name.
Every ClangTidyCheck reports errors through a DiagnosticsEngine provided by this context.
void check(const ast_matchers::MatchFinder::MatchResult &Result) override
ClangTidyChecks that register ASTMatchers should do the actual work in here.
virtual SmartPtrClassMatcher getSmartPointerClassMatcher() const =0
Returns matcher that match with different smart pointer classes.
static const char PointerTypeN[]
void registerMatchers(ast_matchers::MatchFinder *Finder) override
Override this to register AST matchers with Finder.
SmartPtrArrayMismatchCheck(StringRef Name, ClangTidyContext *Context, StringRef SmartPointerName)
void storeOptions(ClangTidyOptions::OptionMap &Opts) override
Should store all options supported by this check with their current values or default values for opti...
bool rangeCanBeFixed(SourceRange Range, const SourceManager *SM)
llvm::StringMap< ClangTidyValue > OptionMap