71 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 "StdAllocatorConstCheck.h"10#include "clang/ASTMatchers/ASTMatchFinder.h"11 12using namespace clang::ast_matchers;13 14namespace clang::tidy::portability {15 16void StdAllocatorConstCheck::registerMatchers(MatchFinder *Finder) {17 // Match std::allocator<const T>.18 auto AllocatorConst = qualType(hasCanonicalType(19 recordType(hasDeclaration(classTemplateSpecializationDecl(20 hasName("::std::allocator"),21 hasTemplateArgument(0,22 refersToType(qualType(isConstQualified()))))))));23 24 auto HasContainerName =25 hasAnyName("::std::vector", "::std::deque", "::std::list",26 "::std::multiset", "::std::set", "::std::unordered_multiset",27 "::std::unordered_set", "::absl::flat_hash_set");28 29 // Match `std::vector<const T> var;` and other common containers like deque,30 // list, and absl::flat_hash_set. Containers like queue and stack use deque31 // but do not directly use std::allocator as a template argument, so they32 // aren't caught.33 Finder->addMatcher(34 typeLoc(35 anyOf(templateSpecializationTypeLoc(),36 qualifiedTypeLoc(37 hasUnqualifiedLoc(templateSpecializationTypeLoc()))),38 loc(qualType(anyOf(39 recordType(hasDeclaration(classTemplateSpecializationDecl(40 HasContainerName,41 anyOf(42 hasTemplateArgument(1, refersToType(AllocatorConst)),43 hasTemplateArgument(2, refersToType(AllocatorConst)),44 hasTemplateArgument(3, refersToType(AllocatorConst)))))),45 // Match std::vector<const dependent>46 templateSpecializationType(47 templateArgumentCountIs(1),48 hasTemplateArgument(49 0, refersToType(qualType(isConstQualified()))),50 hasDeclaration(namedDecl(HasContainerName)))))))51 .bind("type_loc"),52 this);53}54 55void StdAllocatorConstCheck::check(const MatchFinder::MatchResult &Result) {56 const auto *T = Result.Nodes.getNodeAs<TypeLoc>("type_loc");57 if (!T)58 return;59 // Exclude TypeLoc matches in STL headers.60 if (isSystem(Result.Context->getSourceManager().getFileCharacteristic(61 T->getBeginLoc())))62 return;63 64 diag(T->getBeginLoc(),65 "container using std::allocator<const T> is a deprecated libc++ "66 "extension; remove const for compatibility with other standard "67 "libraries");68}69 70} // namespace clang::tidy::portability71