1 //===--- UnnamedNamespaceInHeaderCheck.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 "UnnamedNamespaceInHeaderCheck.h"
11 #include "clang/AST/ASTContext.h"
12 #include "clang/ASTMatchers/ASTMatchFinder.h"
13 #include "clang/ASTMatchers/ASTMatchers.h"
14 
15 using namespace clang::ast_matchers;
16 
17 namespace clang {
18 namespace tidy {
19 namespace google {
20 namespace build {
21 
22 UnnamedNamespaceInHeaderCheck::UnnamedNamespaceInHeaderCheck(
23     StringRef Name, ClangTidyContext *Context)
24     : ClangTidyCheck(Name, Context),
25       RawStringHeaderFileExtensions(
26           Options.getLocalOrGlobal("HeaderFileExtensions", "h,hh,hpp,hxx")) {
27   if (!utils::parseHeaderFileExtensions(RawStringHeaderFileExtensions,
28                                         HeaderFileExtensions,
29                                         ',')) {
30     llvm::errs() << "Invalid header file extension: "
31                  << RawStringHeaderFileExtensions << "\n";
32   }
33 }
34 
35 void UnnamedNamespaceInHeaderCheck::storeOptions(
36     ClangTidyOptions::OptionMap &Opts) {
37   Options.store(Opts, "HeaderFileExtensions", RawStringHeaderFileExtensions);
38 }
39 
40 void UnnamedNamespaceInHeaderCheck::registerMatchers(
41     ast_matchers::MatchFinder *Finder) {
42   // Only register the matchers for C++; the functionality currently does not
43   // provide any benefit to other languages, despite being benign.
44   if (getLangOpts().CPlusPlus)
45     Finder->addMatcher(namespaceDecl(isAnonymous()).bind("anonymousNamespace"),
46                        this);
47 }
48 
49 void
50 UnnamedNamespaceInHeaderCheck::check(const MatchFinder::MatchResult &Result) {
51   const auto *N = Result.Nodes.getNodeAs<NamespaceDecl>("anonymousNamespace");
52   SourceLocation Loc = N->getLocStart();
53   if (!Loc.isValid())
54     return;
55 
56   if (utils::isPresumedLocInHeaderFile(Loc, *Result.SourceManager,
57                                        HeaderFileExtensions))
58     diag(Loc, "do not use unnamed namespaces in header files");
59 }
60 
61 } // namespace build
62 } // namespace google
63 } // namespace tidy
64 } // namespace clang
65