clang-tools  16.0.0git
PostfixOperatorCheck.cpp
Go to the documentation of this file.
1 //===--- PostfixOperatorCheck.cpp - clang-tidy-----------------------------===//
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-exception
6 //
7 //===----------------------------------------------------------------------===//
8 
9 #include "PostfixOperatorCheck.h"
10 #include "clang/AST/ASTContext.h"
11 #include "clang/ASTMatchers/ASTMatchFinder.h"
12 #include "clang/Lex/Lexer.h"
13 
14 using namespace clang::ast_matchers;
15 
16 namespace clang {
17 namespace tidy {
18 namespace cert {
19 
20 void PostfixOperatorCheck::registerMatchers(MatchFinder *Finder) {
21  Finder->addMatcher(functionDecl(hasAnyOverloadedOperatorName("++", "--"),
22  unless(isInstantiated()))
23  .bind("decl"),
24  this);
25 }
26 
27 void PostfixOperatorCheck::check(const MatchFinder::MatchResult &Result) {
28  const auto *FuncDecl = Result.Nodes.getNodeAs<FunctionDecl>("decl");
29 
30  bool HasThis = false;
31  if (const auto *MethodDecl = dyn_cast<CXXMethodDecl>(FuncDecl))
32  HasThis = MethodDecl->isInstance();
33 
34  // Check if the operator is a postfix one.
35  if (FuncDecl->getNumParams() != (HasThis ? 1 : 2))
36  return;
37 
38  SourceRange ReturnRange = FuncDecl->getReturnTypeSourceRange();
39  SourceLocation Location = ReturnRange.getBegin();
40  if (!Location.isValid())
41  return;
42 
43  QualType ReturnType = FuncDecl->getReturnType();
44 
45  // Warn when the operators return a reference.
46  if (const auto *RefType = ReturnType->getAs<ReferenceType>()) {
47  auto Diag = diag(Location, "overloaded %0 returns a reference instead of a "
48  "constant object type")
49  << FuncDecl;
50 
51  if (Location.isMacroID() || ReturnType->getAs<TypedefType>() ||
52  RefType->getPointeeTypeAsWritten()->getAs<TypedefType>())
53  return;
54 
55  QualType ReplaceType =
56  ReturnType.getNonReferenceType().getLocalUnqualifiedType();
57  // The getReturnTypeSourceRange omits the qualifiers. We do not want to
58  // duplicate the const.
59  if (!ReturnType->getPointeeType().isConstQualified())
60  ReplaceType.addConst();
61 
62  Diag << FixItHint::CreateReplacement(
63  ReturnRange,
64  ReplaceType.getAsString(Result.Context->getPrintingPolicy()) + " ");
65 
66  return;
67  }
68 
69  if (ReturnType.isConstQualified() || ReturnType->isBuiltinType() ||
70  ReturnType->isPointerType())
71  return;
72 
73  auto Diag =
74  diag(Location, "overloaded %0 returns a non-constant object instead of a "
75  "constant object type")
76  << FuncDecl;
77 
78  if (!Location.isMacroID() && !ReturnType->getAs<TypedefType>())
79  Diag << FixItHint::CreateInsertion(Location, "const ");
80 }
81 
82 } // namespace cert
83 } // namespace tidy
84 } // namespace clang
Location
Definition: Modularize.cpp:381
clang::ast_matchers
Definition: AbseilMatcher.h:14
PostfixOperatorCheck.h
clang
===– Representation.cpp - ClangDoc Representation --------—*- C++ -*-===//
Definition: ApplyReplacements.h:27
clang::clangd::check
bool check(llvm::StringRef File, const ThreadsafeFS &TFS, const ClangdLSPServer::Options &Opts)
Definition: Check.cpp:418
ReturnType
std::string ReturnType
Definition: CodeComplete.cpp:459