clang-tools 8.0.0

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