diff options
author | Alexander Kornienko <alexfh@google.com> | 2014-06-18 09:33:46 +0000 |
---|---|---|
committer | Alexander Kornienko <alexfh@google.com> | 2014-06-18 09:33:46 +0000 |
commit | 72f1e754a78e3504983cfe11e2888a09a2bc9e79 (patch) | |
tree | edcff6993618a7ce09ad14ffeb6a312d31fd7723 /clang-tools-extra/clang-tidy/google/ExplicitConstructorCheck.cpp | |
parent | 853a232e6647612fee168b776add72f510d2e0d3 (diff) | |
download | bcm5719-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.cpp | 85 |
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 |