aboutsummaryrefslogtreecommitdiff
path: root/clang/lib/Tooling/Inclusions/HeaderIncludes.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'clang/lib/Tooling/Inclusions/HeaderIncludes.cpp')
-rw-r--r--clang/lib/Tooling/Inclusions/HeaderIncludes.cpp41
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)),