tor-browser

The Tor Browser
git clone https://git.dasho.dev/tor-browser.git
Log | Files | Refs | README | LICENSE

NaNExprChecker.cpp (2333B)


      1 /* This Source Code Form is subject to the terms of the Mozilla Public
      2 * License, v. 2.0. If a copy of the MPL was not distributed with this
      3 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
      4 
      5 #include "NaNExprChecker.h"
      6 #include "CustomMatchers.h"
      7 
      8 void NaNExprChecker::registerMatchers(MatchFinder *AstMatcher) {
      9  AstMatcher->addMatcher(
     10      binaryOperator(
     11          allOf(binaryEqualityOperator(),
     12                hasLHS(has(ignoringParenImpCasts(
     13                    declRefExpr(hasType(qualType((isFloat())))).bind("lhs")))),
     14                hasRHS(has(ignoringParenImpCasts(
     15                    declRefExpr(hasType(qualType((isFloat())))).bind("rhs")))),
     16                isFirstParty(),
     17                unless(isInWhitelistForNaNExpr())))
     18          .bind("node"),
     19      this);
     20 }
     21 
     22 void NaNExprChecker::check(const MatchFinder::MatchResult &Result) {
     23  if (!Result.Context->getLangOpts().CPlusPlus) {
     24    return;
     25  }
     26 
     27  const BinaryOperator *Expression =
     28      Result.Nodes.getNodeAs<BinaryOperator>("node");
     29  const DeclRefExpr *LHS = Result.Nodes.getNodeAs<DeclRefExpr>("lhs");
     30  const DeclRefExpr *RHS = Result.Nodes.getNodeAs<DeclRefExpr>("rhs");
     31  const ImplicitCastExpr *LHSExpr =
     32      dyn_cast<ImplicitCastExpr>(Expression->getLHS());
     33  const ImplicitCastExpr *RHSExpr =
     34      dyn_cast<ImplicitCastExpr>(Expression->getRHS());
     35  // The AST subtree that we are looking for will look like this:
     36  // -BinaryOperator ==/!=
     37  //  |-ImplicitCastExpr LValueToRValue
     38  //  | |-DeclRefExpr
     39  //  |-ImplicitCastExpr LValueToRValue
     40  //    |-DeclRefExpr
     41  // The check below ensures that we are dealing with the correct AST subtree
     42  // shape, and
     43  // also that both of the found DeclRefExpr's point to the same declaration.
     44  if (LHS->getFoundDecl() == RHS->getFoundDecl() && LHSExpr && RHSExpr &&
     45      std::distance(LHSExpr->child_begin(), LHSExpr->child_end()) == 1 &&
     46      std::distance(RHSExpr->child_begin(), RHSExpr->child_end()) == 1 &&
     47      *LHSExpr->child_begin() == LHS && *RHSExpr->child_begin() == RHS) {
     48    diag(Expression->getBeginLoc(),
     49         "comparing a floating point value to itself for "
     50         "NaN checking can lead to incorrect results",
     51         DiagnosticIDs::Error);
     52    diag(Expression->getBeginLoc(), "consider using std::isnan instead",
     53         DiagnosticIDs::Note);
     54  }
     55 }