238 const auto EmitValueWarning = [
this,
239 &Result](
const NestedNameSpecifierLoc &QualLoc,
240 SourceLocation EndLoc) {
241 SourceLocation TemplateNameEndLoc;
242 if (
const auto TSTL =
243 QualLoc.getAsTypeLoc().getAs<TemplateSpecializationTypeLoc>())
244 TemplateNameEndLoc = Lexer::getLocForEndOfToken(
245 TSTL.getTemplateNameLoc(), 0, *Result.SourceManager,
246 Result.Context->getLangOpts());
250 if (EndLoc.isMacroID() || QualLoc.getEndLoc().isMacroID() ||
251 TemplateNameEndLoc.isMacroID()) {
254 diag(QualLoc.getBeginLoc(),
"use c++17 style variable templates");
257 diag(QualLoc.getBeginLoc(),
"use c++17 style variable templates")
258 << FixItHint::CreateInsertion(TemplateNameEndLoc,
"_v")
259 << FixItHint::CreateRemoval({QualLoc.getEndLoc(), EndLoc});
262 const auto EmitTypeWarning = [
this,
263 &Result](
const NestedNameSpecifierLoc &QualLoc,
264 SourceLocation EndLoc,
265 SourceLocation TypenameLoc) {
266 SourceLocation TemplateNameEndLoc;
267 if (
const auto TSTL =
268 QualLoc.getAsTypeLoc().getAs<TemplateSpecializationTypeLoc>())
269 TemplateNameEndLoc = Lexer::getLocForEndOfToken(
270 TSTL.getTemplateNameLoc(), 0, *Result.SourceManager,
271 Result.Context->getLangOpts());
275 if (EndLoc.isMacroID() || QualLoc.getEndLoc().isMacroID() ||
276 TemplateNameEndLoc.isMacroID() || TypenameLoc.isMacroID()) {
279 diag(QualLoc.getBeginLoc(),
"use c++14 style type templates");
283 diag(QualLoc.getBeginLoc(),
"use c++14 style type templates");
285 if (TypenameLoc.isValid())
286 Diag << FixItHint::CreateRemoval(TypenameLoc);
287 Diag << FixItHint::CreateInsertion(TemplateNameEndLoc,
"_t")
288 << FixItHint::CreateRemoval({QualLoc.getEndLoc(), EndLoc});
291 if (
const auto *DRE = Result.Nodes.getNodeAs<DeclRefExpr>(
Bind)) {
292 if (!DRE->hasQualifier())
294 if (
const auto *CTSD = dyn_cast_if_present<ClassTemplateSpecializationDecl>(
295 DRE->getQualifier().getAsRecordDecl());
297 EmitValueWarning(DRE->getQualifierLoc(), DRE->getEndLoc());
302 if (
const auto *TL = Result.Nodes.getNodeAs<TypedefTypeLoc>(
Bind)) {
303 const NestedNameSpecifierLoc QualLoc = TL->getQualifierLoc();
304 const NestedNameSpecifier NNS = QualLoc.getNestedNameSpecifier();
305 if (
const auto *CTSD = dyn_cast_if_present<ClassTemplateSpecializationDecl>(
306 NNS.getAsRecordDecl());
308 EmitTypeWarning(TL->getQualifierLoc(), TL->getEndLoc(),
309 TL->getElaboratedKeywordLoc());
314 if (
const auto *DSDRE =
315 Result.Nodes.getNodeAs<DependentScopeDeclRefExpr>(
Bind)) {
317 EmitValueWarning(DSDRE->getQualifierLoc(), DSDRE->getEndLoc());
321 if (
const auto *DNTL = Result.Nodes.getNodeAs<DependentNameTypeLoc>(
Bind)) {
322 const NestedNameSpecifierLoc QualLoc = DNTL->getQualifierLoc();
324 EmitTypeWarning(QualLoc, DNTL->getEndLoc(),
325 DNTL->getElaboratedKeywordLoc());
329 if (
const auto *TSTL = Result.Nodes.getNodeAs<TemplateSpecializationTypeLoc>(
331 const auto InnerTL = TSTL->getArgLoc(0)
334 .castAs<TemplateSpecializationTypeLoc>();
336 (TSTL->getBeginLoc().isMacroID() || InnerTL.getBeginLoc().isMacroID()))
339 const auto Diag = diag(TSTL->getBeginLoc(),
"use c++20 type alias");
340 Diag << FixItHint::CreateReplacement(
341 SourceRange(TSTL->getBeginLoc(), InnerTL.getLAngleLoc()),
342 "std::remove_cvref_t<")
343 << FixItHint::CreateRemoval(InnerTL.getRAngleLoc());
Every ClangTidyCheck reports errors through a DiagnosticsEngine provided by this context.