44 Options.get(
"ReplacementFunction",
"std::to_underlying")),
45 ReplacementFunctionHeader(Options.get(
"ReplacementFunctionHeader",
"")),
46 IncludeInserter(Options.getLocalOrGlobal(
"IncludeStyle",
47 utils::IncludeSorter::IS_LLVM),
48 areDiagsSelfContained()) {
49 if (ReplacementFunction ==
"std::to_underlying") {
50 if (ReplacementFunctionHeader.empty())
51 ReplacementFunctionHeader =
"<utility>";
52 else if (ReplacementFunctionHeader !=
"<utility>")
53 configurationDiag(
"'std::to_underlying' is declared in '<utility>', but "
54 "'ReplacementFunctionHeader' is set to '%0'")
55 << ReplacementFunctionHeader;
100 const auto *Cast = Result.Nodes.getNodeAs<ExplicitCastExpr>(
"cast");
101 const auto *Operand = Result.Nodes.getNodeAs<Expr>(
"operand");
102 const auto *Enum = Result.Nodes.getNodeAs<EnumDecl>(
"enum");
104 const QualType DestType = Cast->getType().getCanonicalType();
105 const QualType UnderlyingType =
106 Enum->getIntegerType().getCanonicalType().getUnqualifiedType();
107 const QualType DestUnqualified = DestType.getUnqualifiedType();
108 const bool IsPrecise = UnderlyingType == DestUnqualified;
113 if (DestType->isBooleanType() && !IsPrecise)
119 auto Diag = diag(Cast->getBeginLoc(),
120 "use '%0' to convert a scoped enumeration to its "
122 << ReplacementFunction;
127 const StringRef OperandText =
128 tooling::fixit::getText(*Operand, *Result.Context);
129 if (OperandText.empty())
132 const std::string Call =
133 (ReplacementFunction +
"(" + OperandText +
")").str();
135 const bool ReplaceWholeCast =
137 if (ReplaceWholeCast) {
139 Diag << tooling::fixit::createReplacement(*Cast, Call);
142 Diag << tooling::fixit::createReplacement(*Operand, Call);
145 if (!ReplacementFunctionHeader.empty())
146 Diag << IncludeInserter.createIncludeInsertion(
147 Result.SourceManager->getFileID(
148 Result.SourceManager->getExpansionLoc(Cast->getBeginLoc())),
149 ReplacementFunctionHeader);
Every ClangTidyCheck reports errors through a DiagnosticsEngine provided by this context.