| 
 | 1 | +//===----------------------------------------------------------------------===//  | 
 | 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 "FloatTypesCheck.h"  | 
 | 10 | +#include "clang/ASTMatchers/ASTMatchFinder.h"  | 
 | 11 | +#include "clang/Lex/Lexer.h"  | 
 | 12 | + | 
 | 13 | +namespace clang {  | 
 | 14 | + | 
 | 15 | +using namespace ast_matchers;  | 
 | 16 | + | 
 | 17 | +namespace {  | 
 | 18 | + | 
 | 19 | +AST_POLYMORPHIC_MATCHER(isValidAndNotInMacro,  | 
 | 20 | +                        AST_POLYMORPHIC_SUPPORTED_TYPES(TypeLoc,  | 
 | 21 | +                                                        FloatingLiteral)) {  | 
 | 22 | +  const SourceLocation Loc = Node.getBeginLoc();  | 
 | 23 | +  return Loc.isValid() && !Loc.isMacroID();  | 
 | 24 | +}  | 
 | 25 | + | 
 | 26 | +AST_MATCHER(TypeLoc, isLongDoubleType) {  | 
 | 27 | +  TypeLoc TL = Node;  | 
 | 28 | +  if (const auto QualLoc = Node.getAs<QualifiedTypeLoc>())  | 
 | 29 | +    TL = QualLoc.getUnqualifiedLoc();  | 
 | 30 | + | 
 | 31 | +  const auto BuiltinLoc = TL.getAs<BuiltinTypeLoc>();  | 
 | 32 | +  if (!BuiltinLoc)  | 
 | 33 | +    return false;  | 
 | 34 | + | 
 | 35 | +  if (const auto *BT = BuiltinLoc.getTypePtr())  | 
 | 36 | +    return BT->getKind() == BuiltinType::LongDouble;  | 
 | 37 | +  return false;  | 
 | 38 | +}  | 
 | 39 | + | 
 | 40 | +AST_MATCHER(FloatingLiteral, isLongDoubleLiteral) {  | 
 | 41 | +  if (const auto *BT =  | 
 | 42 | +          dyn_cast_if_present<BuiltinType>(Node.getType().getTypePtr()))  | 
 | 43 | +    return BT->getKind() == BuiltinType::LongDouble;  | 
 | 44 | +  return false;  | 
 | 45 | +}  | 
 | 46 | + | 
 | 47 | +} // namespace  | 
 | 48 | + | 
 | 49 | +namespace tidy::google::runtime {  | 
 | 50 | + | 
 | 51 | +void RuntimeFloatCheck::registerMatchers(MatchFinder *Finder) {  | 
 | 52 | +  Finder->addMatcher(typeLoc(loc(realFloatingPointType()),  | 
 | 53 | +                             isValidAndNotInMacro(), isLongDoubleType())  | 
 | 54 | +                         .bind("longDoubleTypeLoc"),  | 
 | 55 | +                     this);  | 
 | 56 | +  Finder->addMatcher(floatLiteral(isValidAndNotInMacro(), isLongDoubleLiteral())  | 
 | 57 | +                         .bind("longDoubleFloatLiteral"),  | 
 | 58 | +                     this);  | 
 | 59 | +}  | 
 | 60 | + | 
 | 61 | +void RuntimeFloatCheck::check(const MatchFinder::MatchResult &Result) {  | 
 | 62 | +  if (const auto *TL = Result.Nodes.getNodeAs<TypeLoc>("longDoubleTypeLoc")) {  | 
 | 63 | +    diag(TL->getBeginLoc(), "%0 type is not portable and should not be used")  | 
 | 64 | +        << TL->getType();  | 
 | 65 | +  }  | 
 | 66 | + | 
 | 67 | +  if (const auto *FL =  | 
 | 68 | +          Result.Nodes.getNodeAs<FloatingLiteral>("longDoubleFloatLiteral")) {  | 
 | 69 | +    diag(FL->getBeginLoc(), "%0 type from literal suffix 'L' is not portable "  | 
 | 70 | +                            "and should not be used")  | 
 | 71 | +        << FL->getType();  | 
 | 72 | +  }  | 
 | 73 | +}  | 
 | 74 | + | 
 | 75 | +} // namespace tidy::google::runtime  | 
 | 76 | + | 
 | 77 | +} // namespace clang  | 
0 commit comments