blob: 3d5fb021db2965de718ef250d0e0b415851d3831 [file] [log] [blame]
//===----------------------------------------------------------------------===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//
#include "FloatTypesCheck.h"
#include "clang/ASTMatchers/ASTMatchFinder.h"
#include "clang/Lex/Lexer.h"
namespace clang {
using namespace ast_matchers;
namespace {
AST_POLYMORPHIC_MATCHER(isValidAndNotInMacro,
AST_POLYMORPHIC_SUPPORTED_TYPES(TypeLoc,
FloatingLiteral)) {
const SourceLocation Loc = Node.getBeginLoc();
return Loc.isValid() && !Loc.isMacroID();
}
AST_MATCHER(TypeLoc, isLongDoubleType) {
TypeLoc TL = Node;
if (const auto QualLoc = Node.getAs<QualifiedTypeLoc>())
TL = QualLoc.getUnqualifiedLoc();
const auto BuiltinLoc = TL.getAs<BuiltinTypeLoc>();
if (!BuiltinLoc)
return false;
if (const auto *BT = BuiltinLoc.getTypePtr())
return BT->getKind() == BuiltinType::LongDouble;
return false;
}
AST_MATCHER(FloatingLiteral, isLongDoubleLiteral) {
if (const auto *BT =
dyn_cast_if_present<BuiltinType>(Node.getType().getTypePtr()))
return BT->getKind() == BuiltinType::LongDouble;
return false;
}
} // namespace
namespace tidy::google::runtime {
void RuntimeFloatCheck::registerMatchers(MatchFinder *Finder) {
Finder->addMatcher(typeLoc(loc(realFloatingPointType()),
isValidAndNotInMacro(), isLongDoubleType())
.bind("longDoubleTypeLoc"),
this);
Finder->addMatcher(floatLiteral(isValidAndNotInMacro(), isLongDoubleLiteral())
.bind("longDoubleFloatLiteral"),
this);
}
void RuntimeFloatCheck::check(const MatchFinder::MatchResult &Result) {
if (const auto *TL = Result.Nodes.getNodeAs<TypeLoc>("longDoubleTypeLoc")) {
diag(TL->getBeginLoc(), "%0 type is not portable and should not be used")
<< TL->getType();
}
if (const auto *FL =
Result.Nodes.getNodeAs<FloatingLiteral>("longDoubleFloatLiteral")) {
diag(FL->getBeginLoc(), "%0 type from literal suffix 'L' is not portable "
"and should not be used")
<< FL->getType();
}
}
} // namespace tidy::google::runtime
} // namespace clang