clang-tools 17.0.0git
GlobalNamesInHeadersCheck.cpp
Go to the documentation of this file.
1//===--- GlobalNamesInHeadersCheck.cpp - clang-tidy -----------------*- C++ -*-===//
2//
3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4// See https://llvm.org/LICENSE.txt for license information.
5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6//
7//===----------------------------------------------------------------------===//
8
10#include "clang/AST/ASTContext.h"
11#include "clang/ASTMatchers/ASTMatchFinder.h"
12#include "clang/ASTMatchers/ASTMatchers.h"
13#include "clang/Lex/Lexer.h"
14
15using namespace clang::ast_matchers;
16
18
20 ClangTidyContext *Context)
21 : ClangTidyCheck(Name, Context) {
22 std::optional<StringRef> HeaderFileExtensionsOption =
23 Options.get("HeaderFileExtensions");
24 RawStringHeaderFileExtensions =
25 HeaderFileExtensionsOption.value_or(utils::defaultHeaderFileExtensions());
26 if (HeaderFileExtensionsOption) {
27 if (!utils::parseFileExtensions(RawStringHeaderFileExtensions,
28 HeaderFileExtensions,
30 this->configurationDiag("Invalid header file extension: '%0'")
31 << RawStringHeaderFileExtensions;
32 }
33 } else
34 HeaderFileExtensions = Context->getHeaderFileExtensions();
35}
36
39 Options.store(Opts, "HeaderFileExtensions", RawStringHeaderFileExtensions);
40}
41
43 ast_matchers::MatchFinder *Finder) {
44 Finder->addMatcher(decl(anyOf(usingDecl(), usingDirectiveDecl()),
45 hasDeclContext(translationUnitDecl()))
46 .bind("using_decl"),
47 this);
48}
49
50void GlobalNamesInHeadersCheck::check(const MatchFinder::MatchResult &Result) {
51 const auto *D = Result.Nodes.getNodeAs<Decl>("using_decl");
52 // If it comes from a macro, we'll assume it is fine.
53 if (D->getBeginLoc().isMacroID())
54 return;
55
56 // Ignore if it comes from the "main" file ...
57 if (Result.SourceManager->isInMainFile(
58 Result.SourceManager->getExpansionLoc(D->getBeginLoc()))) {
59 // unless that file is a header.
61 D->getBeginLoc(), *Result.SourceManager, HeaderFileExtensions))
62 return;
63 }
64
65 if (const auto *UsingDirective = dyn_cast<UsingDirectiveDecl>(D)) {
66 if (UsingDirective->getNominatedNamespace()->isAnonymousNamespace()) {
67 // Anonymous namespaces inject a using directive into the AST to import
68 // the names into the containing namespace.
69 // We should not have them in headers, but there is another warning for
70 // that.
71 return;
72 }
73 }
74
75 diag(D->getBeginLoc(),
76 "using declarations in the global namespace in headers are prohibited");
77}
78
79} // namespace clang::tidy::google::readability
const FunctionDecl * Decl
Token Name
std::optional< StringRef > get(StringRef LocalName) const
Read a named option from the Context.
void store(ClangTidyOptions::OptionMap &Options, StringRef LocalName, StringRef Value) const
Stores an option with the check-local name LocalName with string value Value to Options.
Base class for all clang-tidy checks.
DiagnosticBuilder diag(SourceLocation Loc, StringRef Description, DiagnosticIDs::Level Level=DiagnosticIDs::Warning)
Add a diagnostic with the check's name.
DiagnosticBuilder configurationDiag(StringRef Description, DiagnosticIDs::Level Level=DiagnosticIDs::Warning) const
Adds a diagnostic to report errors in the check's configuration.
Every ClangTidyCheck reports errors through a DiagnosticsEngine provided by this context.
void storeOptions(ClangTidyOptions::OptionMap &Opts) override
Should store all options supported by this check with their current values or default values for opti...
void registerMatchers(ast_matchers::MatchFinder *Finder) override
Override this to register AST matchers with Finder.
GlobalNamesInHeadersCheck(StringRef Name, ClangTidyContext *Context)
void check(const ast_matchers::MatchFinder::MatchResult &Result) override
ClangTidyChecks that register ASTMatchers should do the actual work in here.
StringRef defaultHeaderFileExtensions()
Returns recommended default value for the list of header file extensions.
StringRef defaultFileExtensionDelimiters()
Returns recommended default value for the list of file extension delimiters.
bool parseFileExtensions(StringRef AllFileExtensions, FileExtensionsSet &FileExtensions, StringRef Delimiters)
Parses header file extensions from a semicolon-separated list.
bool isSpellingLocInHeaderFile(SourceLocation Loc, SourceManager &SM, const FileExtensionsSet &HeaderFileExtensions)
Checks whether spelling location of Loc is in header file.
llvm::StringMap< ClangTidyValue > OptionMap