clang-tools  3.8.0
AssignOperatorSignatureCheck.cpp
Go to the documentation of this file.
1 //===--- AssignOperatorSignatureCheck.cpp - clang-tidy ----------*- C++ -*-===//
2 //
3 // The LLVM Compiler Infrastructure
4 //
5 // This file is distributed under the University of Illinois Open Source
6 // License. See LICENSE.TXT for details.
7 //
8 //===----------------------------------------------------------------------===//
9 
11 #include "clang/ASTMatchers/ASTMatchFinder.h"
12 #include "clang/ASTMatchers/ASTMatchers.h"
13 
14 using namespace clang::ast_matchers;
15 
16 namespace clang {
17 namespace tidy {
18 namespace misc {
19 
20 void AssignOperatorSignatureCheck::registerMatchers(
21  ast_matchers::MatchFinder *Finder) {
22  // Only register the matchers for C++; the functionality currently does not
23  // provide any benefit to other languages, despite being benign.
24  if (!getLangOpts().CPlusPlus)
25  return;
26 
27  const auto HasGoodReturnType = cxxMethodDecl(returns(
28  lValueReferenceType(pointee(unless(isConstQualified()),
29  hasDeclaration(equalsBoundNode("class"))))));
30 
31  const auto IsSelf = qualType(
32  anyOf(hasDeclaration(equalsBoundNode("class")),
33  referenceType(pointee(hasDeclaration(equalsBoundNode("class"))))));
34  const auto IsSelfAssign =
35  cxxMethodDecl(unless(anyOf(isDeleted(), isPrivate(), isImplicit())),
36  hasName("operator="), ofClass(recordDecl().bind("class")),
37  hasParameter(0, parmVarDecl(hasType(IsSelf))))
38  .bind("method");
39 
40  Finder->addMatcher(
41  cxxMethodDecl(IsSelfAssign, unless(HasGoodReturnType)).bind("ReturnType"),
42  this);
43 
44  const auto BadSelf = referenceType(
45  anyOf(lValueReferenceType(pointee(unless(isConstQualified()))),
46  rValueReferenceType(pointee(isConstQualified()))));
47 
48  Finder->addMatcher(
49  cxxMethodDecl(IsSelfAssign,
50  hasParameter(0, parmVarDecl(hasType(BadSelf))))
51  .bind("ArgumentType"),
52  this);
53 
54  Finder->addMatcher(
55  cxxMethodDecl(IsSelfAssign, anyOf(isConst(), isVirtual())).bind("cv"),
56  this);
57 }
58 
59 void AssignOperatorSignatureCheck::check(
60  const MatchFinder::MatchResult &Result) {
61  const auto* Method = Result.Nodes.getNodeAs<CXXMethodDecl>("method");
62  std::string Name = Method->getParent()->getName();
63 
64  static const char *const Messages[][2] = {
65  {"ReturnType", "operator=() should return '%0&'"},
66  {"ArgumentType", "operator=() should take '%0 const&', '%0&&' or '%0'"},
67  {"cv", "operator=() should not be marked '%1'"}
68  };
69 
70  for (const auto &Message : Messages) {
71  if (Result.Nodes.getNodeAs<Decl>(Message[0]))
72  diag(Method->getLocStart(), Message[1])
73  << Name << (Method->isConst() ? "const" : "virtual");
74  }
75 }
76 
77 } // namespace misc
78 } // namespace tidy
79 } // namespace clang
StringHandle Name
std::unique_ptr< ast_matchers::MatchFinder > Finder
Definition: ClangTidy.cpp:188
const NamedDecl * Result
Definition: USRFinder.cpp:121