70 lines · cpp
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-exception6//7//===----------------------------------------------------------------------===//8 9#include "IncorrectEnableIfCheck.h"10#include "clang/AST/ASTContext.h"11#include "clang/ASTMatchers/ASTMatchFinder.h"12 13using namespace clang::ast_matchers;14 15namespace clang::tidy::bugprone {16 17namespace {18 19AST_MATCHER_P(TemplateTypeParmDecl, hasUnnamedDefaultArgument,20 ast_matchers::internal::Matcher<TypeLoc>, InnerMatcher) {21 if (Node.getIdentifier() != nullptr || !Node.hasDefaultArgument() ||22 Node.getDefaultArgument().getArgument().isNull())23 return false;24 25 const TypeLoc DefaultArgTypeLoc =26 Node.getDefaultArgument().getTypeSourceInfo()->getTypeLoc();27 return InnerMatcher.matches(DefaultArgTypeLoc, Finder, Builder);28}29 30} // namespace31 32void IncorrectEnableIfCheck::registerMatchers(MatchFinder *Finder) {33 Finder->addMatcher(34 templateTypeParmDecl(35 hasUnnamedDefaultArgument(templateSpecializationTypeLoc(36 loc(qualType(hasDeclaration(namedDecl(37 hasName("::std::enable_if"))))))38 .bind("enable_if_specialization")))39 .bind("enable_if"),40 this);41}42 43void IncorrectEnableIfCheck::check(const MatchFinder::MatchResult &Result) {44 const auto *EnableIf =45 Result.Nodes.getNodeAs<TemplateTypeParmDecl>("enable_if");46 const auto *EnableIfSpecializationLoc =47 Result.Nodes.getNodeAs<TemplateSpecializationTypeLoc>(48 "enable_if_specialization");49 50 if (!EnableIf || !EnableIfSpecializationLoc)51 return;52 53 const SourceManager &SM = *Result.SourceManager;54 const SourceLocation RAngleLoc =55 SM.getExpansionLoc(EnableIfSpecializationLoc->getRAngleLoc());56 57 auto Diag = diag(EnableIf->getBeginLoc(),58 "incorrect std::enable_if usage detected; use "59 "'typename std::enable_if<...>::type'");60 // FIXME: This should handle the enable_if specialization already having an61 // elaborated keyword.62 if (!getLangOpts().CPlusPlus20) {63 Diag << FixItHint::CreateInsertion(EnableIfSpecializationLoc->getBeginLoc(),64 "typename ");65 }66 Diag << FixItHint::CreateInsertion(RAngleLoc.getLocWithOffset(1), "::type");67}68 69} // namespace clang::tidy::bugprone70