annotate clang-tools-extra/clangd/Preamble.cpp @ 221:79ff65ed7e25

LLVM12 Original
author Shinji KONO <kono@ie.u-ryukyu.ac.jp>
date Tue, 15 Jun 2021 19:15:29 +0900
parents 0572611fdcc8
children 5f17cb93ff66
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
rev   line source
150
anatofuz
parents:
diff changeset
1 //===--- Preamble.cpp - Reusing expensive parts of the AST ----------------===//
anatofuz
parents:
diff changeset
2 //
anatofuz
parents:
diff changeset
3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
anatofuz
parents:
diff changeset
4 // See https://llvm.org/LICENSE.txt for license information.
anatofuz
parents:
diff changeset
5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
anatofuz
parents:
diff changeset
6 //
anatofuz
parents:
diff changeset
7 //===----------------------------------------------------------------------===//
anatofuz
parents:
diff changeset
8
anatofuz
parents:
diff changeset
9 #include "Preamble.h"
173
0572611fdcc8 reorgnization done
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 150
diff changeset
10 #include "Compiler.h"
0572611fdcc8 reorgnization done
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 150
diff changeset
11 #include "Headers.h"
0572611fdcc8 reorgnization done
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 150
diff changeset
12 #include "SourceCode.h"
0572611fdcc8 reorgnization done
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 150
diff changeset
13 #include "support/Logger.h"
221
79ff65ed7e25 LLVM12 Original
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 173
diff changeset
14 #include "support/ThreadsafeFS.h"
173
0572611fdcc8 reorgnization done
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 150
diff changeset
15 #include "support/Trace.h"
221
79ff65ed7e25 LLVM12 Original
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 173
diff changeset
16 #include "clang/AST/DeclTemplate.h"
173
0572611fdcc8 reorgnization done
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 150
diff changeset
17 #include "clang/Basic/Diagnostic.h"
221
79ff65ed7e25 LLVM12 Original
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 173
diff changeset
18 #include "clang/Basic/DiagnosticLex.h"
173
0572611fdcc8 reorgnization done
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 150
diff changeset
19 #include "clang/Basic/LangOptions.h"
150
anatofuz
parents:
diff changeset
20 #include "clang/Basic/SourceLocation.h"
221
79ff65ed7e25 LLVM12 Original
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 173
diff changeset
21 #include "clang/Basic/SourceManager.h"
173
0572611fdcc8 reorgnization done
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 150
diff changeset
22 #include "clang/Basic/TokenKinds.h"
0572611fdcc8 reorgnization done
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 150
diff changeset
23 #include "clang/Frontend/CompilerInvocation.h"
0572611fdcc8 reorgnization done
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 150
diff changeset
24 #include "clang/Frontend/FrontendActions.h"
0572611fdcc8 reorgnization done
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 150
diff changeset
25 #include "clang/Lex/Lexer.h"
150
anatofuz
parents:
diff changeset
26 #include "clang/Lex/PPCallbacks.h"
173
0572611fdcc8 reorgnization done
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 150
diff changeset
27 #include "clang/Lex/Preprocessor.h"
150
anatofuz
parents:
diff changeset
28 #include "clang/Lex/PreprocessorOptions.h"
173
0572611fdcc8 reorgnization done
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 150
diff changeset
29 #include "clang/Tooling/CompilationDatabase.h"
0572611fdcc8 reorgnization done
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 150
diff changeset
30 #include "llvm/ADT/ArrayRef.h"
221
79ff65ed7e25 LLVM12 Original
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 173
diff changeset
31 #include "llvm/ADT/DenseMap.h"
79ff65ed7e25 LLVM12 Original
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 173
diff changeset
32 #include "llvm/ADT/DenseSet.h"
173
0572611fdcc8 reorgnization done
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 150
diff changeset
33 #include "llvm/ADT/IntrusiveRefCntPtr.h"
221
79ff65ed7e25 LLVM12 Original
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 173
diff changeset
34 #include "llvm/ADT/None.h"
79ff65ed7e25 LLVM12 Original
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 173
diff changeset
35 #include "llvm/ADT/Optional.h"
173
0572611fdcc8 reorgnization done
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 150
diff changeset
36 #include "llvm/ADT/STLExtras.h"
0572611fdcc8 reorgnization done
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 150
diff changeset
37 #include "llvm/ADT/SmallString.h"
0572611fdcc8 reorgnization done
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 150
diff changeset
38 #include "llvm/ADT/StringExtras.h"
0572611fdcc8 reorgnization done
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 150
diff changeset
39 #include "llvm/ADT/StringRef.h"
0572611fdcc8 reorgnization done
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 150
diff changeset
40 #include "llvm/ADT/StringSet.h"
0572611fdcc8 reorgnization done
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 150
diff changeset
41 #include "llvm/Support/Error.h"
0572611fdcc8 reorgnization done
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 150
diff changeset
42 #include "llvm/Support/ErrorHandling.h"
0572611fdcc8 reorgnization done
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 150
diff changeset
43 #include "llvm/Support/FormatVariadic.h"
0572611fdcc8 reorgnization done
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 150
diff changeset
44 #include "llvm/Support/MemoryBuffer.h"
0572611fdcc8 reorgnization done
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 150
diff changeset
45 #include "llvm/Support/Path.h"
0572611fdcc8 reorgnization done
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 150
diff changeset
46 #include "llvm/Support/VirtualFileSystem.h"
0572611fdcc8 reorgnization done
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 150
diff changeset
47 #include "llvm/Support/raw_ostream.h"
0572611fdcc8 reorgnization done
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 150
diff changeset
48 #include <iterator>
0572611fdcc8 reorgnization done
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 150
diff changeset
49 #include <memory>
0572611fdcc8 reorgnization done
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 150
diff changeset
50 #include <string>
0572611fdcc8 reorgnization done
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 150
diff changeset
51 #include <system_error>
0572611fdcc8 reorgnization done
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 150
diff changeset
52 #include <utility>
0572611fdcc8 reorgnization done
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 150
diff changeset
53 #include <vector>
150
anatofuz
parents:
diff changeset
54
anatofuz
parents:
diff changeset
55 namespace clang {
anatofuz
parents:
diff changeset
56 namespace clangd {
anatofuz
parents:
diff changeset
57 namespace {
221
79ff65ed7e25 LLVM12 Original
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 173
diff changeset
58 constexpr llvm::StringLiteral PreamblePatchHeaderName = "__preamble_patch__.h";
150
anatofuz
parents:
diff changeset
59
anatofuz
parents:
diff changeset
60 bool compileCommandsAreEqual(const tooling::CompileCommand &LHS,
anatofuz
parents:
diff changeset
61 const tooling::CompileCommand &RHS) {
anatofuz
parents:
diff changeset
62 // We don't check for Output, it should not matter to clangd.
anatofuz
parents:
diff changeset
63 return LHS.Directory == RHS.Directory && LHS.Filename == RHS.Filename &&
anatofuz
parents:
diff changeset
64 llvm::makeArrayRef(LHS.CommandLine).equals(RHS.CommandLine);
anatofuz
parents:
diff changeset
65 }
anatofuz
parents:
diff changeset
66
anatofuz
parents:
diff changeset
67 class CppFilePreambleCallbacks : public PreambleCallbacks {
anatofuz
parents:
diff changeset
68 public:
anatofuz
parents:
diff changeset
69 CppFilePreambleCallbacks(PathRef File, PreambleParsedCallback ParsedCallback)
anatofuz
parents:
diff changeset
70 : File(File), ParsedCallback(ParsedCallback) {}
anatofuz
parents:
diff changeset
71
anatofuz
parents:
diff changeset
72 IncludeStructure takeIncludes() { return std::move(Includes); }
anatofuz
parents:
diff changeset
73
anatofuz
parents:
diff changeset
74 MainFileMacros takeMacros() { return std::move(Macros); }
anatofuz
parents:
diff changeset
75
anatofuz
parents:
diff changeset
76 CanonicalIncludes takeCanonicalIncludes() { return std::move(CanonIncludes); }
anatofuz
parents:
diff changeset
77
anatofuz
parents:
diff changeset
78 void AfterExecute(CompilerInstance &CI) override {
anatofuz
parents:
diff changeset
79 if (!ParsedCallback)
anatofuz
parents:
diff changeset
80 return;
anatofuz
parents:
diff changeset
81 trace::Span Tracer("Running PreambleCallback");
anatofuz
parents:
diff changeset
82 ParsedCallback(CI.getASTContext(), CI.getPreprocessorPtr(), CanonIncludes);
anatofuz
parents:
diff changeset
83 }
anatofuz
parents:
diff changeset
84
anatofuz
parents:
diff changeset
85 void BeforeExecute(CompilerInstance &CI) override {
anatofuz
parents:
diff changeset
86 CanonIncludes.addSystemHeadersMapping(CI.getLangOpts());
anatofuz
parents:
diff changeset
87 LangOpts = &CI.getLangOpts();
anatofuz
parents:
diff changeset
88 SourceMgr = &CI.getSourceManager();
anatofuz
parents:
diff changeset
89 }
anatofuz
parents:
diff changeset
90
anatofuz
parents:
diff changeset
91 std::unique_ptr<PPCallbacks> createPPCallbacks() override {
anatofuz
parents:
diff changeset
92 assert(SourceMgr && LangOpts &&
anatofuz
parents:
diff changeset
93 "SourceMgr and LangOpts must be set at this point");
anatofuz
parents:
diff changeset
94
anatofuz
parents:
diff changeset
95 return std::make_unique<PPChainedCallbacks>(
anatofuz
parents:
diff changeset
96 collectIncludeStructureCallback(*SourceMgr, &Includes),
173
0572611fdcc8 reorgnization done
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 150
diff changeset
97 std::make_unique<CollectMainFileMacros>(*SourceMgr, Macros));
150
anatofuz
parents:
diff changeset
98 }
anatofuz
parents:
diff changeset
99
anatofuz
parents:
diff changeset
100 CommentHandler *getCommentHandler() override {
anatofuz
parents:
diff changeset
101 IWYUHandler = collectIWYUHeaderMaps(&CanonIncludes);
anatofuz
parents:
diff changeset
102 return IWYUHandler.get();
anatofuz
parents:
diff changeset
103 }
anatofuz
parents:
diff changeset
104
221
79ff65ed7e25 LLVM12 Original
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 173
diff changeset
105 bool shouldSkipFunctionBody(Decl *D) override {
79ff65ed7e25 LLVM12 Original
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 173
diff changeset
106 // Generally we skip function bodies in preambles for speed.
79ff65ed7e25 LLVM12 Original
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 173
diff changeset
107 // We can make exceptions for functions that are cheap to parse and
79ff65ed7e25 LLVM12 Original
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 173
diff changeset
108 // instantiate, widely used, and valuable (e.g. commonly produce errors).
79ff65ed7e25 LLVM12 Original
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 173
diff changeset
109 if (const auto *FT = llvm::dyn_cast<clang::FunctionTemplateDecl>(D)) {
79ff65ed7e25 LLVM12 Original
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 173
diff changeset
110 if (const auto *II = FT->getDeclName().getAsIdentifierInfo())
79ff65ed7e25 LLVM12 Original
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 173
diff changeset
111 // std::make_unique is trivial, and we diagnose bad constructor calls.
79ff65ed7e25 LLVM12 Original
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 173
diff changeset
112 if (II->isStr("make_unique") && FT->isInStdNamespace())
79ff65ed7e25 LLVM12 Original
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 173
diff changeset
113 return false;
79ff65ed7e25 LLVM12 Original
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 173
diff changeset
114 }
79ff65ed7e25 LLVM12 Original
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 173
diff changeset
115 return true;
79ff65ed7e25 LLVM12 Original
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 173
diff changeset
116 }
79ff65ed7e25 LLVM12 Original
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 173
diff changeset
117
150
anatofuz
parents:
diff changeset
118 private:
anatofuz
parents:
diff changeset
119 PathRef File;
anatofuz
parents:
diff changeset
120 PreambleParsedCallback ParsedCallback;
anatofuz
parents:
diff changeset
121 IncludeStructure Includes;
anatofuz
parents:
diff changeset
122 CanonicalIncludes CanonIncludes;
anatofuz
parents:
diff changeset
123 MainFileMacros Macros;
anatofuz
parents:
diff changeset
124 std::unique_ptr<CommentHandler> IWYUHandler = nullptr;
anatofuz
parents:
diff changeset
125 const clang::LangOptions *LangOpts = nullptr;
anatofuz
parents:
diff changeset
126 const SourceManager *SourceMgr = nullptr;
anatofuz
parents:
diff changeset
127 };
anatofuz
parents:
diff changeset
128
221
79ff65ed7e25 LLVM12 Original
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 173
diff changeset
129 // Represents directives other than includes, where basic textual information is
79ff65ed7e25 LLVM12 Original
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 173
diff changeset
130 // enough.
79ff65ed7e25 LLVM12 Original
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 173
diff changeset
131 struct TextualPPDirective {
79ff65ed7e25 LLVM12 Original
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 173
diff changeset
132 unsigned DirectiveLine;
79ff65ed7e25 LLVM12 Original
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 173
diff changeset
133 // Full text that's representing the directive, including the `#`.
79ff65ed7e25 LLVM12 Original
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 173
diff changeset
134 std::string Text;
79ff65ed7e25 LLVM12 Original
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 173
diff changeset
135
79ff65ed7e25 LLVM12 Original
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 173
diff changeset
136 bool operator==(const TextualPPDirective &RHS) const {
79ff65ed7e25 LLVM12 Original
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 173
diff changeset
137 return std::tie(DirectiveLine, Text) ==
79ff65ed7e25 LLVM12 Original
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 173
diff changeset
138 std::tie(RHS.DirectiveLine, RHS.Text);
173
0572611fdcc8 reorgnization done
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 150
diff changeset
139 }
0572611fdcc8 reorgnization done
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 150
diff changeset
140 };
0572611fdcc8 reorgnization done
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 150
diff changeset
141
221
79ff65ed7e25 LLVM12 Original
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 173
diff changeset
142 // Formats a PP directive consisting of Prefix (e.g. "#define ") and Body ("X
79ff65ed7e25 LLVM12 Original
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 173
diff changeset
143 // 10"). The formatting is copied so that the tokens in Body have PresumedLocs
79ff65ed7e25 LLVM12 Original
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 173
diff changeset
144 // with correct columns and lines.
79ff65ed7e25 LLVM12 Original
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 173
diff changeset
145 std::string spellDirective(llvm::StringRef Prefix,
79ff65ed7e25 LLVM12 Original
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 173
diff changeset
146 CharSourceRange DirectiveRange,
79ff65ed7e25 LLVM12 Original
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 173
diff changeset
147 const LangOptions &LangOpts, const SourceManager &SM,
79ff65ed7e25 LLVM12 Original
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 173
diff changeset
148 unsigned &DirectiveLine) {
79ff65ed7e25 LLVM12 Original
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 173
diff changeset
149 std::string SpelledDirective;
79ff65ed7e25 LLVM12 Original
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 173
diff changeset
150 llvm::raw_string_ostream OS(SpelledDirective);
79ff65ed7e25 LLVM12 Original
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 173
diff changeset
151 OS << Prefix;
79ff65ed7e25 LLVM12 Original
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 173
diff changeset
152
79ff65ed7e25 LLVM12 Original
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 173
diff changeset
153 // Make sure DirectiveRange is a char range and doesn't contain macro ids.
79ff65ed7e25 LLVM12 Original
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 173
diff changeset
154 DirectiveRange = SM.getExpansionRange(DirectiveRange);
79ff65ed7e25 LLVM12 Original
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 173
diff changeset
155 if (DirectiveRange.isTokenRange()) {
79ff65ed7e25 LLVM12 Original
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 173
diff changeset
156 DirectiveRange.setEnd(
79ff65ed7e25 LLVM12 Original
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 173
diff changeset
157 Lexer::getLocForEndOfToken(DirectiveRange.getEnd(), 0, SM, LangOpts));
79ff65ed7e25 LLVM12 Original
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 173
diff changeset
158 }
79ff65ed7e25 LLVM12 Original
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 173
diff changeset
159
79ff65ed7e25 LLVM12 Original
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 173
diff changeset
160 auto DecompLoc = SM.getDecomposedLoc(DirectiveRange.getBegin());
79ff65ed7e25 LLVM12 Original
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 173
diff changeset
161 DirectiveLine = SM.getLineNumber(DecompLoc.first, DecompLoc.second);
79ff65ed7e25 LLVM12 Original
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 173
diff changeset
162 auto TargetColumn = SM.getColumnNumber(DecompLoc.first, DecompLoc.second) - 1;
79ff65ed7e25 LLVM12 Original
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 173
diff changeset
163
79ff65ed7e25 LLVM12 Original
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 173
diff changeset
164 // Pad with spaces before DirectiveRange to make sure it will be on right
79ff65ed7e25 LLVM12 Original
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 173
diff changeset
165 // column when patched.
79ff65ed7e25 LLVM12 Original
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 173
diff changeset
166 if (Prefix.size() <= TargetColumn) {
79ff65ed7e25 LLVM12 Original
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 173
diff changeset
167 // There is enough space for Prefix and space before directive, use it.
79ff65ed7e25 LLVM12 Original
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 173
diff changeset
168 // We try to squeeze the Prefix into the same line whenever we can, as
79ff65ed7e25 LLVM12 Original
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 173
diff changeset
169 // putting onto a separate line won't work at the beginning of the file.
79ff65ed7e25 LLVM12 Original
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 173
diff changeset
170 OS << std::string(TargetColumn - Prefix.size(), ' ');
79ff65ed7e25 LLVM12 Original
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 173
diff changeset
171 } else {
79ff65ed7e25 LLVM12 Original
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 173
diff changeset
172 // Prefix was longer than the space we had. We produce e.g.:
79ff65ed7e25 LLVM12 Original
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 173
diff changeset
173 // #line N-1
79ff65ed7e25 LLVM12 Original
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 173
diff changeset
174 // #define \
79ff65ed7e25 LLVM12 Original
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 173
diff changeset
175 // X 10
79ff65ed7e25 LLVM12 Original
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 173
diff changeset
176 OS << "\\\n" << std::string(TargetColumn, ' ');
79ff65ed7e25 LLVM12 Original
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 173
diff changeset
177 // Decrement because we put an additional line break before
79ff65ed7e25 LLVM12 Original
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 173
diff changeset
178 // DirectiveRange.begin().
79ff65ed7e25 LLVM12 Original
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 173
diff changeset
179 --DirectiveLine;
79ff65ed7e25 LLVM12 Original
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 173
diff changeset
180 }
79ff65ed7e25 LLVM12 Original
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 173
diff changeset
181 OS << toSourceCode(SM, DirectiveRange.getAsRange());
79ff65ed7e25 LLVM12 Original
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 173
diff changeset
182 return OS.str();
79ff65ed7e25 LLVM12 Original
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 173
diff changeset
183 }
79ff65ed7e25 LLVM12 Original
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 173
diff changeset
184
79ff65ed7e25 LLVM12 Original
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 173
diff changeset
185 // Collects #define directives inside the main file.
79ff65ed7e25 LLVM12 Original
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 173
diff changeset
186 struct DirectiveCollector : public PPCallbacks {
79ff65ed7e25 LLVM12 Original
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 173
diff changeset
187 DirectiveCollector(const Preprocessor &PP,
79ff65ed7e25 LLVM12 Original
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 173
diff changeset
188 std::vector<TextualPPDirective> &TextualDirectives)
79ff65ed7e25 LLVM12 Original
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 173
diff changeset
189 : LangOpts(PP.getLangOpts()), SM(PP.getSourceManager()),
79ff65ed7e25 LLVM12 Original
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 173
diff changeset
190 TextualDirectives(TextualDirectives) {}
79ff65ed7e25 LLVM12 Original
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 173
diff changeset
191
79ff65ed7e25 LLVM12 Original
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 173
diff changeset
192 void FileChanged(SourceLocation Loc, FileChangeReason Reason,
79ff65ed7e25 LLVM12 Original
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 173
diff changeset
193 SrcMgr::CharacteristicKind FileType,
79ff65ed7e25 LLVM12 Original
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 173
diff changeset
194 FileID PrevFID) override {
79ff65ed7e25 LLVM12 Original
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 173
diff changeset
195 InMainFile = SM.isWrittenInMainFile(Loc);
79ff65ed7e25 LLVM12 Original
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 173
diff changeset
196 }
79ff65ed7e25 LLVM12 Original
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 173
diff changeset
197
79ff65ed7e25 LLVM12 Original
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 173
diff changeset
198 void MacroDefined(const Token &MacroNameTok,
79ff65ed7e25 LLVM12 Original
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 173
diff changeset
199 const MacroDirective *MD) override {
79ff65ed7e25 LLVM12 Original
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 173
diff changeset
200 if (!InMainFile)
79ff65ed7e25 LLVM12 Original
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 173
diff changeset
201 return;
79ff65ed7e25 LLVM12 Original
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 173
diff changeset
202 TextualDirectives.emplace_back();
79ff65ed7e25 LLVM12 Original
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 173
diff changeset
203 TextualPPDirective &TD = TextualDirectives.back();
79ff65ed7e25 LLVM12 Original
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 173
diff changeset
204
79ff65ed7e25 LLVM12 Original
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 173
diff changeset
205 const auto *MI = MD->getMacroInfo();
79ff65ed7e25 LLVM12 Original
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 173
diff changeset
206 TD.Text =
79ff65ed7e25 LLVM12 Original
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 173
diff changeset
207 spellDirective("#define ",
79ff65ed7e25 LLVM12 Original
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 173
diff changeset
208 CharSourceRange::getTokenRange(
79ff65ed7e25 LLVM12 Original
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 173
diff changeset
209 MI->getDefinitionLoc(), MI->getDefinitionEndLoc()),
79ff65ed7e25 LLVM12 Original
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 173
diff changeset
210 LangOpts, SM, TD.DirectiveLine);
79ff65ed7e25 LLVM12 Original
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 173
diff changeset
211 }
79ff65ed7e25 LLVM12 Original
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 173
diff changeset
212
79ff65ed7e25 LLVM12 Original
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 173
diff changeset
213 private:
79ff65ed7e25 LLVM12 Original
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 173
diff changeset
214 bool InMainFile = true;
79ff65ed7e25 LLVM12 Original
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 173
diff changeset
215 const LangOptions &LangOpts;
79ff65ed7e25 LLVM12 Original
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 173
diff changeset
216 const SourceManager &SM;
79ff65ed7e25 LLVM12 Original
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 173
diff changeset
217 std::vector<TextualPPDirective> &TextualDirectives;
79ff65ed7e25 LLVM12 Original
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 173
diff changeset
218 };
79ff65ed7e25 LLVM12 Original
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 173
diff changeset
219
79ff65ed7e25 LLVM12 Original
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 173
diff changeset
220 struct ScannedPreamble {
79ff65ed7e25 LLVM12 Original
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 173
diff changeset
221 std::vector<Inclusion> Includes;
79ff65ed7e25 LLVM12 Original
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 173
diff changeset
222 std::vector<TextualPPDirective> TextualDirectives;
79ff65ed7e25 LLVM12 Original
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 173
diff changeset
223 PreambleBounds Bounds = {0, false};
79ff65ed7e25 LLVM12 Original
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 173
diff changeset
224 };
79ff65ed7e25 LLVM12 Original
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 173
diff changeset
225
79ff65ed7e25 LLVM12 Original
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 173
diff changeset
226 /// Scans the preprocessor directives in the preamble section of the file by
79ff65ed7e25 LLVM12 Original
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 173
diff changeset
227 /// running preprocessor over \p Contents. Returned includes do not contain
79ff65ed7e25 LLVM12 Original
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 173
diff changeset
228 /// resolved paths. \p Cmd is used to build the compiler invocation, which might
79ff65ed7e25 LLVM12 Original
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 173
diff changeset
229 /// stat/read files.
79ff65ed7e25 LLVM12 Original
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 173
diff changeset
230 llvm::Expected<ScannedPreamble>
79ff65ed7e25 LLVM12 Original
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 173
diff changeset
231 scanPreamble(llvm::StringRef Contents, const tooling::CompileCommand &Cmd) {
79ff65ed7e25 LLVM12 Original
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 173
diff changeset
232 class EmptyFS : public ThreadsafeFS {
79ff65ed7e25 LLVM12 Original
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 173
diff changeset
233 private:
79ff65ed7e25 LLVM12 Original
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 173
diff changeset
234 llvm::IntrusiveRefCntPtr<llvm::vfs::FileSystem> viewImpl() const override {
79ff65ed7e25 LLVM12 Original
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 173
diff changeset
235 return new llvm::vfs::InMemoryFileSystem;
79ff65ed7e25 LLVM12 Original
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 173
diff changeset
236 }
79ff65ed7e25 LLVM12 Original
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 173
diff changeset
237 };
79ff65ed7e25 LLVM12 Original
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 173
diff changeset
238 EmptyFS FS;
173
0572611fdcc8 reorgnization done
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 150
diff changeset
239 // Build and run Preprocessor over the preamble.
0572611fdcc8 reorgnization done
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 150
diff changeset
240 ParseInputs PI;
0572611fdcc8 reorgnization done
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 150
diff changeset
241 PI.Contents = Contents.str();
221
79ff65ed7e25 LLVM12 Original
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 173
diff changeset
242 PI.TFS = &FS;
173
0572611fdcc8 reorgnization done
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 150
diff changeset
243 PI.CompileCommand = Cmd;
0572611fdcc8 reorgnization done
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 150
diff changeset
244 IgnoringDiagConsumer IgnoreDiags;
0572611fdcc8 reorgnization done
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 150
diff changeset
245 auto CI = buildCompilerInvocation(PI, IgnoreDiags);
0572611fdcc8 reorgnization done
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 150
diff changeset
246 if (!CI)
221
79ff65ed7e25 LLVM12 Original
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 173
diff changeset
247 return error("failed to create compiler invocation");
173
0572611fdcc8 reorgnization done
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 150
diff changeset
248 CI->getDiagnosticOpts().IgnoreWarnings = true;
0572611fdcc8 reorgnization done
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 150
diff changeset
249 auto ContentsBuffer = llvm::MemoryBuffer::getMemBuffer(Contents);
221
79ff65ed7e25 LLVM12 Original
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 173
diff changeset
250 // This means we're scanning (though not preprocessing) the preamble section
79ff65ed7e25 LLVM12 Original
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 173
diff changeset
251 // twice. However, it's important to precisely follow the preamble bounds used
79ff65ed7e25 LLVM12 Original
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 173
diff changeset
252 // elsewhere.
79ff65ed7e25 LLVM12 Original
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 173
diff changeset
253 auto Bounds = ComputePreambleBounds(*CI->getLangOpts(), *ContentsBuffer, 0);
79ff65ed7e25 LLVM12 Original
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 173
diff changeset
254 auto PreambleContents =
79ff65ed7e25 LLVM12 Original
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 173
diff changeset
255 llvm::MemoryBuffer::getMemBufferCopy(Contents.substr(0, Bounds.Size));
173
0572611fdcc8 reorgnization done
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 150
diff changeset
256 auto Clang = prepareCompilerInstance(
221
79ff65ed7e25 LLVM12 Original
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 173
diff changeset
257 std::move(CI), nullptr, std::move(PreambleContents),
173
0572611fdcc8 reorgnization done
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 150
diff changeset
258 // Provide an empty FS to prevent preprocessor from performing IO. This
0572611fdcc8 reorgnization done
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 150
diff changeset
259 // also implies missing resolved paths for includes.
221
79ff65ed7e25 LLVM12 Original
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 173
diff changeset
260 FS.view(llvm::None), IgnoreDiags);
173
0572611fdcc8 reorgnization done
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 150
diff changeset
261 if (Clang->getFrontendOpts().Inputs.empty())
221
79ff65ed7e25 LLVM12 Original
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 173
diff changeset
262 return error("compiler instance had no inputs");
173
0572611fdcc8 reorgnization done
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 150
diff changeset
263 // We are only interested in main file includes.
0572611fdcc8 reorgnization done
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 150
diff changeset
264 Clang->getPreprocessorOpts().SingleFileParseMode = true;
221
79ff65ed7e25 LLVM12 Original
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 173
diff changeset
265 PreprocessOnlyAction Action;
173
0572611fdcc8 reorgnization done
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 150
diff changeset
266 if (!Action.BeginSourceFile(*Clang, Clang->getFrontendOpts().Inputs[0]))
221
79ff65ed7e25 LLVM12 Original
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 173
diff changeset
267 return error("failed BeginSourceFile");
79ff65ed7e25 LLVM12 Original
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 173
diff changeset
268 const auto &SM = Clang->getSourceManager();
173
0572611fdcc8 reorgnization done
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 150
diff changeset
269 Preprocessor &PP = Clang->getPreprocessor();
0572611fdcc8 reorgnization done
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 150
diff changeset
270 IncludeStructure Includes;
221
79ff65ed7e25 LLVM12 Original
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 173
diff changeset
271 PP.addPPCallbacks(collectIncludeStructureCallback(SM, &Includes));
79ff65ed7e25 LLVM12 Original
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 173
diff changeset
272 ScannedPreamble SP;
79ff65ed7e25 LLVM12 Original
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 173
diff changeset
273 SP.Bounds = Bounds;
173
0572611fdcc8 reorgnization done
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 150
diff changeset
274 PP.addPPCallbacks(
221
79ff65ed7e25 LLVM12 Original
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 173
diff changeset
275 std::make_unique<DirectiveCollector>(PP, SP.TextualDirectives));
173
0572611fdcc8 reorgnization done
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 150
diff changeset
276 if (llvm::Error Err = Action.Execute())
0572611fdcc8 reorgnization done
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 150
diff changeset
277 return std::move(Err);
0572611fdcc8 reorgnization done
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 150
diff changeset
278 Action.EndSourceFile();
221
79ff65ed7e25 LLVM12 Original
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 173
diff changeset
279 SP.Includes = std::move(Includes.MainFileIncludes);
79ff65ed7e25 LLVM12 Original
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 173
diff changeset
280 return SP;
173
0572611fdcc8 reorgnization done
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 150
diff changeset
281 }
0572611fdcc8 reorgnization done
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 150
diff changeset
282
0572611fdcc8 reorgnization done
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 150
diff changeset
283 const char *spellingForIncDirective(tok::PPKeywordKind IncludeDirective) {
0572611fdcc8 reorgnization done
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 150
diff changeset
284 switch (IncludeDirective) {
0572611fdcc8 reorgnization done
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 150
diff changeset
285 case tok::pp_include:
0572611fdcc8 reorgnization done
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 150
diff changeset
286 return "include";
0572611fdcc8 reorgnization done
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 150
diff changeset
287 case tok::pp_import:
0572611fdcc8 reorgnization done
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 150
diff changeset
288 return "import";
0572611fdcc8 reorgnization done
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 150
diff changeset
289 case tok::pp_include_next:
0572611fdcc8 reorgnization done
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 150
diff changeset
290 return "include_next";
0572611fdcc8 reorgnization done
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 150
diff changeset
291 default:
0572611fdcc8 reorgnization done
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 150
diff changeset
292 break;
0572611fdcc8 reorgnization done
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 150
diff changeset
293 }
0572611fdcc8 reorgnization done
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 150
diff changeset
294 llvm_unreachable("not an include directive");
0572611fdcc8 reorgnization done
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 150
diff changeset
295 }
221
79ff65ed7e25 LLVM12 Original
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 173
diff changeset
296
79ff65ed7e25 LLVM12 Original
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 173
diff changeset
297 // Checks whether \p FileName is a valid spelling of main file.
79ff65ed7e25 LLVM12 Original
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 173
diff changeset
298 bool isMainFile(llvm::StringRef FileName, const SourceManager &SM) {
79ff65ed7e25 LLVM12 Original
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 173
diff changeset
299 auto FE = SM.getFileManager().getFile(FileName);
79ff65ed7e25 LLVM12 Original
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 173
diff changeset
300 return FE && *FE == SM.getFileEntryForID(SM.getMainFileID());
79ff65ed7e25 LLVM12 Original
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 173
diff changeset
301 }
79ff65ed7e25 LLVM12 Original
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 173
diff changeset
302
150
anatofuz
parents:
diff changeset
303 } // namespace
anatofuz
parents:
diff changeset
304
173
0572611fdcc8 reorgnization done
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 150
diff changeset
305 PreambleData::PreambleData(const ParseInputs &Inputs,
0572611fdcc8 reorgnization done
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 150
diff changeset
306 PrecompiledPreamble Preamble,
150
anatofuz
parents:
diff changeset
307 std::vector<Diag> Diags, IncludeStructure Includes,
anatofuz
parents:
diff changeset
308 MainFileMacros Macros,
anatofuz
parents:
diff changeset
309 std::unique_ptr<PreambleFileStatusCache> StatCache,
anatofuz
parents:
diff changeset
310 CanonicalIncludes CanonIncludes)
173
0572611fdcc8 reorgnization done
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 150
diff changeset
311 : Version(Inputs.Version), CompileCommand(Inputs.CompileCommand),
0572611fdcc8 reorgnization done
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 150
diff changeset
312 Preamble(std::move(Preamble)), Diags(std::move(Diags)),
150
anatofuz
parents:
diff changeset
313 Includes(std::move(Includes)), Macros(std::move(Macros)),
anatofuz
parents:
diff changeset
314 StatCache(std::move(StatCache)), CanonIncludes(std::move(CanonIncludes)) {
anatofuz
parents:
diff changeset
315 }
anatofuz
parents:
diff changeset
316
anatofuz
parents:
diff changeset
317 std::shared_ptr<const PreambleData>
173
0572611fdcc8 reorgnization done
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 150
diff changeset
318 buildPreamble(PathRef FileName, CompilerInvocation CI,
150
anatofuz
parents:
diff changeset
319 const ParseInputs &Inputs, bool StoreInMemory,
anatofuz
parents:
diff changeset
320 PreambleParsedCallback PreambleCallback) {
anatofuz
parents:
diff changeset
321 // Note that we don't need to copy the input contents, preamble can live
anatofuz
parents:
diff changeset
322 // without those.
anatofuz
parents:
diff changeset
323 auto ContentsBuffer =
anatofuz
parents:
diff changeset
324 llvm::MemoryBuffer::getMemBuffer(Inputs.Contents, FileName);
221
79ff65ed7e25 LLVM12 Original
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 173
diff changeset
325 auto Bounds = ComputePreambleBounds(*CI.getLangOpts(), *ContentsBuffer, 0);
150
anatofuz
parents:
diff changeset
326
anatofuz
parents:
diff changeset
327 trace::Span Tracer("BuildPreamble");
anatofuz
parents:
diff changeset
328 SPAN_ATTACH(Tracer, "File", FileName);
221
79ff65ed7e25 LLVM12 Original
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 173
diff changeset
329 std::vector<std::unique_ptr<FeatureModule::ASTListener>> ASTListeners;
79ff65ed7e25 LLVM12 Original
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 173
diff changeset
330 if (Inputs.FeatureModules) {
79ff65ed7e25 LLVM12 Original
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 173
diff changeset
331 for (auto &M : *Inputs.FeatureModules) {
79ff65ed7e25 LLVM12 Original
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 173
diff changeset
332 if (auto Listener = M.astListeners())
79ff65ed7e25 LLVM12 Original
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 173
diff changeset
333 ASTListeners.emplace_back(std::move(Listener));
79ff65ed7e25 LLVM12 Original
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 173
diff changeset
334 }
79ff65ed7e25 LLVM12 Original
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 173
diff changeset
335 }
150
anatofuz
parents:
diff changeset
336 StoreDiags PreambleDiagnostics;
221
79ff65ed7e25 LLVM12 Original
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 173
diff changeset
337 PreambleDiagnostics.setDiagCallback(
79ff65ed7e25 LLVM12 Original
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 173
diff changeset
338 [&ASTListeners](const clang::Diagnostic &D, clangd::Diag &Diag) {
79ff65ed7e25 LLVM12 Original
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 173
diff changeset
339 llvm::for_each(ASTListeners,
79ff65ed7e25 LLVM12 Original
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 173
diff changeset
340 [&](const auto &L) { L->sawDiagnostic(D, Diag); });
79ff65ed7e25 LLVM12 Original
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 173
diff changeset
341 });
150
anatofuz
parents:
diff changeset
342 llvm::IntrusiveRefCntPtr<DiagnosticsEngine> PreambleDiagsEngine =
anatofuz
parents:
diff changeset
343 CompilerInstance::createDiagnostics(&CI.getDiagnosticOpts(),
anatofuz
parents:
diff changeset
344 &PreambleDiagnostics, false);
221
79ff65ed7e25 LLVM12 Original
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 173
diff changeset
345 PreambleDiagnostics.setLevelAdjuster(
79ff65ed7e25 LLVM12 Original
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 173
diff changeset
346 [&](DiagnosticsEngine::Level DiagLevel, const clang::Diagnostic &Info) {
79ff65ed7e25 LLVM12 Original
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 173
diff changeset
347 switch (Info.getID()) {
79ff65ed7e25 LLVM12 Original
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 173
diff changeset
348 case diag::warn_no_newline_eof:
79ff65ed7e25 LLVM12 Original
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 173
diff changeset
349 case diag::warn_cxx98_compat_no_newline_eof:
79ff65ed7e25 LLVM12 Original
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 173
diff changeset
350 case diag::ext_no_newline_eof:
79ff65ed7e25 LLVM12 Original
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 173
diff changeset
351 // If the preamble doesn't span the whole file, drop the no newline at
79ff65ed7e25 LLVM12 Original
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 173
diff changeset
352 // eof warnings.
79ff65ed7e25 LLVM12 Original
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 173
diff changeset
353 return Bounds.Size != ContentsBuffer->getBufferSize()
79ff65ed7e25 LLVM12 Original
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 173
diff changeset
354 ? DiagnosticsEngine::Level::Ignored
79ff65ed7e25 LLVM12 Original
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 173
diff changeset
355 : DiagLevel;
79ff65ed7e25 LLVM12 Original
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 173
diff changeset
356 }
79ff65ed7e25 LLVM12 Original
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 173
diff changeset
357 return DiagLevel;
79ff65ed7e25 LLVM12 Original
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 173
diff changeset
358 });
150
anatofuz
parents:
diff changeset
359
anatofuz
parents:
diff changeset
360 // Skip function bodies when building the preamble to speed up building
anatofuz
parents:
diff changeset
361 // the preamble and make it smaller.
anatofuz
parents:
diff changeset
362 assert(!CI.getFrontendOpts().SkipFunctionBodies);
anatofuz
parents:
diff changeset
363 CI.getFrontendOpts().SkipFunctionBodies = true;
anatofuz
parents:
diff changeset
364 // We don't want to write comment locations into PCH. They are racy and slow
anatofuz
parents:
diff changeset
365 // to read back. We rely on dynamic index for the comments instead.
anatofuz
parents:
diff changeset
366 CI.getPreprocessorOpts().WriteCommentListToPCH = false;
anatofuz
parents:
diff changeset
367
anatofuz
parents:
diff changeset
368 CppFilePreambleCallbacks SerializedDeclsCollector(FileName, PreambleCallback);
221
79ff65ed7e25 LLVM12 Original
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 173
diff changeset
369 auto VFS = Inputs.TFS->view(Inputs.CompileCommand.Directory);
150
anatofuz
parents:
diff changeset
370 llvm::SmallString<32> AbsFileName(FileName);
221
79ff65ed7e25 LLVM12 Original
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 173
diff changeset
371 VFS->makeAbsolute(AbsFileName);
150
anatofuz
parents:
diff changeset
372 auto StatCache = std::make_unique<PreambleFileStatusCache>(AbsFileName);
anatofuz
parents:
diff changeset
373 auto BuiltPreamble = PrecompiledPreamble::Build(
anatofuz
parents:
diff changeset
374 CI, ContentsBuffer.get(), Bounds, *PreambleDiagsEngine,
221
79ff65ed7e25 LLVM12 Original
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 173
diff changeset
375 StatCache->getProducingFS(VFS),
150
anatofuz
parents:
diff changeset
376 std::make_shared<PCHContainerOperations>(), StoreInMemory,
anatofuz
parents:
diff changeset
377 SerializedDeclsCollector);
anatofuz
parents:
diff changeset
378
anatofuz
parents:
diff changeset
379 // When building the AST for the main file, we do want the function
anatofuz
parents:
diff changeset
380 // bodies.
anatofuz
parents:
diff changeset
381 CI.getFrontendOpts().SkipFunctionBodies = false;
anatofuz
parents:
diff changeset
382
anatofuz
parents:
diff changeset
383 if (BuiltPreamble) {
173
0572611fdcc8 reorgnization done
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 150
diff changeset
384 vlog("Built preamble of size {0} for file {1} version {2}",
0572611fdcc8 reorgnization done
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 150
diff changeset
385 BuiltPreamble->getSize(), FileName, Inputs.Version);
150
anatofuz
parents:
diff changeset
386 std::vector<Diag> Diags = PreambleDiagnostics.take();
anatofuz
parents:
diff changeset
387 return std::make_shared<PreambleData>(
173
0572611fdcc8 reorgnization done
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 150
diff changeset
388 Inputs, std::move(*BuiltPreamble), std::move(Diags),
150
anatofuz
parents:
diff changeset
389 SerializedDeclsCollector.takeIncludes(),
anatofuz
parents:
diff changeset
390 SerializedDeclsCollector.takeMacros(), std::move(StatCache),
anatofuz
parents:
diff changeset
391 SerializedDeclsCollector.takeCanonicalIncludes());
anatofuz
parents:
diff changeset
392 } else {
173
0572611fdcc8 reorgnization done
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 150
diff changeset
393 elog("Could not build a preamble for file {0} version {1}", FileName,
0572611fdcc8 reorgnization done
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 150
diff changeset
394 Inputs.Version);
150
anatofuz
parents:
diff changeset
395 return nullptr;
anatofuz
parents:
diff changeset
396 }
anatofuz
parents:
diff changeset
397 }
anatofuz
parents:
diff changeset
398
173
0572611fdcc8 reorgnization done
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 150
diff changeset
399 bool isPreambleCompatible(const PreambleData &Preamble,
0572611fdcc8 reorgnization done
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 150
diff changeset
400 const ParseInputs &Inputs, PathRef FileName,
0572611fdcc8 reorgnization done
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 150
diff changeset
401 const CompilerInvocation &CI) {
0572611fdcc8 reorgnization done
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 150
diff changeset
402 auto ContentsBuffer =
0572611fdcc8 reorgnization done
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 150
diff changeset
403 llvm::MemoryBuffer::getMemBuffer(Inputs.Contents, FileName);
221
79ff65ed7e25 LLVM12 Original
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 173
diff changeset
404 auto Bounds = ComputePreambleBounds(*CI.getLangOpts(), *ContentsBuffer, 0);
79ff65ed7e25 LLVM12 Original
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 173
diff changeset
405 auto VFS = Inputs.TFS->view(Inputs.CompileCommand.Directory);
173
0572611fdcc8 reorgnization done
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 150
diff changeset
406 return compileCommandsAreEqual(Inputs.CompileCommand,
0572611fdcc8 reorgnization done
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 150
diff changeset
407 Preamble.CompileCommand) &&
221
79ff65ed7e25 LLVM12 Original
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 173
diff changeset
408 Preamble.Preamble.CanReuse(CI, *ContentsBuffer, Bounds, *VFS);
173
0572611fdcc8 reorgnization done
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 150
diff changeset
409 }
0572611fdcc8 reorgnization done
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 150
diff changeset
410
0572611fdcc8 reorgnization done
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 150
diff changeset
411 void escapeBackslashAndQuotes(llvm::StringRef Text, llvm::raw_ostream &OS) {
0572611fdcc8 reorgnization done
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 150
diff changeset
412 for (char C : Text) {
0572611fdcc8 reorgnization done
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 150
diff changeset
413 switch (C) {
0572611fdcc8 reorgnization done
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 150
diff changeset
414 case '\\':
0572611fdcc8 reorgnization done
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 150
diff changeset
415 case '"':
0572611fdcc8 reorgnization done
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 150
diff changeset
416 OS << '\\';
0572611fdcc8 reorgnization done
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 150
diff changeset
417 break;
0572611fdcc8 reorgnization done
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 150
diff changeset
418 default:
0572611fdcc8 reorgnization done
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 150
diff changeset
419 break;
0572611fdcc8 reorgnization done
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 150
diff changeset
420 }
0572611fdcc8 reorgnization done
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 150
diff changeset
421 OS << C;
0572611fdcc8 reorgnization done
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 150
diff changeset
422 }
0572611fdcc8 reorgnization done
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 150
diff changeset
423 }
0572611fdcc8 reorgnization done
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 150
diff changeset
424
0572611fdcc8 reorgnization done
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 150
diff changeset
425 PreamblePatch PreamblePatch::create(llvm::StringRef FileName,
0572611fdcc8 reorgnization done
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 150
diff changeset
426 const ParseInputs &Modified,
0572611fdcc8 reorgnization done
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 150
diff changeset
427 const PreambleData &Baseline) {
221
79ff65ed7e25 LLVM12 Original
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 173
diff changeset
428 trace::Span Tracer("CreatePreamblePatch");
79ff65ed7e25 LLVM12 Original
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 173
diff changeset
429 SPAN_ATTACH(Tracer, "File", FileName);
79ff65ed7e25 LLVM12 Original
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 173
diff changeset
430 assert(llvm::sys::path::is_absolute(FileName) && "relative FileName!");
79ff65ed7e25 LLVM12 Original
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 173
diff changeset
431 // First scan preprocessor directives in Baseline and Modified. These will be
173
0572611fdcc8 reorgnization done
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 150
diff changeset
432 // used to figure out newly added directives in Modified. Scanning can fail,
0572611fdcc8 reorgnization done
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 150
diff changeset
433 // the code just bails out and creates an empty patch in such cases, as:
0572611fdcc8 reorgnization done
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 150
diff changeset
434 // - If scanning for Baseline fails, no knowledge of existing includes hence
0572611fdcc8 reorgnization done
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 150
diff changeset
435 // patch will contain all the includes in Modified. Leading to rebuild of
0572611fdcc8 reorgnization done
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 150
diff changeset
436 // whole preamble, which is terribly slow.
0572611fdcc8 reorgnization done
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 150
diff changeset
437 // - If scanning for Modified fails, cannot figure out newly added ones so
0572611fdcc8 reorgnization done
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 150
diff changeset
438 // there's nothing to do but generate an empty patch.
221
79ff65ed7e25 LLVM12 Original
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 173
diff changeset
439 auto BaselineScan = scanPreamble(
173
0572611fdcc8 reorgnization done
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 150
diff changeset
440 // Contents needs to be null-terminated.
221
79ff65ed7e25 LLVM12 Original
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 173
diff changeset
441 Baseline.Preamble.getContents().str(), Modified.CompileCommand);
79ff65ed7e25 LLVM12 Original
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 173
diff changeset
442 if (!BaselineScan) {
79ff65ed7e25 LLVM12 Original
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 173
diff changeset
443 elog("Failed to scan baseline of {0}: {1}", FileName,
79ff65ed7e25 LLVM12 Original
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 173
diff changeset
444 BaselineScan.takeError());
79ff65ed7e25 LLVM12 Original
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 173
diff changeset
445 return PreamblePatch::unmodified(Baseline);
173
0572611fdcc8 reorgnization done
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 150
diff changeset
446 }
221
79ff65ed7e25 LLVM12 Original
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 173
diff changeset
447 auto ModifiedScan = scanPreamble(Modified.Contents, Modified.CompileCommand);
79ff65ed7e25 LLVM12 Original
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 173
diff changeset
448 if (!ModifiedScan) {
79ff65ed7e25 LLVM12 Original
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 173
diff changeset
449 elog("Failed to scan modified contents of {0}: {1}", FileName,
79ff65ed7e25 LLVM12 Original
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 173
diff changeset
450 ModifiedScan.takeError());
79ff65ed7e25 LLVM12 Original
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 173
diff changeset
451 return PreamblePatch::unmodified(Baseline);
173
0572611fdcc8 reorgnization done
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 150
diff changeset
452 }
221
79ff65ed7e25 LLVM12 Original
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 173
diff changeset
453
79ff65ed7e25 LLVM12 Original
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 173
diff changeset
454 bool IncludesChanged = BaselineScan->Includes != ModifiedScan->Includes;
79ff65ed7e25 LLVM12 Original
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 173
diff changeset
455 bool DirectivesChanged =
79ff65ed7e25 LLVM12 Original
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 173
diff changeset
456 BaselineScan->TextualDirectives != ModifiedScan->TextualDirectives;
79ff65ed7e25 LLVM12 Original
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 173
diff changeset
457 if (!IncludesChanged && !DirectivesChanged)
79ff65ed7e25 LLVM12 Original
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 173
diff changeset
458 return PreamblePatch::unmodified(Baseline);
173
0572611fdcc8 reorgnization done
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 150
diff changeset
459
0572611fdcc8 reorgnization done
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 150
diff changeset
460 PreamblePatch PP;
0572611fdcc8 reorgnization done
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 150
diff changeset
461 // This shouldn't coincide with any real file name.
0572611fdcc8 reorgnization done
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 150
diff changeset
462 llvm::SmallString<128> PatchName;
0572611fdcc8 reorgnization done
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 150
diff changeset
463 llvm::sys::path::append(PatchName, llvm::sys::path::parent_path(FileName),
221
79ff65ed7e25 LLVM12 Original
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 173
diff changeset
464 PreamblePatchHeaderName);
173
0572611fdcc8 reorgnization done
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 150
diff changeset
465 PP.PatchFileName = PatchName.str().str();
221
79ff65ed7e25 LLVM12 Original
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 173
diff changeset
466 PP.ModifiedBounds = ModifiedScan->Bounds;
173
0572611fdcc8 reorgnization done
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 150
diff changeset
467
0572611fdcc8 reorgnization done
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 150
diff changeset
468 llvm::raw_string_ostream Patch(PP.PatchContents);
0572611fdcc8 reorgnization done
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 150
diff changeset
469 // Set default filename for subsequent #line directives
0572611fdcc8 reorgnization done
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 150
diff changeset
470 Patch << "#line 0 \"";
0572611fdcc8 reorgnization done
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 150
diff changeset
471 // FileName part of a line directive is subject to backslash escaping, which
0572611fdcc8 reorgnization done
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 150
diff changeset
472 // might lead to problems on windows especially.
0572611fdcc8 reorgnization done
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 150
diff changeset
473 escapeBackslashAndQuotes(FileName, Patch);
0572611fdcc8 reorgnization done
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 150
diff changeset
474 Patch << "\"\n";
221
79ff65ed7e25 LLVM12 Original
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 173
diff changeset
475
79ff65ed7e25 LLVM12 Original
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 173
diff changeset
476 if (IncludesChanged) {
79ff65ed7e25 LLVM12 Original
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 173
diff changeset
477 // We are only interested in newly added includes, record the ones in
79ff65ed7e25 LLVM12 Original
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 173
diff changeset
478 // Baseline for exclusion.
79ff65ed7e25 LLVM12 Original
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 173
diff changeset
479 llvm::DenseMap<std::pair<tok::PPKeywordKind, llvm::StringRef>,
79ff65ed7e25 LLVM12 Original
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 173
diff changeset
480 /*Resolved=*/llvm::StringRef>
79ff65ed7e25 LLVM12 Original
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 173
diff changeset
481 ExistingIncludes;
79ff65ed7e25 LLVM12 Original
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 173
diff changeset
482 for (const auto &Inc : Baseline.Includes.MainFileIncludes)
79ff65ed7e25 LLVM12 Original
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 173
diff changeset
483 ExistingIncludes[{Inc.Directive, Inc.Written}] = Inc.Resolved;
79ff65ed7e25 LLVM12 Original
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 173
diff changeset
484 // There might be includes coming from disabled regions, record these for
79ff65ed7e25 LLVM12 Original
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 173
diff changeset
485 // exclusion too. note that we don't have resolved paths for those.
79ff65ed7e25 LLVM12 Original
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 173
diff changeset
486 for (const auto &Inc : BaselineScan->Includes)
79ff65ed7e25 LLVM12 Original
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 173
diff changeset
487 ExistingIncludes.try_emplace({Inc.Directive, Inc.Written});
79ff65ed7e25 LLVM12 Original
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 173
diff changeset
488 // Calculate extra includes that needs to be inserted.
79ff65ed7e25 LLVM12 Original
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 173
diff changeset
489 for (auto &Inc : ModifiedScan->Includes) {
79ff65ed7e25 LLVM12 Original
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 173
diff changeset
490 auto It = ExistingIncludes.find({Inc.Directive, Inc.Written});
79ff65ed7e25 LLVM12 Original
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 173
diff changeset
491 // Include already present in the baseline preamble. Set resolved path and
79ff65ed7e25 LLVM12 Original
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 173
diff changeset
492 // put into preamble includes.
79ff65ed7e25 LLVM12 Original
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 173
diff changeset
493 if (It != ExistingIncludes.end()) {
79ff65ed7e25 LLVM12 Original
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 173
diff changeset
494 Inc.Resolved = It->second.str();
79ff65ed7e25 LLVM12 Original
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 173
diff changeset
495 PP.PreambleIncludes.push_back(Inc);
79ff65ed7e25 LLVM12 Original
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 173
diff changeset
496 continue;
79ff65ed7e25 LLVM12 Original
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 173
diff changeset
497 }
79ff65ed7e25 LLVM12 Original
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 173
diff changeset
498 // Include is new in the modified preamble. Inject it into the patch and
79ff65ed7e25 LLVM12 Original
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 173
diff changeset
499 // use #line to set the presumed location to where it is spelled.
79ff65ed7e25 LLVM12 Original
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 173
diff changeset
500 auto LineCol = offsetToClangLineColumn(Modified.Contents, Inc.HashOffset);
79ff65ed7e25 LLVM12 Original
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 173
diff changeset
501 Patch << llvm::formatv("#line {0}\n", LineCol.first);
79ff65ed7e25 LLVM12 Original
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 173
diff changeset
502 Patch << llvm::formatv(
79ff65ed7e25 LLVM12 Original
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 173
diff changeset
503 "#{0} {1}\n", spellingForIncDirective(Inc.Directive), Inc.Written);
79ff65ed7e25 LLVM12 Original
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 173
diff changeset
504 }
173
0572611fdcc8 reorgnization done
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 150
diff changeset
505 }
221
79ff65ed7e25 LLVM12 Original
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 173
diff changeset
506
79ff65ed7e25 LLVM12 Original
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 173
diff changeset
507 if (DirectivesChanged) {
79ff65ed7e25 LLVM12 Original
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 173
diff changeset
508 // We need to patch all the directives, since they are order dependent. e.g:
79ff65ed7e25 LLVM12 Original
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 173
diff changeset
509 // #define BAR(X) NEW(X) // Newly introduced in Modified
79ff65ed7e25 LLVM12 Original
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 173
diff changeset
510 // #define BAR(X) OLD(X) // Exists in the Baseline
79ff65ed7e25 LLVM12 Original
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 173
diff changeset
511 //
79ff65ed7e25 LLVM12 Original
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 173
diff changeset
512 // If we've patched only the first directive, the macro definition would've
79ff65ed7e25 LLVM12 Original
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 173
diff changeset
513 // been wrong for the rest of the file, since patch is applied after the
79ff65ed7e25 LLVM12 Original
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 173
diff changeset
514 // baseline preamble.
79ff65ed7e25 LLVM12 Original
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 173
diff changeset
515 //
79ff65ed7e25 LLVM12 Original
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 173
diff changeset
516 // Note that we deliberately ignore conditional directives and undefs to
79ff65ed7e25 LLVM12 Original
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 173
diff changeset
517 // reduce complexity. The former might cause problems because scanning is
79ff65ed7e25 LLVM12 Original
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 173
diff changeset
518 // imprecise and might pick directives from disabled regions.
79ff65ed7e25 LLVM12 Original
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 173
diff changeset
519 for (const auto &TD : ModifiedScan->TextualDirectives) {
79ff65ed7e25 LLVM12 Original
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 173
diff changeset
520 Patch << "#line " << TD.DirectiveLine << '\n';
79ff65ed7e25 LLVM12 Original
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 173
diff changeset
521 Patch << TD.Text << '\n';
79ff65ed7e25 LLVM12 Original
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 173
diff changeset
522 }
79ff65ed7e25 LLVM12 Original
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 173
diff changeset
523 }
79ff65ed7e25 LLVM12 Original
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 173
diff changeset
524 dlog("Created preamble patch: {0}", Patch.str());
173
0572611fdcc8 reorgnization done
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 150
diff changeset
525 Patch.flush();
0572611fdcc8 reorgnization done
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 150
diff changeset
526 return PP;
0572611fdcc8 reorgnization done
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 150
diff changeset
527 }
0572611fdcc8 reorgnization done
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 150
diff changeset
528
0572611fdcc8 reorgnization done
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 150
diff changeset
529 void PreamblePatch::apply(CompilerInvocation &CI) const {
0572611fdcc8 reorgnization done
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 150
diff changeset
530 // No need to map an empty file.
0572611fdcc8 reorgnization done
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 150
diff changeset
531 if (PatchContents.empty())
0572611fdcc8 reorgnization done
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 150
diff changeset
532 return;
0572611fdcc8 reorgnization done
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 150
diff changeset
533 auto &PPOpts = CI.getPreprocessorOpts();
0572611fdcc8 reorgnization done
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 150
diff changeset
534 auto PatchBuffer =
0572611fdcc8 reorgnization done
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 150
diff changeset
535 // we copy here to ensure contents are still valid if CI outlives the
0572611fdcc8 reorgnization done
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 150
diff changeset
536 // PreamblePatch.
0572611fdcc8 reorgnization done
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 150
diff changeset
537 llvm::MemoryBuffer::getMemBufferCopy(PatchContents, PatchFileName);
0572611fdcc8 reorgnization done
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 150
diff changeset
538 // CI will take care of the lifetime of the buffer.
0572611fdcc8 reorgnization done
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 150
diff changeset
539 PPOpts.addRemappedFile(PatchFileName, PatchBuffer.release());
0572611fdcc8 reorgnization done
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 150
diff changeset
540 // The patch will be parsed after loading the preamble ast and before parsing
0572611fdcc8 reorgnization done
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 150
diff changeset
541 // the main file.
0572611fdcc8 reorgnization done
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 150
diff changeset
542 PPOpts.Includes.push_back(PatchFileName);
0572611fdcc8 reorgnization done
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 150
diff changeset
543 }
0572611fdcc8 reorgnization done
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 150
diff changeset
544
221
79ff65ed7e25 LLVM12 Original
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 173
diff changeset
545 std::vector<Inclusion> PreamblePatch::preambleIncludes() const {
79ff65ed7e25 LLVM12 Original
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 173
diff changeset
546 return PreambleIncludes;
79ff65ed7e25 LLVM12 Original
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 173
diff changeset
547 }
79ff65ed7e25 LLVM12 Original
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 173
diff changeset
548
79ff65ed7e25 LLVM12 Original
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 173
diff changeset
549 PreamblePatch PreamblePatch::unmodified(const PreambleData &Preamble) {
79ff65ed7e25 LLVM12 Original
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 173
diff changeset
550 PreamblePatch PP;
79ff65ed7e25 LLVM12 Original
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 173
diff changeset
551 PP.PreambleIncludes = Preamble.Includes.MainFileIncludes;
79ff65ed7e25 LLVM12 Original
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 173
diff changeset
552 PP.ModifiedBounds = Preamble.Preamble.getBounds();
79ff65ed7e25 LLVM12 Original
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 173
diff changeset
553 return PP;
79ff65ed7e25 LLVM12 Original
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 173
diff changeset
554 }
79ff65ed7e25 LLVM12 Original
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 173
diff changeset
555
79ff65ed7e25 LLVM12 Original
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 173
diff changeset
556 SourceLocation translatePreamblePatchLocation(SourceLocation Loc,
79ff65ed7e25 LLVM12 Original
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 173
diff changeset
557 const SourceManager &SM) {
79ff65ed7e25 LLVM12 Original
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 173
diff changeset
558 auto DefFile = SM.getFileID(Loc);
79ff65ed7e25 LLVM12 Original
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 173
diff changeset
559 if (auto *FE = SM.getFileEntryForID(DefFile)) {
79ff65ed7e25 LLVM12 Original
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 173
diff changeset
560 auto IncludeLoc = SM.getIncludeLoc(DefFile);
79ff65ed7e25 LLVM12 Original
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 173
diff changeset
561 // Preamble patch is included inside the builtin file.
79ff65ed7e25 LLVM12 Original
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 173
diff changeset
562 if (IncludeLoc.isValid() && SM.isWrittenInBuiltinFile(IncludeLoc) &&
79ff65ed7e25 LLVM12 Original
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 173
diff changeset
563 FE->getName().endswith(PreamblePatchHeaderName)) {
79ff65ed7e25 LLVM12 Original
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 173
diff changeset
564 auto Presumed = SM.getPresumedLoc(Loc);
79ff65ed7e25 LLVM12 Original
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 173
diff changeset
565 // Check that line directive is pointing at main file.
79ff65ed7e25 LLVM12 Original
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 173
diff changeset
566 if (Presumed.isValid() && Presumed.getFileID().isInvalid() &&
79ff65ed7e25 LLVM12 Original
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 173
diff changeset
567 isMainFile(Presumed.getFilename(), SM)) {
79ff65ed7e25 LLVM12 Original
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 173
diff changeset
568 Loc = SM.translateLineCol(SM.getMainFileID(), Presumed.getLine(),
79ff65ed7e25 LLVM12 Original
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 173
diff changeset
569 Presumed.getColumn());
79ff65ed7e25 LLVM12 Original
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 173
diff changeset
570 }
79ff65ed7e25 LLVM12 Original
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 173
diff changeset
571 }
79ff65ed7e25 LLVM12 Original
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 173
diff changeset
572 }
79ff65ed7e25 LLVM12 Original
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 173
diff changeset
573 return Loc;
79ff65ed7e25 LLVM12 Original
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 173
diff changeset
574 }
150
anatofuz
parents:
diff changeset
575 } // namespace clangd
anatofuz
parents:
diff changeset
576 } // namespace clang