summaryrefslogtreecommitdiffstats
path: root/clang-tools-extra/clang-tidy/google/ExplicitConstructorCheck.cpp
diff options
context:
space:
mode:
authorAlexander Kornienko <alexfh@google.com>2014-06-18 09:33:46 +0000
committerAlexander Kornienko <alexfh@google.com>2014-06-18 09:33:46 +0000
commit72f1e754a78e3504983cfe11e2888a09a2bc9e79 (patch)
treeedcff6993618a7ce09ad14ffeb6a312d31fd7723 /clang-tools-extra/clang-tidy/google/ExplicitConstructorCheck.cpp
parent853a232e6647612fee168b776add72f510d2e0d3 (diff)
downloadbcm5719-llvm-72f1e754a78e3504983cfe11e2888a09a2bc9e79.tar.gz
bcm5719-llvm-72f1e754a78e3504983cfe11e2888a09a2bc9e79.zip
Move google-explicit-constructor check to a separate source file.
Summary: No functional changes. Reviewers: djasper Reviewed By: djasper Subscribers: cfe-commits Differential Revision: http://reviews.llvm.org/D4188 llvm-svn: 211154
Diffstat (limited to 'clang-tools-extra/clang-tidy/google/ExplicitConstructorCheck.cpp')
-rw-r--r--clang-tools-extra/clang-tidy/google/ExplicitConstructorCheck.cpp85
1 files changed, 85 insertions, 0 deletions
diff --git a/clang-tools-extra/clang-tidy/google/ExplicitConstructorCheck.cpp b/clang-tools-extra/clang-tidy/google/ExplicitConstructorCheck.cpp
new file mode 100644
index 00000000000..764f18031c8
--- /dev/null
+++ b/clang-tools-extra/clang-tidy/google/ExplicitConstructorCheck.cpp
@@ -0,0 +1,85 @@
+//===--- ExplicitConstructorCheck.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 "ExplicitConstructorCheck.h"
+#include "clang/AST/ASTContext.h"
+#include "clang/ASTMatchers/ASTMatchFinder.h"
+#include "clang/ASTMatchers/ASTMatchers.h"
+#include "clang/Lex/Lexer.h"
+
+using namespace clang::ast_matchers;
+
+namespace clang {
+namespace tidy {
+
+void ExplicitConstructorCheck::registerMatchers(MatchFinder *Finder) {
+ Finder->addMatcher(constructorDecl().bind("ctor"), this);
+}
+
+// Looks for the token matching the predicate and returns the range of the found
+// token including trailing whitespace.
+SourceRange FindToken(const SourceManager &Sources, LangOptions LangOpts,
+ SourceLocation StartLoc, SourceLocation EndLoc,
+ bool (*Pred)(const Token &)) {
+ if (StartLoc.isMacroID() || EndLoc.isMacroID())
+ return SourceRange();
+ FileID File = Sources.getFileID(Sources.getSpellingLoc(StartLoc));
+ StringRef Buf = Sources.getBufferData(File);
+ const char *StartChar = Sources.getCharacterData(StartLoc);
+ Lexer Lex(StartLoc, LangOpts, StartChar, StartChar, Buf.end());
+ Lex.SetCommentRetentionState(true);
+ Token Tok;
+ do {
+ Lex.LexFromRawLexer(Tok);
+ if (Pred(Tok)) {
+ Token NextTok;
+ Lex.LexFromRawLexer(NextTok);
+ return SourceRange(Tok.getLocation(), NextTok.getLocation());
+ }
+ } while (Tok.isNot(tok::eof) && Tok.getLocation() < EndLoc);
+
+ return SourceRange();
+}
+
+void ExplicitConstructorCheck::check(const MatchFinder::MatchResult &Result) {
+ const CXXConstructorDecl *Ctor =
+ Result.Nodes.getNodeAs<CXXConstructorDecl>("ctor");
+ // Do not be confused: isExplicit means 'explicit' keyword is present,
+ // isImplicit means that it's a compiler-generated constructor.
+ if (Ctor->isOutOfLine() || Ctor->isImplicit() || Ctor->isDeleted())
+ return;
+
+ if (Ctor->isExplicit() && Ctor->isCopyOrMoveConstructor()) {
+ auto isKWExplicit = [](const Token &Tok) {
+ return Tok.is(tok::raw_identifier) &&
+ Tok.getRawIdentifier() == "explicit";
+ };
+ SourceRange ExplicitTokenRange =
+ FindToken(*Result.SourceManager, Result.Context->getLangOpts(),
+ Ctor->getOuterLocStart(), Ctor->getLocEnd(), isKWExplicit);
+ DiagnosticBuilder Diag =
+ diag(Ctor->getLocation(), "%0 constructor declared explicit.")
+ << (Ctor->isMoveConstructor() ? "Move" : "Copy");
+ if (ExplicitTokenRange.isValid()) {
+ Diag << FixItHint::CreateRemoval(
+ CharSourceRange::getCharRange(ExplicitTokenRange));
+ }
+ }
+
+ if (Ctor->isExplicit() || Ctor->isCopyOrMoveConstructor() ||
+ Ctor->getNumParams() == 0 || Ctor->getMinRequiredArguments() > 1)
+ return;
+
+ SourceLocation Loc = Ctor->getLocation();
+ diag(Loc, "Single-argument constructors must be explicit")
+ << FixItHint::CreateInsertion(Loc, "explicit ");
+}
+
+} // namespace tidy
+} // namespace clang
OpenPOWER on IntegriCloud