1*10602c2bSCongcong Cai //===--- AvoidNestedConditionalOperatorCheck.cpp - clang-tidy -------------===//
28e21557dSCongcong Cai //
38e21557dSCongcong Cai // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
48e21557dSCongcong Cai // See https://llvm.org/LICENSE.txt for license information.
58e21557dSCongcong Cai // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
68e21557dSCongcong Cai //
78e21557dSCongcong Cai //===----------------------------------------------------------------------===//
88e21557dSCongcong Cai 
98e21557dSCongcong Cai #include "AvoidNestedConditionalOperatorCheck.h"
108e21557dSCongcong Cai #include "clang/ASTMatchers/ASTMatchFinder.h"
118e21557dSCongcong Cai #include "clang/ASTMatchers/ASTMatchers.h"
128e21557dSCongcong Cai #include "clang/Basic/DiagnosticIDs.h"
138e21557dSCongcong Cai 
148e21557dSCongcong Cai using namespace clang::ast_matchers;
158e21557dSCongcong Cai 
168e21557dSCongcong Cai namespace clang::tidy::readability {
178e21557dSCongcong Cai 
registerMatchers(MatchFinder * Finder)188e21557dSCongcong Cai void AvoidNestedConditionalOperatorCheck::registerMatchers(
198e21557dSCongcong Cai     MatchFinder *Finder) {
208e21557dSCongcong Cai   Finder->addMatcher(
218e21557dSCongcong Cai       conditionalOperator(
228e21557dSCongcong Cai           anyOf(
238e21557dSCongcong Cai               hasCondition(ignoringParenCasts(
248e21557dSCongcong Cai                   conditionalOperator().bind("nested-conditional-operator"))),
258e21557dSCongcong Cai               hasTrueExpression(ignoringParenCasts(
268e21557dSCongcong Cai                   conditionalOperator().bind("nested-conditional-operator"))),
278e21557dSCongcong Cai               hasFalseExpression(ignoringParenCasts(
288e21557dSCongcong Cai                   conditionalOperator().bind("nested-conditional-operator")))))
298e21557dSCongcong Cai           .bind("conditional-operator"),
308e21557dSCongcong Cai       this);
318e21557dSCongcong Cai }
328e21557dSCongcong Cai 
check(const MatchFinder::MatchResult & Result)338e21557dSCongcong Cai void AvoidNestedConditionalOperatorCheck::check(
348e21557dSCongcong Cai     const MatchFinder::MatchResult &Result) {
358e21557dSCongcong Cai   const auto *CO =
368e21557dSCongcong Cai       Result.Nodes.getNodeAs<ConditionalOperator>("conditional-operator");
378e21557dSCongcong Cai   const auto *NCO = Result.Nodes.getNodeAs<ConditionalOperator>(
388e21557dSCongcong Cai       "nested-conditional-operator");
398e21557dSCongcong Cai   assert(CO);
408e21557dSCongcong Cai   assert(NCO);
418e21557dSCongcong Cai 
428e21557dSCongcong Cai   if (CO->getBeginLoc().isMacroID() || NCO->getBeginLoc().isMacroID())
438e21557dSCongcong Cai     return;
448e21557dSCongcong Cai 
458e21557dSCongcong Cai   diag(NCO->getBeginLoc(),
468e21557dSCongcong Cai        "conditional operator is used as sub-expression of parent conditional "
478e21557dSCongcong Cai        "operator, refrain from using nested conditional operators");
488e21557dSCongcong Cai   diag(CO->getBeginLoc(), "parent conditional operator here",
498e21557dSCongcong Cai        DiagnosticIDs::Note);
508e21557dSCongcong Cai }
518e21557dSCongcong Cai 
528e21557dSCongcong Cai } // namespace clang::tidy::readability
53