//===--- UseNullptrCheck.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 "UseNullptrCheck.h" #include "../utils/Matchers.h" #include "../utils/OptionsUtils.h" #include "clang/AST/ASTContext.h" #include "clang/AST/RecursiveASTVisitor.h" #include "clang/ASTMatchers/ASTMatchFinder.h" #include "clang/Lex/Lexer.h" usingnamespaceclang; usingnamespaceclang::ast_matchers; usingnamespacellvm; namespace clang::tidy::modernize { namespace { const char CastSequence[] = …; AST_MATCHER(Type, sugaredNullptrType) { … } /// Create a matcher that finds implicit casts as well as the head of a /// sequence of zero or more nested explicit casts that have an implicit cast /// to null within. /// Finding sequences of explicit casts is necessary so that an entire sequence /// can be replaced instead of just the inner-most implicit cast. /// /// TODO/NOTE: The second "anyOf" below discards matches on a substituted type, /// since we don't know if that would _always_ be a pointer type for all other /// specializations, unless the expression was "__null", in which case we assume /// that all specializations are expected to be for pointer types. Ideally this /// would check for the "NULL" macro instead, but that'd be harder to express. /// In practice, "NULL" is often defined as "__null", and this is a useful /// condition. StatementMatcher makeCastSequenceMatcher(llvm::ArrayRef<StringRef> NameList) { … } bool isReplaceableRange(SourceLocation StartLoc, SourceLocation EndLoc, const SourceManager &SM) { … } /// Replaces the provided range with the text "nullptr", but only if /// the start and end location are both in main file. /// Returns true if and only if a replacement was made. void replaceWithNullptr(ClangTidyCheck &Check, SourceManager &SM, SourceLocation StartLoc, SourceLocation EndLoc) { … } /// Returns the name of the outermost macro. /// /// Given /// \code /// #define MY_NULL NULL /// \endcode /// If \p Loc points to NULL, this function will return the name MY_NULL. StringRef getOutermostMacroName(SourceLocation Loc, const SourceManager &SM, const LangOptions &LO) { … } /// RecursiveASTVisitor for ensuring all nodes rooted at a given AST /// subtree that have file-level source locations corresponding to a macro /// argument have implicit NullTo(Member)Pointer nodes as ancestors. class MacroArgUsageVisitor : public RecursiveASTVisitor<MacroArgUsageVisitor> { … }; /// Looks for implicit casts as well as sequences of 0 or more explicit /// casts with an implicit null-to-pointer cast within. /// /// The matcher this visitor is used with will find a single implicit cast or a /// top-most explicit cast (i.e. it has no explicit casts as an ancestor) where /// an implicit cast is nested within. However, there is no guarantee that only /// explicit casts exist between the found top-most explicit cast and the /// possibly more than one nested implicit cast. This visitor finds all cast /// sequences with an implicit cast to null within and creates a replacement /// leaving the outermost explicit cast unchanged to avoid introducing /// ambiguities. class CastSequenceVisitor : public RecursiveASTVisitor<CastSequenceVisitor> { … }; } // namespace UseNullptrCheck::UseNullptrCheck(StringRef Name, ClangTidyContext *Context) : … { … } void UseNullptrCheck::storeOptions(ClangTidyOptions::OptionMap &Opts) { … } void UseNullptrCheck::registerMatchers(MatchFinder *Finder) { … } void UseNullptrCheck::check(const MatchFinder::MatchResult &Result) { … } } // namespace clang::tidy::modernize