blob: 71049d993915a7e39f533c1f1629b8d0dd3439b0 [file] [log] [blame]
Samuel Benzaquen59c8aa92015-02-11 21:21:05 +00001//===--- GlobalNamesInHeadersCheck.cpp - clang-tidy -----------------*- C++ -*-===//
2//
3// The LLVM Compiler Infrastructure
4//
5// This file is distributed under the University of Illinois Open Source
6// License. See LICENSE.TXT for details.
7//
8//===----------------------------------------------------------------------===//
9
10#include "GlobalNamesInHeadersCheck.h"
11#include "clang/AST/ASTContext.h"
12#include "clang/ASTMatchers/ASTMatchFinder.h"
13#include "clang/ASTMatchers/ASTMatchers.h"
14#include "clang/Lex/Lexer.h"
15
16using namespace clang::ast_matchers;
17
18namespace clang {
19namespace tidy {
Alexander Kornienkoed824e02015-03-05 13:46:14 +000020namespace google {
Samuel Benzaquen59c8aa92015-02-11 21:21:05 +000021namespace readability {
22
Haojian Wuc2d75772016-02-05 11:23:59 +000023GlobalNamesInHeadersCheck::GlobalNamesInHeadersCheck(StringRef Name,
24 ClangTidyContext *Context)
25 : ClangTidyCheck(Name, Context),
26 RawStringHeaderFileExtensions(
27 Options.getLocalOrGlobal("HeaderFileExtensions", "h")) {
28 if (!utils::parseHeaderFileExtensions(RawStringHeaderFileExtensions,
Mandeep Singh Grang7c7ea7d2016-11-08 07:50:19 +000029 HeaderFileExtensions, ',')) {
Haojian Wuc2d75772016-02-05 11:23:59 +000030 llvm::errs() << "Invalid header file extension: "
31 << RawStringHeaderFileExtensions << "\n";
32 }
33}
34
35void GlobalNamesInHeadersCheck::storeOptions(
36 ClangTidyOptions::OptionMap &Opts) {
37 Options.store(Opts, "HeaderFileExtensions", RawStringHeaderFileExtensions);
38}
39
Mandeep Singh Grang7c7ea7d2016-11-08 07:50:19 +000040void GlobalNamesInHeadersCheck::registerMatchers(
41 ast_matchers::MatchFinder *Finder) {
42 Finder->addMatcher(decl(anyOf(usingDecl(), usingDirectiveDecl()),
43 hasDeclContext(translationUnitDecl()))
44 .bind("using_decl"),
45 this);
Samuel Benzaquen59c8aa92015-02-11 21:21:05 +000046}
47
48void GlobalNamesInHeadersCheck::check(const MatchFinder::MatchResult &Result) {
49 const auto *D = Result.Nodes.getNodeAs<Decl>("using_decl");
50 // If it comes from a macro, we'll assume it is fine.
51 if (D->getLocStart().isMacroID())
52 return;
53
54 // Ignore if it comes from the "main" file ...
55 if (Result.SourceManager->isInMainFile(
56 Result.SourceManager->getExpansionLoc(D->getLocStart()))) {
57 // unless that file is a header.
Haojian Wuc2d75772016-02-05 11:23:59 +000058 if (!utils::isSpellingLocInHeaderFile(
59 D->getLocStart(), *Result.SourceManager, HeaderFileExtensions))
Samuel Benzaquen59c8aa92015-02-11 21:21:05 +000060 return;
61 }
62
Mandeep Singh Grang7c7ea7d2016-11-08 07:50:19 +000063 if (const auto *UsingDirective = dyn_cast<UsingDirectiveDecl>(D)) {
Samuel Benzaquen3199b9a2015-03-24 15:21:45 +000064 if (UsingDirective->getNominatedNamespace()->isAnonymousNamespace()) {
65 // Anynoumous namespaces inject a using directive into the AST to import
66 // the names into the containing namespace.
67 // We should not have them in headers, but there is another warning for
68 // that.
69 return;
70 }
71 }
72
Samuel Benzaquen59c8aa92015-02-11 21:21:05 +000073 diag(D->getLocStart(),
74 "using declarations in the global namespace in headers are prohibited");
75}
76
77} // namespace readability
Alexander Kornienkoed824e02015-03-05 13:46:14 +000078} // namespace google
Samuel Benzaquen59c8aa92015-02-11 21:21:05 +000079} // namespace tidy
80} // namespace clang