clang-tools 10.0.0

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 if (!getLangOpts().CPlusPlus)
22 return;
23
24 Finder->addMatcher(functionDecl(anyOf(hasOverloadedOperatorName("++"),
25 hasOverloadedOperatorName("--")),
26 unless(isInstantiated()))
27 .bind("decl"),
28 this);
29 }
30
31 void PostfixOperatorCheck::check(const MatchFinder::MatchResult &Result) {
32 const auto *FuncDecl = Result.Nodes.getNodeAs<FunctionDecl>("decl");
33
34 bool HasThis = false;
35 if (const auto *MethodDecl = dyn_cast<CXXMethodDecl>(FuncDecl))
36 HasThis = MethodDecl->isInstance();
37
38 // Check if the operator is a postfix one.
39 if (FuncDecl->getNumParams() != (HasThis ? 1 : 2))
40 return;
41
42 SourceRange ReturnRange = FuncDecl->getReturnTypeSourceRange();
43 SourceLocation Location = ReturnRange.getBegin();
44 if (!Location.isValid())
45 return;
46
47 QualType ReturnType = FuncDecl->getReturnType();
48
49 // Warn when the operators return a reference.
50 if (const auto *RefType = ReturnType->getAs<ReferenceType>()) {
51 auto Diag = diag(Location, "overloaded %0 returns a reference instead of a "
52 "constant object type")
53 << FuncDecl;
54
55 if (Location.isMacroID() || ReturnType->getAs<TypedefType>() ||
56 RefType->getPointeeTypeAsWritten()->getAs<TypedefType>())
57 return;
58
59 QualType ReplaceType =
60 ReturnType.getNonReferenceType().getLocalUnqualifiedType();
61 // The getReturnTypeSourceRange omits the qualifiers. We do not want to
62 // duplicate the const.
63 if (!ReturnType->getPointeeType().isConstQualified())
64 ReplaceType.addConst();
65
66 Diag << FixItHint::CreateReplacement(
67 ReturnRange,
68 ReplaceType.getAsString(Result.Context->getPrintingPolicy()) + " ");
69
70 return;
71 }
72
73 if (ReturnType.isConstQualified() || ReturnType->isBuiltinType() ||
74 ReturnType->isPointerType())
75 return;
76
77 auto Diag =
78 diag(Location, "overloaded %0 returns a non-constant object instead of a "
79 "constant object type")
80 << FuncDecl;
81
82 if (!Location.isMacroID() && !ReturnType->getAs<TypedefType>())
83 Diag << FixItHint::CreateInsertion(Location, "const ");
84 }
85
86 } // namespace cert
87 } // namespace tidy
88 } // namespace clang
clang::ast_matchers
Definition: AbseilMatcher.h:14
PostfixOperatorCheck.h
ReturnType
std::string ReturnType
Definition: CodeComplete.cpp:395
clang
===– Representation.cpp - ClangDoc Representation --------—*- C++ -*-===//
Definition: ApplyReplacements.h:27
Location
Definition: Modularize.cpp:383