238 auto EmitValueWarning = [
this, &Result](
const NestedNameSpecifierLoc &QualLoc,
239 SourceLocation EndLoc) {
240 SourceLocation TemplateNameEndLoc;
242 QualLoc.getAsTypeLoc().getAs<TemplateSpecializationTypeLoc>())
243 TemplateNameEndLoc = Lexer::getLocForEndOfToken(
244 TSTL.getTemplateNameLoc(), 0, *Result.SourceManager,
245 Result.Context->getLangOpts());
249 if (EndLoc.isMacroID() || QualLoc.getEndLoc().isMacroID() ||
250 TemplateNameEndLoc.isMacroID()) {
253 diag(QualLoc.getBeginLoc(),
"use c++17 style variable templates");
256 diag(QualLoc.getBeginLoc(),
"use c++17 style variable templates")
257 << FixItHint::CreateInsertion(TemplateNameEndLoc,
"_v")
258 << FixItHint::CreateRemoval({QualLoc.getEndLoc(), EndLoc});
261 auto EmitTypeWarning = [
this, &Result](
const NestedNameSpecifierLoc &QualLoc,
262 SourceLocation EndLoc,
263 SourceLocation TypenameLoc) {
264 SourceLocation TemplateNameEndLoc;
266 QualLoc.getAsTypeLoc().getAs<TemplateSpecializationTypeLoc>())
267 TemplateNameEndLoc = Lexer::getLocForEndOfToken(
268 TSTL.getTemplateNameLoc(), 0, *Result.SourceManager,
269 Result.Context->getLangOpts());
273 if (EndLoc.isMacroID() || QualLoc.getEndLoc().isMacroID() ||
274 TemplateNameEndLoc.isMacroID() || TypenameLoc.isMacroID()) {
277 diag(QualLoc.getBeginLoc(),
"use c++14 style type templates");
280 auto Diag = diag(QualLoc.getBeginLoc(),
"use c++14 style type templates");
282 if (TypenameLoc.isValid())
283 Diag << FixItHint::CreateRemoval(TypenameLoc);
284 Diag << FixItHint::CreateInsertion(TemplateNameEndLoc,
"_t")
285 << FixItHint::CreateRemoval({QualLoc.getEndLoc(), EndLoc});
288 if (
const auto *DRE = Result.Nodes.getNodeAs<DeclRefExpr>(
Bind)) {
289 if (!DRE->hasQualifier())
291 if (
const auto *CTSD = dyn_cast_if_present<ClassTemplateSpecializationDecl>(
292 DRE->getQualifier().getAsRecordDecl())) {
294 EmitValueWarning(DRE->getQualifierLoc(), DRE->getEndLoc());
299 if (
const auto *TL = Result.Nodes.getNodeAs<TypedefTypeLoc>(
Bind)) {
300 const NestedNameSpecifierLoc QualLoc = TL->getQualifierLoc();
301 const NestedNameSpecifier NNS = QualLoc.getNestedNameSpecifier();
302 if (
const auto *CTSD = dyn_cast_if_present<ClassTemplateSpecializationDecl>(
303 NNS.getAsRecordDecl())) {
305 EmitTypeWarning(TL->getQualifierLoc(), TL->getEndLoc(),
306 TL->getElaboratedKeywordLoc());
311 if (
const auto *DSDRE =
312 Result.Nodes.getNodeAs<DependentScopeDeclRefExpr>(
Bind)) {
314 EmitValueWarning(DSDRE->getQualifierLoc(), DSDRE->getEndLoc());
318 if (
const auto *DNTL = Result.Nodes.getNodeAs<DependentNameTypeLoc>(
Bind)) {
319 const NestedNameSpecifierLoc QualLoc = DNTL->getQualifierLoc();
321 EmitTypeWarning(QualLoc, DNTL->getEndLoc(),
322 DNTL->getElaboratedKeywordLoc());
326 if (
const auto *TSTL = Result.Nodes.getNodeAs<TemplateSpecializationTypeLoc>(
328 auto InnerTL = TSTL->getArgLoc(0)
331 .castAs<TemplateSpecializationTypeLoc>();
333 (TSTL->getBeginLoc().isMacroID() || InnerTL.getBeginLoc().isMacroID()))
336 auto Diag = diag(TSTL->getBeginLoc(),
"use c++20 type alias");
337 Diag << FixItHint::CreateReplacement(
338 SourceRange(TSTL->getBeginLoc(), InnerTL.getLAngleLoc()),
339 "std::remove_cvref_t<")
340 << FixItHint::CreateRemoval(InnerTL.getRAngleLoc());
Every ClangTidyCheck reports errors through a DiagnosticsEngine provided by this context.