[clang][modules] Don't prevent translation of FW_Private includes when explicitly...
[llvm-project.git] / clang-tools-extra / clang-tidy / cert / PostfixOperatorCheck.cpp
blob8ff63ade7315db8531caf8e68a6d7919e5db64e6
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 //===----------------------------------------------------------------------===//
9 #include "PostfixOperatorCheck.h"
10 #include "clang/AST/ASTContext.h"
11 #include "clang/ASTMatchers/ASTMatchFinder.h"
12 #include "clang/Lex/Lexer.h"
14 using namespace clang::ast_matchers;
16 namespace clang::tidy::cert {
18 void PostfixOperatorCheck::registerMatchers(MatchFinder *Finder) {
19 Finder->addMatcher(functionDecl(hasAnyOverloadedOperatorName("++", "--"),
20 unless(isInstantiated()))
21 .bind("decl"),
22 this);
25 void PostfixOperatorCheck::check(const MatchFinder::MatchResult &Result) {
26 const auto *FuncDecl = Result.Nodes.getNodeAs<FunctionDecl>("decl");
28 bool HasThis = false;
29 if (const auto *MethodDecl = dyn_cast<CXXMethodDecl>(FuncDecl))
30 HasThis = MethodDecl->isInstance();
32 // Check if the operator is a postfix one.
33 if (FuncDecl->getNumParams() != (HasThis ? 1 : 2))
34 return;
36 SourceRange ReturnRange = FuncDecl->getReturnTypeSourceRange();
37 SourceLocation Location = ReturnRange.getBegin();
38 if (!Location.isValid())
39 return;
41 QualType ReturnType = FuncDecl->getReturnType();
43 // Warn when the operators return a reference.
44 if (const auto *RefType = ReturnType->getAs<ReferenceType>()) {
45 auto Diag = diag(Location, "overloaded %0 returns a reference instead of a "
46 "constant object type")
47 << FuncDecl;
49 if (Location.isMacroID() || ReturnType->getAs<TypedefType>() ||
50 RefType->getPointeeTypeAsWritten()->getAs<TypedefType>())
51 return;
53 QualType ReplaceType =
54 ReturnType.getNonReferenceType().getLocalUnqualifiedType();
55 // The getReturnTypeSourceRange omits the qualifiers. We do not want to
56 // duplicate the const.
57 if (!ReturnType->getPointeeType().isConstQualified())
58 ReplaceType.addConst();
60 Diag << FixItHint::CreateReplacement(
61 ReturnRange,
62 ReplaceType.getAsString(Result.Context->getPrintingPolicy()) + " ");
64 return;
67 if (ReturnType.isConstQualified() || ReturnType->isBuiltinType() ||
68 ReturnType->isPointerType())
69 return;
71 auto Diag =
72 diag(Location, "overloaded %0 returns a non-constant object instead of a "
73 "constant object type")
74 << FuncDecl;
76 if (!Location.isMacroID() && !ReturnType->getAs<TypedefType>())
77 Diag << FixItHint::CreateInsertion(Location, "const ");
80 } // namespace clang::tidy::cert