@@ -94,158 +94,6 @@ static void debugFailWithCrash() { LLVM_BUILTIN_TRAP; }
94
94
95
95
namespace swift {
96
96
97
- // / Implement argument semantics in a way that will make it easier to have
98
- // / >1 primary file (or even a primary file list) in the future without
99
- // / breaking anything today.
100
- // /
101
- // / Semantics today:
102
- // / If input files are on command line, primary files on command line are also
103
- // / input files; they are not repeated without -primary-file. If input files are
104
- // / in a file list, the primary files on the command line are repeated in the
105
- // / file list. Thus, if there are any primary files, it is illegal to have both
106
- // / (non-primary) input files and a file list. Finally, the order of input files
107
- // / must match the order given on the command line or the file list.
108
- // /
109
- // / Side note:
110
- // / since each input file will cause a lot of work for the compiler, this code
111
- // / is biased towards clarity and not optimized.
112
- // / In the near future, it will be possible to put primary files in the
113
- // / filelist, or to have a separate filelist for primaries. The organization
114
- // / here anticipates that evolution.
115
-
116
- class ArgsToFrontendInputsConverter {
117
- DiagnosticEngine &Diags;
118
- const ArgList &Args;
119
- FrontendInputs &Inputs;
120
-
121
- Arg const *const FilelistPathArg;
122
- Arg const *const PrimaryFilelistPathArg;
123
-
124
- SmallVector<std::unique_ptr<llvm::MemoryBuffer>, 4 > BuffersToKeepAlive;
125
-
126
- llvm::SetVector<StringRef> Files;
127
-
128
- public:
129
- ArgsToFrontendInputsConverter (DiagnosticEngine &Diags, const ArgList &Args,
130
- FrontendInputs &Inputs)
131
- : Diags(Diags), Args(Args), Inputs(Inputs),
132
- FilelistPathArg (Args.getLastArg(options::OPT_filelist)),
133
- PrimaryFilelistPathArg(Args.getLastArg(options::OPT_primary_filelist)) {
134
- }
135
-
136
- bool convert () {
137
- if (enforceFilelistExclusion ())
138
- return true ;
139
- if (FilelistPathArg ? readInputFilesFromFilelist ()
140
- : readInputFilesFromCommandLine ())
141
- return true ;
142
- Optional<std::set<StringRef>> primaryFiles = readPrimaryFiles ();
143
- if (!primaryFiles)
144
- return true ;
145
- std::set<StringRef> unusedPrimaryFiles =
146
- createInputFilesConsumingPrimaries (*primaryFiles);
147
- return checkForMissingPrimaryFiles (unusedPrimaryFiles);
148
- }
149
-
150
- private:
151
- bool enforceFilelistExclusion () {
152
- if (Args.hasArg (options::OPT_INPUT) && FilelistPathArg) {
153
- Diags.diagnose (SourceLoc (),
154
- diag::error_cannot_have_input_files_with_file_list);
155
- return true ;
156
- }
157
- // The following is not strictly necessary, but the restriction makes
158
- // it easier to understand a given command line:
159
- if (Args.hasArg (options::OPT_primary_file) && PrimaryFilelistPathArg) {
160
- Diags.diagnose (
161
- SourceLoc (),
162
- diag::error_cannot_have_primary_files_with_primary_file_list);
163
- return true ;
164
- }
165
- return false ;
166
- }
167
-
168
- bool readInputFilesFromCommandLine () {
169
- bool hadDuplicates = false ;
170
- for (const Arg *A :
171
- Args.filtered (options::OPT_INPUT, options::OPT_primary_file)) {
172
- hadDuplicates = addFile (A->getValue ()) || hadDuplicates;
173
- }
174
- return false ; // FIXME: Don't bail out for duplicates, too many tests depend
175
- // on it.
176
- }
177
-
178
- bool readInputFilesFromFilelist () {
179
- bool hadDuplicates = false ;
180
- bool hadError =
181
- forAllFilesInFilelist (FilelistPathArg, [&](StringRef file) -> void {
182
- hadDuplicates = addFile (file) || hadDuplicates;
183
- });
184
- if (hadError)
185
- return true ;
186
- return false ; // FIXME: Don't bail out for duplicates, too many tests depend on it.
187
- }
188
-
189
- bool forAllFilesInFilelist (Arg const *const pathArg,
190
- llvm::function_ref<void (StringRef)> fn) {
191
- if (!pathArg)
192
- return false ;
193
- StringRef path = pathArg->getValue ();
194
- llvm::ErrorOr<std::unique_ptr<llvm::MemoryBuffer>> filelistBufferOrError =
195
- llvm::MemoryBuffer::getFile (path);
196
- if (!filelistBufferOrError) {
197
- Diags.diagnose (SourceLoc (), diag::cannot_open_file, path,
198
- filelistBufferOrError.getError ().message ());
199
- return true ;
200
- }
201
- for (auto file :
202
- llvm::make_range (llvm::line_iterator (*filelistBufferOrError->get ()),
203
- llvm::line_iterator ()))
204
- fn (file);
205
- BuffersToKeepAlive.push_back (std::move (*filelistBufferOrError));
206
- return false ;
207
- }
208
-
209
- bool addFile (StringRef file) {
210
- if (Files.insert (file))
211
- return false ;
212
- Diags.diagnose (SourceLoc (), diag::error_duplicate_input_file, file);
213
- return true ;
214
- }
215
-
216
- Optional<std::set<StringRef>> readPrimaryFiles () {
217
- std::set<StringRef> primaryFiles;
218
- for (const Arg *A : Args.filtered (options::OPT_primary_file))
219
- primaryFiles.insert (A->getValue ());
220
- if (forAllFilesInFilelist (
221
- PrimaryFilelistPathArg,
222
- [&](StringRef file) -> void { primaryFiles.insert (file); }))
223
- return None;
224
- return primaryFiles;
225
- }
226
-
227
- std::set<StringRef>
228
- createInputFilesConsumingPrimaries (std::set<StringRef> primaryFiles) {
229
- for (auto &file : Files) {
230
- bool isPrimary = primaryFiles.count (file) > 0 ;
231
- Inputs.addInput (InputFile (file, isPrimary));
232
- if (isPrimary)
233
- primaryFiles.erase (file);
234
- }
235
- return primaryFiles;
236
- }
237
-
238
- bool checkForMissingPrimaryFiles (std::set<StringRef> primaryFiles) {
239
- for (auto &file : primaryFiles) {
240
- // Catch "swiftc -frontend -c -filelist foo -primary-file
241
- // some-file-not-in-foo".
242
- assert (FilelistPathArg && " Missing primary with no filelist" );
243
- Diags.diagnose (SourceLoc (), diag::error_primary_file_not_found, file,
244
- FilelistPathArg->getValue ());
245
- }
246
- return !primaryFiles.empty ();
247
- }
248
- };
249
97
class FrontendArgsToOptionsConverter {
250
98
private:
251
99
DiagnosticEngine &Diags;
0 commit comments