Index: clang-tidy/misc/CMakeLists.txt =================================================================== --- clang-tidy/misc/CMakeLists.txt +++ clang-tidy/misc/CMakeLists.txt @@ -7,6 +7,7 @@ InaccurateEraseCheck.cpp InefficientAlgorithmCheck.cpp MiscTidyModule.cpp + MissingNamespaceStdCheck.cpp SwappedArgumentsCheck.cpp UndelegatedConstructor.cpp UnusedRAII.cpp Index: clang-tidy/misc/MiscTidyModule.cpp =================================================================== --- clang-tidy/misc/MiscTidyModule.cpp +++ clang-tidy/misc/MiscTidyModule.cpp @@ -13,6 +13,7 @@ #include "ArgumentCommentCheck.h" #include "AssignOperatorSignatureCheck.h" #include "BoolPointerImplicitConversion.h" +#include "MissingNamespaceStdCheck.h" #include "InaccurateEraseCheck.h" #include "InefficientAlgorithmCheck.h" #include "SwappedArgumentsCheck.h" @@ -44,6 +45,7 @@ "misc-uniqueptr-reset-release"); CheckFactories.registerCheck("misc-unused-raii"); CheckFactories.registerCheck("misc-use-override"); + CheckFactories.registerCheck("misc-missing-namespace-std"); } }; Index: clang-tidy/misc/MissingNamespaceStdCheck.h =================================================================== --- /dev/null +++ clang-tidy/misc/MissingNamespaceStdCheck.h @@ -0,0 +1,30 @@ +//===--- MissingNamespaceStdCheck.h - clang-tidy---------------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_MISC_ADD_NAMESPACE_STD_H +#define LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_MISC_ADD_NAMESPACE_STD_H + +#include "../ClangTidy.h" + +namespace clang { +namespace tidy { + +class MissingNamespaceStdCheck : public ClangTidyCheck { +public: + MissingNamespaceStdCheck(StringRef Name, ClangTidyContext *Context) + : ClangTidyCheck(Name, Context) {} + void registerMatchers(ast_matchers::MatchFinder *Finder) override; + void check(const ast_matchers::MatchFinder::MatchResult &Result) override; +}; + +} // namespace tidy +} // namespace clang + +#endif // LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_MISC_ADD_NAMESPACE_STD_H + Index: clang-tidy/misc/MissingNamespaceStdCheck.cpp =================================================================== --- /dev/null +++ clang-tidy/misc/MissingNamespaceStdCheck.cpp @@ -0,0 +1,61 @@ +//===--- MissingNamespaceStdCheck.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 "MissingNamespaceStdCheck.h" +#include "clang/AST/ASTContext.h" +#include "clang/ASTMatchers/ASTMatchFinder.h" +#include "clang/Lex/Lexer.h" + +using namespace clang::ast_matchers; + +namespace clang { +namespace tidy { + +void MissingNamespaceStdCheck::registerMatchers(MatchFinder *Finder) { + Finder->addMatcher(decl(anyOf(fieldDecl(),varDecl())).bind("field_or_variable"), this); +} + +StringRef getTypeNameSource(const DeclaratorDecl& decl, const SourceManager& SM, const ASTContext& Context) +{ + UnqualTypeLoc UnqualifiedTypeLocation = decl.getTypeSourceInfo()->getTypeLoc().getUnqualifiedLoc(); + SourceRange TokRange(UnqualifiedTypeLocation.getLocStart(), UnqualifiedTypeLocation.getLocEnd()); + return Lexer::getSourceText(CharSourceRange::getTokenRange(TokRange), SM, Context.getLangOpts()); +} + +void MissingNamespaceStdCheck::check(const MatchFinder::MatchResult &Result) { + + const DeclaratorDecl *MatchedDecl = Result.Nodes.getNodeAs("field_or_variable"); + + auto MatchedType = MatchedDecl->getType().getTypePtr(); + if (!MatchedType->isStructureOrClassType()) + return; + + const RecordType* recordType = static_cast(MatchedType); + const RecordDecl* recordDecl = recordType->getAsCXXRecordDecl(); + const DeclContext* recordContext = recordDecl->getDeclContext(); + if (!recordContext->isStdNamespace()) + return; + + // Check to see that type actually is missing namespace std + StringRef typeNameSource = getTypeNameSource(*MatchedDecl, *Result.SourceManager, *Result.Context); + if (typeNameSource.startswith("::std") || typeNameSource.startswith("std")) + return; + + auto FieldTypeName = MatchedDecl->getType().getUnqualifiedType().getAsString(); + diag(MatchedDecl->getTypeSourceInfo()->getTypeLoc().getLocStart(), + "type '%0' is missing namespace std") + << FieldTypeName + << FixItHint::CreateInsertion( + MatchedDecl->getTypeSourceInfo()->getTypeLoc().getLocStart(), + "std::"); +} + +} // namespace tidy +} // namespace clang + Index: test/clang-tidy/misc-missing-namespace-std.cpp =================================================================== --- /dev/null +++ test/clang-tidy/misc-missing-namespace-std.cpp @@ -0,0 +1,12 @@ +// RUN: $(dirname %s)/check_clang_tidy.sh %s misc-missing-namespace-std %t +// REQUIRES: shell + +namespace std { struct Demo{}; } + +using namespace std; + +Demo global_demo_instance; +// CHECK: warning: type 'Demo' is missing namespace std. +// CHECK-FIXES: std::Demo global_demo_instance; + +std::Demo global_demo_instance_with_std; // no-warning