brintos

brintos / llvm-project-archived public Read only

0
0
Text · 4.1 KiB · 78bcc3e Raw
124 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 "AvoidConstOrRefDataMembersCheck.h"10#include "clang/AST/ASTContext.h"11#include "clang/ASTMatchers/ASTMatchFinder.h"12 13using namespace clang::ast_matchers;14 15namespace clang::tidy::cppcoreguidelines {16 17static bool isCopyConstructible(const CXXRecordDecl &Node) {18  if (Node.needsOverloadResolutionForCopyConstructor() &&19      Node.needsImplicitCopyConstructor()) {20    // unresolved21    for (const CXXBaseSpecifier &BS : Node.bases()) {22      const CXXRecordDecl *BRD = BS.getType()->getAsCXXRecordDecl();23      if (BRD != nullptr && !isCopyConstructible(*BRD))24        return false;25    }26  }27  if (Node.hasSimpleCopyConstructor())28    return true;29  for (const CXXConstructorDecl *Ctor : Node.ctors())30    if (Ctor->isCopyConstructor())31      return !Ctor->isDeleted();32  return false;33}34 35static bool isMoveConstructible(const CXXRecordDecl &Node) {36  if (Node.needsOverloadResolutionForMoveConstructor() &&37      Node.needsImplicitMoveConstructor()) {38    // unresolved39    for (const CXXBaseSpecifier &BS : Node.bases()) {40      const CXXRecordDecl *BRD = BS.getType()->getAsCXXRecordDecl();41      if (BRD != nullptr && !isMoveConstructible(*BRD))42        return false;43    }44  }45  if (Node.hasSimpleMoveConstructor())46    return true;47  for (const CXXConstructorDecl *Ctor : Node.ctors())48    if (Ctor->isMoveConstructor())49      return !Ctor->isDeleted();50  return false;51}52 53static bool isCopyAssignable(const CXXRecordDecl &Node) {54  if (Node.needsOverloadResolutionForCopyAssignment() &&55      Node.needsImplicitCopyAssignment()) {56    // unresolved57    for (const CXXBaseSpecifier &BS : Node.bases()) {58      const CXXRecordDecl *BRD = BS.getType()->getAsCXXRecordDecl();59      if (BRD != nullptr && !isCopyAssignable(*BRD))60        return false;61    }62  }63  if (Node.hasSimpleCopyAssignment())64    return true;65  for (const CXXMethodDecl *Method : Node.methods())66    if (Method->isCopyAssignmentOperator())67      return !Method->isDeleted();68  return false;69}70 71static bool isMoveAssignable(const CXXRecordDecl &Node) {72  if (Node.needsOverloadResolutionForMoveAssignment() &&73      Node.needsImplicitMoveAssignment()) {74    // unresolved75    for (const CXXBaseSpecifier &BS : Node.bases()) {76      const CXXRecordDecl *BRD = BS.getType()->getAsCXXRecordDecl();77      if (BRD != nullptr && !isMoveAssignable(*BRD))78        return false;79    }80  }81  if (Node.hasSimpleMoveAssignment())82    return true;83  for (const CXXMethodDecl *Method : Node.methods())84    if (Method->isMoveAssignmentOperator())85      return !Method->isDeleted();86  return false;87}88 89namespace {90 91AST_MATCHER(FieldDecl, isMemberOfLambda) {92  return Node.getParent()->isLambda();93}94 95AST_MATCHER(CXXRecordDecl, isCopyableOrMovable) {96  return isCopyConstructible(Node) || isMoveConstructible(Node) ||97         isCopyAssignable(Node) || isMoveAssignable(Node);98}99 100} // namespace101 102void AvoidConstOrRefDataMembersCheck::registerMatchers(MatchFinder *Finder) {103  Finder->addMatcher(104      fieldDecl(105          unless(isMemberOfLambda()),106          anyOf(107              fieldDecl(hasType(hasCanonicalType(referenceType()))).bind("ref"),108              fieldDecl(hasType(qualType(isConstQualified()))).bind("const")),109          hasDeclContext(cxxRecordDecl(isCopyableOrMovable()))),110      this);111}112 113void AvoidConstOrRefDataMembersCheck::check(114    const MatchFinder::MatchResult &Result) {115  if (const auto *MatchedDecl = Result.Nodes.getNodeAs<FieldDecl>("ref"))116    diag(MatchedDecl->getLocation(), "member %0 of type %1 is a reference")117        << MatchedDecl << MatchedDecl->getType();118  if (const auto *MatchedDecl = Result.Nodes.getNodeAs<FieldDecl>("const"))119    diag(MatchedDecl->getLocation(), "member %0 of type %1 is const qualified")120        << MatchedDecl << MatchedDecl->getType();121}122 123} // namespace clang::tidy::cppcoreguidelines124