[clang-tools-extra] r356750 - [clang-tidy] Expand modular headers for PPCallbacks
Alexander Kornienko via cfe-commits
cfe-commits at lists.llvm.org
Fri Mar 22 06:42:48 PDT 2019
Author: alexfh
Date: Fri Mar 22 06:42:48 2019
New Revision: 356750
URL: http://llvm.org/viewvc/llvm-project?rev=356750&view=rev
Log:
[clang-tidy] Expand modular headers for PPCallbacks
Summary:
Add a way to expand modular headers for PPCallbacks. Checks can opt-in for this
expansion by overriding the new registerPPCallbacks virtual method and
registering their PPCallbacks in the preprocessor created for this specific
purpose.
Use module expansion in the readability-identifier-naming check
Reviewers: gribozavr, usaxena95, sammccall
Reviewed By: gribozavr
Subscribers: nemanjai, mgorny, xazax.hun, kbarton, jdoerfert, cfe-commits
Tags: #clang, #clang-tools-extra
Differential Revision: https://reviews.llvm.org/D59528
Added:
clang-tools-extra/trunk/clang-tidy/ExpandModularHeadersPPCallbacks.cpp
clang-tools-extra/trunk/clang-tidy/ExpandModularHeadersPPCallbacks.h
clang-tools-extra/trunk/test/clang-tidy/Inputs/expand-modular-headers-ppcallbacks/
clang-tools-extra/trunk/test/clang-tidy/Inputs/expand-modular-headers-ppcallbacks/a.h
clang-tools-extra/trunk/test/clang-tidy/Inputs/expand-modular-headers-ppcallbacks/b.h
clang-tools-extra/trunk/test/clang-tidy/Inputs/expand-modular-headers-ppcallbacks/c.h
clang-tools-extra/trunk/test/clang-tidy/Inputs/expand-modular-headers-ppcallbacks/module.modulemap
clang-tools-extra/trunk/test/clang-tidy/expand-modular-headers-ppcallbacks.cpp
Modified:
clang-tools-extra/trunk/clang-tidy/CMakeLists.txt
clang-tools-extra/trunk/clang-tidy/ClangTidy.cpp
clang-tools-extra/trunk/clang-tidy/ClangTidy.h
clang-tools-extra/trunk/clang-tidy/readability/IdentifierNamingCheck.cpp
clang-tools-extra/trunk/clang-tidy/readability/IdentifierNamingCheck.h
clang-tools-extra/trunk/clang-tidy/tool/ClangTidyMain.cpp
clang-tools-extra/trunk/test/CMakeLists.txt
Modified: clang-tools-extra/trunk/clang-tidy/CMakeLists.txt
URL: http://llvm.org/viewvc/llvm-project/clang-tools-extra/trunk/clang-tidy/CMakeLists.txt?rev=356750&r1=356749&r2=356750&view=diff
==============================================================================
--- clang-tools-extra/trunk/clang-tidy/CMakeLists.txt (original)
+++ clang-tools-extra/trunk/clang-tidy/CMakeLists.txt Fri Mar 22 06:42:48 2019
@@ -8,6 +8,7 @@ add_clang_library(clangTidy
ClangTidyDiagnosticConsumer.cpp
ClangTidyOptions.cpp
ClangTidyProfiling.cpp
+ ExpandModularHeadersPPCallbacks.cpp
DEPENDS
ClangSACheckers
Modified: clang-tools-extra/trunk/clang-tidy/ClangTidy.cpp
URL: http://llvm.org/viewvc/llvm-project/clang-tools-extra/trunk/clang-tidy/ClangTidy.cpp?rev=356750&r1=356749&r2=356750&view=diff
==============================================================================
--- clang-tools-extra/trunk/clang-tidy/ClangTidy.cpp (original)
+++ clang-tools-extra/trunk/clang-tidy/ClangTidy.cpp Fri Mar 22 06:42:48 2019
@@ -18,6 +18,7 @@
#include "ClangTidyDiagnosticConsumer.h"
#include "ClangTidyModuleRegistry.h"
#include "ClangTidyProfiling.h"
+#include "ExpandModularHeadersPPCallbacks.h"
#include "clang/AST/ASTConsumer.h"
#include "clang/AST/ASTContext.h"
#include "clang/AST/Decl.h"
@@ -290,8 +291,10 @@ private:
} // namespace
ClangTidyASTConsumerFactory::ClangTidyASTConsumerFactory(
- ClangTidyContext &Context)
- : Context(Context), CheckFactories(new ClangTidyCheckFactories) {
+ ClangTidyContext &Context,
+ IntrusiveRefCntPtr<llvm::vfs::OverlayFileSystem> OverlayFS)
+ : Context(Context), OverlayFS(OverlayFS),
+ CheckFactories(new ClangTidyCheckFactories) {
for (ClangTidyModuleRegistry::iterator I = ClangTidyModuleRegistry::begin(),
E = ClangTidyModuleRegistry::end();
I != E; ++I) {
@@ -351,7 +354,8 @@ ClangTidyASTConsumerFactory::CreateASTCo
clang::CompilerInstance &Compiler, StringRef File) {
// FIXME: Move this to a separate method, so that CreateASTConsumer doesn't
// modify Compiler.
- Context.setSourceManager(&Compiler.getSourceManager());
+ SourceManager *SM = &Compiler.getSourceManager();
+ Context.setSourceManager(SM);
Context.setCurrentFile(File);
Context.setASTContext(&Compiler.getASTContext());
@@ -377,9 +381,20 @@ ClangTidyASTConsumerFactory::CreateASTCo
std::unique_ptr<ast_matchers::MatchFinder> Finder(
new ast_matchers::MatchFinder(std::move(FinderOptions)));
+ Preprocessor *PP = &Compiler.getPreprocessor();
+ Preprocessor *ModuleExpanderPP = PP;
+
+ if (Context.getLangOpts().Modules && OverlayFS != nullptr) {
+ auto ModuleExpander = llvm::make_unique<ExpandModularHeadersPPCallbacks>(
+ &Compiler, OverlayFS);
+ ModuleExpanderPP = ModuleExpander->getPreprocessor();
+ PP->addPPCallbacks(std::move(ModuleExpander));
+ }
+
for (auto &Check : Checks) {
Check->registerMatchers(&*Finder);
Check->registerPPCallbacks(Compiler);
+ Check->registerPPCallbacks(*SM, PP, ModuleExpanderPP);
}
std::vector<std::unique_ptr<ASTConsumer>> Consumers;
@@ -505,7 +520,7 @@ std::vector<ClangTidyError>
runClangTidy(clang::tidy::ClangTidyContext &Context,
const CompilationDatabase &Compilations,
ArrayRef<std::string> InputFiles,
- llvm::IntrusiveRefCntPtr<llvm::vfs::FileSystem> BaseFS,
+ llvm::IntrusiveRefCntPtr<llvm::vfs::OverlayFileSystem> BaseFS,
bool EnableCheckProfile, llvm::StringRef StoreCheckProfile) {
ClangTool Tool(Compilations, InputFiles,
std::make_shared<PCHContainerOperations>(), BaseFS);
@@ -541,7 +556,9 @@ runClangTidy(clang::tidy::ClangTidyConte
class ActionFactory : public FrontendActionFactory {
public:
- ActionFactory(ClangTidyContext &Context) : ConsumerFactory(Context) {}
+ ActionFactory(ClangTidyContext &Context,
+ IntrusiveRefCntPtr<llvm::vfs::OverlayFileSystem> BaseFS)
+ : ConsumerFactory(Context, BaseFS) {}
FrontendAction *create() override { return new Action(&ConsumerFactory); }
bool runInvocation(std::shared_ptr<CompilerInvocation> Invocation,
@@ -572,7 +589,7 @@ runClangTidy(clang::tidy::ClangTidyConte
ClangTidyASTConsumerFactory ConsumerFactory;
};
- ActionFactory Factory(Context);
+ ActionFactory Factory(Context, BaseFS);
Tool.run(&Factory);
return DiagConsumer.take();
}
Modified: clang-tools-extra/trunk/clang-tidy/ClangTidy.h
URL: http://llvm.org/viewvc/llvm-project/clang-tools-extra/trunk/clang-tidy/ClangTidy.h?rev=356750&r1=356749&r2=356750&view=diff
==============================================================================
--- clang-tools-extra/trunk/clang-tidy/ClangTidy.h (original)
+++ clang-tools-extra/trunk/clang-tidy/ClangTidy.h Fri Mar 22 06:42:48 2019
@@ -143,6 +143,24 @@ public:
/// dependent properties, e.g. the order of include directives.
virtual void registerPPCallbacks(CompilerInstance &Compiler) {}
+ /// \brief Override this to register ``PPCallbacks`` in the preprocessor.
+ ///
+ /// This should be used for clang-tidy checks that analyze preprocessor-
+ /// dependent properties, e.g. include directives and macro definitions.
+ ///
+ /// There are two Preprocessors to choose from that differ in how they handle
+ /// modular #includes:
+ /// - PP is the real Preprocessor. It doesn't walk into modular #includes and
+ /// thus doesn't generate PPCallbacks for their contents.
+ /// - ModuleExpanderPP preprocesses the whole translation unit in the
+ /// non-modular mode, which allows it to generate PPCallbacks not only for
+ /// the main file and textual headers, but also for all transitively
+ /// included modular headers when the analysis runs with modules enabled.
+ /// When modules are not enabled ModuleExpanderPP just points to the real
+ /// preprocessor.
+ virtual void registerPPCallbacks(const SourceManager &SM, Preprocessor *PP,
+ Preprocessor *ModuleExpanderPP) {}
+
/// \brief Override this to register AST matchers with \p Finder.
///
/// This should be used by clang-tidy checks that analyze code properties that
@@ -190,7 +208,9 @@ class ClangTidyCheckFactories;
class ClangTidyASTConsumerFactory {
public:
- ClangTidyASTConsumerFactory(ClangTidyContext &Context);
+ ClangTidyASTConsumerFactory(
+ ClangTidyContext &Context,
+ IntrusiveRefCntPtr<llvm::vfs::OverlayFileSystem> OverlayFS = nullptr);
/// \brief Returns an ASTConsumer that runs the specified clang-tidy checks.
std::unique_ptr<clang::ASTConsumer>
@@ -204,6 +224,7 @@ public:
private:
ClangTidyContext &Context;
+ IntrusiveRefCntPtr<llvm::vfs::OverlayFileSystem> OverlayFS;
std::unique_ptr<ClangTidyCheckFactories> CheckFactories;
};
@@ -233,7 +254,7 @@ std::vector<ClangTidyError>
runClangTidy(clang::tidy::ClangTidyContext &Context,
const tooling::CompilationDatabase &Compilations,
ArrayRef<std::string> InputFiles,
- llvm::IntrusiveRefCntPtr<llvm::vfs::FileSystem> BaseFS,
+ llvm::IntrusiveRefCntPtr<llvm::vfs::OverlayFileSystem> BaseFS,
bool EnableCheckProfile = false,
llvm::StringRef StoreCheckProfile = StringRef());
Added: clang-tools-extra/trunk/clang-tidy/ExpandModularHeadersPPCallbacks.cpp
URL: http://llvm.org/viewvc/llvm-project/clang-tools-extra/trunk/clang-tidy/ExpandModularHeadersPPCallbacks.cpp?rev=356750&view=auto
==============================================================================
--- clang-tools-extra/trunk/clang-tidy/ExpandModularHeadersPPCallbacks.cpp (added)
+++ clang-tools-extra/trunk/clang-tidy/ExpandModularHeadersPPCallbacks.cpp Fri Mar 22 06:42:48 2019
@@ -0,0 +1,294 @@
+//===- ExpandModularHeadersPPCallbacks.h - clang-tidy -----------*- C++ -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#include "ExpandModularHeadersPPCallbacks.h"
+#include "clang/Frontend/CompilerInstance.h"
+#include "clang/Lex/PreprocessorOptions.h"
+#include "clang/Serialization/ASTReader.h"
+
+namespace clang {
+namespace tooling {
+
+class ExpandModularHeadersPPCallbacks::FileRecorder {
+public:
+ /// Records that a given file entry is needed for replaying callbacks.
+ void addNecessaryFile(const FileEntry *File) { FilesToRecord.insert(File); }
+
+ /// Records content for a file and adds it to the FileSystem.
+ void recordFileContent(const FileEntry *File,
+ const SrcMgr::ContentCache &ContentCache,
+ llvm::vfs::InMemoryFileSystem &InMemoryFs) {
+ // Return if we are not interested in the contents of this file.
+ if (!FilesToRecord.count(File))
+ return;
+
+ // FIXME: Why is this happening? We might be losing contents here.
+ if (!ContentCache.getRawBuffer())
+ return;
+
+ InMemoryFs.addFile(File->getName(), /*ModificationTime=*/0,
+ llvm::MemoryBuffer::getMemBufferCopy(
+ ContentCache.getRawBuffer()->getBuffer()));
+ // Remove the file from the set of necessary files.
+ FilesToRecord.erase(File);
+ }
+
+ /// Makes sure we have contents for all the files we were interested in. Ideally
+ /// `FilesToRecord` should be empty.
+ void checkAllFilesRecorded() {
+ for (auto FileEntry : FilesToRecord)
+ llvm::errs() << "Did not record contents for input file: "
+ << FileEntry->getName() << "\n";
+ }
+
+private:
+ /// A set of files whose contents are to be recorded.
+ llvm::DenseSet<const FileEntry *> FilesToRecord;
+};
+
+ExpandModularHeadersPPCallbacks::ExpandModularHeadersPPCallbacks(
+ CompilerInstance *CI,
+ IntrusiveRefCntPtr<llvm::vfs::OverlayFileSystem> OverlayFS)
+ : Recorder(llvm::make_unique<FileRecorder>()), Compiler(*CI),
+ InMemoryFs(new llvm::vfs::InMemoryFileSystem),
+ Sources(Compiler.getSourceManager()),
+ // Forward the new diagnostics to the original DiagnosticConsumer.
+ Diags(new DiagnosticIDs, new DiagnosticOptions,
+ new ForwardingDiagnosticConsumer(Compiler.getDiagnosticClient())),
+ LangOpts(Compiler.getLangOpts()) {
+ // Add a FileSystem containing the extra files needed in place of modular
+ // headers.
+ OverlayFS->pushOverlay(InMemoryFs);
+
+ Diags.setSourceManager(&Sources);
+
+ LangOpts.Modules = false;
+
+ auto HSO = std::make_shared<HeaderSearchOptions>();
+ *HSO = Compiler.getHeaderSearchOpts();
+
+ HeaderInfo = llvm::make_unique<HeaderSearch>(HSO, Sources, Diags, LangOpts,
+ &Compiler.getTarget());
+
+ auto PO = std::make_shared<PreprocessorOptions>();
+ *PO = Compiler.getPreprocessorOpts();
+
+ Preprocessor = llvm::make_unique<clang::Preprocessor>(
+ PO, Diags, LangOpts, Sources, *HeaderInfo, ModuleLoader,
+ /*IILookup=*/nullptr,
+ /*OwnsHeaderSearch=*/false);
+ Preprocessor->Initialize(Compiler.getTarget(), Compiler.getAuxTarget());
+ InitializePreprocessor(*Preprocessor, *PO, Compiler.getPCHContainerReader(),
+ Compiler.getFrontendOpts());
+ ApplyHeaderSearchOptions(*HeaderInfo, *HSO, LangOpts,
+ Compiler.getTarget().getTriple());
+}
+
+ExpandModularHeadersPPCallbacks::~ExpandModularHeadersPPCallbacks() = default;
+
+Preprocessor *ExpandModularHeadersPPCallbacks::getPreprocessor() const {
+ return Preprocessor.get();
+}
+
+void ExpandModularHeadersPPCallbacks::handleModuleFile(
+ serialization::ModuleFile *MF) {
+ if (!MF)
+ return;
+ // Avoid processing a ModuleFile more than once.
+ if (VisitedModules.count(MF))
+ return;
+ VisitedModules.insert(MF);
+
+ // Visit all the input files of this module and mark them to record their
+ // contents later.
+ Compiler.getModuleManager()->visitInputFiles(
+ *MF, true, false,
+ [this](const serialization::InputFile &IF, bool /*IsSystem*/) {
+ Recorder->addNecessaryFile(IF.getFile());
+ });
+ // Recursively handle all transitively imported modules.
+ for (auto Import : MF->Imports)
+ handleModuleFile(Import);
+}
+
+void ExpandModularHeadersPPCallbacks::parseToLocation(SourceLocation Loc) {
+ // Load all source locations present in the external sources.
+ for (unsigned I = 0, N = Sources.loaded_sloc_entry_size(); I != N; ++I) {
+ Sources.getLoadedSLocEntry(I, nullptr);
+ }
+ // Record contents of files we are interested in and add to the FileSystem.
+ for (auto It = Sources.fileinfo_begin(); It != Sources.fileinfo_end(); ++It) {
+ Recorder->recordFileContent(It->getFirst(), *It->getSecond(), *InMemoryFs);
+ }
+ Recorder->checkAllFilesRecorded();
+
+ if (!StartedLexing) {
+ StartedLexing = true;
+ Preprocessor->Lex(CurrentToken);
+ }
+ while (!CurrentToken.is(tok::eof) &&
+ Sources.isBeforeInTranslationUnit(CurrentToken.getLocation(), Loc)) {
+ Preprocessor->Lex(CurrentToken);
+ }
+}
+
+void ExpandModularHeadersPPCallbacks::FileChanged(
+ SourceLocation Loc, FileChangeReason Reason,
+ SrcMgr::CharacteristicKind FileType, FileID PrevFID = FileID()) {
+ if (!EnteredMainFile) {
+ EnteredMainFile = true;
+ Preprocessor->EnterMainSourceFile();
+ }
+}
+
+void ExpandModularHeadersPPCallbacks::InclusionDirective(
+ SourceLocation DirectiveLoc, const Token &IncludeToken,
+ StringRef IncludedFilename, bool IsAngled, CharSourceRange FilenameRange,
+ const FileEntry *IncludedFile, StringRef SearchPath, StringRef RelativePath,
+ const Module *Imported, SrcMgr::CharacteristicKind FileType) {
+ if (Imported) {
+ serialization::ModuleFile *MF =
+ Compiler.getModuleManager()->getModuleManager().lookup(
+ Imported->getASTFile());
+ handleModuleFile(MF);
+ }
+ parseToLocation(DirectiveLoc);
+}
+
+void ExpandModularHeadersPPCallbacks::EndOfMainFile() {
+ while (!CurrentToken.is(tok::eof))
+ Preprocessor->Lex(CurrentToken);
+}
+
+// Handle all other callbacks.
+// Just parse to the corresponding location to generate the same callback for
+// the PPCallbacks registered in our custom preprocessor.
+void ExpandModularHeadersPPCallbacks::Ident(SourceLocation Loc, StringRef) {
+ parseToLocation(Loc);
+}
+void ExpandModularHeadersPPCallbacks::PragmaDirective(SourceLocation Loc,
+ PragmaIntroducerKind) {
+ parseToLocation(Loc);
+}
+void ExpandModularHeadersPPCallbacks::PragmaComment(SourceLocation Loc,
+ const IdentifierInfo *,
+ StringRef) {
+ parseToLocation(Loc);
+}
+void ExpandModularHeadersPPCallbacks::PragmaDetectMismatch(SourceLocation Loc,
+ StringRef,
+ StringRef) {
+ parseToLocation(Loc);
+}
+void ExpandModularHeadersPPCallbacks::PragmaDebug(SourceLocation Loc,
+ StringRef) {
+ parseToLocation(Loc);
+}
+void ExpandModularHeadersPPCallbacks::PragmaMessage(SourceLocation Loc,
+ StringRef,
+ PragmaMessageKind,
+ StringRef) {
+ parseToLocation(Loc);
+}
+void ExpandModularHeadersPPCallbacks::PragmaDiagnosticPush(SourceLocation Loc,
+ StringRef) {
+ parseToLocation(Loc);
+}
+void ExpandModularHeadersPPCallbacks::PragmaDiagnosticPop(SourceLocation Loc,
+ StringRef) {
+ parseToLocation(Loc);
+}
+void ExpandModularHeadersPPCallbacks::PragmaDiagnostic(SourceLocation Loc,
+ StringRef,
+ diag::Severity,
+ StringRef) {
+ parseToLocation(Loc);
+}
+void ExpandModularHeadersPPCallbacks::HasInclude(SourceLocation Loc, StringRef,
+ bool, const FileEntry *,
+ SrcMgr::CharacteristicKind) {
+ parseToLocation(Loc);
+}
+void ExpandModularHeadersPPCallbacks::PragmaOpenCLExtension(
+ SourceLocation NameLoc, const IdentifierInfo *, SourceLocation StateLoc,
+ unsigned) {
+ // FIME: Figure out whether it's the right location to parse to.
+ parseToLocation(NameLoc);
+}
+void ExpandModularHeadersPPCallbacks::PragmaWarning(SourceLocation Loc,
+ StringRef, ArrayRef<int>) {
+ parseToLocation(Loc);
+}
+void ExpandModularHeadersPPCallbacks::PragmaWarningPush(SourceLocation Loc,
+ int) {
+ parseToLocation(Loc);
+}
+void ExpandModularHeadersPPCallbacks::PragmaWarningPop(SourceLocation Loc) {
+ parseToLocation(Loc);
+}
+void ExpandModularHeadersPPCallbacks::PragmaAssumeNonNullBegin(
+ SourceLocation Loc) {
+ parseToLocation(Loc);
+}
+void ExpandModularHeadersPPCallbacks::PragmaAssumeNonNullEnd(
+ SourceLocation Loc) {
+ parseToLocation(Loc);
+}
+void ExpandModularHeadersPPCallbacks::MacroExpands(const Token &MacroNameTok,
+ const MacroDefinition &,
+ SourceRange Range,
+ const MacroArgs *) {
+ // FIME: Figure out whether it's the right location to parse to.
+ parseToLocation(Range.getBegin());
+}
+void ExpandModularHeadersPPCallbacks::MacroDefined(const Token &MacroNameTok,
+ const MacroDirective *MD) {
+ parseToLocation(MD->getLocation());
+}
+void ExpandModularHeadersPPCallbacks::MacroUndefined(
+ const Token &, const MacroDefinition &, const MacroDirective *Undef) {
+ if (Undef)
+ parseToLocation(Undef->getLocation());
+}
+void ExpandModularHeadersPPCallbacks::Defined(const Token &MacroNameTok,
+ const MacroDefinition &,
+ SourceRange Range) {
+ // FIME: Figure out whether it's the right location to parse to.
+ parseToLocation(Range.getBegin());
+}
+void ExpandModularHeadersPPCallbacks::SourceRangeSkipped(
+ SourceRange Range, SourceLocation EndifLoc) {
+ // FIME: Figure out whether it's the right location to parse to.
+ parseToLocation(EndifLoc);
+}
+void ExpandModularHeadersPPCallbacks::If(SourceLocation Loc, SourceRange,
+ ConditionValueKind) {
+ parseToLocation(Loc);
+}
+void ExpandModularHeadersPPCallbacks::Elif(SourceLocation Loc, SourceRange,
+ ConditionValueKind, SourceLocation) {
+ parseToLocation(Loc);
+}
+void ExpandModularHeadersPPCallbacks::Ifdef(SourceLocation Loc, const Token &,
+ const MacroDefinition &) {
+ parseToLocation(Loc);
+}
+void ExpandModularHeadersPPCallbacks::Ifndef(SourceLocation Loc, const Token &,
+ const MacroDefinition &) {
+ parseToLocation(Loc);
+}
+void ExpandModularHeadersPPCallbacks::Else(SourceLocation Loc, SourceLocation) {
+ parseToLocation(Loc);
+}
+void ExpandModularHeadersPPCallbacks::Endif(SourceLocation Loc,
+ SourceLocation) {
+ parseToLocation(Loc);
+}
+
+} // namespace tooling
+} // namespace clang
Added: clang-tools-extra/trunk/clang-tidy/ExpandModularHeadersPPCallbacks.h
URL: http://llvm.org/viewvc/llvm-project/clang-tools-extra/trunk/clang-tidy/ExpandModularHeadersPPCallbacks.h?rev=356750&view=auto
==============================================================================
--- clang-tools-extra/trunk/clang-tidy/ExpandModularHeadersPPCallbacks.h (added)
+++ clang-tools-extra/trunk/clang-tidy/ExpandModularHeadersPPCallbacks.h Fri Mar 22 06:42:48 2019
@@ -0,0 +1,137 @@
+//===- ExpandModularHeadersPPCallbacks.h - clang-tidy -----------*- C++ -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_CLANG_TOOLING_EXPANDMODULARHEADERSPPCALLBACKS_H_
+#define LLVM_CLANG_TOOLING_EXPANDMODULARHEADERSPPCALLBACKS_H_
+
+#include "clang/Lex/PPCallbacks.h"
+#include "clang/Lex/Preprocessor.h"
+#include "llvm/ADT/DenseSet.h"
+
+namespace clang {
+class CompilerInstance;
+
+namespace serialization {
+class ModuleFile;
+} // namespace serialization
+
+namespace tooling {
+
+/// \brief Handles PPCallbacks and re-runs preprocessing of the whole
+/// translation unit with modules disabled.
+///
+/// This way it's possible to get PPCallbacks for the whole translation unit
+/// including the contents of the modular headers and all their transitive
+/// includes.
+///
+/// This allows existing tools based on PPCallbacks to retain their functionality
+/// when running with C++ modules enabled. This only works in the backwards
+/// compatible modules mode, i.e. when code can still be parsed in non-modular
+/// way.
+class ExpandModularHeadersPPCallbacks : public PPCallbacks {
+public:
+ ExpandModularHeadersPPCallbacks(
+ CompilerInstance *Compiler,
+ IntrusiveRefCntPtr<llvm::vfs::OverlayFileSystem> OverlayFS);
+ ~ExpandModularHeadersPPCallbacks();
+
+ /// \brief Returns the preprocessor that provides callbacks for the whole
+ /// translation unit, including the main file, textual headers, and modular
+ /// headers.
+ ///
+ /// This preprocessor is separate from the one used by the rest of the
+ /// compiler.
+ Preprocessor *getPreprocessor() const;
+
+private:
+ class FileRecorder;
+
+ void handleModuleFile(serialization::ModuleFile *MF);
+ void parseToLocation(SourceLocation Loc);
+
+ // Handle PPCallbacks.
+ void FileChanged(SourceLocation Loc, FileChangeReason Reason,
+ SrcMgr::CharacteristicKind FileType,
+ FileID PrevFID) override;
+
+ void InclusionDirective(SourceLocation DirectiveLoc,
+ const Token &IncludeToken, StringRef IncludedFilename,
+ bool IsAngled, CharSourceRange FilenameRange,
+ const FileEntry *IncludedFile, StringRef SearchPath,
+ StringRef RelativePath, const Module *Imported,
+ SrcMgr::CharacteristicKind FileType) override;
+
+ void EndOfMainFile() override;
+
+ // Handle all other callbacks.
+ // Just parse to the corresponding location to generate PPCallbacks for the
+ // corresponding range
+ void Ident(SourceLocation Loc, StringRef) override;
+ void PragmaDirective(SourceLocation Loc, PragmaIntroducerKind) override;
+ void PragmaComment(SourceLocation Loc, const IdentifierInfo *,
+ StringRef) override;
+ void PragmaDetectMismatch(SourceLocation Loc, StringRef, StringRef) override;
+ void PragmaDebug(SourceLocation Loc, StringRef) override;
+ void PragmaMessage(SourceLocation Loc, StringRef, PragmaMessageKind,
+ StringRef) override;
+ void PragmaDiagnosticPush(SourceLocation Loc, StringRef) override;
+ void PragmaDiagnosticPop(SourceLocation Loc, StringRef) override;
+ void PragmaDiagnostic(SourceLocation Loc, StringRef, diag::Severity,
+ StringRef) override;
+ void HasInclude(SourceLocation Loc, StringRef, bool, const FileEntry *,
+ SrcMgr::CharacteristicKind) override;
+ void PragmaOpenCLExtension(SourceLocation NameLoc, const IdentifierInfo *,
+ SourceLocation StateLoc, unsigned) override;
+ void PragmaWarning(SourceLocation Loc, StringRef, ArrayRef<int>) override;
+ void PragmaWarningPush(SourceLocation Loc, int) override;
+ void PragmaWarningPop(SourceLocation Loc) override;
+ void PragmaAssumeNonNullBegin(SourceLocation Loc) override;
+ void PragmaAssumeNonNullEnd(SourceLocation Loc) override;
+ void MacroExpands(const Token &MacroNameTok, const MacroDefinition &,
+ SourceRange Range, const MacroArgs *) override;
+ void MacroDefined(const Token &MacroNameTok,
+ const MacroDirective *MD) override;
+ void MacroUndefined(const Token &, const MacroDefinition &,
+ const MacroDirective *Undef) override;
+ void Defined(const Token &MacroNameTok, const MacroDefinition &,
+ SourceRange Range) override;
+ void SourceRangeSkipped(SourceRange Range, SourceLocation EndifLoc) override;
+ void If(SourceLocation Loc, SourceRange, ConditionValueKind) override;
+ void Elif(SourceLocation Loc, SourceRange, ConditionValueKind,
+ SourceLocation) override;
+ void Ifdef(SourceLocation Loc, const Token &,
+ const MacroDefinition &) override;
+ void Ifndef(SourceLocation Loc, const Token &,
+ const MacroDefinition &) override;
+ void Else(SourceLocation Loc, SourceLocation) override;
+ void Endif(SourceLocation Loc, SourceLocation) override;
+
+ std::unique_ptr<FileRecorder> Recorder;
+ // Set of all the modules visited. Avoids processing a module more than once.
+ llvm::DenseSet<serialization::ModuleFile *> VisitedModules;
+
+ CompilerInstance &Compiler;
+ // Additional filesystem for replay. Provides all input files from modules.
+ llvm::IntrusiveRefCntPtr<llvm::vfs::InMemoryFileSystem> InMemoryFs;
+
+ SourceManager &Sources;
+ DiagnosticsEngine Diags;
+ LangOptions LangOpts;
+ TrivialModuleLoader ModuleLoader;
+
+ std::unique_ptr<HeaderSearch> HeaderInfo;
+ std::unique_ptr<Preprocessor> Preprocessor;
+ bool EnteredMainFile = false;
+ bool StartedLexing = false;
+ Token CurrentToken;
+};
+
+} // namespace tooling
+} // namespace clang
+
+#endif // LLVM_CLANG_TOOLING_EXPANDMODULARHEADERSPPCALLBACKS_H_
Modified: clang-tools-extra/trunk/clang-tidy/readability/IdentifierNamingCheck.cpp
URL: http://llvm.org/viewvc/llvm-project/clang-tools-extra/trunk/clang-tidy/readability/IdentifierNamingCheck.cpp?rev=356750&r1=356749&r2=356750&view=diff
==============================================================================
--- clang-tools-extra/trunk/clang-tidy/readability/IdentifierNamingCheck.cpp (original)
+++ clang-tools-extra/trunk/clang-tidy/readability/IdentifierNamingCheck.cpp Fri Mar 22 06:42:48 2019
@@ -240,10 +240,11 @@ void IdentifierNamingCheck::registerMatc
Finder->addMatcher(nestedNameSpecifierLoc().bind("nestedNameLoc"), this);
}
-void IdentifierNamingCheck::registerPPCallbacks(CompilerInstance &Compiler) {
- Compiler.getPreprocessor().addPPCallbacks(
- llvm::make_unique<IdentifierNamingCheckPPCallbacks>(
- &Compiler.getPreprocessor(), this));
+void IdentifierNamingCheck::registerPPCallbacks(
+ const SourceManager &SM, Preprocessor *PP, Preprocessor *ModuleExpanderPP) {
+ ModuleExpanderPP->addPPCallbacks(
+ llvm::make_unique<IdentifierNamingCheckPPCallbacks>(ModuleExpanderPP,
+ this));
}
static bool matchesStyle(StringRef Name,
Modified: clang-tools-extra/trunk/clang-tidy/readability/IdentifierNamingCheck.h
URL: http://llvm.org/viewvc/llvm-project/clang-tools-extra/trunk/clang-tidy/readability/IdentifierNamingCheck.h?rev=356750&r1=356749&r2=356750&view=diff
==============================================================================
--- clang-tools-extra/trunk/clang-tidy/readability/IdentifierNamingCheck.h (original)
+++ clang-tools-extra/trunk/clang-tidy/readability/IdentifierNamingCheck.h Fri Mar 22 06:42:48 2019
@@ -38,7 +38,8 @@ public:
void storeOptions(ClangTidyOptions::OptionMap &Opts) override;
void registerMatchers(ast_matchers::MatchFinder *Finder) override;
void check(const ast_matchers::MatchFinder::MatchResult &Result) override;
- void registerPPCallbacks(CompilerInstance &Compiler) override;
+ void registerPPCallbacks(const SourceManager &SM, Preprocessor *PP,
+ Preprocessor *ModuleExpanderPP) override;
void onEndOfTranslationUnit() override;
enum CaseType {
Modified: clang-tools-extra/trunk/clang-tidy/tool/ClangTidyMain.cpp
URL: http://llvm.org/viewvc/llvm-project/clang-tools-extra/trunk/clang-tidy/tool/ClangTidyMain.cpp?rev=356750&r1=356749&r2=356750&view=diff
==============================================================================
--- clang-tools-extra/trunk/clang-tidy/tool/ClangTidyMain.cpp (original)
+++ clang-tools-extra/trunk/clang-tidy/tool/ClangTidyMain.cpp Fri Mar 22 06:42:48 2019
@@ -304,11 +304,10 @@ static std::unique_ptr<ClangTidyOptionsP
}
llvm::IntrusiveRefCntPtr<vfs::FileSystem>
-getVfsOverlayFromFile(const std::string &OverlayFile) {
- llvm::IntrusiveRefCntPtr<vfs::OverlayFileSystem> OverlayFS(
- new vfs::OverlayFileSystem(vfs::getRealFileSystem()));
+getVfsFromFile(const std::string &OverlayFile,
+ llvm::IntrusiveRefCntPtr<vfs::FileSystem> BaseFS) {
llvm::ErrorOr<std::unique_ptr<llvm::MemoryBuffer>> Buffer =
- OverlayFS->getBufferForFile(OverlayFile);
+ BaseFS->getBufferForFile(OverlayFile);
if (!Buffer) {
llvm::errs() << "Can't load virtual filesystem overlay file '"
<< OverlayFile << "': " << Buffer.getError().message()
@@ -323,19 +322,23 @@ getVfsOverlayFromFile(const std::string
<< OverlayFile << "'.\n";
return nullptr;
}
- OverlayFS->pushOverlay(FS);
- return OverlayFS;
+ return FS;
}
static int clangTidyMain(int argc, const char **argv) {
llvm::sys::PrintStackTraceOnErrorSignal(argv[0]);
CommonOptionsParser OptionsParser(argc, argv, ClangTidyCategory,
cl::ZeroOrMore);
- llvm::IntrusiveRefCntPtr<vfs::FileSystem> BaseFS(
- VfsOverlay.empty() ? vfs::getRealFileSystem()
- : getVfsOverlayFromFile(VfsOverlay));
- if (!BaseFS)
- return 1;
+ llvm::IntrusiveRefCntPtr<vfs::OverlayFileSystem> BaseFS(
+ new vfs::OverlayFileSystem(vfs::getRealFileSystem()));
+
+ if (!VfsOverlay.empty()) {
+ IntrusiveRefCntPtr<vfs::FileSystem> VfsFromFile =
+ getVfsFromFile(VfsOverlay, BaseFS);
+ if (!VfsFromFile)
+ return 1;
+ BaseFS->pushOverlay(VfsFromFile);
+ }
auto OwningOptionsProvider = createOptionsProvider(BaseFS);
auto *OptionsProvider = OwningOptionsProvider.get();
Modified: clang-tools-extra/trunk/test/CMakeLists.txt
URL: http://llvm.org/viewvc/llvm-project/clang-tools-extra/trunk/test/CMakeLists.txt?rev=356750&r1=356749&r2=356750&view=diff
==============================================================================
--- clang-tools-extra/trunk/test/CMakeLists.txt (original)
+++ clang-tools-extra/trunk/test/CMakeLists.txt Fri Mar 22 06:42:48 2019
@@ -62,6 +62,8 @@ set(CLANG_TOOLS_TEST_DEPS
clang-resource-headers
clang-tidy
+ # Clang-tidy tests need clang for building modules.
+ clang
)
if(CLANGD_BUILD_XPC_SUPPORT)
Added: clang-tools-extra/trunk/test/clang-tidy/Inputs/expand-modular-headers-ppcallbacks/a.h
URL: http://llvm.org/viewvc/llvm-project/clang-tools-extra/trunk/test/clang-tidy/Inputs/expand-modular-headers-ppcallbacks/a.h?rev=356750&view=auto
==============================================================================
--- clang-tools-extra/trunk/test/clang-tidy/Inputs/expand-modular-headers-ppcallbacks/a.h (added)
+++ clang-tools-extra/trunk/test/clang-tidy/Inputs/expand-modular-headers-ppcallbacks/a.h Fri Mar 22 06:42:48 2019
@@ -0,0 +1 @@
+#define a
Added: clang-tools-extra/trunk/test/clang-tidy/Inputs/expand-modular-headers-ppcallbacks/b.h
URL: http://llvm.org/viewvc/llvm-project/clang-tools-extra/trunk/test/clang-tidy/Inputs/expand-modular-headers-ppcallbacks/b.h?rev=356750&view=auto
==============================================================================
--- clang-tools-extra/trunk/test/clang-tidy/Inputs/expand-modular-headers-ppcallbacks/b.h (added)
+++ clang-tools-extra/trunk/test/clang-tidy/Inputs/expand-modular-headers-ppcallbacks/b.h Fri Mar 22 06:42:48 2019
@@ -0,0 +1,2 @@
+#include "a.h"
+#define b
Added: clang-tools-extra/trunk/test/clang-tidy/Inputs/expand-modular-headers-ppcallbacks/c.h
URL: http://llvm.org/viewvc/llvm-project/clang-tools-extra/trunk/test/clang-tidy/Inputs/expand-modular-headers-ppcallbacks/c.h?rev=356750&view=auto
==============================================================================
--- clang-tools-extra/trunk/test/clang-tidy/Inputs/expand-modular-headers-ppcallbacks/c.h (added)
+++ clang-tools-extra/trunk/test/clang-tidy/Inputs/expand-modular-headers-ppcallbacks/c.h Fri Mar 22 06:42:48 2019
@@ -0,0 +1,2 @@
+#include "b.h"
+#define c
Added: clang-tools-extra/trunk/test/clang-tidy/Inputs/expand-modular-headers-ppcallbacks/module.modulemap
URL: http://llvm.org/viewvc/llvm-project/clang-tools-extra/trunk/test/clang-tidy/Inputs/expand-modular-headers-ppcallbacks/module.modulemap?rev=356750&view=auto
==============================================================================
--- clang-tools-extra/trunk/test/clang-tidy/Inputs/expand-modular-headers-ppcallbacks/module.modulemap (added)
+++ clang-tools-extra/trunk/test/clang-tidy/Inputs/expand-modular-headers-ppcallbacks/module.modulemap Fri Mar 22 06:42:48 2019
@@ -0,0 +1,3 @@
+module a { header "a.h" export * }
+module b { header "b.h" export * use a }
+module c { header "c.h" export * use b }
Added: clang-tools-extra/trunk/test/clang-tidy/expand-modular-headers-ppcallbacks.cpp
URL: http://llvm.org/viewvc/llvm-project/clang-tools-extra/trunk/test/clang-tidy/expand-modular-headers-ppcallbacks.cpp?rev=356750&view=auto
==============================================================================
--- clang-tools-extra/trunk/test/clang-tidy/expand-modular-headers-ppcallbacks.cpp (added)
+++ clang-tools-extra/trunk/test/clang-tidy/expand-modular-headers-ppcallbacks.cpp Fri Mar 22 06:42:48 2019
@@ -0,0 +1,35 @@
+// Sanity-check. Run without modules:
+// RUN: rm -rf %t
+// RUN: mkdir %t
+// RUN: cp %S/Inputs/expand-modular-headers-ppcallbacks/* %t/
+// RUN: %check_clang_tidy %s readability-identifier-naming %t/without-modules -- \
+// RUN: -config="CheckOptions: [{ \
+// RUN: key: readability-identifier-naming.MacroDefinitionCase, value: UPPER_CASE }]" \
+// RUN: -header-filter=.* \
+// RUN: -- -x c++ -std=c++11 -I%t/
+//
+// Run clang-tidy on a file with modular includes:
+//
+// RUN: rm -rf %t
+// RUN: mkdir %t
+// RUN: cp %S/Inputs/expand-modular-headers-ppcallbacks/* %t/
+// RUN: %check_clang_tidy %s readability-identifier-naming %t/with-modules -- \
+// RUN: -config="CheckOptions: [{ \
+// RUN: key: readability-identifier-naming.MacroDefinitionCase, value: UPPER_CASE }]" \
+// RUN: -header-filter=.* \
+// RUN: -- -x c++ -std=c++11 -I%t/ \
+// RUN: -fmodules -fimplicit-modules -fno-implicit-module-maps \
+// RUN: -fmodule-map-file=%t/module.modulemap \
+// RUN: -fmodules-cache-path=%t/module-cache/
+#include "c.h"
+
+// CHECK-MESSAGES: a.h:1:9: warning: invalid case style for macro definition 'a' [readability-identifier-naming]
+// CHECK-MESSAGES: a.h:1:9: note: FIX-IT applied suggested code changes
+// CHECK-MESSAGES: b.h:2:9: warning: invalid case style for macro definition 'b'
+// CHECK-MESSAGES: b.h:2:9: note: FIX-IT applied suggested code changes
+// CHECK-MESSAGES: c.h:2:9: warning: invalid case style for macro definition 'c'
+// CHECK-MESSAGES: c.h:2:9: note: FIX-IT applied suggested code changes
+
+#define m
+// CHECK-MESSAGES: :[[@LINE-1]]:9: warning: invalid case style for macro definition 'm'
+// CHECK-MESSAGES: :[[@LINE-2]]:9: note: FIX-IT applied suggested code changes
More information about the cfe-commits
mailing list