10#include "clang/AST/ASTContext.h"
11#include "clang/ASTMatchers/ASTMatchFinder.h"
20 HeaderFileExtensions) {
22 Node.getBeginLoc(), Finder->getASTContext().getSourceManager(),
23 HeaderFileExtensions);
31 UseHeaderFileExtension(Options.get(
"UseHeaderFileExtension", true)) {
32 std::optional<StringRef> HeaderFileExtensionsOption =
34 RawStringHeaderFileExtensions =
36 if (HeaderFileExtensionsOption) {
41 << RawStringHeaderFileExtensions;
44 HeaderFileExtensions = Context->getHeaderFileExtensions();
49 Options.
store(Opts,
"UseHeaderFileExtension", UseHeaderFileExtension);
50 Options.
store(Opts,
"HeaderFileExtensions", RawStringHeaderFileExtensions);
54 auto DefinitionMatcher =
55 anyOf(functionDecl(isDefinition(), unless(isDeleted())),
56 varDecl(isDefinition()));
57 if (UseHeaderFileExtension) {
58 Finder->addMatcher(namedDecl(DefinitionMatcher,
59 usesHeaderFileExtension(HeaderFileExtensions))
64 namedDecl(DefinitionMatcher,
65 anyOf(usesHeaderFileExtension(HeaderFileExtensions),
66 unless(isExpansionInMainFile())))
74 if (Result.Context->getDiagnostics().hasUncompilableErrorOccurred())
85 const auto *ND = Result.Nodes.getNodeAs<NamedDecl>(
"name-decl");
87 if (ND->isInvalidDecl())
97 if (!ND->hasExternalFormalLinkage() || ND->isInAnonymousNamespace())
100 if (
const auto *FD = dyn_cast<FunctionDecl>(ND)) {
105 if (FD->getTemplatedKind() == FunctionDecl::TK_FunctionTemplate)
108 if (FD->isTemplateInstantiation())
112 if (
const auto *MD = dyn_cast<CXXMethodDecl>(FD)) {
113 const auto *DC = MD->getDeclContext();
114 while (DC->isRecord()) {
115 if (
const auto *RD = dyn_cast<CXXRecordDecl>(DC)) {
116 if (isa<ClassTemplatePartialSpecializationDecl>(RD))
118 if (RD->getDescribedClassTemplate())
121 DC = DC->getParent();
125 bool IsFullSpec = FD->getTemplateSpecializationKind() != TSK_Undeclared;
126 diag(FD->getLocation(),
127 "%select{function|full function template specialization}0 %1 defined "
128 "in a header file; function definitions in header files can lead to "
134 diag(FD->getLocation(),
"make as 'inline'",
136 << FixItHint::CreateInsertion(FD->getInnerLocStart(),
"inline ");
137 }
else if (
const auto *VD = dyn_cast<VarDecl>(ND)) {
139 if (VD->getDescribedVarTemplate())
142 if (VD->getDeclContext()->isDependentContext() && VD->isStaticDataMember())
145 if (isTemplateInstantiation(VD->getTemplateSpecializationKind()))
148 if (VD->hasLocalStorage() || VD->isStaticLocal())
154 if (isa<VarTemplatePartialSpecializationDecl>(VD))
157 diag(VD->getLocation(),
158 "variable %0 defined in a header file; "
159 "variable definitions in header files can lead to ODR violations")
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.
AST_MATCHER_P(FunctionDecl, parameterCountGE, unsigned, N)
Matches functions that have at least the specified amount of parameters.
bool isExpansionLocInHeaderFile(SourceLocation Loc, const SourceManager &SM, const FileExtensionsSet &HeaderFileExtensions)
Checks whether expansion location of Loc is in header file.
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.
llvm::SmallSet< llvm::StringRef, 5 > FileExtensionsSet
llvm::StringMap< ClangTidyValue > OptionMap