forked from OSchip/llvm-project
				
			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
This commit is contained in:
		
							parent
							
								
									853a232e66
								
							
						
					
					
						commit
						72f1e754a7
					
				| 
						 | 
					@ -1,6 +1,7 @@
 | 
				
			||||||
set(LLVM_LINK_COMPONENTS support)
 | 
					set(LLVM_LINK_COMPONENTS support)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
add_clang_library(clangTidyGoogleModule
 | 
					add_clang_library(clangTidyGoogleModule
 | 
				
			||||||
 | 
					  ExplicitConstructorCheck.cpp
 | 
				
			||||||
  GoogleTidyModule.cpp
 | 
					  GoogleTidyModule.cpp
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  LINK_LIBS
 | 
					  LINK_LIBS
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -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
 | 
				
			||||||
| 
						 | 
					@ -1,4 +1,4 @@
 | 
				
			||||||
//===--- GoogleTidyModule.h - clang-tidy ------------------------*- C++ -*-===//
 | 
					//===--- ExplicitConstructorCheck.h - clang-tidy ----------------*- C++ -*-===//
 | 
				
			||||||
//
 | 
					//
 | 
				
			||||||
//                     The LLVM Compiler Infrastructure
 | 
					//                     The LLVM Compiler Infrastructure
 | 
				
			||||||
//
 | 
					//
 | 
				
			||||||
| 
						 | 
					@ -7,8 +7,8 @@
 | 
				
			||||||
//
 | 
					//
 | 
				
			||||||
//===----------------------------------------------------------------------===//
 | 
					//===----------------------------------------------------------------------===//
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#ifndef LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_GOOGLE_GOOGLE_TIDY_MODULE_H
 | 
					#ifndef LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_GOOGLE_EXPLICIT_CONSTRUCTOR_CHECK_H
 | 
				
			||||||
#define LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_GOOGLE_GOOGLE_TIDY_MODULE_H
 | 
					#define LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_GOOGLE_EXPLICIT_CONSTRUCTOR_CHECK_H
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#include "../ClangTidy.h"
 | 
					#include "../ClangTidy.h"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -28,4 +28,4 @@ public:
 | 
				
			||||||
} // namespace tidy
 | 
					} // namespace tidy
 | 
				
			||||||
} // namespace clang
 | 
					} // namespace clang
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#endif // LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_GOOGLE_GOOGLE_TIDY_MODULE_H
 | 
					#endif // LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_GOOGLE_EXPLICIT_CONSTRUCTOR_CHECK_H
 | 
				
			||||||
| 
						 | 
					@ -7,87 +7,16 @@
 | 
				
			||||||
//
 | 
					//
 | 
				
			||||||
//===----------------------------------------------------------------------===//
 | 
					//===----------------------------------------------------------------------===//
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#include "GoogleTidyModule.h"
 | 
					 | 
				
			||||||
#include "../ClangTidy.h"
 | 
					#include "../ClangTidy.h"
 | 
				
			||||||
#include "../ClangTidyModule.h"
 | 
					#include "../ClangTidyModule.h"
 | 
				
			||||||
#include "../ClangTidyModuleRegistry.h"
 | 
					#include "../ClangTidyModuleRegistry.h"
 | 
				
			||||||
#include "clang/AST/ASTContext.h"
 | 
					#include "ExplicitConstructorCheck.h"
 | 
				
			||||||
#include "clang/ASTMatchers/ASTMatchFinder.h"
 | 
					 | 
				
			||||||
#include "clang/ASTMatchers/ASTMatchers.h"
 | 
					 | 
				
			||||||
#include "clang/Frontend/CompilerInstance.h"
 | 
					 | 
				
			||||||
#include "clang/Lex/Lexer.h"
 | 
					 | 
				
			||||||
#include "clang/Lex/PPCallbacks.h"
 | 
					 | 
				
			||||||
#include "clang/Lex/Preprocessor.h"
 | 
					 | 
				
			||||||
#include "llvm/Support/raw_ostream.h"
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
using namespace clang::ast_matchers;
 | 
					using namespace clang::ast_matchers;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
namespace clang {
 | 
					namespace clang {
 | 
				
			||||||
namespace tidy {
 | 
					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 ");
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
class GoogleModule : public ClangTidyModule {
 | 
					class GoogleModule : public ClangTidyModule {
 | 
				
			||||||
public:
 | 
					public:
 | 
				
			||||||
  void addCheckFactories(ClangTidyCheckFactories &CheckFactories) override {
 | 
					  void addCheckFactories(ClangTidyCheckFactories &CheckFactories) override {
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -1,5 +1,5 @@
 | 
				
			||||||
#include "ClangTidyTest.h"
 | 
					#include "ClangTidyTest.h"
 | 
				
			||||||
#include "google/GoogleTidyModule.h"
 | 
					#include "google/ExplicitConstructorCheck.h"
 | 
				
			||||||
#include "gtest/gtest.h"
 | 
					#include "gtest/gtest.h"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
namespace clang {
 | 
					namespace clang {
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
		Loading…
	
		Reference in New Issue