1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980 |
- //===--- PostfixOperatorCheck.cpp - clang-tidy-----------------------------===//
- //
- // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
- // See https://llvm.org/LICENSE.txt for license information.
- // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
- //
- //===----------------------------------------------------------------------===//
- #include "PostfixOperatorCheck.h"
- #include "clang/AST/ASTContext.h"
- #include "clang/ASTMatchers/ASTMatchFinder.h"
- #include "clang/Lex/Lexer.h"
- using namespace clang::ast_matchers;
- namespace clang::tidy::cert {
- void PostfixOperatorCheck::registerMatchers(MatchFinder *Finder) {
- Finder->addMatcher(functionDecl(hasAnyOverloadedOperatorName("++", "--"),
- unless(isInstantiated()))
- .bind("decl"),
- this);
- }
- void PostfixOperatorCheck::check(const MatchFinder::MatchResult &Result) {
- const auto *FuncDecl = Result.Nodes.getNodeAs<FunctionDecl>("decl");
- bool HasThis = false;
- if (const auto *MethodDecl = dyn_cast<CXXMethodDecl>(FuncDecl))
- HasThis = MethodDecl->isInstance();
- // Check if the operator is a postfix one.
- if (FuncDecl->getNumParams() != (HasThis ? 1 : 2))
- return;
- SourceRange ReturnRange = FuncDecl->getReturnTypeSourceRange();
- SourceLocation Location = ReturnRange.getBegin();
- if (!Location.isValid())
- return;
- QualType ReturnType = FuncDecl->getReturnType();
- // Warn when the operators return a reference.
- if (const auto *RefType = ReturnType->getAs<ReferenceType>()) {
- auto Diag = diag(Location, "overloaded %0 returns a reference instead of a "
- "constant object type")
- << FuncDecl;
- if (Location.isMacroID() || ReturnType->getAs<TypedefType>() ||
- RefType->getPointeeTypeAsWritten()->getAs<TypedefType>())
- return;
- QualType ReplaceType =
- ReturnType.getNonReferenceType().getLocalUnqualifiedType();
- // The getReturnTypeSourceRange omits the qualifiers. We do not want to
- // duplicate the const.
- if (!ReturnType->getPointeeType().isConstQualified())
- ReplaceType.addConst();
- Diag << FixItHint::CreateReplacement(
- ReturnRange,
- ReplaceType.getAsString(Result.Context->getPrintingPolicy()) + " ");
- return;
- }
- if (ReturnType.isConstQualified() || ReturnType->isBuiltinType() ||
- ReturnType->isPointerType())
- return;
- auto Diag =
- diag(Location, "overloaded %0 returns a non-constant object instead of a "
- "constant object type")
- << FuncDecl;
- if (!Location.isMacroID() && !ReturnType->getAs<TypedefType>())
- Diag << FixItHint::CreateInsertion(Location, "const ");
- }
- } // namespace clang::tidy::cert
|