UseNullptrCheck.cpp 19 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511
  1. //===--- UseNullptrCheck.cpp - clang-tidy----------------------------------===//
  2. //
  3. // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
  4. // See https://llvm.org/LICENSE.txt for license information.
  5. // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
  6. //
  7. //===----------------------------------------------------------------------===//
  8. #include "UseNullptrCheck.h"
  9. #include "clang/AST/ASTContext.h"
  10. #include "clang/AST/RecursiveASTVisitor.h"
  11. #include "clang/ASTMatchers/ASTMatchFinder.h"
  12. #include "clang/Lex/Lexer.h"
  13. using namespace clang;
  14. using namespace clang::ast_matchers;
  15. using namespace llvm;
  16. namespace clang::tidy::modernize {
  17. namespace {
  18. const char CastSequence[] = "sequence";
  19. AST_MATCHER(Type, sugaredNullptrType) {
  20. const Type *DesugaredType = Node.getUnqualifiedDesugaredType();
  21. if (const auto *BT = dyn_cast<BuiltinType>(DesugaredType))
  22. return BT->getKind() == BuiltinType::NullPtr;
  23. return false;
  24. }
  25. /// Create a matcher that finds implicit casts as well as the head of a
  26. /// sequence of zero or more nested explicit casts that have an implicit cast
  27. /// to null within.
  28. /// Finding sequences of explicit casts is necessary so that an entire sequence
  29. /// can be replaced instead of just the inner-most implicit cast.
  30. StatementMatcher makeCastSequenceMatcher() {
  31. StatementMatcher ImplicitCastToNull = implicitCastExpr(
  32. anyOf(hasCastKind(CK_NullToPointer), hasCastKind(CK_NullToMemberPointer)),
  33. unless(hasImplicitDestinationType(qualType(substTemplateTypeParmType()))),
  34. unless(hasSourceExpression(hasType(sugaredNullptrType()))));
  35. auto IsOrHasDescendant = [](auto InnerMatcher) {
  36. return anyOf(InnerMatcher, hasDescendant(InnerMatcher));
  37. };
  38. return traverse(
  39. TK_AsIs,
  40. anyOf(castExpr(anyOf(ImplicitCastToNull,
  41. explicitCastExpr(hasDescendant(ImplicitCastToNull))),
  42. unless(hasAncestor(explicitCastExpr())),
  43. unless(hasAncestor(cxxRewrittenBinaryOperator())))
  44. .bind(CastSequence),
  45. cxxRewrittenBinaryOperator(
  46. // Match rewritten operators, but verify (in the check method)
  47. // that if an implicit cast is found, it is not from another
  48. // nested rewritten operator.
  49. expr().bind("matchBinopOperands"),
  50. hasEitherOperand(IsOrHasDescendant(
  51. implicitCastExpr(
  52. ImplicitCastToNull,
  53. hasAncestor(cxxRewrittenBinaryOperator().bind(
  54. "checkBinopOperands")))
  55. .bind(CastSequence))),
  56. // Skip defaulted comparison operators.
  57. unless(hasAncestor(functionDecl(isDefaulted()))))));
  58. }
  59. bool isReplaceableRange(SourceLocation StartLoc, SourceLocation EndLoc,
  60. const SourceManager &SM) {
  61. return SM.isWrittenInSameFile(StartLoc, EndLoc);
  62. }
  63. /// Replaces the provided range with the text "nullptr", but only if
  64. /// the start and end location are both in main file.
  65. /// Returns true if and only if a replacement was made.
  66. void replaceWithNullptr(ClangTidyCheck &Check, SourceManager &SM,
  67. SourceLocation StartLoc, SourceLocation EndLoc) {
  68. CharSourceRange Range(SourceRange(StartLoc, EndLoc), true);
  69. // Add a space if nullptr follows an alphanumeric character. This happens
  70. // whenever there is an c-style explicit cast to nullptr not surrounded by
  71. // parentheses and right beside a return statement.
  72. SourceLocation PreviousLocation = StartLoc.getLocWithOffset(-1);
  73. bool NeedsSpace = isAlphanumeric(*SM.getCharacterData(PreviousLocation));
  74. Check.diag(Range.getBegin(), "use nullptr") << FixItHint::CreateReplacement(
  75. Range, NeedsSpace ? " nullptr" : "nullptr");
  76. }
  77. /// Returns the name of the outermost macro.
  78. ///
  79. /// Given
  80. /// \code
  81. /// #define MY_NULL NULL
  82. /// \endcode
  83. /// If \p Loc points to NULL, this function will return the name MY_NULL.
  84. StringRef getOutermostMacroName(SourceLocation Loc, const SourceManager &SM,
  85. const LangOptions &LO) {
  86. assert(Loc.isMacroID());
  87. SourceLocation OutermostMacroLoc;
  88. while (Loc.isMacroID()) {
  89. OutermostMacroLoc = Loc;
  90. Loc = SM.getImmediateMacroCallerLoc(Loc);
  91. }
  92. return Lexer::getImmediateMacroName(OutermostMacroLoc, SM, LO);
  93. }
  94. /// RecursiveASTVisitor for ensuring all nodes rooted at a given AST
  95. /// subtree that have file-level source locations corresponding to a macro
  96. /// argument have implicit NullTo(Member)Pointer nodes as ancestors.
  97. class MacroArgUsageVisitor : public RecursiveASTVisitor<MacroArgUsageVisitor> {
  98. public:
  99. MacroArgUsageVisitor(SourceLocation CastLoc, const SourceManager &SM)
  100. : CastLoc(CastLoc), SM(SM), Visited(false), CastFound(false),
  101. InvalidFound(false) {
  102. assert(CastLoc.isFileID());
  103. }
  104. bool TraverseStmt(Stmt *S) {
  105. bool VisitedPreviously = Visited;
  106. if (!RecursiveASTVisitor<MacroArgUsageVisitor>::TraverseStmt(S))
  107. return false;
  108. // The point at which VisitedPreviously is false and Visited is true is the
  109. // root of a subtree containing nodes whose locations match CastLoc. It's
  110. // at this point we test that the Implicit NullTo(Member)Pointer cast was
  111. // found or not.
  112. if (!VisitedPreviously) {
  113. if (Visited && !CastFound) {
  114. // Found nodes with matching SourceLocations but didn't come across a
  115. // cast. This is an invalid macro arg use. Can stop traversal
  116. // completely now.
  117. InvalidFound = true;
  118. return false;
  119. }
  120. // Reset state as we unwind back up the tree.
  121. CastFound = false;
  122. Visited = false;
  123. }
  124. return true;
  125. }
  126. bool VisitStmt(Stmt *S) {
  127. if (SM.getFileLoc(S->getBeginLoc()) != CastLoc)
  128. return true;
  129. Visited = true;
  130. const ImplicitCastExpr *Cast = dyn_cast<ImplicitCastExpr>(S);
  131. if (Cast && (Cast->getCastKind() == CK_NullToPointer ||
  132. Cast->getCastKind() == CK_NullToMemberPointer))
  133. CastFound = true;
  134. return true;
  135. }
  136. bool TraverseInitListExpr(InitListExpr *S) {
  137. // Only go through the semantic form of the InitListExpr, because
  138. // ImplicitCast might not appear in the syntactic form, and this results in
  139. // finding usages of the macro argument that don't have a ImplicitCast as an
  140. // ancestor (thus invalidating the replacement) when they actually have.
  141. return RecursiveASTVisitor<MacroArgUsageVisitor>::
  142. TraverseSynOrSemInitListExpr(
  143. S->isSemanticForm() ? S : S->getSemanticForm());
  144. }
  145. bool foundInvalid() const { return InvalidFound; }
  146. private:
  147. SourceLocation CastLoc;
  148. const SourceManager &SM;
  149. bool Visited;
  150. bool CastFound;
  151. bool InvalidFound;
  152. };
  153. /// Looks for implicit casts as well as sequences of 0 or more explicit
  154. /// casts with an implicit null-to-pointer cast within.
  155. ///
  156. /// The matcher this visitor is used with will find a single implicit cast or a
  157. /// top-most explicit cast (i.e. it has no explicit casts as an ancestor) where
  158. /// an implicit cast is nested within. However, there is no guarantee that only
  159. /// explicit casts exist between the found top-most explicit cast and the
  160. /// possibly more than one nested implicit cast. This visitor finds all cast
  161. /// sequences with an implicit cast to null within and creates a replacement
  162. /// leaving the outermost explicit cast unchanged to avoid introducing
  163. /// ambiguities.
  164. class CastSequenceVisitor : public RecursiveASTVisitor<CastSequenceVisitor> {
  165. public:
  166. CastSequenceVisitor(ASTContext &Context, ArrayRef<StringRef> NullMacros,
  167. ClangTidyCheck &Check)
  168. : SM(Context.getSourceManager()), Context(Context),
  169. NullMacros(NullMacros), Check(Check), FirstSubExpr(nullptr),
  170. PruneSubtree(false) {}
  171. bool TraverseStmt(Stmt *S) {
  172. // Stop traversing down the tree if requested.
  173. if (PruneSubtree) {
  174. PruneSubtree = false;
  175. return true;
  176. }
  177. return RecursiveASTVisitor<CastSequenceVisitor>::TraverseStmt(S);
  178. }
  179. // Only VisitStmt is overridden as we shouldn't find other base AST types
  180. // within a cast expression.
  181. bool VisitStmt(Stmt *S) {
  182. auto *C = dyn_cast<CastExpr>(S);
  183. // Catch the castExpr inside cxxDefaultArgExpr.
  184. if (auto *E = dyn_cast<CXXDefaultArgExpr>(S)) {
  185. C = dyn_cast<CastExpr>(E->getExpr());
  186. FirstSubExpr = nullptr;
  187. }
  188. if (!C) {
  189. FirstSubExpr = nullptr;
  190. return true;
  191. }
  192. auto* CastSubExpr = C->getSubExpr()->IgnoreParens();
  193. // Ignore cast expressions which cast nullptr literal.
  194. if (isa<CXXNullPtrLiteralExpr>(CastSubExpr)) {
  195. return true;
  196. }
  197. if (!FirstSubExpr)
  198. FirstSubExpr = CastSubExpr;
  199. if (C->getCastKind() != CK_NullToPointer &&
  200. C->getCastKind() != CK_NullToMemberPointer) {
  201. return true;
  202. }
  203. SourceLocation StartLoc = FirstSubExpr->getBeginLoc();
  204. SourceLocation EndLoc = FirstSubExpr->getEndLoc();
  205. // If the location comes from a macro arg expansion, *all* uses of that
  206. // arg must be checked to result in NullTo(Member)Pointer casts.
  207. //
  208. // If the location comes from a macro body expansion, check to see if its
  209. // coming from one of the allowed 'NULL' macros.
  210. if (SM.isMacroArgExpansion(StartLoc) && SM.isMacroArgExpansion(EndLoc)) {
  211. SourceLocation FileLocStart = SM.getFileLoc(StartLoc),
  212. FileLocEnd = SM.getFileLoc(EndLoc);
  213. SourceLocation ImmediateMacroArgLoc, MacroLoc;
  214. // Skip NULL macros used in macro.
  215. if (!getMacroAndArgLocations(StartLoc, ImmediateMacroArgLoc, MacroLoc) ||
  216. ImmediateMacroArgLoc != FileLocStart)
  217. return skipSubTree();
  218. if (isReplaceableRange(FileLocStart, FileLocEnd, SM) &&
  219. allArgUsesValid(C)) {
  220. replaceWithNullptr(Check, SM, FileLocStart, FileLocEnd);
  221. }
  222. return true;
  223. }
  224. if (SM.isMacroBodyExpansion(StartLoc) && SM.isMacroBodyExpansion(EndLoc)) {
  225. StringRef OutermostMacroName =
  226. getOutermostMacroName(StartLoc, SM, Context.getLangOpts());
  227. // Check to see if the user wants to replace the macro being expanded.
  228. if (!llvm::is_contained(NullMacros, OutermostMacroName))
  229. return skipSubTree();
  230. StartLoc = SM.getFileLoc(StartLoc);
  231. EndLoc = SM.getFileLoc(EndLoc);
  232. }
  233. if (!isReplaceableRange(StartLoc, EndLoc, SM)) {
  234. return skipSubTree();
  235. }
  236. replaceWithNullptr(Check, SM, StartLoc, EndLoc);
  237. return true;
  238. }
  239. private:
  240. bool skipSubTree() {
  241. PruneSubtree = true;
  242. return true;
  243. }
  244. /// Tests that all expansions of a macro arg, one of which expands to
  245. /// result in \p CE, yield NullTo(Member)Pointer casts.
  246. bool allArgUsesValid(const CastExpr *CE) {
  247. SourceLocation CastLoc = CE->getBeginLoc();
  248. // Step 1: Get location of macro arg and location of the macro the arg was
  249. // provided to.
  250. SourceLocation ArgLoc, MacroLoc;
  251. if (!getMacroAndArgLocations(CastLoc, ArgLoc, MacroLoc))
  252. return false;
  253. // Step 2: Find the first ancestor that doesn't expand from this macro.
  254. DynTypedNode ContainingAncestor;
  255. if (!findContainingAncestor(DynTypedNode::create<Stmt>(*CE), MacroLoc,
  256. ContainingAncestor))
  257. return false;
  258. // Step 3:
  259. // Visit children of this containing parent looking for the least-descended
  260. // nodes of the containing parent which are macro arg expansions that expand
  261. // from the given arg location.
  262. // Visitor needs: arg loc.
  263. MacroArgUsageVisitor ArgUsageVisitor(SM.getFileLoc(CastLoc), SM);
  264. if (const auto *D = ContainingAncestor.get<Decl>())
  265. ArgUsageVisitor.TraverseDecl(const_cast<Decl *>(D));
  266. else if (const auto *S = ContainingAncestor.get<Stmt>())
  267. ArgUsageVisitor.TraverseStmt(const_cast<Stmt *>(S));
  268. else
  269. llvm_unreachable("Unhandled ContainingAncestor node type");
  270. return !ArgUsageVisitor.foundInvalid();
  271. }
  272. /// Given the SourceLocation for a macro arg expansion, finds the
  273. /// non-macro SourceLocation of the macro the arg was passed to and the
  274. /// non-macro SourceLocation of the argument in the arg list to that macro.
  275. /// These results are returned via \c MacroLoc and \c ArgLoc respectively.
  276. /// These values are undefined if the return value is false.
  277. ///
  278. /// \returns false if one of the returned SourceLocations would be a
  279. /// SourceLocation pointing within the definition of another macro.
  280. bool getMacroAndArgLocations(SourceLocation Loc, SourceLocation &ArgLoc,
  281. SourceLocation &MacroLoc) {
  282. assert(Loc.isMacroID() && "Only reasonable to call this on macros");
  283. ArgLoc = Loc;
  284. // Find the location of the immediate macro expansion.
  285. while (true) {
  286. std::pair<FileID, unsigned> LocInfo = SM.getDecomposedLoc(ArgLoc);
  287. const SrcMgr::SLocEntry *E = &SM.getSLocEntry(LocInfo.first);
  288. const SrcMgr::ExpansionInfo &Expansion = E->getExpansion();
  289. SourceLocation OldArgLoc = ArgLoc;
  290. ArgLoc = Expansion.getExpansionLocStart();
  291. if (!Expansion.isMacroArgExpansion()) {
  292. if (!MacroLoc.isFileID())
  293. return false;
  294. StringRef Name =
  295. Lexer::getImmediateMacroName(OldArgLoc, SM, Context.getLangOpts());
  296. return llvm::is_contained(NullMacros, Name);
  297. }
  298. MacroLoc = SM.getExpansionRange(ArgLoc).getBegin();
  299. ArgLoc = Expansion.getSpellingLoc().getLocWithOffset(LocInfo.second);
  300. if (ArgLoc.isFileID())
  301. return true;
  302. // If spelling location resides in the same FileID as macro expansion
  303. // location, it means there is no inner macro.
  304. FileID MacroFID = SM.getFileID(MacroLoc);
  305. if (SM.isInFileID(ArgLoc, MacroFID)) {
  306. // Don't transform this case. If the characters that caused the
  307. // null-conversion come from within a macro, they can't be changed.
  308. return false;
  309. }
  310. }
  311. llvm_unreachable("getMacroAndArgLocations");
  312. }
  313. /// Tests if TestMacroLoc is found while recursively unravelling
  314. /// expansions starting at TestLoc. TestMacroLoc.isFileID() must be true.
  315. /// Implementation is very similar to getMacroAndArgLocations() except in this
  316. /// case, it's not assumed that TestLoc is expanded from a macro argument.
  317. /// While unravelling expansions macro arguments are handled as with
  318. /// getMacroAndArgLocations() but in this function macro body expansions are
  319. /// also handled.
  320. ///
  321. /// False means either:
  322. /// - TestLoc is not from a macro expansion.
  323. /// - TestLoc is from a different macro expansion.
  324. bool expandsFrom(SourceLocation TestLoc, SourceLocation TestMacroLoc) {
  325. if (TestLoc.isFileID()) {
  326. return false;
  327. }
  328. SourceLocation Loc = TestLoc, MacroLoc;
  329. while (true) {
  330. std::pair<FileID, unsigned> LocInfo = SM.getDecomposedLoc(Loc);
  331. const SrcMgr::SLocEntry *E = &SM.getSLocEntry(LocInfo.first);
  332. const SrcMgr::ExpansionInfo &Expansion = E->getExpansion();
  333. Loc = Expansion.getExpansionLocStart();
  334. if (!Expansion.isMacroArgExpansion()) {
  335. if (Loc.isFileID()) {
  336. return Loc == TestMacroLoc;
  337. }
  338. // Since Loc is still a macro ID and it's not an argument expansion, we
  339. // don't need to do the work of handling an argument expansion. Simply
  340. // keep recursively expanding until we hit a FileID or a macro arg
  341. // expansion or a macro arg expansion.
  342. continue;
  343. }
  344. MacroLoc = SM.getImmediateExpansionRange(Loc).getBegin();
  345. if (MacroLoc.isFileID() && MacroLoc == TestMacroLoc) {
  346. // Match made.
  347. return true;
  348. }
  349. Loc = Expansion.getSpellingLoc().getLocWithOffset(LocInfo.second);
  350. if (Loc.isFileID()) {
  351. // If we made it this far without finding a match, there is no match to
  352. // be made.
  353. return false;
  354. }
  355. }
  356. llvm_unreachable("expandsFrom");
  357. }
  358. /// Given a starting point \c Start in the AST, find an ancestor that
  359. /// doesn't expand from the macro called at file location \c MacroLoc.
  360. ///
  361. /// \pre MacroLoc.isFileID()
  362. /// \returns true if such an ancestor was found, false otherwise.
  363. bool findContainingAncestor(DynTypedNode Start, SourceLocation MacroLoc,
  364. DynTypedNode &Result) {
  365. // Below we're only following the first parent back up the AST. This should
  366. // be fine since for the statements we care about there should only be one
  367. // parent, except for the case specified below.
  368. assert(MacroLoc.isFileID());
  369. while (true) {
  370. const auto &Parents = Context.getParents(Start);
  371. if (Parents.empty())
  372. return false;
  373. if (Parents.size() > 1) {
  374. // If there are more than one parents, don't do the replacement unless
  375. // they are InitListsExpr (semantic and syntactic form). In this case we
  376. // can choose any one here, and the ASTVisitor will take care of
  377. // traversing the right one.
  378. for (const auto &Parent : Parents) {
  379. if (!Parent.get<InitListExpr>())
  380. return false;
  381. }
  382. }
  383. const DynTypedNode &Parent = Parents[0];
  384. SourceLocation Loc;
  385. if (const auto *D = Parent.get<Decl>())
  386. Loc = D->getBeginLoc();
  387. else if (const auto *S = Parent.get<Stmt>())
  388. Loc = S->getBeginLoc();
  389. // TypeLoc and NestedNameSpecifierLoc are members of the parent map. Skip
  390. // them and keep going up.
  391. if (Loc.isValid()) {
  392. if (!expandsFrom(Loc, MacroLoc)) {
  393. Result = Parent;
  394. return true;
  395. }
  396. }
  397. Start = Parent;
  398. }
  399. llvm_unreachable("findContainingAncestor");
  400. }
  401. private:
  402. SourceManager &SM;
  403. ASTContext &Context;
  404. ArrayRef<StringRef> NullMacros;
  405. ClangTidyCheck &Check;
  406. Expr *FirstSubExpr;
  407. bool PruneSubtree;
  408. };
  409. } // namespace
  410. UseNullptrCheck::UseNullptrCheck(StringRef Name, ClangTidyContext *Context)
  411. : ClangTidyCheck(Name, Context),
  412. NullMacrosStr(Options.get("NullMacros", "")) {
  413. StringRef(NullMacrosStr).split(NullMacros, ",");
  414. }
  415. void UseNullptrCheck::storeOptions(ClangTidyOptions::OptionMap &Opts) {
  416. Options.store(Opts, "NullMacros", NullMacrosStr);
  417. }
  418. void UseNullptrCheck::registerMatchers(MatchFinder *Finder) {
  419. Finder->addMatcher(makeCastSequenceMatcher(), this);
  420. }
  421. void UseNullptrCheck::check(const MatchFinder::MatchResult &Result) {
  422. const auto *NullCast = Result.Nodes.getNodeAs<CastExpr>(CastSequence);
  423. assert(NullCast && "Bad Callback. No node provided");
  424. if (Result.Nodes.getNodeAs<CXXRewrittenBinaryOperator>(
  425. "matchBinopOperands") !=
  426. Result.Nodes.getNodeAs<CXXRewrittenBinaryOperator>("checkBinopOperands"))
  427. return;
  428. // Given an implicit null-ptr cast or an explicit cast with an implicit
  429. // null-to-pointer cast within use CastSequenceVisitor to identify sequences
  430. // of explicit casts that can be converted into 'nullptr'.
  431. CastSequenceVisitor(*Result.Context, NullMacros, *this)
  432. .TraverseStmt(const_cast<CastExpr *>(NullCast));
  433. }
  434. } // namespace clang::tidy::modernize