1 //===--- AvoidNestedConditionalOperatorCheck.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 9 #include "AvoidNestedConditionalOperatorCheck.h" 10 #include "clang/ASTMatchers/ASTMatchFinder.h" 11 #include "clang/ASTMatchers/ASTMatchers.h" 12 #include "clang/Basic/DiagnosticIDs.h" 13 14 using namespace clang::ast_matchers; 15 16 namespace clang::tidy::readability { 17 registerMatchers(MatchFinder * Finder)18void AvoidNestedConditionalOperatorCheck::registerMatchers( 19 MatchFinder *Finder) { 20 Finder->addMatcher( 21 conditionalOperator( 22 anyOf( 23 hasCondition(ignoringParenCasts( 24 conditionalOperator().bind("nested-conditional-operator"))), 25 hasTrueExpression(ignoringParenCasts( 26 conditionalOperator().bind("nested-conditional-operator"))), 27 hasFalseExpression(ignoringParenCasts( 28 conditionalOperator().bind("nested-conditional-operator"))))) 29 .bind("conditional-operator"), 30 this); 31 } 32 check(const MatchFinder::MatchResult & Result)33void AvoidNestedConditionalOperatorCheck::check( 34 const MatchFinder::MatchResult &Result) { 35 const auto *CO = 36 Result.Nodes.getNodeAs<ConditionalOperator>("conditional-operator"); 37 const auto *NCO = Result.Nodes.getNodeAs<ConditionalOperator>( 38 "nested-conditional-operator"); 39 assert(CO); 40 assert(NCO); 41 42 if (CO->getBeginLoc().isMacroID() || NCO->getBeginLoc().isMacroID()) 43 return; 44 45 diag(NCO->getBeginLoc(), 46 "conditional operator is used as sub-expression of parent conditional " 47 "operator, refrain from using nested conditional operators"); 48 diag(CO->getBeginLoc(), "parent conditional operator here", 49 DiagnosticIDs::Note); 50 } 51 52 } // namespace clang::tidy::readability 53