summaryrefslogtreecommitdiffstats
path: root/clang-tools-extra/clang-tidy/performance/UnnecessaryCopyInitialization.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'clang-tools-extra/clang-tidy/performance/UnnecessaryCopyInitialization.cpp')
-rw-r--r--clang-tools-extra/clang-tidy/performance/UnnecessaryCopyInitialization.cpp73
1 files changed, 73 insertions, 0 deletions
diff --git a/clang-tools-extra/clang-tidy/performance/UnnecessaryCopyInitialization.cpp b/clang-tools-extra/clang-tidy/performance/UnnecessaryCopyInitialization.cpp
new file mode 100644
index 00000000000..f1c24f8ca89
--- /dev/null
+++ b/clang-tools-extra/clang-tidy/performance/UnnecessaryCopyInitialization.cpp
@@ -0,0 +1,73 @@
+//===--- UnnecessaryCopyInitialization.cpp - clang-tidy--------------------===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "UnnecessaryCopyInitialization.h"
+
+#include "../utils/LexerUtils.h"
+#include "../utils/Matchers.h"
+
+namespace clang {
+namespace tidy {
+namespace performance {
+
+using namespace ::clang::ast_matchers;
+
+namespace {
+AST_MATCHER(VarDecl, isLocalVarDecl) { return Node.isLocalVarDecl(); }
+AST_MATCHER(QualType, isPointerType) { return Node->isPointerType(); }
+} // namespace
+
+void UnnecessaryCopyInitialization::registerMatchers(
+ ast_matchers::MatchFinder *Finder) {
+ auto ConstReference = referenceType(pointee(qualType(isConstQualified())));
+ auto ConstOrConstReference =
+ allOf(anyOf(ConstReference, isConstQualified()),
+ unless(allOf(isPointerType(), unless(pointerType(pointee(qualType(
+ isConstQualified())))))));
+ // Match method call expressions where the this argument is a const
+ // type or const reference. This returned const reference is highly likely to
+ // outlive the local const reference of the variable being declared.
+ // The assumption is that the const reference being returned either points
+ // to a global static variable or to a member of the called object.
+ auto ConstRefReturningMethodCallOfConstParam = cxxMemberCallExpr(
+ callee(cxxMethodDecl(returns(ConstReference))),
+ on(declRefExpr(to(varDecl(hasType(qualType(ConstOrConstReference)))))));
+ auto ConstRefReturningFunctionCall =
+ callExpr(callee(functionDecl(returns(ConstReference))),
+ unless(callee(cxxMethodDecl())));
+ Finder->addMatcher(
+ varDecl(
+ isLocalVarDecl(), hasType(isConstQualified()),
+ hasType(matchers::isExpensiveToCopy()),
+ hasInitializer(cxxConstructExpr(
+ hasDeclaration(cxxConstructorDecl(isCopyConstructor())),
+ hasArgument(0, anyOf(ConstRefReturningFunctionCall,
+ ConstRefReturningMethodCallOfConstParam)))))
+ .bind("varDecl"),
+ this);
+}
+
+void UnnecessaryCopyInitialization::check(
+ const ast_matchers::MatchFinder::MatchResult &Result) {
+ const auto *Var = Result.Nodes.getNodeAs<VarDecl>("varDecl");
+ SourceLocation AmpLocation = Var->getLocation();
+ auto Token = lexer_utils::getPreviousNonCommentToken(*Result.Context,
+ Var->getLocation());
+ if (!Token.is(tok::unknown)) {
+ AmpLocation = Token.getLocation().getLocWithOffset(Token.getLength());
+ }
+ diag(Var->getLocation(),
+ "the const qualified variable '%0' is copy-constructed from a "
+ "const reference; consider making it a const reference")
+ << Var->getName() << FixItHint::CreateInsertion(AmpLocation, "&");
+}
+
+} // namespace performance
+} // namespace tidy
+} // namespace clang
OpenPOWER on IntegriCloud