forked from OSchip/llvm-project
[Tooling/DependencyScanning] Rename refactorings towards transitioning dependency scanning to use pre-lexed preprocessor directive tokens
This is first of a series of patches for making the special lexing for dependency scanning a first-class feature of the `Preprocessor` and `Lexer`. This patch only includes NFC renaming changes to make reviewing of the functionality changing parts easier. Differential Revision: https://reviews.llvm.org/D125484
This commit is contained in:
parent
628b2bfad8
commit
b58a420ff4
|
@ -899,11 +899,11 @@ def err_pp_eof_in_assume_nonnull : Error<
|
|||
|
||||
}
|
||||
|
||||
let CategoryName = "Dependency Directive Source Minimization Issue" in {
|
||||
let CategoryName = "Dependency Directive Source Scanner Issue" in {
|
||||
|
||||
def err_dep_source_minimizer_missing_sema_after_at_import : Error<
|
||||
def err_dep_source_scanner_missing_semi_after_at_import : Error<
|
||||
"could not find ';' after @import">;
|
||||
def err_dep_source_minimizer_unexpected_tokens_at_import : Error<
|
||||
def err_dep_source_scanner_unexpected_tokens_at_import : Error<
|
||||
"unexpected extra tokens at end of @import declaration">;
|
||||
|
||||
}
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
//===- clang/Lex/DependencyDirectivesSourceMinimizer.h - ----------*- C++ -*-//
|
||||
//===- clang/Lex/DependencyDirectivesScanner.h ---------------------*- C++ -*-//
|
||||
//
|
||||
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
|
||||
// See https://llvm.org/LICENSE.txt for license information.
|
||||
|
@ -7,15 +7,15 @@
|
|||
//===----------------------------------------------------------------------===//
|
||||
///
|
||||
/// \file
|
||||
/// This is the interface for minimizing header and source files to the
|
||||
/// This is the interface for scanning header and source files to get the
|
||||
/// minimum necessary preprocessor directives for evaluating includes. It
|
||||
/// reduces the source down to #define, #include, #import, @import, and any
|
||||
/// conditional preprocessor logic that contains one of those.
|
||||
///
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#ifndef LLVM_CLANG_LEX_DEPENDENCYDIRECTIVESSOURCEMINIMIZER_H
|
||||
#define LLVM_CLANG_LEX_DEPENDENCYDIRECTIVESSOURCEMINIMIZER_H
|
||||
#ifndef LLVM_CLANG_LEX_DEPENDENCYDIRECTIVESSCANNER_H
|
||||
#define LLVM_CLANG_LEX_DEPENDENCYDIRECTIVESSCANNER_H
|
||||
|
||||
#include "clang/Basic/SourceLocation.h"
|
||||
#include "llvm/ADT/ArrayRef.h"
|
||||
|
@ -26,11 +26,11 @@ namespace clang {
|
|||
|
||||
class DiagnosticsEngine;
|
||||
|
||||
namespace minimize_source_to_dependency_directives {
|
||||
namespace dependency_directives_scan {
|
||||
|
||||
/// Represents the kind of preprocessor directive or a module declaration that
|
||||
/// is tracked by the source minimizer in its token output.
|
||||
enum TokenKind {
|
||||
/// is tracked by the scanner in its token output.
|
||||
enum DirectiveKind : uint8_t {
|
||||
pp_none,
|
||||
pp_include,
|
||||
pp___include_macros,
|
||||
|
@ -58,17 +58,17 @@ enum TokenKind {
|
|||
pp_eof,
|
||||
};
|
||||
|
||||
/// Represents a simplified token that's lexed as part of the source
|
||||
/// minimization. It's used to track the location of various preprocessor
|
||||
/// directives that could potentially have an effect on the depedencies.
|
||||
struct Token {
|
||||
/// Represents a directive that's lexed as part of the dependency directives
|
||||
/// scanning. It's used to track various preprocessor directives that could
|
||||
/// potentially have an effect on the depedencies.
|
||||
struct Directive {
|
||||
/// The kind of token.
|
||||
TokenKind K = pp_none;
|
||||
DirectiveKind Kind = pp_none;
|
||||
|
||||
/// Offset into the output byte stream of where the directive begins.
|
||||
int Offset = -1;
|
||||
|
||||
Token(TokenKind K, int Offset) : K(K), Offset(Offset) {}
|
||||
Directive(DirectiveKind K, int Offset) : Kind(K), Offset(Offset) {}
|
||||
};
|
||||
|
||||
/// Simplified token range to track the range of a potentially skippable PP
|
||||
|
@ -86,10 +86,10 @@ struct SkippedRange {
|
|||
/// when skipping a directive like #if, #ifdef or #elsif.
|
||||
///
|
||||
/// \returns false on success, true on error.
|
||||
bool computeSkippedRanges(ArrayRef<Token> Input,
|
||||
bool computeSkippedRanges(ArrayRef<Directive> Input,
|
||||
llvm::SmallVectorImpl<SkippedRange> &Range);
|
||||
|
||||
} // end namespace minimize_source_to_dependency_directives
|
||||
} // end namespace dependency_directives_scan
|
||||
|
||||
/// Minimize the input down to the preprocessor directives that might have
|
||||
/// an effect on the dependencies for a compilation unit.
|
||||
|
@ -103,13 +103,12 @@ bool computeSkippedRanges(ArrayRef<Token> Input,
|
|||
/// \returns false on success, true on error. If the diagnostic engine is not
|
||||
/// null, an appropriate error is reported using the given input location
|
||||
/// with the offset that corresponds to the minimizer's current buffer offset.
|
||||
bool minimizeSourceToDependencyDirectives(
|
||||
bool scanSourceForDependencyDirectives(
|
||||
llvm::StringRef Input, llvm::SmallVectorImpl<char> &Output,
|
||||
llvm::SmallVectorImpl<minimize_source_to_dependency_directives::Token>
|
||||
&Tokens,
|
||||
llvm::SmallVectorImpl<dependency_directives_scan::Directive> &Directives,
|
||||
DiagnosticsEngine *Diags = nullptr,
|
||||
SourceLocation InputSourceLoc = SourceLocation());
|
||||
|
||||
} // end namespace clang
|
||||
|
||||
#endif // LLVM_CLANG_LEX_DEPENDENCYDIRECTIVESSOURCEMINIMIZER_H
|
||||
#endif // LLVM_CLANG_LEX_DEPENDENCYDIRECTIVESSCANNER_H
|
|
@ -28,14 +28,14 @@ struct CachedFileContents {
|
|||
CachedFileContents(std::unique_ptr<llvm::MemoryBuffer> Original)
|
||||
: Original(std::move(Original)), MinimizedAccess(nullptr) {}
|
||||
|
||||
/// Owning storage for the minimized contents.
|
||||
/// Owning storage for the original contents.
|
||||
std::unique_ptr<llvm::MemoryBuffer> Original;
|
||||
|
||||
/// The mutex that must be locked before mutating minimized contents.
|
||||
/// The mutex that must be locked before mutating directive tokens.
|
||||
std::mutex ValueLock;
|
||||
/// Owning storage for the minimized contents.
|
||||
std::unique_ptr<llvm::MemoryBuffer> MinimizedStorage;
|
||||
/// Accessor to the minimized contents that's atomic to avoid data races.
|
||||
/// Accessor to the directive tokens that's atomic to avoid data races.
|
||||
std::atomic<llvm::MemoryBuffer *> MinimizedAccess;
|
||||
/// Skipped range mapping of the minimized contents.
|
||||
/// This is initialized iff `MinimizedAccess != nullptr`.
|
||||
|
@ -46,8 +46,8 @@ struct CachedFileContents {
|
|||
/// the dependency scanning filesystem.
|
||||
///
|
||||
/// It represents one of the following:
|
||||
/// - opened file with original contents and a stat value,
|
||||
/// - opened file with original contents, minimized contents and a stat value,
|
||||
/// - opened file with contents and a stat value,
|
||||
/// - opened file with contents, directive tokens and a stat value,
|
||||
/// - directory entry with its stat value,
|
||||
/// - filesystem error.
|
||||
///
|
||||
|
@ -84,8 +84,9 @@ public:
|
|||
return Contents->Original->getBuffer();
|
||||
}
|
||||
|
||||
/// \returns Minimized contents of the file.
|
||||
StringRef getMinimizedContents() const {
|
||||
/// \returns The scanned preprocessor directive tokens of the file that are
|
||||
/// used to speed up preprocessing, if available.
|
||||
StringRef getDirectiveTokens() const {
|
||||
assert(!isError() && "error");
|
||||
assert(!MaybeStat->isDirectory() && "not a file");
|
||||
assert(Contents && "contents not initialized");
|
||||
|
@ -119,8 +120,8 @@ public:
|
|||
return Contents->PPSkippedRangeMapping;
|
||||
}
|
||||
|
||||
/// \returns The data structure holding both original and minimized contents.
|
||||
CachedFileContents *getContents() const {
|
||||
/// \returns The data structure holding both contents and directive tokens.
|
||||
CachedFileContents *getCachedContents() const {
|
||||
assert(!isError() && "error");
|
||||
assert(!isDirectory() && "not a file");
|
||||
return Contents;
|
||||
|
@ -145,7 +146,7 @@ private:
|
|||
};
|
||||
|
||||
/// This class is a shared cache, that caches the 'stat' and 'open' calls to the
|
||||
/// underlying real file system. It distinguishes between minimized and original
|
||||
/// underlying real file system, and the scanned preprocessor directives of
|
||||
/// files.
|
||||
///
|
||||
/// It is sharded based on the hash of the key to reduce the lock contention for
|
||||
|
@ -210,8 +211,7 @@ private:
|
|||
};
|
||||
|
||||
/// This class is a local cache, that caches the 'stat' and 'open' calls to the
|
||||
/// underlying real file system. It distinguishes between minimized and original
|
||||
/// files.
|
||||
/// underlying real file system.
|
||||
class DependencyScanningFilesystemLocalCache {
|
||||
llvm::StringMap<const CachedFileSystemEntry *, llvm::BumpPtrAllocator> Cache;
|
||||
|
||||
|
@ -234,9 +234,8 @@ public:
|
|||
};
|
||||
|
||||
/// Reference to a CachedFileSystemEntry.
|
||||
/// If the underlying entry is an opened file, this wrapper returns the correct
|
||||
/// contents (original or minimized) and ensures consistency with file size
|
||||
/// reported by status.
|
||||
/// If the underlying entry is an opened file, this wrapper returns the file
|
||||
/// contents and the scanned preprocessor directives.
|
||||
class EntryRef {
|
||||
/// For entry that is an opened file, this bit signifies whether its contents
|
||||
/// are minimized.
|
||||
|
@ -270,8 +269,7 @@ public:
|
|||
}
|
||||
|
||||
StringRef getContents() const {
|
||||
return Minimized ? Entry.getMinimizedContents()
|
||||
: Entry.getOriginalContents();
|
||||
return Minimized ? Entry.getDirectiveTokens() : Entry.getOriginalContents();
|
||||
}
|
||||
|
||||
const PreprocessorSkippedRangeMapping *getPPSkippedRangeMapping() const {
|
||||
|
@ -301,14 +299,14 @@ public:
|
|||
llvm::ErrorOr<std::unique_ptr<llvm::vfs::File>>
|
||||
openFileForRead(const Twine &Path) override;
|
||||
|
||||
/// Disable minimization of the given file.
|
||||
void disableMinimization(StringRef Filename);
|
||||
/// Enable minimization of all files.
|
||||
void enableMinimizationOfAllFiles() { NotToBeMinimized.clear(); }
|
||||
/// Disable directives scanning of the given file.
|
||||
void disableDirectivesScanning(StringRef Filename);
|
||||
/// Enable directives scanning of all files.
|
||||
void enableDirectivesScanningOfAllFiles() { NotToBeScanned.clear(); }
|
||||
|
||||
private:
|
||||
/// Check whether the file should be minimized.
|
||||
bool shouldMinimize(StringRef Filename, llvm::sys::fs::UniqueID UID);
|
||||
/// Check whether the file should be scanned for preprocessor directives.
|
||||
bool shouldScanForDirectives(StringRef Filename, llvm::sys::fs::UniqueID UID);
|
||||
|
||||
/// Returns entry for the given filename.
|
||||
///
|
||||
|
@ -316,7 +314,7 @@ private:
|
|||
/// using the underlying filesystem.
|
||||
llvm::ErrorOr<EntryRef>
|
||||
getOrCreateFileSystemEntry(StringRef Filename,
|
||||
bool DisableMinimization = false);
|
||||
bool DisableDirectivesScanning = false);
|
||||
|
||||
/// For a filename that's not yet associated with any entry in the caches,
|
||||
/// uses the underlying filesystem to either look up the entry based in the
|
||||
|
@ -324,10 +322,10 @@ private:
|
|||
llvm::ErrorOr<const CachedFileSystemEntry &>
|
||||
computeAndStoreResult(StringRef Filename);
|
||||
|
||||
/// Minimizes the given entry if necessary and returns a wrapper object with
|
||||
/// reference semantics.
|
||||
EntryRef minimizeIfNecessary(const CachedFileSystemEntry &Entry,
|
||||
StringRef Filename, bool Disable);
|
||||
/// Scan for preprocessor directives for the given entry if necessary and
|
||||
/// returns a wrapper object with reference semantics.
|
||||
EntryRef scanForDirectivesIfNecessary(const CachedFileSystemEntry &Entry,
|
||||
StringRef Filename, bool Disable);
|
||||
|
||||
/// Represents a filesystem entry that has been stat-ed (and potentially read)
|
||||
/// and that's about to be inserted into the cache as `CachedFileSystemEntry`.
|
||||
|
@ -402,8 +400,8 @@ private:
|
|||
/// excluded conditional directive skip mappings that are used by the
|
||||
/// currently active preprocessor.
|
||||
ExcludedPreprocessorDirectiveSkipMapping &PPSkipMappings;
|
||||
/// The set of files that should not be minimized.
|
||||
llvm::DenseSet<llvm::sys::fs::UniqueID> NotToBeMinimized;
|
||||
/// The set of files that should not be scanned for PP directives.
|
||||
llvm::DenseSet<llvm::sys::fs::UniqueID> NotToBeScanned;
|
||||
};
|
||||
|
||||
} // end namespace dependencies
|
||||
|
|
|
@ -19,15 +19,13 @@ namespace dependencies {
|
|||
/// dependencies.
|
||||
enum class ScanningMode {
|
||||
/// This mode is used to compute the dependencies by running the preprocessor
|
||||
/// over
|
||||
/// the unmodified source files.
|
||||
/// over the source files.
|
||||
CanonicalPreprocessing,
|
||||
|
||||
/// This mode is used to compute the dependencies by running the preprocessor
|
||||
/// over
|
||||
/// the source files that have been minimized to contents that might affect
|
||||
/// the dependencies.
|
||||
MinimizedSourcePreprocessing
|
||||
/// with special kind of lexing after scanning header and source files to get
|
||||
/// the minimum necessary preprocessor directives for evaluating includes.
|
||||
DependencyDirectivesScan,
|
||||
};
|
||||
|
||||
/// The format that is output by the dependency scanner.
|
||||
|
|
|
@ -18,7 +18,7 @@
|
|||
#include "clang/Frontend/FrontendDiagnostic.h"
|
||||
#include "clang/Frontend/MultiplexConsumer.h"
|
||||
#include "clang/Frontend/Utils.h"
|
||||
#include "clang/Lex/DependencyDirectivesSourceMinimizer.h"
|
||||
#include "clang/Lex/DependencyDirectivesScanner.h"
|
||||
#include "clang/Lex/HeaderSearch.h"
|
||||
#include "clang/Lex/Preprocessor.h"
|
||||
#include "clang/Lex/PreprocessorOptions.h"
|
||||
|
@ -1158,9 +1158,9 @@ void PrintDependencyDirectivesSourceMinimizerAction::ExecuteAction() {
|
|||
llvm::MemoryBufferRef FromFile = SM.getBufferOrFake(SM.getMainFileID());
|
||||
|
||||
llvm::SmallString<1024> Output;
|
||||
llvm::SmallVector<minimize_source_to_dependency_directives::Token, 32> Toks;
|
||||
if (minimizeSourceToDependencyDirectives(
|
||||
FromFile.getBuffer(), Output, Toks, &CI.getDiagnostics(),
|
||||
llvm::SmallVector<dependency_directives_scan::Directive, 32> Directives;
|
||||
if (scanSourceForDependencyDirectives(
|
||||
FromFile.getBuffer(), Output, Directives, &CI.getDiagnostics(),
|
||||
SM.getLocForStartOfFile(SM.getMainFileID()))) {
|
||||
assert(CI.getDiagnostics().hasErrorOccurred() &&
|
||||
"no errors reported for failure");
|
||||
|
|
|
@ -3,7 +3,7 @@
|
|||
set(LLVM_LINK_COMPONENTS support)
|
||||
|
||||
add_clang_library(clangLex
|
||||
DependencyDirectivesSourceMinimizer.cpp
|
||||
DependencyDirectivesScanner.cpp
|
||||
HeaderMap.cpp
|
||||
HeaderSearch.cpp
|
||||
InitHeaderSearch.cpp
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
//===- DependencyDirectivesSourceMinimizer.cpp - -------------------------===//
|
||||
//===- DependencyDirectivesScanner.cpp ------------------------------------===//
|
||||
//
|
||||
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
|
||||
// See https://llvm.org/LICENSE.txt for license information.
|
||||
|
@ -7,14 +7,14 @@
|
|||
//===----------------------------------------------------------------------===//
|
||||
///
|
||||
/// \file
|
||||
/// This is the implementation for minimizing header and source files to the
|
||||
/// This is the interface for scanning header and source files to get the
|
||||
/// minimum necessary preprocessor directives for evaluating includes. It
|
||||
/// reduces the source down to #define, #include, #import, @import, and any
|
||||
/// conditional preprocessor logic that contains one of those.
|
||||
///
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#include "clang/Lex/DependencyDirectivesSourceMinimizer.h"
|
||||
#include "clang/Lex/DependencyDirectivesScanner.h"
|
||||
#include "clang/Basic/CharInfo.h"
|
||||
#include "clang/Basic/Diagnostic.h"
|
||||
#include "clang/Lex/LexDiagnostic.h"
|
||||
|
@ -24,26 +24,26 @@
|
|||
|
||||
using namespace llvm;
|
||||
using namespace clang;
|
||||
using namespace clang::minimize_source_to_dependency_directives;
|
||||
using namespace clang::dependency_directives_scan;
|
||||
|
||||
namespace {
|
||||
|
||||
struct Minimizer {
|
||||
struct Scanner {
|
||||
/// Minimized output.
|
||||
SmallVectorImpl<char> &Out;
|
||||
/// The known tokens encountered during the minimization.
|
||||
SmallVectorImpl<Token> &Tokens;
|
||||
SmallVectorImpl<Directive> &Directives;
|
||||
|
||||
Minimizer(SmallVectorImpl<char> &Out, SmallVectorImpl<Token> &Tokens,
|
||||
StringRef Input, DiagnosticsEngine *Diags,
|
||||
SourceLocation InputSourceLoc)
|
||||
: Out(Out), Tokens(Tokens), Input(Input), Diags(Diags),
|
||||
Scanner(SmallVectorImpl<char> &Out, SmallVectorImpl<Directive> &Directives,
|
||||
StringRef Input, DiagnosticsEngine *Diags,
|
||||
SourceLocation InputSourceLoc)
|
||||
: Out(Out), Directives(Directives), Input(Input), Diags(Diags),
|
||||
InputSourceLoc(InputSourceLoc) {}
|
||||
|
||||
/// Lex the provided source and emit the minimized output.
|
||||
/// Lex the provided source and emit the directive tokens.
|
||||
///
|
||||
/// \returns True on error.
|
||||
bool minimize();
|
||||
bool scan();
|
||||
|
||||
private:
|
||||
struct IdInfo {
|
||||
|
@ -57,31 +57,33 @@ private:
|
|||
LLVM_NODISCARD IdInfo lexIdentifier(const char *First, const char *const End);
|
||||
LLVM_NODISCARD bool isNextIdentifier(StringRef Id, const char *&First,
|
||||
const char *const End);
|
||||
LLVM_NODISCARD bool minimizeImpl(const char *First, const char *const End);
|
||||
LLVM_NODISCARD bool scanImpl(const char *First, const char *const End);
|
||||
LLVM_NODISCARD bool lexPPLine(const char *&First, const char *const End);
|
||||
LLVM_NODISCARD bool lexAt(const char *&First, const char *const End);
|
||||
LLVM_NODISCARD bool lexModule(const char *&First, const char *const End);
|
||||
LLVM_NODISCARD bool lexDefine(const char *&First, const char *const End);
|
||||
LLVM_NODISCARD bool lexPragma(const char *&First, const char *const End);
|
||||
LLVM_NODISCARD bool lexEndif(const char *&First, const char *const End);
|
||||
LLVM_NODISCARD bool lexDefault(TokenKind Kind, StringRef Directive,
|
||||
LLVM_NODISCARD bool lexDefault(DirectiveKind Kind, StringRef Directive,
|
||||
const char *&First, const char *const End);
|
||||
Token &makeToken(TokenKind K) {
|
||||
Tokens.emplace_back(K, Out.size());
|
||||
return Tokens.back();
|
||||
Directive &pushDirective(DirectiveKind K) {
|
||||
Directives.emplace_back(K, Out.size());
|
||||
return Directives.back();
|
||||
}
|
||||
void popToken() {
|
||||
Out.resize(Tokens.back().Offset);
|
||||
Tokens.pop_back();
|
||||
void popDirective() {
|
||||
Out.resize(Directives.back().Offset);
|
||||
Directives.pop_back();
|
||||
}
|
||||
DirectiveKind topDirective() const {
|
||||
return Directives.empty() ? pp_none : Directives.back().Kind;
|
||||
}
|
||||
TokenKind top() const { return Tokens.empty() ? pp_none : Tokens.back().K; }
|
||||
|
||||
Minimizer &put(char Byte) {
|
||||
Scanner &put(char Byte) {
|
||||
Out.push_back(Byte);
|
||||
return *this;
|
||||
}
|
||||
Minimizer &append(StringRef S) { return append(S.begin(), S.end()); }
|
||||
Minimizer &append(const char *First, const char *Last) {
|
||||
Scanner &append(StringRef S) { return append(S.begin(), S.end()); }
|
||||
Scanner &append(const char *First, const char *Last) {
|
||||
Out.append(First, Last);
|
||||
return *this;
|
||||
}
|
||||
|
@ -106,7 +108,7 @@ private:
|
|||
|
||||
} // end anonymous namespace
|
||||
|
||||
bool Minimizer::reportError(const char *CurPtr, unsigned Err) {
|
||||
bool Scanner::reportError(const char *CurPtr, unsigned Err) {
|
||||
if (!Diags)
|
||||
return true;
|
||||
assert(CurPtr >= Input.data() && "invalid buffer ptr");
|
||||
|
@ -279,8 +281,7 @@ static const char *findLastNonSpaceNonBackslash(const char *First,
|
|||
return Last;
|
||||
}
|
||||
|
||||
static const char *findFirstTrailingSpace(const char *First,
|
||||
const char *Last) {
|
||||
static const char *findFirstTrailingSpace(const char *First, const char *Last) {
|
||||
const char *LastNonSpace = findLastNonSpace(First, Last);
|
||||
if (Last == LastNonSpace)
|
||||
return Last;
|
||||
|
@ -395,13 +396,14 @@ static void skipDirective(StringRef Name, const char *&First,
|
|||
skipLine(First, End);
|
||||
}
|
||||
|
||||
void Minimizer::printToNewline(const char *&First, const char *const End) {
|
||||
void Scanner::printToNewline(const char *&First, const char *const End) {
|
||||
while (First != End && !isVerticalWhitespace(*First)) {
|
||||
const char *Last = First;
|
||||
do {
|
||||
// Iterate over strings correctly to avoid comments and newlines.
|
||||
if (*Last == '"' || *Last == '\'' ||
|
||||
(*Last == '<' && (top() == pp_include || top() == pp_import))) {
|
||||
(*Last == '<' &&
|
||||
(topDirective() == pp_include || topDirective() == pp_import))) {
|
||||
if (LLVM_UNLIKELY(isRawStringLiteral(First, Last)))
|
||||
skipRawString(Last, End);
|
||||
else
|
||||
|
@ -487,8 +489,8 @@ static void skipWhitespace(const char *&First, const char *const End) {
|
|||
}
|
||||
}
|
||||
|
||||
void Minimizer::printAdjacentModuleNameParts(const char *&First,
|
||||
const char *const End) {
|
||||
void Scanner::printAdjacentModuleNameParts(const char *&First,
|
||||
const char *const End) {
|
||||
// Skip over parts of the body.
|
||||
const char *Last = First;
|
||||
do
|
||||
|
@ -498,7 +500,7 @@ void Minimizer::printAdjacentModuleNameParts(const char *&First,
|
|||
First = Last;
|
||||
}
|
||||
|
||||
bool Minimizer::printAtImportBody(const char *&First, const char *const End) {
|
||||
bool Scanner::printAtImportBody(const char *&First, const char *const End) {
|
||||
for (;;) {
|
||||
skipWhitespace(First, End);
|
||||
if (First == End)
|
||||
|
@ -523,7 +525,7 @@ bool Minimizer::printAtImportBody(const char *&First, const char *const End) {
|
|||
}
|
||||
}
|
||||
|
||||
void Minimizer::printDirectiveBody(const char *&First, const char *const End) {
|
||||
void Scanner::printDirectiveBody(const char *&First, const char *const End) {
|
||||
skipWhitespace(First, End); // Skip initial whitespace.
|
||||
printToNewline(First, End);
|
||||
while (Out.back() == ' ')
|
||||
|
@ -552,8 +554,8 @@ getIdentifierContinuation(const char *First, const char *const End) {
|
|||
return isAsciiIdentifierContinue(First[0]) ? First : nullptr;
|
||||
}
|
||||
|
||||
Minimizer::IdInfo Minimizer::lexIdentifier(const char *First,
|
||||
const char *const End) {
|
||||
Scanner::IdInfo Scanner::lexIdentifier(const char *First,
|
||||
const char *const End) {
|
||||
const char *Last = lexRawIdentifier(First, End);
|
||||
const char *Next = getIdentifierContinuation(Last, End);
|
||||
if (LLVM_LIKELY(!Next))
|
||||
|
@ -571,8 +573,8 @@ Minimizer::IdInfo Minimizer::lexIdentifier(const char *First,
|
|||
SplitIds.try_emplace(StringRef(Id.begin(), Id.size()), 0).first->first()};
|
||||
}
|
||||
|
||||
void Minimizer::printAdjacentMacroArgs(const char *&First,
|
||||
const char *const End) {
|
||||
void Scanner::printAdjacentMacroArgs(const char *&First,
|
||||
const char *const End) {
|
||||
// Skip over parts of the body.
|
||||
const char *Last = First;
|
||||
do
|
||||
|
@ -583,7 +585,7 @@ void Minimizer::printAdjacentMacroArgs(const char *&First,
|
|||
First = Last;
|
||||
}
|
||||
|
||||
bool Minimizer::printMacroArgs(const char *&First, const char *const End) {
|
||||
bool Scanner::printMacroArgs(const char *&First, const char *const End) {
|
||||
assert(*First == '(');
|
||||
put(*First++);
|
||||
for (;;) {
|
||||
|
@ -608,8 +610,8 @@ bool Minimizer::printMacroArgs(const char *&First, const char *const End) {
|
|||
///
|
||||
/// Updates "First" to just past the next identifier, if any. Returns true iff
|
||||
/// the identifier matches "Id".
|
||||
bool Minimizer::isNextIdentifier(StringRef Id, const char *&First,
|
||||
const char *const End) {
|
||||
bool Scanner::isNextIdentifier(StringRef Id, const char *&First,
|
||||
const char *const End) {
|
||||
skipWhitespace(First, End);
|
||||
if (First == End || !isAsciiIdentifierStart(*First))
|
||||
return false;
|
||||
|
@ -619,29 +621,29 @@ bool Minimizer::isNextIdentifier(StringRef Id, const char *&First,
|
|||
return FoundId.Name == Id;
|
||||
}
|
||||
|
||||
bool Minimizer::lexAt(const char *&First, const char *const End) {
|
||||
bool Scanner::lexAt(const char *&First, const char *const End) {
|
||||
// Handle "@import".
|
||||
const char *ImportLoc = First++;
|
||||
if (!isNextIdentifier("import", First, End)) {
|
||||
skipLine(First, End);
|
||||
return false;
|
||||
}
|
||||
makeToken(decl_at_import);
|
||||
pushDirective(decl_at_import);
|
||||
append("@import ");
|
||||
if (printAtImportBody(First, End))
|
||||
return reportError(
|
||||
ImportLoc, diag::err_dep_source_minimizer_missing_sema_after_at_import);
|
||||
ImportLoc, diag::err_dep_source_scanner_missing_semi_after_at_import);
|
||||
skipWhitespace(First, End);
|
||||
if (First == End)
|
||||
return false;
|
||||
if (!isVerticalWhitespace(*First))
|
||||
return reportError(
|
||||
ImportLoc, diag::err_dep_source_minimizer_unexpected_tokens_at_import);
|
||||
ImportLoc, diag::err_dep_source_scanner_unexpected_tokens_at_import);
|
||||
skipNewline(First, End);
|
||||
return false;
|
||||
}
|
||||
|
||||
bool Minimizer::lexModule(const char *&First, const char *const End) {
|
||||
bool Scanner::lexModule(const char *&First, const char *const End) {
|
||||
IdInfo Id = lexIdentifier(First, End);
|
||||
First = Id.Last;
|
||||
bool Export = false;
|
||||
|
@ -679,14 +681,14 @@ bool Minimizer::lexModule(const char *&First, const char *const End) {
|
|||
}
|
||||
|
||||
if (Export) {
|
||||
makeToken(cxx_export_decl);
|
||||
pushDirective(cxx_export_decl);
|
||||
append("export ");
|
||||
}
|
||||
|
||||
if (Id.Name == "module")
|
||||
makeToken(cxx_module_decl);
|
||||
pushDirective(cxx_module_decl);
|
||||
else
|
||||
makeToken(cxx_import_decl);
|
||||
pushDirective(cxx_import_decl);
|
||||
append(Id.Name);
|
||||
append(" ");
|
||||
printToNewline(First, End);
|
||||
|
@ -694,8 +696,8 @@ bool Minimizer::lexModule(const char *&First, const char *const End) {
|
|||
return false;
|
||||
}
|
||||
|
||||
bool Minimizer::lexDefine(const char *&First, const char *const End) {
|
||||
makeToken(pp_define);
|
||||
bool Scanner::lexDefine(const char *&First, const char *const End) {
|
||||
pushDirective(pp_define);
|
||||
append("#define ");
|
||||
skipWhitespace(First, End);
|
||||
|
||||
|
@ -728,7 +730,7 @@ bool Minimizer::lexDefine(const char *&First, const char *const End) {
|
|||
return false;
|
||||
}
|
||||
|
||||
bool Minimizer::lexPragma(const char *&First, const char *const End) {
|
||||
bool Scanner::lexPragma(const char *&First, const char *const End) {
|
||||
// #pragma.
|
||||
skipWhitespace(First, End);
|
||||
if (First == End || !isAsciiIdentifierStart(*First))
|
||||
|
@ -739,27 +741,27 @@ bool Minimizer::lexPragma(const char *&First, const char *const End) {
|
|||
if (FoundId.Name == "once") {
|
||||
// #pragma once
|
||||
skipLine(First, End);
|
||||
makeToken(pp_pragma_once);
|
||||
pushDirective(pp_pragma_once);
|
||||
append("#pragma once\n");
|
||||
return false;
|
||||
}
|
||||
if (FoundId.Name == "push_macro") {
|
||||
// #pragma push_macro
|
||||
makeToken(pp_pragma_push_macro);
|
||||
pushDirective(pp_pragma_push_macro);
|
||||
append("#pragma push_macro");
|
||||
printDirectiveBody(First, End);
|
||||
return false;
|
||||
}
|
||||
if (FoundId.Name == "pop_macro") {
|
||||
// #pragma pop_macro
|
||||
makeToken(pp_pragma_pop_macro);
|
||||
pushDirective(pp_pragma_pop_macro);
|
||||
append("#pragma pop_macro");
|
||||
printDirectiveBody(First, End);
|
||||
return false;
|
||||
}
|
||||
if (FoundId.Name == "include_alias") {
|
||||
// #pragma include_alias
|
||||
makeToken(pp_pragma_include_alias);
|
||||
pushDirective(pp_pragma_include_alias);
|
||||
append("#pragma include_alias");
|
||||
printDirectiveBody(First, End);
|
||||
return false;
|
||||
|
@ -783,16 +785,16 @@ bool Minimizer::lexPragma(const char *&First, const char *const End) {
|
|||
}
|
||||
|
||||
// #pragma clang module import.
|
||||
makeToken(pp_pragma_import);
|
||||
pushDirective(pp_pragma_import);
|
||||
append("#pragma clang module import ");
|
||||
printDirectiveBody(First, End);
|
||||
return false;
|
||||
}
|
||||
|
||||
bool Minimizer::lexEndif(const char *&First, const char *const End) {
|
||||
bool Scanner::lexEndif(const char *&First, const char *const End) {
|
||||
// Strip out "#else" if it's empty.
|
||||
if (top() == pp_else)
|
||||
popToken();
|
||||
if (topDirective() == pp_else)
|
||||
popDirective();
|
||||
|
||||
// If "#ifdef" is empty, strip it and skip the "#endif".
|
||||
//
|
||||
|
@ -800,8 +802,8 @@ bool Minimizer::lexEndif(const char *&First, const char *const End) {
|
|||
// we can skip empty `#if` and `#elif` blocks as well after scanning for a
|
||||
// literal __has_include in the condition. Even without that rule we could
|
||||
// drop the tokens if we scan for identifiers in the condition and find none.
|
||||
if (top() == pp_ifdef || top() == pp_ifndef) {
|
||||
popToken();
|
||||
if (topDirective() == pp_ifdef || topDirective() == pp_ifndef) {
|
||||
popDirective();
|
||||
skipLine(First, End);
|
||||
return false;
|
||||
}
|
||||
|
@ -809,9 +811,9 @@ bool Minimizer::lexEndif(const char *&First, const char *const End) {
|
|||
return lexDefault(pp_endif, "endif", First, End);
|
||||
}
|
||||
|
||||
bool Minimizer::lexDefault(TokenKind Kind, StringRef Directive,
|
||||
const char *&First, const char *const End) {
|
||||
makeToken(Kind);
|
||||
bool Scanner::lexDefault(DirectiveKind Kind, StringRef Directive,
|
||||
const char *&First, const char *const End) {
|
||||
pushDirective(Kind);
|
||||
put('#').append(Directive).put(' ');
|
||||
printDirectiveBody(First, End);
|
||||
return false;
|
||||
|
@ -829,7 +831,7 @@ static bool isStartOfRelevantLine(char First) {
|
|||
return false;
|
||||
}
|
||||
|
||||
bool Minimizer::lexPPLine(const char *&First, const char *const End) {
|
||||
bool Scanner::lexPPLine(const char *&First, const char *const End) {
|
||||
assert(First != End);
|
||||
|
||||
skipWhitespace(First, End);
|
||||
|
@ -869,7 +871,7 @@ bool Minimizer::lexPPLine(const char *&First, const char *const End) {
|
|||
if (Id.Name == "pragma")
|
||||
return lexPragma(First, End);
|
||||
|
||||
auto Kind = llvm::StringSwitch<TokenKind>(Id.Name)
|
||||
auto Kind = llvm::StringSwitch<DirectiveKind>(Id.Name)
|
||||
.Case("include", pp_include)
|
||||
.Case("__include_macros", pp___include_macros)
|
||||
.Case("define", pp_define)
|
||||
|
@ -906,7 +908,7 @@ static void skipUTF8ByteOrderMark(const char *&First, const char *const End) {
|
|||
First += 3;
|
||||
}
|
||||
|
||||
bool Minimizer::minimizeImpl(const char *First, const char *const End) {
|
||||
bool Scanner::scanImpl(const char *First, const char *const End) {
|
||||
skipUTF8ByteOrderMark(First, End);
|
||||
while (First != End)
|
||||
if (lexPPLine(First, End))
|
||||
|
@ -914,14 +916,14 @@ bool Minimizer::minimizeImpl(const char *First, const char *const End) {
|
|||
return false;
|
||||
}
|
||||
|
||||
bool Minimizer::minimize() {
|
||||
bool Error = minimizeImpl(Input.begin(), Input.end());
|
||||
bool Scanner::scan() {
|
||||
bool Error = scanImpl(Input.begin(), Input.end());
|
||||
|
||||
if (!Error) {
|
||||
// Add a trailing newline and an EOF on success.
|
||||
if (!Out.empty() && Out.back() != '\n')
|
||||
Out.push_back('\n');
|
||||
makeToken(pp_eof);
|
||||
pushDirective(pp_eof);
|
||||
}
|
||||
|
||||
// Null-terminate the output. This way the memory buffer that's passed to
|
||||
|
@ -931,9 +933,9 @@ bool Minimizer::minimize() {
|
|||
return Error;
|
||||
}
|
||||
|
||||
bool clang::minimize_source_to_dependency_directives::computeSkippedRanges(
|
||||
ArrayRef<Token> Input, llvm::SmallVectorImpl<SkippedRange> &Range) {
|
||||
struct Directive {
|
||||
bool clang::dependency_directives_scan::computeSkippedRanges(
|
||||
ArrayRef<Directive> Input, llvm::SmallVectorImpl<SkippedRange> &Range) {
|
||||
struct IfElseDirective {
|
||||
enum DirectiveKind {
|
||||
If, // if/ifdef/ifndef
|
||||
Else // elif/elifdef/elifndef, else
|
||||
|
@ -941,13 +943,13 @@ bool clang::minimize_source_to_dependency_directives::computeSkippedRanges(
|
|||
int Offset;
|
||||
DirectiveKind Kind;
|
||||
};
|
||||
llvm::SmallVector<Directive, 32> Offsets;
|
||||
for (const Token &T : Input) {
|
||||
switch (T.K) {
|
||||
llvm::SmallVector<IfElseDirective, 32> Offsets;
|
||||
for (const Directive &T : Input) {
|
||||
switch (T.Kind) {
|
||||
case pp_if:
|
||||
case pp_ifdef:
|
||||
case pp_ifndef:
|
||||
Offsets.push_back({T.Offset, Directive::If});
|
||||
Offsets.push_back({T.Offset, IfElseDirective::If});
|
||||
break;
|
||||
|
||||
case pp_elif:
|
||||
|
@ -958,7 +960,7 @@ bool clang::minimize_source_to_dependency_directives::computeSkippedRanges(
|
|||
return true;
|
||||
int PreviousOffset = Offsets.back().Offset;
|
||||
Range.push_back({PreviousOffset, T.Offset - PreviousOffset});
|
||||
Offsets.push_back({T.Offset, Directive::Else});
|
||||
Offsets.push_back({T.Offset, IfElseDirective::Else});
|
||||
break;
|
||||
}
|
||||
|
||||
|
@ -968,8 +970,8 @@ bool clang::minimize_source_to_dependency_directives::computeSkippedRanges(
|
|||
int PreviousOffset = Offsets.back().Offset;
|
||||
Range.push_back({PreviousOffset, T.Offset - PreviousOffset});
|
||||
do {
|
||||
Directive::DirectiveKind Kind = Offsets.pop_back_val().Kind;
|
||||
if (Kind == Directive::If)
|
||||
IfElseDirective::DirectiveKind Kind = Offsets.pop_back_val().Kind;
|
||||
if (Kind == IfElseDirective::If)
|
||||
break;
|
||||
} while (!Offsets.empty());
|
||||
break;
|
||||
|
@ -981,11 +983,11 @@ bool clang::minimize_source_to_dependency_directives::computeSkippedRanges(
|
|||
return false;
|
||||
}
|
||||
|
||||
bool clang::minimizeSourceToDependencyDirectives(
|
||||
bool clang::scanSourceForDependencyDirectives(
|
||||
StringRef Input, SmallVectorImpl<char> &Output,
|
||||
SmallVectorImpl<Token> &Tokens, DiagnosticsEngine *Diags,
|
||||
SmallVectorImpl<Directive> &Directives, DiagnosticsEngine *Diags,
|
||||
SourceLocation InputSourceLoc) {
|
||||
Output.clear();
|
||||
Tokens.clear();
|
||||
return Minimizer(Output, Tokens, Input, Diags, InputSourceLoc).minimize();
|
||||
Directives.clear();
|
||||
return Scanner(Output, Directives, Input, Diags, InputSourceLoc).scan();
|
||||
}
|
|
@ -7,7 +7,7 @@
|
|||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#include "clang/Tooling/DependencyScanning/DependencyScanningFilesystem.h"
|
||||
#include "clang/Lex/DependencyDirectivesSourceMinimizer.h"
|
||||
#include "clang/Lex/DependencyDirectivesScanner.h"
|
||||
#include "llvm/Support/MemoryBuffer.h"
|
||||
#include "llvm/Support/SmallVectorMemoryBuffer.h"
|
||||
#include "llvm/Support/Threading.h"
|
||||
|
@ -41,13 +41,13 @@ DependencyScanningWorkerFilesystem::readFile(StringRef Filename) {
|
|||
return TentativeEntry(Stat, std::move(Buffer));
|
||||
}
|
||||
|
||||
EntryRef DependencyScanningWorkerFilesystem::minimizeIfNecessary(
|
||||
EntryRef DependencyScanningWorkerFilesystem::scanForDirectivesIfNecessary(
|
||||
const CachedFileSystemEntry &Entry, StringRef Filename, bool Disable) {
|
||||
if (Entry.isError() || Entry.isDirectory() || Disable ||
|
||||
!shouldMinimize(Filename, Entry.getUniqueID()))
|
||||
!shouldScanForDirectives(Filename, Entry.getUniqueID()))
|
||||
return EntryRef(/*Minimized=*/false, Filename, Entry);
|
||||
|
||||
CachedFileContents *Contents = Entry.getContents();
|
||||
CachedFileContents *Contents = Entry.getCachedContents();
|
||||
assert(Contents && "contents not initialized");
|
||||
|
||||
// Double-checked locking.
|
||||
|
@ -62,9 +62,9 @@ EntryRef DependencyScanningWorkerFilesystem::minimizeIfNecessary(
|
|||
|
||||
llvm::SmallString<1024> MinimizedFileContents;
|
||||
// Minimize the file down to directives that might affect the dependencies.
|
||||
SmallVector<minimize_source_to_dependency_directives::Token, 64> Tokens;
|
||||
if (minimizeSourceToDependencyDirectives(Contents->Original->getBuffer(),
|
||||
MinimizedFileContents, Tokens)) {
|
||||
SmallVector<dependency_directives_scan::Directive, 64> Tokens;
|
||||
if (scanSourceForDependencyDirectives(Contents->Original->getBuffer(),
|
||||
MinimizedFileContents, Tokens)) {
|
||||
// FIXME: Propagate the diagnostic if desired by the client.
|
||||
// Use the original file if the minimization failed.
|
||||
Contents->MinimizedStorage =
|
||||
|
@ -79,10 +79,8 @@ EntryRef DependencyScanningWorkerFilesystem::minimizeIfNecessary(
|
|||
|
||||
// Compute the skipped PP ranges that speedup skipping over inactive
|
||||
// preprocessor blocks.
|
||||
llvm::SmallVector<minimize_source_to_dependency_directives::SkippedRange, 32>
|
||||
SkippedRanges;
|
||||
minimize_source_to_dependency_directives::computeSkippedRanges(Tokens,
|
||||
SkippedRanges);
|
||||
llvm::SmallVector<dependency_directives_scan::SkippedRange, 32> SkippedRanges;
|
||||
dependency_directives_scan::computeSkippedRanges(Tokens, SkippedRanges);
|
||||
PreprocessorSkippedRangeMapping Mapping;
|
||||
for (const auto &Range : SkippedRanges) {
|
||||
if (Range.Length < 16) {
|
||||
|
@ -189,7 +187,7 @@ DependencyScanningFilesystemSharedCache::CacheShard::
|
|||
///
|
||||
/// This is kinda hacky, it would be better if we knew what kind of file Clang
|
||||
/// was expecting instead.
|
||||
static bool shouldMinimizeBasedOnExtension(StringRef Filename) {
|
||||
static bool shouldScanForDirectivesBasedOnExtension(StringRef Filename) {
|
||||
StringRef Ext = llvm::sys::path::extension(Filename);
|
||||
if (Ext.empty())
|
||||
return true; // C++ standard library
|
||||
|
@ -207,22 +205,22 @@ static bool shouldCacheStatFailures(StringRef Filename) {
|
|||
if (Ext.empty())
|
||||
return false; // This may be the module cache directory.
|
||||
// Only cache stat failures on source files.
|
||||
return shouldMinimizeBasedOnExtension(Filename);
|
||||
return shouldScanForDirectivesBasedOnExtension(Filename);
|
||||
}
|
||||
|
||||
void DependencyScanningWorkerFilesystem::disableMinimization(
|
||||
void DependencyScanningWorkerFilesystem::disableDirectivesScanning(
|
||||
StringRef Filename) {
|
||||
// Since we're not done setting up `NotToBeMinimized` yet, we need to disable
|
||||
// minimization explicitly.
|
||||
if (llvm::ErrorOr<EntryRef> Result =
|
||||
getOrCreateFileSystemEntry(Filename, /*DisableMinimization=*/true))
|
||||
NotToBeMinimized.insert(Result->getStatus().getUniqueID());
|
||||
// Since we're not done setting up `NotToBeScanned` yet, we need to disable
|
||||
// directive scanning explicitly.
|
||||
if (llvm::ErrorOr<EntryRef> Result = getOrCreateFileSystemEntry(
|
||||
Filename, /*DisableDirectivesScanning=*/true))
|
||||
NotToBeScanned.insert(Result->getStatus().getUniqueID());
|
||||
}
|
||||
|
||||
bool DependencyScanningWorkerFilesystem::shouldMinimize(
|
||||
bool DependencyScanningWorkerFilesystem::shouldScanForDirectives(
|
||||
StringRef Filename, llvm::sys::fs::UniqueID UID) {
|
||||
return shouldMinimizeBasedOnExtension(Filename) &&
|
||||
!NotToBeMinimized.contains(UID);
|
||||
return shouldScanForDirectivesBasedOnExtension(Filename) &&
|
||||
!NotToBeScanned.contains(UID);
|
||||
}
|
||||
|
||||
const CachedFileSystemEntry &
|
||||
|
@ -275,14 +273,16 @@ DependencyScanningWorkerFilesystem::computeAndStoreResult(StringRef Filename) {
|
|||
|
||||
llvm::ErrorOr<EntryRef>
|
||||
DependencyScanningWorkerFilesystem::getOrCreateFileSystemEntry(
|
||||
StringRef Filename, bool DisableMinimization) {
|
||||
StringRef Filename, bool DisableDirectivesScanning) {
|
||||
if (const auto *Entry = findEntryByFilenameWithWriteThrough(Filename))
|
||||
return minimizeIfNecessary(*Entry, Filename, DisableMinimization)
|
||||
return scanForDirectivesIfNecessary(*Entry, Filename,
|
||||
DisableDirectivesScanning)
|
||||
.unwrapError();
|
||||
auto MaybeEntry = computeAndStoreResult(Filename);
|
||||
if (!MaybeEntry)
|
||||
return MaybeEntry.getError();
|
||||
return minimizeIfNecessary(*MaybeEntry, Filename, DisableMinimization)
|
||||
return scanForDirectivesIfNecessary(*MaybeEntry, Filename,
|
||||
DisableDirectivesScanning)
|
||||
.unwrapError();
|
||||
}
|
||||
|
||||
|
@ -301,10 +301,10 @@ namespace {
|
|||
|
||||
/// The VFS that is used by clang consumes the \c CachedFileSystemEntry using
|
||||
/// this subclass.
|
||||
class MinimizedVFSFile final : public llvm::vfs::File {
|
||||
class DepScanFile final : public llvm::vfs::File {
|
||||
public:
|
||||
MinimizedVFSFile(std::unique_ptr<llvm::MemoryBuffer> Buffer,
|
||||
llvm::vfs::Status Stat)
|
||||
DepScanFile(std::unique_ptr<llvm::MemoryBuffer> Buffer,
|
||||
llvm::vfs::Status Stat)
|
||||
: Buffer(std::move(Buffer)), Stat(std::move(Stat)) {}
|
||||
|
||||
static llvm::ErrorOr<std::unique_ptr<llvm::vfs::File>>
|
||||
|
@ -328,14 +328,15 @@ private:
|
|||
|
||||
} // end anonymous namespace
|
||||
|
||||
llvm::ErrorOr<std::unique_ptr<llvm::vfs::File>> MinimizedVFSFile::create(
|
||||
EntryRef Entry, ExcludedPreprocessorDirectiveSkipMapping &PPSkipMappings) {
|
||||
llvm::ErrorOr<std::unique_ptr<llvm::vfs::File>>
|
||||
DepScanFile::create(EntryRef Entry,
|
||||
ExcludedPreprocessorDirectiveSkipMapping &PPSkipMappings) {
|
||||
assert(!Entry.isError() && "error");
|
||||
|
||||
if (Entry.isDirectory())
|
||||
return std::make_error_code(std::errc::is_a_directory);
|
||||
|
||||
auto Result = std::make_unique<MinimizedVFSFile>(
|
||||
auto Result = std::make_unique<DepScanFile>(
|
||||
llvm::MemoryBuffer::getMemBuffer(Entry.getContents(),
|
||||
Entry.getStatus().getName(),
|
||||
/*RequiresNullTerminator=*/false),
|
||||
|
@ -357,5 +358,5 @@ DependencyScanningWorkerFilesystem::openFileForRead(const Twine &Path) {
|
|||
llvm::ErrorOr<EntryRef> Result = getOrCreateFileSystemEntry(Filename);
|
||||
if (!Result)
|
||||
return Result.getError();
|
||||
return MinimizedVFSFile::create(Result.get(), PPSkipMappings);
|
||||
return DepScanFile::create(Result.get(), PPSkipMappings);
|
||||
}
|
||||
|
|
|
@ -183,19 +183,19 @@ public:
|
|||
|
||||
// Use the dependency scanning optimized file system if requested to do so.
|
||||
if (DepFS) {
|
||||
DepFS->enableMinimizationOfAllFiles();
|
||||
DepFS->enableDirectivesScanningOfAllFiles();
|
||||
// Don't minimize any files that contributed to prebuilt modules. The
|
||||
// implicit build validates the modules by comparing the reported sizes of
|
||||
// their inputs to the current state of the filesystem. Minimization would
|
||||
// throw this mechanism off.
|
||||
for (const auto &File : PrebuiltModulesInputFiles)
|
||||
DepFS->disableMinimization(File.getKey());
|
||||
DepFS->disableDirectivesScanning(File.getKey());
|
||||
// Don't minimize any files that were explicitly passed in the build
|
||||
// settings and that might be opened.
|
||||
for (const auto &E : ScanInstance.getHeaderSearchOpts().UserEntries)
|
||||
DepFS->disableMinimization(E.Path);
|
||||
DepFS->disableDirectivesScanning(E.Path);
|
||||
for (const auto &F : ScanInstance.getHeaderSearchOpts().VFSOverlayFiles)
|
||||
DepFS->disableMinimization(F);
|
||||
DepFS->disableDirectivesScanning(F);
|
||||
|
||||
// Support for virtual file system overlays on top of the caching
|
||||
// filesystem.
|
||||
|
@ -287,7 +287,7 @@ DependencyScanningWorker::DependencyScanningWorker(
|
|||
OverlayFS->pushOverlay(InMemoryFS);
|
||||
RealFS = OverlayFS;
|
||||
|
||||
if (Service.getMode() == ScanningMode::MinimizedSourcePreprocessing)
|
||||
if (Service.getMode() == ScanningMode::DependencyDirectivesScan)
|
||||
DepFS = new DependencyScanningWorkerFilesystem(Service.getSharedCache(),
|
||||
RealFS, PPSkipMappings);
|
||||
if (Service.canReuseFileManager())
|
||||
|
|
|
@ -10,7 +10,7 @@
|
|||
// RUN: cp %S/Inputs/header.h %t.dir/Inputs/header4.h
|
||||
// RUN: sed -e "s|DIR|%/t.dir|g" %S/Inputs/has_include_if_elif.json > %t.cdb
|
||||
//
|
||||
// RUN: clang-scan-deps -compilation-database %t.cdb -j 1 -mode preprocess-minimized-sources | \
|
||||
// RUN: clang-scan-deps -compilation-database %t.cdb -j 1 -mode preprocess-dependency-directives | \
|
||||
// RUN: FileCheck %s
|
||||
// RUN: clang-scan-deps -compilation-database %t.cdb -j 1 -mode preprocess | \
|
||||
// RUN: FileCheck %s
|
||||
|
|
|
@ -0,0 +1,40 @@
|
|||
// This checks that there's no issue with the preprocessor handling user or built-in macro
|
||||
// expansion during dependency scanning.
|
||||
|
||||
// RUN: rm -rf %t
|
||||
// RUN: split-file %s %t
|
||||
// RUN: sed -e "s|DIR|%/t|g" %t/cdb.json.template > %t/cdb.json
|
||||
|
||||
// RUN: clang-scan-deps -compilation-database %t/cdb.json | FileCheck %s
|
||||
|
||||
// CHECK: test.o:
|
||||
// CHECK-NEXT: test.cpp
|
||||
// CHECK-NEXT: header1.h
|
||||
// CHECK-NEXT: header2.h
|
||||
|
||||
//--- cdb.json.template
|
||||
[{
|
||||
"directory" : "DIR",
|
||||
"command" : "clang -c DIR/test.cpp -o DIR/test.o",
|
||||
"file" : "DIR/test.o"
|
||||
}]
|
||||
|
||||
//--- test.cpp
|
||||
#define FN_MACRO(x) 1
|
||||
#if FN_MACRO(a)
|
||||
#include "header1.h"
|
||||
#endif
|
||||
|
||||
#if __has_cpp_attribute(clang::fallthrough)
|
||||
#include "header2.h"
|
||||
#endif
|
||||
|
||||
//--- header1.h
|
||||
#ifndef _HEADER1_H_
|
||||
#define _HEADER1_H_
|
||||
#endif
|
||||
|
||||
//--- header2.h
|
||||
#ifndef _HEADER2_H_
|
||||
#define _HEADER2_H_
|
||||
#endif
|
|
@ -3,7 +3,7 @@
|
|||
// RUN: sed -e "s|DIR|%/t.dir|g" %t.dir/build/compile-commands.json.in > %t.dir/build/compile-commands.json
|
||||
// RUN: sed -e "s|DIR|%/t.dir|g" %t.dir/build/vfs.yaml.in > %t.dir/build/vfs.yaml
|
||||
// RUN: clang-scan-deps -compilation-database %t.dir/build/compile-commands.json -j 1 -format experimental-full \
|
||||
// RUN: -mode preprocess-minimized-sources -generate-modules-path-args > %t.db
|
||||
// RUN: -mode preprocess-dependency-directives -generate-modules-path-args > %t.db
|
||||
// RUN: %deps-to-rsp %t.db --module-name=A > %t.A.cc1.rsp
|
||||
// RUN: cat %t.A.cc1.rsp | sed 's:\\\\\?:/:g' | FileCheck %s
|
||||
|
||||
|
|
|
@ -10,7 +10,7 @@
|
|||
// RUN: sed -e "s|DIR|%/t.dir|g" %S/Inputs/module_fmodule_name_cdb.json > %t.cdb
|
||||
|
||||
// RUN: clang-scan-deps -compilation-database %t.cdb -j 1 -format experimental-full \
|
||||
// RUN: -generate-modules-path-args -mode preprocess-minimized-sources > %t.result
|
||||
// RUN: -generate-modules-path-args -mode preprocess-dependency-directives > %t.result
|
||||
// RUN: cat %t.result | sed 's:\\\\\?:/:g' | FileCheck -DPREFIX=%/t.dir --check-prefixes=CHECK %s
|
||||
|
||||
#import "header3.h"
|
||||
|
|
|
@ -12,11 +12,11 @@
|
|||
// RUN: sed -e "s|DIR|%/t.dir|g" %S/Inputs/modules_cdb_clangcl_by_mod_name.json > %t_clangcl.cdb
|
||||
//
|
||||
// RUN: clang-scan-deps -compilation-database %t.cdb -j 4 -format experimental-full \
|
||||
// RUN: -mode preprocess-minimized-sources -module-name=header1 > %t.result
|
||||
// RUN: -mode preprocess-dependency-directives -module-name=header1 > %t.result
|
||||
// RUN: cat %t.result | sed 's:\\\\\?:/:g' | FileCheck -DPREFIX=%/t.dir --check-prefixes=CHECK %s
|
||||
//
|
||||
// RUN: clang-scan-deps -compilation-database %t_clangcl.cdb -j 4 -format experimental-full \
|
||||
// RUN: -mode preprocess-minimized-sources -module-name=header1 > %t_clangcl.result
|
||||
// RUN: -mode preprocess-dependency-directives -module-name=header1 > %t_clangcl.result
|
||||
// RUN: cat %t_clangcl.result | sed 's:\\\\\?:/:g' | FileCheck -DPREFIX=%/t.dir --check-prefixes=CHECK %s
|
||||
|
||||
// CHECK: {
|
||||
|
|
|
@ -11,20 +11,20 @@
|
|||
// RUN: sed -e "s|DIR|%/t.dir|g" %S/Inputs/modules_cdb_clangcl.json > %t_clangcl.cdb
|
||||
//
|
||||
// RUN: clang-scan-deps -compilation-database %t.cdb -j 4 -format experimental-full \
|
||||
// RUN: -mode preprocess-minimized-sources > %t.result
|
||||
// RUN: -mode preprocess-dependency-directives > %t.result
|
||||
// RUN: cat %t.result | sed 's:\\\\\?:/:g' | FileCheck -DPREFIX=%/t.dir --check-prefixes=CHECK,CHECK-NO-ABS %s
|
||||
//
|
||||
// RUN: clang-scan-deps -compilation-database %t.cdb -j 4 -format experimental-full \
|
||||
// RUN: -generate-modules-path-args -mode preprocess-minimized-sources > %t.result
|
||||
// RUN: -generate-modules-path-args -mode preprocess-dependency-directives > %t.result
|
||||
// RUN: cat %t.result | sed 's:\\\\\?:/:g' | FileCheck -DPREFIX=%/t.dir --check-prefixes=CHECK,CHECK-ABS %s
|
||||
//
|
||||
// RUN: clang-scan-deps -compilation-database %t.cdb -j 4 -format experimental-full \
|
||||
// RUN: -generate-modules-path-args -module-files-dir %t.dir/custom \
|
||||
// RUN: -mode preprocess-minimized-sources > %t.result
|
||||
// RUN: -mode preprocess-dependency-directives > %t.result
|
||||
// RUN: cat %t.result | sed 's:\\\\\?:/:g' | FileCheck -DPREFIX=%/t.dir --check-prefixes=CHECK,CHECK-CUSTOM %s
|
||||
//
|
||||
// RUN: clang-scan-deps -compilation-database %t_clangcl.cdb -j 4 -format experimental-full \
|
||||
// RUN: -mode preprocess-minimized-sources > %t_clangcl.result
|
||||
// RUN: -mode preprocess-dependency-directives > %t_clangcl.result
|
||||
// RUN: cat %t_clangcl.result | sed 's:\\\\\?:/:g' | FileCheck -DPREFIX=%/t.dir --check-prefixes=CHECK,CHECK-NO-ABS %s
|
||||
|
||||
#include "header.h"
|
||||
|
|
|
@ -6,7 +6,7 @@
|
|||
// RUN: %S/Inputs/modules_inferred_cdb.json > %t.cdb
|
||||
//
|
||||
// RUN: clang-scan-deps -compilation-database %t.cdb -j 1 -format experimental-full \
|
||||
// RUN: -mode preprocess-minimized-sources -generate-modules-path-args > %t.db
|
||||
// RUN: -mode preprocess-dependency-directives -generate-modules-path-args > %t.db
|
||||
// RUN: %deps-to-rsp %t.db --module-name=Inferred > %t.inferred.cc1.rsp
|
||||
// RUN: %deps-to-rsp %t.db --module-name=System > %t.system.cc1.rsp
|
||||
// RUN: %deps-to-rsp %t.db --tu-index=0 > %t.tu.rsp
|
||||
|
|
|
@ -6,7 +6,7 @@
|
|||
// RUN: %/S/Inputs/modules_inferred_cdb.json > %t.cdb
|
||||
//
|
||||
// RUN: clang-scan-deps -compilation-database %t.cdb -j 1 -format experimental-full \
|
||||
// RUN: -generate-modules-path-args -mode preprocess-minimized-sources > %t.result
|
||||
// RUN: -generate-modules-path-args -mode preprocess-dependency-directives > %t.result
|
||||
// RUN: cat %t.result | sed 's:\\\\\?:/:g' | FileCheck %s -DPREFIX=%/t.dir -DSOURCEDIR=%/S --check-prefixes=CHECK
|
||||
|
||||
#include <Inferred/Inferred.h>
|
||||
|
|
|
@ -13,9 +13,9 @@
|
|||
// RUN: sed -e "s|DIR|%/t.dir|g" %S/Inputs/modules_cdb.json > %t.cdb
|
||||
// RUN: sed -e "s|DIR|%/t.dir|g" %S/Inputs/modules_cdb_clangcl.json > %t_clangcl.cdb
|
||||
//
|
||||
// RUN: clang-scan-deps -compilation-database %t.cdb -j 1 -mode preprocess-minimized-sources | \
|
||||
// RUN: clang-scan-deps -compilation-database %t.cdb -j 1 -mode preprocess-dependency-directives | \
|
||||
// RUN: FileCheck --check-prefixes=CHECK1,CHECK2,CHECK2NO %s
|
||||
// RUN: clang-scan-deps -compilation-database %t_clangcl.cdb -j 1 -mode preprocess-minimized-sources | \
|
||||
// RUN: clang-scan-deps -compilation-database %t_clangcl.cdb -j 1 -mode preprocess-dependency-directives | \
|
||||
// RUN: FileCheck --check-prefixes=CHECK1,CHECK2,CHECK2NO %s
|
||||
//
|
||||
// The output order is non-deterministic when using more than one thread,
|
||||
|
@ -23,17 +23,17 @@
|
|||
// as it might fail if the results for `modules_cdb_input.cpp` are reported before
|
||||
// `modules_cdb_input2.cpp`.
|
||||
//
|
||||
// RUN: clang-scan-deps -compilation-database %t.cdb -j 2 -mode preprocess-minimized-sources | \
|
||||
// RUN: clang-scan-deps -compilation-database %t.cdb -j 2 -mode preprocess-dependency-directives | \
|
||||
// RUN: FileCheck --check-prefix=CHECK1 %s
|
||||
// RUN: clang-scan-deps -compilation-database %t_clangcl.cdb -j 2 -mode preprocess-minimized-sources | \
|
||||
// RUN: clang-scan-deps -compilation-database %t_clangcl.cdb -j 2 -mode preprocess-dependency-directives | \
|
||||
// RUN: FileCheck --check-prefix=CHECK1 %s
|
||||
// RUN: clang-scan-deps -compilation-database %t.cdb -j 2 -mode preprocess | \
|
||||
// RUN: FileCheck --check-prefix=CHECK1 %s
|
||||
// RUN: clang-scan-deps -compilation-database %t_clangcl.cdb -j 2 -mode preprocess | \
|
||||
// RUN: FileCheck --check-prefix=CHECK1 %s
|
||||
// RUN: clang-scan-deps -compilation-database %t.cdb -j 2 -mode preprocess-minimized-sources | \
|
||||
// RUN: clang-scan-deps -compilation-database %t.cdb -j 2 -mode preprocess-dependency-directives | \
|
||||
// RUN: FileCheck --check-prefix=CHECK2 %s
|
||||
// RUN: clang-scan-deps -compilation-database %t_clangcl.cdb -j 2 -mode preprocess-minimized-sources | \
|
||||
// RUN: clang-scan-deps -compilation-database %t_clangcl.cdb -j 2 -mode preprocess-dependency-directives | \
|
||||
// RUN: FileCheck --check-prefix=CHECK2 %s
|
||||
// RUN: clang-scan-deps -compilation-database %t.cdb -j 2 -mode preprocess | \
|
||||
// RUN: FileCheck --check-prefix=CHECK2 %s
|
||||
|
|
|
@ -11,7 +11,7 @@
|
|||
// RUN: touch %t.dir/Inputs/c_alias.h
|
||||
// RUN: sed -e "s|DIR|%/t.dir|g" %S/Inputs/preprocess_minimized_pragmas_cdb.json > %t.cdb
|
||||
//
|
||||
// RUN: clang-scan-deps -compilation-database %t.cdb -j 1 -mode preprocess-minimized-sources | \
|
||||
// RUN: clang-scan-deps -compilation-database %t.cdb -j 1 -mode preprocess-dependency-directives | \
|
||||
// RUN: FileCheck %s
|
||||
// RUN: clang-scan-deps -compilation-database %t.cdb -j 1 -mode preprocess | \
|
||||
// RUN: FileCheck %s
|
||||
|
|
|
@ -10,9 +10,9 @@
|
|||
// RUN: sed -e "s|DIR|%/t.dir|g" %S/Inputs/regular_cdb.json > %t.cdb
|
||||
// RUN: sed -e "s|DIR|%/t.dir|g" %S/Inputs/regular_cdb_clangcl.json > %t_clangcl.cdb
|
||||
//
|
||||
// RUN: clang-scan-deps -compilation-database %t.cdb -j 1 -mode preprocess-minimized-sources | \
|
||||
// RUN: clang-scan-deps -compilation-database %t.cdb -j 1 -mode preprocess-dependency-directives | \
|
||||
// RUN: FileCheck --check-prefixes=CHECK1,CHECK2,CHECK2NO,CHECK3 %s
|
||||
// RUN: clang-scan-deps -compilation-database %t_clangcl.cdb -j 1 -mode preprocess-minimized-sources | \
|
||||
// RUN: clang-scan-deps -compilation-database %t_clangcl.cdb -j 1 -mode preprocess-dependency-directives | \
|
||||
// RUN: FileCheck --check-prefixes=CHECK1,CHECK2,CHECK2NO,CHECK3 %s
|
||||
|
||||
// RUN: clang-scan-deps -compilation-database %t.cdb -j 1 -mode preprocess | \
|
||||
|
@ -31,9 +31,9 @@
|
|||
// as it might fail if the results for `regular_cdb_input.cpp` are reported before
|
||||
// `regular_cdb_input2.cpp`.
|
||||
//
|
||||
// RUN: clang-scan-deps -compilation-database %t.cdb -j 2 -mode preprocess-minimized-sources | \
|
||||
// RUN: clang-scan-deps -compilation-database %t.cdb -j 2 -mode preprocess-dependency-directives | \
|
||||
// RUN: FileCheck --check-prefix=CHECK1 %s
|
||||
// RUN: clang-scan-deps -compilation-database %t_clangcl.cdb -j 2 -mode preprocess-minimized-sources | \
|
||||
// RUN: clang-scan-deps -compilation-database %t_clangcl.cdb -j 2 -mode preprocess-dependency-directives | \
|
||||
// RUN: FileCheck --check-prefix=CHECK1 %s
|
||||
|
||||
// RUN: clang-scan-deps -compilation-database %t.cdb -j 2 -mode preprocess | \
|
||||
|
@ -41,9 +41,9 @@
|
|||
// RUN: clang-scan-deps -compilation-database %t_clangcl.cdb -j 2 -mode preprocess | \
|
||||
// RUN: FileCheck --check-prefix=CHECK1 %s
|
||||
|
||||
// RUN: clang-scan-deps -compilation-database %t.cdb -j 2 -mode preprocess-minimized-sources | \
|
||||
// RUN: clang-scan-deps -compilation-database %t.cdb -j 2 -mode preprocess-dependency-directives | \
|
||||
// RUN: FileCheck --check-prefix=CHECK2 %s
|
||||
// RUN: clang-scan-deps -compilation-database %t_clangcl.cdb -j 2 -mode preprocess-minimized-sources | \
|
||||
// RUN: clang-scan-deps -compilation-database %t_clangcl.cdb -j 2 -mode preprocess-dependency-directives | \
|
||||
// RUN: FileCheck --check-prefix=CHECK2 %s
|
||||
|
||||
// RUN: clang-scan-deps -compilation-database %t.cdb -j 2 -mode preprocess | \
|
||||
|
|
|
@ -116,15 +116,15 @@ static llvm::cl::opt<ScanningMode> ScanMode(
|
|||
"mode",
|
||||
llvm::cl::desc("The preprocessing mode used to compute the dependencies"),
|
||||
llvm::cl::values(
|
||||
clEnumValN(ScanningMode::MinimizedSourcePreprocessing,
|
||||
"preprocess-minimized-sources",
|
||||
"The set of dependencies is computed by preprocessing the "
|
||||
"source files that were minimized to only include the "
|
||||
"contents that might affect the dependencies"),
|
||||
clEnumValN(ScanningMode::DependencyDirectivesScan,
|
||||
"preprocess-dependency-directives",
|
||||
"The set of dependencies is computed by preprocessing with "
|
||||
"special lexing after scanning the source files to get the "
|
||||
"directives that might affect the dependencies"),
|
||||
clEnumValN(ScanningMode::CanonicalPreprocessing, "preprocess",
|
||||
"The set of dependencies is computed by preprocessing the "
|
||||
"unmodified source files")),
|
||||
llvm::cl::init(ScanningMode::MinimizedSourcePreprocessing),
|
||||
"source files")),
|
||||
llvm::cl::init(ScanningMode::DependencyDirectivesScan),
|
||||
llvm::cl::cat(DependencyScannerCategory));
|
||||
|
||||
static llvm::cl::opt<ScanningOutputFormat> Format(
|
||||
|
|
|
@ -3,7 +3,7 @@ set(LLVM_LINK_COMPONENTS
|
|||
)
|
||||
|
||||
add_clang_unittest(LexTests
|
||||
DependencyDirectivesSourceMinimizerTest.cpp
|
||||
DependencyDirectivesScannerTest.cpp
|
||||
HeaderMapTest.cpp
|
||||
HeaderSearchTest.cpp
|
||||
LexerTest.cpp
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
//===- unittests/Lex/DependencyDirectivesSourceMinimizer.cpp - -----------===//
|
||||
//===- unittests/Lex/DependencyDirectivesScannerTest.cpp ------------------===//
|
||||
//
|
||||
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
|
||||
// See https://llvm.org/LICENSE.txt for license information.
|
||||
|
@ -6,45 +6,48 @@
|
|||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#include "clang/Lex/DependencyDirectivesSourceMinimizer.h"
|
||||
#include "clang/Lex/DependencyDirectivesScanner.h"
|
||||
#include "llvm/ADT/SmallString.h"
|
||||
#include "gtest/gtest.h"
|
||||
|
||||
using namespace llvm;
|
||||
using namespace clang;
|
||||
using namespace clang::minimize_source_to_dependency_directives;
|
||||
using namespace clang::dependency_directives_scan;
|
||||
|
||||
namespace clang {
|
||||
|
||||
bool minimizeSourceToDependencyDirectives(StringRef Input,
|
||||
SmallVectorImpl<char> &Out) {
|
||||
SmallVector<minimize_source_to_dependency_directives::Token, 32> Tokens;
|
||||
return minimizeSourceToDependencyDirectives(Input, Out, Tokens);
|
||||
static bool minimizeSourceToDependencyDirectives(StringRef Input,
|
||||
SmallVectorImpl<char> &Out) {
|
||||
SmallVector<dependency_directives_scan::Directive, 32> Directives;
|
||||
return scanSourceForDependencyDirectives(Input, Out, Directives);
|
||||
}
|
||||
|
||||
} // end namespace clang
|
||||
static bool
|
||||
minimizeSourceToDependencyDirectives(StringRef Input,
|
||||
SmallVectorImpl<char> &Out,
|
||||
SmallVectorImpl<Directive> &Directives) {
|
||||
return scanSourceForDependencyDirectives(Input, Out, Directives);
|
||||
}
|
||||
|
||||
namespace {
|
||||
|
||||
TEST(MinimizeSourceToDependencyDirectivesTest, Empty) {
|
||||
SmallVector<char, 128> Out;
|
||||
SmallVector<Token, 4> Tokens;
|
||||
SmallVector<Directive, 4> Directives;
|
||||
|
||||
ASSERT_FALSE(minimizeSourceToDependencyDirectives("", Out, Tokens));
|
||||
ASSERT_FALSE(minimizeSourceToDependencyDirectives("", Out, Directives));
|
||||
EXPECT_TRUE(Out.empty());
|
||||
ASSERT_EQ(1u, Tokens.size());
|
||||
ASSERT_EQ(pp_eof, Tokens.back().K);
|
||||
ASSERT_EQ(1u, Directives.size());
|
||||
ASSERT_EQ(pp_eof, Directives.back().Kind);
|
||||
|
||||
ASSERT_FALSE(
|
||||
minimizeSourceToDependencyDirectives("abc def\nxyz", Out, Tokens));
|
||||
minimizeSourceToDependencyDirectives("abc def\nxyz", Out, Directives));
|
||||
EXPECT_TRUE(Out.empty());
|
||||
ASSERT_EQ(1u, Tokens.size());
|
||||
ASSERT_EQ(pp_eof, Tokens.back().K);
|
||||
ASSERT_EQ(1u, Directives.size());
|
||||
ASSERT_EQ(pp_eof, Directives.back().Kind);
|
||||
}
|
||||
|
||||
TEST(MinimizeSourceToDependencyDirectivesTest, AllTokens) {
|
||||
TEST(MinimizeSourceToDependencyDirectivesTest, AllDirectives) {
|
||||
SmallVector<char, 128> Out;
|
||||
SmallVector<Token, 4> Tokens;
|
||||
SmallVector<Directive, 4> Directives;
|
||||
|
||||
ASSERT_FALSE(
|
||||
minimizeSourceToDependencyDirectives("#define A\n"
|
||||
|
@ -68,41 +71,41 @@ TEST(MinimizeSourceToDependencyDirectivesTest, AllTokens) {
|
|||
"#pragma include_alias(<A>, <B>)\n"
|
||||
"export module m;\n"
|
||||
"import m;\n",
|
||||
Out, Tokens));
|
||||
EXPECT_EQ(pp_define, Tokens[0].K);
|
||||
EXPECT_EQ(pp_undef, Tokens[1].K);
|
||||
EXPECT_EQ(pp_endif, Tokens[2].K);
|
||||
EXPECT_EQ(pp_if, Tokens[3].K);
|
||||
EXPECT_EQ(pp_ifdef, Tokens[4].K);
|
||||
EXPECT_EQ(pp_ifndef, Tokens[5].K);
|
||||
EXPECT_EQ(pp_elifdef, Tokens[6].K);
|
||||
EXPECT_EQ(pp_elifndef, Tokens[7].K);
|
||||
EXPECT_EQ(pp_elif, Tokens[8].K);
|
||||
EXPECT_EQ(pp_else, Tokens[9].K);
|
||||
EXPECT_EQ(pp_include, Tokens[10].K);
|
||||
EXPECT_EQ(pp_include_next, Tokens[11].K);
|
||||
EXPECT_EQ(pp___include_macros, Tokens[12].K);
|
||||
EXPECT_EQ(pp_import, Tokens[13].K);
|
||||
EXPECT_EQ(decl_at_import, Tokens[14].K);
|
||||
EXPECT_EQ(pp_pragma_import, Tokens[15].K);
|
||||
EXPECT_EQ(pp_pragma_push_macro, Tokens[16].K);
|
||||
EXPECT_EQ(pp_pragma_pop_macro, Tokens[17].K);
|
||||
EXPECT_EQ(pp_pragma_include_alias, Tokens[18].K);
|
||||
EXPECT_EQ(cxx_export_decl, Tokens[19].K);
|
||||
EXPECT_EQ(cxx_module_decl, Tokens[20].K);
|
||||
EXPECT_EQ(cxx_import_decl, Tokens[21].K);
|
||||
EXPECT_EQ(pp_eof, Tokens[22].K);
|
||||
Out, Directives));
|
||||
EXPECT_EQ(pp_define, Directives[0].Kind);
|
||||
EXPECT_EQ(pp_undef, Directives[1].Kind);
|
||||
EXPECT_EQ(pp_endif, Directives[2].Kind);
|
||||
EXPECT_EQ(pp_if, Directives[3].Kind);
|
||||
EXPECT_EQ(pp_ifdef, Directives[4].Kind);
|
||||
EXPECT_EQ(pp_ifndef, Directives[5].Kind);
|
||||
EXPECT_EQ(pp_elifdef, Directives[6].Kind);
|
||||
EXPECT_EQ(pp_elifndef, Directives[7].Kind);
|
||||
EXPECT_EQ(pp_elif, Directives[8].Kind);
|
||||
EXPECT_EQ(pp_else, Directives[9].Kind);
|
||||
EXPECT_EQ(pp_include, Directives[10].Kind);
|
||||
EXPECT_EQ(pp_include_next, Directives[11].Kind);
|
||||
EXPECT_EQ(pp___include_macros, Directives[12].Kind);
|
||||
EXPECT_EQ(pp_import, Directives[13].Kind);
|
||||
EXPECT_EQ(decl_at_import, Directives[14].Kind);
|
||||
EXPECT_EQ(pp_pragma_import, Directives[15].Kind);
|
||||
EXPECT_EQ(pp_pragma_push_macro, Directives[16].Kind);
|
||||
EXPECT_EQ(pp_pragma_pop_macro, Directives[17].Kind);
|
||||
EXPECT_EQ(pp_pragma_include_alias, Directives[18].Kind);
|
||||
EXPECT_EQ(cxx_export_decl, Directives[19].Kind);
|
||||
EXPECT_EQ(cxx_module_decl, Directives[20].Kind);
|
||||
EXPECT_EQ(cxx_import_decl, Directives[21].Kind);
|
||||
EXPECT_EQ(pp_eof, Directives[22].Kind);
|
||||
}
|
||||
|
||||
TEST(MinimizeSourceToDependencyDirectivesTest, Define) {
|
||||
SmallVector<char, 128> Out;
|
||||
SmallVector<Token, 4> Tokens;
|
||||
SmallVector<Directive, 4> Directives;
|
||||
|
||||
ASSERT_FALSE(
|
||||
minimizeSourceToDependencyDirectives("#define MACRO", Out, Tokens));
|
||||
minimizeSourceToDependencyDirectives("#define MACRO", Out, Directives));
|
||||
EXPECT_STREQ("#define MACRO\n", Out.data());
|
||||
ASSERT_EQ(2u, Tokens.size());
|
||||
ASSERT_EQ(pp_define, Tokens.front().K);
|
||||
ASSERT_EQ(2u, Directives.size());
|
||||
ASSERT_EQ(pp_define, Directives.front().Kind);
|
||||
}
|
||||
|
||||
TEST(MinimizeSourceToDependencyDirectivesTest, DefineSpacing) {
|
||||
|
@ -679,18 +682,17 @@ int z = 128'78;
|
|||
|
||||
TEST(MinimizeSourceToDependencyDirectivesTest, PragmaOnce) {
|
||||
SmallVector<char, 128> Out;
|
||||
SmallVector<Token, 4> Tokens;
|
||||
SmallVector<Directive, 4> Directives;
|
||||
|
||||
StringRef Source = R"(// comment
|
||||
#pragma once
|
||||
// another comment
|
||||
#include <test.h>
|
||||
)";
|
||||
ASSERT_FALSE(minimizeSourceToDependencyDirectives(Source, Out, Tokens));
|
||||
ASSERT_FALSE(minimizeSourceToDependencyDirectives(Source, Out, Directives));
|
||||
EXPECT_STREQ("#pragma once\n#include <test.h>\n", Out.data());
|
||||
ASSERT_EQ(Tokens.size(), 3u);
|
||||
EXPECT_EQ(Tokens[0].K,
|
||||
minimize_source_to_dependency_directives::pp_pragma_once);
|
||||
ASSERT_EQ(Directives.size(), 3u);
|
||||
EXPECT_EQ(Directives[0].Kind, dependency_directives_scan::pp_pragma_once);
|
||||
|
||||
Source = R"(// comment
|
||||
#pragma once extra tokens
|
||||
|
@ -758,7 +760,7 @@ TEST(MinimizeSourceToDependencyDirectivesTest,
|
|||
|
||||
TEST(MinimizeSourceToDependencyDirectivesTest, CxxModules) {
|
||||
SmallVector<char, 128> Out;
|
||||
SmallVector<Token, 4> Tokens;
|
||||
SmallVector<Directive, 4> Directives;
|
||||
|
||||
StringRef Source = R"(
|
||||
module;
|
||||
|
@ -787,29 +789,28 @@ ort \
|
|||
import f(->a = 3);
|
||||
}
|
||||
)";
|
||||
ASSERT_FALSE(minimizeSourceToDependencyDirectives(Source, Out, Tokens));
|
||||
ASSERT_FALSE(minimizeSourceToDependencyDirectives(Source, Out, Directives));
|
||||
EXPECT_STREQ("#include \"textual-header.h\"\nexport module m;\n"
|
||||
"export import :l [[rename]];\n"
|
||||
"import <<= 3;\nimport a b d e d e f e;\n"
|
||||
"import foo [[no_unique_address]];\nimport foo();\n"
|
||||
"import f(:sefse);\nimport f(->a = 3);\n", Out.data());
|
||||
ASSERT_EQ(Tokens.size(), 12u);
|
||||
EXPECT_EQ(Tokens[0].K,
|
||||
minimize_source_to_dependency_directives::pp_include);
|
||||
EXPECT_EQ(Tokens[2].K,
|
||||
minimize_source_to_dependency_directives::cxx_module_decl);
|
||||
"import f(:sefse);\nimport f(->a = 3);\n",
|
||||
Out.data());
|
||||
ASSERT_EQ(Directives.size(), 12u);
|
||||
EXPECT_EQ(Directives[0].Kind, dependency_directives_scan::pp_include);
|
||||
EXPECT_EQ(Directives[2].Kind, dependency_directives_scan::cxx_module_decl);
|
||||
}
|
||||
|
||||
TEST(MinimizeSourceToDependencyDirectivesTest, SkippedPPRangesBasic) {
|
||||
SmallString<128> Out;
|
||||
SmallVector<Token, 32> Toks;
|
||||
SmallVector<Directive, 32> Directives;
|
||||
StringRef Source = "#ifndef GUARD\n"
|
||||
"#define GUARD\n"
|
||||
"void foo();\n"
|
||||
"#endif\n";
|
||||
ASSERT_FALSE(minimizeSourceToDependencyDirectives(Source, Out, Toks));
|
||||
ASSERT_FALSE(minimizeSourceToDependencyDirectives(Source, Out, Directives));
|
||||
SmallVector<SkippedRange, 4> Ranges;
|
||||
ASSERT_FALSE(computeSkippedRanges(Toks, Ranges));
|
||||
ASSERT_FALSE(computeSkippedRanges(Directives, Ranges));
|
||||
EXPECT_EQ(Ranges.size(), 1u);
|
||||
EXPECT_EQ(Ranges[0].Offset, 0);
|
||||
EXPECT_EQ(Ranges[0].Length, (int)Out.find("#endif"));
|
||||
|
@ -817,7 +818,7 @@ TEST(MinimizeSourceToDependencyDirectivesTest, SkippedPPRangesBasic) {
|
|||
|
||||
TEST(MinimizeSourceToDependencyDirectivesTest, SkippedPPRangesBasicElifdef) {
|
||||
SmallString<128> Out;
|
||||
SmallVector<Token, 32> Toks;
|
||||
SmallVector<Directive, 32> Directives;
|
||||
StringRef Source = "#ifdef BLAH\n"
|
||||
"void skip();\n"
|
||||
"#elifdef BLAM\n"
|
||||
|
@ -826,9 +827,9 @@ TEST(MinimizeSourceToDependencyDirectivesTest, SkippedPPRangesBasicElifdef) {
|
|||
"#define GUARD\n"
|
||||
"void foo();\n"
|
||||
"#endif\n";
|
||||
ASSERT_FALSE(minimizeSourceToDependencyDirectives(Source, Out, Toks));
|
||||
ASSERT_FALSE(minimizeSourceToDependencyDirectives(Source, Out, Directives));
|
||||
SmallVector<SkippedRange, 4> Ranges;
|
||||
ASSERT_FALSE(computeSkippedRanges(Toks, Ranges));
|
||||
ASSERT_FALSE(computeSkippedRanges(Directives, Ranges));
|
||||
EXPECT_EQ(Ranges.size(), 3u);
|
||||
EXPECT_EQ(Ranges[0].Offset, 0);
|
||||
EXPECT_EQ(Ranges[0].Length, (int)Out.find("#elifdef"));
|
||||
|
@ -840,7 +841,7 @@ TEST(MinimizeSourceToDependencyDirectivesTest, SkippedPPRangesBasicElifdef) {
|
|||
|
||||
TEST(MinimizeSourceToDependencyDirectivesTest, SkippedPPRangesNested) {
|
||||
SmallString<128> Out;
|
||||
SmallVector<Token, 32> Toks;
|
||||
SmallVector<Directive, 32> Directives;
|
||||
StringRef Source = "#ifndef GUARD\n"
|
||||
"#define GUARD\n"
|
||||
"#if FOO\n"
|
||||
|
@ -851,9 +852,9 @@ TEST(MinimizeSourceToDependencyDirectivesTest, SkippedPPRangesNested) {
|
|||
"#else\n"
|
||||
"#include nothing\n"
|
||||
"#endif\n";
|
||||
ASSERT_FALSE(minimizeSourceToDependencyDirectives(Source, Out, Toks));
|
||||
ASSERT_FALSE(minimizeSourceToDependencyDirectives(Source, Out, Directives));
|
||||
SmallVector<SkippedRange, 4> Ranges;
|
||||
ASSERT_FALSE(computeSkippedRanges(Toks, Ranges));
|
||||
ASSERT_FALSE(computeSkippedRanges(Directives, Ranges));
|
||||
EXPECT_EQ(Ranges.size(), 4u);
|
||||
EXPECT_EQ(Ranges[0].Offset, (int)Out.find("#if FOO"));
|
||||
EXPECT_EQ(Ranges[0].Offset + Ranges[0].Length, (int)Out.find("#elif"));
|
|
@ -215,9 +215,9 @@ TEST(DependencyScanningFilesystem, IgnoredFilesAreCachedSeparately1) {
|
|||
ExcludedPreprocessorDirectiveSkipMapping Mappings;
|
||||
DependencyScanningWorkerFilesystem DepFS(SharedCache, VFS, Mappings);
|
||||
|
||||
DepFS.enableMinimizationOfAllFiles(); // Let's be explicit for clarity.
|
||||
DepFS.enableDirectivesScanningOfAllFiles(); // Let's be explicit for clarity.
|
||||
auto StatusMinimized0 = DepFS.status("/mod.h");
|
||||
DepFS.disableMinimization("/mod.h");
|
||||
DepFS.disableDirectivesScanning("/mod.h");
|
||||
auto StatusFull1 = DepFS.status("/mod.h");
|
||||
|
||||
EXPECT_TRUE(StatusMinimized0);
|
||||
|
@ -238,9 +238,9 @@ TEST(DependencyScanningFilesystem, IgnoredFilesAreCachedSeparately2) {
|
|||
ExcludedPreprocessorDirectiveSkipMapping Mappings;
|
||||
DependencyScanningWorkerFilesystem DepFS(SharedCache, VFS, Mappings);
|
||||
|
||||
DepFS.disableMinimization("/mod.h");
|
||||
DepFS.disableDirectivesScanning("/mod.h");
|
||||
auto StatusFull0 = DepFS.status("/mod.h");
|
||||
DepFS.enableMinimizationOfAllFiles();
|
||||
DepFS.enableDirectivesScanningOfAllFiles();
|
||||
auto StatusMinimized1 = DepFS.status("/mod.h");
|
||||
|
||||
EXPECT_TRUE(StatusFull0);
|
||||
|
|
Loading…
Reference in New Issue