diff options
Diffstat (limited to 'clang/lib/Tooling/Inclusions/HeaderIncludes.cpp')
-rw-r--r-- | clang/lib/Tooling/Inclusions/HeaderIncludes.cpp | 41 |
1 files changed, 31 insertions, 10 deletions
diff --git a/clang/lib/Tooling/Inclusions/HeaderIncludes.cpp b/clang/lib/Tooling/Inclusions/HeaderIncludes.cpp index 2b5a293..e11319e 100644 --- a/clang/lib/Tooling/Inclusions/HeaderIncludes.cpp +++ b/clang/lib/Tooling/Inclusions/HeaderIncludes.cpp @@ -74,13 +74,24 @@ void skipComments(Lexer &Lex, Token &Tok) { return; } -// Returns the offset after header guard directives and any comments -// before/after header guards (e.g. #ifndef/#define pair, #pragma once). If no -// header guard is present in the code, this will return the offset after -// skipping all comments from the start of the code. -unsigned getOffsetAfterHeaderGuardsAndComments(StringRef FileName, - StringRef Code, - const IncludeStyle &Style) { +bool checkAndConsumeModuleDecl(const SourceManager &SM, Lexer &Lex, + Token &Tok) { + bool Matched = Tok.is(tok::raw_identifier) && + Tok.getRawIdentifier() == "module" && + !Lex.LexFromRawLexer(Tok) && Tok.is(tok::semi) && + !Lex.LexFromRawLexer(Tok); + return Matched; +} + +// Determines the minimum offset into the file where we want to insert header +// includes. This will be put (when available): +// - after `#pragma once` +// - after header guards (`#ifdef` and `#define`) +// - after opening global module (`module;`) +// - after any comments at the start of the file or immediately following one of +// the above constructs +unsigned getMinHeaderInsertionOffset(StringRef FileName, StringRef Code, + const IncludeStyle &Style) { // \p Consume returns location after header guard or 0 if no header guard is // found. auto ConsumeHeaderGuardAndComment = @@ -95,7 +106,17 @@ unsigned getOffsetAfterHeaderGuardsAndComments(StringRef FileName, return std::max(InitialOffset, Consume(SM, Lex, Tok)); }); }; - return std::max( + + auto ModuleDecl = ConsumeHeaderGuardAndComment( + [](const SourceManager &SM, Lexer &Lex, Token Tok) -> unsigned { + if (checkAndConsumeModuleDecl(SM, Lex, Tok)) { + skipComments(Lex, Tok); + return SM.getFileOffset(Tok.getLocation()); + } + return 0; + }); + + auto HeaderAndPPOffset = std::max( // #ifndef/#define ConsumeHeaderGuardAndComment( [](const SourceManager &SM, Lexer &Lex, Token Tok) -> unsigned { @@ -115,6 +136,7 @@ unsigned getOffsetAfterHeaderGuardsAndComments(StringRef FileName, return SM.getFileOffset(Tok.getLocation()); return 0; })); + return std::max(HeaderAndPPOffset, ModuleDecl); } // Check if a sequence of tokens is like @@ -280,8 +302,7 @@ const llvm::Regex HeaderIncludes::IncludeRegex(IncludeRegexPattern); HeaderIncludes::HeaderIncludes(StringRef FileName, StringRef Code, const IncludeStyle &Style) : FileName(FileName), Code(Code), FirstIncludeOffset(-1), - MinInsertOffset( - getOffsetAfterHeaderGuardsAndComments(FileName, Code, Style)), + MinInsertOffset(getMinHeaderInsertionOffset(FileName, Code, Style)), MaxInsertOffset(MinInsertOffset + getMaxHeaderInsertionOffset( FileName, Code.drop_front(MinInsertOffset), Style)), |