clang 23.0.0git
InterpolatingCompilationDatabase.cpp
Go to the documentation of this file.
1//===- InterpolatingCompilationDatabase.cpp ---------------------*- C++ -*-===//
2//
3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4// See https://llvm.org/LICENSE.txt for license information.
5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6//
7//===----------------------------------------------------------------------===//
8//
9// InterpolatingCompilationDatabase wraps another CompilationDatabase and
10// attempts to heuristically determine appropriate compile commands for files
11// that are not included, such as headers or newly created files.
12//
13// Motivating cases include:
14// Header files that live next to their implementation files. These typically
15// share a base filename. (libclang/CXString.h, libclang/CXString.cpp).
16// Some projects separate headers from includes. Filenames still typically
17// match, maybe other path segments too. (include/llvm/IR/Use.h, lib/IR/Use.cc).
18// Matches are sometimes only approximate (Sema.h, SemaDecl.cpp). This goes
19// for directories too (Support/Unix/Process.inc, lib/Support/Process.cpp).
20// Even if we can't find a "right" compile command, even a random one from
21// the project will tend to get important flags like -I and -x right.
22//
23// We "borrow" the compile command for the closest available file:
24// - points are awarded if the filename matches (ignoring extension)
25// - points are awarded if the directory structure matches
26// - ties are broken by length of path prefix match
27//
28// The compile command is adjusted, replacing the filename and removing output
29// file arguments. The -x and -std flags may be affected too.
30//
31// Source language is a tricky issue: is it OK to use a .c file's command
32// for building a .cc file? What language is a .h file in?
33// - We only consider compile commands for c-family languages as candidates.
34// - For files whose language is implied by the filename (e.g. .m, .hpp)
35// we prefer candidates from the same language.
36// If we must cross languages, we drop any -x and -std flags.
37// - For .h files, candidates from any c-family language are acceptable.
38// We use the candidate's language, inserting e.g. -x c++-header.
39//
40// This class is only useful when wrapping databases that can enumerate all
41// their compile commands. If getAllFilenames() is empty, no inference occurs.
42//
43//===----------------------------------------------------------------------===//
44
46#include "clang/Driver/Driver.h"
47#include "clang/Driver/Types.h"
50#include "llvm/ADT/ArrayRef.h"
51#include "llvm/ADT/DenseMap.h"
52#include "llvm/ADT/StringExtras.h"
53#include "llvm/Option/ArgList.h"
54#include "llvm/Option/OptTable.h"
55#include "llvm/Support/Debug.h"
56#include "llvm/Support/Path.h"
57#include "llvm/Support/StringSaver.h"
58#include "llvm/Support/raw_ostream.h"
59#include <memory>
60#include <optional>
61
62namespace clang {
63namespace tooling {
64namespace {
65using namespace llvm;
66namespace types = clang::driver::types;
67namespace path = llvm::sys::path;
68
69// The length of the prefix these two strings have in common.
70size_t matchingPrefix(StringRef L, StringRef R) {
71 size_t Limit = std::min(L.size(), R.size());
72 for (size_t I = 0; I < Limit; ++I)
73 if (L[I] != R[I])
74 return I;
75 return Limit;
76}
77
78// A comparator for searching SubstringWithIndexes with std::equal_range etc.
79// Optionaly prefix semantics: compares equal if the key is a prefix.
80template <bool Prefix> struct Less {
81 bool operator()(StringRef Key, std::pair<StringRef, size_t> Value) const {
82 StringRef V = Prefix ? Value.first.substr(0, Key.size()) : Value.first;
83 return Key < V;
84 }
85 bool operator()(std::pair<StringRef, size_t> Value, StringRef Key) const {
86 StringRef V = Prefix ? Value.first.substr(0, Key.size()) : Value.first;
87 return V < Key;
88 }
89};
90
91// Infer type from filename. If we might have gotten it wrong, set *Certain.
92// *.h will be inferred as a C header, but not certain.
93types::ID guessType(StringRef Filename, bool *Certain = nullptr) {
94 // path::extension is ".cpp", lookupTypeForExtension wants "cpp".
95 auto Lang =
96 types::lookupTypeForExtension(path::extension(Filename).substr(1));
97 if (Certain)
98 *Certain = Lang != types::TY_CHeader && Lang != types::TY_INVALID;
99 return Lang;
100}
101
102// Return Lang as one of the canonical supported types.
103// e.g. c-header --> c; fortran --> TY_INVALID
104static types::ID foldType(types::ID Lang) {
105 switch (Lang) {
106 case types::TY_C:
107 case types::TY_CHeader:
108 return types::TY_C;
109 case types::TY_ObjC:
110 case types::TY_ObjCHeader:
111 return types::TY_ObjC;
112 case types::TY_CXX:
113 case types::TY_CXXHeader:
114 return types::TY_CXX;
115 case types::TY_ObjCXX:
116 case types::TY_ObjCXXHeader:
117 return types::TY_ObjCXX;
118 case types::TY_CUDA:
119 case types::TY_CUDA_DEVICE:
120 return types::TY_CUDA;
121 default:
122 return types::TY_INVALID;
123 }
124}
125
126// Return the language standard that's activated by the /std:clatest
127// flag in clang-CL mode.
128static LangStandard::Kind latestLangStandardC() {
129 // FIXME: Have a single source of truth for the mapping from
130 // clatest --> c23 that's shared by the driver code
131 // (clang/lib/Driver/ToolChains/Clang.cpp) and this file.
132 return LangStandard::lang_c23;
133}
134
135// Return the language standard that's activated by the /std:c++latest
136// flag in clang-CL mode.
137static LangStandard::Kind latestLangStandardCXX() {
138 // FIXME: Have a single source of truth for the mapping from
139 // c++latest --> c++26 that's shared by the driver code
140 // (clang/lib/Driver/ToolChains/Clang.cpp) and this file.
141 return LangStandard::lang_cxx26;
142}
143
144// A CompileCommand that can be applied to another file.
145struct TransferableCommand {
146 // Flags that should not apply to all files are stripped from CommandLine.
147 CompileCommand Cmd;
148 // Language detected from -x or the filename. Never TY_INVALID.
149 std::optional<types::ID> Type;
150 // Standard specified by -std.
152 // Whether the command line is for the cl-compatible driver.
153 bool ClangCLMode;
154
155 TransferableCommand(CompileCommand C)
156 : Cmd(std::move(C)), Type(guessType(Cmd.Filename)) {
157 std::vector<std::string> OldArgs = std::move(Cmd.CommandLine);
158 Cmd.CommandLine.clear();
159
160 // Wrap the old arguments in an InputArgList.
161 llvm::opt::InputArgList ArgList;
162 {
163 SmallVector<const char *, 16> TmpArgv;
164 for (const std::string &S : OldArgs)
165 TmpArgv.push_back(S.c_str());
166 ClangCLMode = !TmpArgv.empty() &&
168 TmpArgv.front(), llvm::ArrayRef(TmpArgv).slice(1)));
169 ArgList = {TmpArgv.begin(), TmpArgv.end()};
170 }
171
172 // Parse the old args in order to strip out and record unwanted flags.
173 // We parse each argument individually so that we can retain the exact
174 // spelling of each argument; re-rendering is lossy for aliased flags.
175 // E.g. in CL mode, /W4 maps to -Wall.
176 auto &OptTable = getDriverOptTable();
177 if (!OldArgs.empty())
178 Cmd.CommandLine.emplace_back(OldArgs.front());
179 for (unsigned Pos = 1; Pos < OldArgs.size();) {
180 using namespace options;
181
182 const unsigned OldPos = Pos;
183 std::unique_ptr<llvm::opt::Arg> Arg(OptTable.ParseOneArg(
184 ArgList, Pos,
185 llvm::opt::Visibility(ClangCLMode ? CLOption : ClangOption)));
186
187 if (!Arg)
188 continue;
189
190 const llvm::opt::Option &Opt = Arg->getOption();
191
192 // Strip input and output files.
193 if (Opt.matches(OPT_INPUT) || Opt.matches(OPT_o) ||
194 (ClangCLMode && (Opt.matches(OPT__SLASH_Fa) ||
195 Opt.matches(OPT__SLASH_Fe) ||
196 Opt.matches(OPT__SLASH_Fi) ||
197 Opt.matches(OPT__SLASH_Fo))))
198 continue;
199
200 // ...including when the inputs are passed after --.
201 if (Opt.matches(OPT__DASH_DASH))
202 break;
203
204 // Strip -x, but record the overridden language.
205 if (const auto GivenType = tryParseTypeArg(*Arg)) {
206 Type = *GivenType;
207 continue;
208 }
209
210 // Strip -std, but record the value.
211 if (const auto GivenStd = tryParseStdArg(*Arg)) {
212 if (*GivenStd != LangStandard::lang_unspecified)
213 Std = *GivenStd;
214 continue;
215 }
216
217 Cmd.CommandLine.insert(Cmd.CommandLine.end(),
218 OldArgs.data() + OldPos, OldArgs.data() + Pos);
219 }
220
221 // Make use of -std iff -x was missing.
222 if (Type == types::TY_INVALID && Std != LangStandard::lang_unspecified)
223 Type = toType(LangStandard::getLangStandardForKind(Std).getLanguage());
224 Type = foldType(*Type);
225 // The contract is to store None instead of TY_INVALID.
226 if (Type == types::TY_INVALID)
227 Type = std::nullopt;
228 }
229
230 // Produce a CompileCommand for \p filename, based on this one.
231 // (This consumes the TransferableCommand just to avoid copying Cmd).
232 CompileCommand transferTo(StringRef Filename) && {
233 CompileCommand Result = std::move(Cmd);
234 Result.Heuristic = "inferred from " + Result.Filename;
235 Result.Filename = std::string(Filename);
236 bool TypeCertain;
237 auto TargetType = guessType(Filename, &TypeCertain);
238 // If the filename doesn't determine the language (.h), transfer with -x.
239 if ((!TargetType || !TypeCertain) && Type) {
240 // Use *Type, or its header variant if the file is a header.
241 // Treat no/invalid extension as header (e.g. C++ standard library).
242 TargetType =
243 (!TargetType || types::onlyPrecompileType(TargetType)) // header?
244 ? types::lookupHeaderTypeForSourceType(*Type)
245 : *Type;
246 if (ClangCLMode) {
247 const StringRef Flag = toCLFlag(TargetType);
248 if (!Flag.empty())
249 Result.CommandLine.push_back(std::string(Flag));
250 } else {
251 Result.CommandLine.push_back("-x");
252 Result.CommandLine.push_back(types::getTypeName(TargetType));
253 }
254 }
255
256 // --std flag may only be transferred if the language is the same.
257 // We may consider "translating" these, e.g. c++11 -> c11.
258 if (Std != LangStandard::lang_unspecified && foldType(TargetType) == Type) {
259 const char *Spelling =
261
262 // In clang-cl mode, some standards have different spellings, so emit
263 // the spelling that the driver does accept.
264 // Keep in sync with OPT__SLASH_std handling in Clang::ConstructJob().
265 if (ClangCLMode) {
266 if (Std == LangStandard::lang_cxx23)
267 Spelling = "c++23preview";
268 else if (Std == latestLangStandardC())
269 Spelling = "clatest";
270 else if (Std == latestLangStandardCXX())
271 Spelling = "c++latest";
272 }
273
274 Result.CommandLine.emplace_back(
275 (llvm::Twine(ClangCLMode ? "/std:" : "-std=") + Spelling).str());
276 }
277
278 Result.CommandLine.push_back("--");
279 Result.CommandLine.push_back(std::string(Filename));
280 return Result;
281 }
282
283private:
284 // Map the language from the --std flag to that of the -x flag.
285 static types::ID toType(Language Lang) {
286 switch (Lang) {
287 case Language::C:
288 return types::TY_C;
289 case Language::CXX:
290 return types::TY_CXX;
291 case Language::ObjC:
292 return types::TY_ObjC;
293 case Language::ObjCXX:
294 return types::TY_ObjCXX;
295 default:
296 return types::TY_INVALID;
297 }
298 }
299
300 // Convert a file type to the matching CL-style type flag.
301 static StringRef toCLFlag(types::ID Type) {
302 switch (Type) {
303 case types::TY_C:
304 case types::TY_CHeader:
305 return "/TC";
306 case types::TY_CXX:
307 case types::TY_CXXHeader:
308 return "/TP";
309 default:
310 return StringRef();
311 }
312 }
313
314 // Try to interpret the argument as a type specifier, e.g. '-x'.
315 std::optional<types::ID> tryParseTypeArg(const llvm::opt::Arg &Arg) {
316 const llvm::opt::Option &Opt = Arg.getOption();
317 using namespace options;
318 if (ClangCLMode) {
319 if (Opt.matches(OPT__SLASH_TC) || Opt.matches(OPT__SLASH_Tc))
320 return types::TY_C;
321 if (Opt.matches(OPT__SLASH_TP) || Opt.matches(OPT__SLASH_Tp))
322 return types::TY_CXX;
323 } else {
324 if (Opt.matches(options::OPT_x))
325 return types::lookupTypeForTypeSpecifier(Arg.getValue());
326 }
327 return std::nullopt;
328 }
329
330 // Try to interpret the argument as '-std='.
331 std::optional<LangStandard::Kind> tryParseStdArg(const llvm::opt::Arg &Arg) {
332 using namespace options;
333 if (Arg.getOption().matches(ClangCLMode ? OPT__SLASH_std : OPT_std_EQ)) {
334 if (ClangCLMode) {
335 // Handle clang-cl spellings not in LangStandards.def.
336 // Keep in sync with OPT__SLASH_std handling in Clang::ConstructJob().
337 if (StringRef(Arg.getValue()) == "c++23preview")
338 return LangStandard::lang_cxx23;
339 if (StringRef(Arg.getValue()) == "clatest")
340 return latestLangStandardC();
341 if (StringRef(Arg.getValue()) == "c++latest")
342 return latestLangStandardCXX();
343 }
344 return LangStandard::getLangKind(Arg.getValue());
345 }
346 return std::nullopt;
347 }
348};
349
350// Given a filename, FileIndex picks the best matching file from the underlying
351// DB. This is the proxy file whose CompileCommand will be reused. The
352// heuristics incorporate file name, extension, and directory structure.
353// Strategy:
354// - Build indexes of each of the substrings we want to look up by.
355// These indexes are just sorted lists of the substrings.
356// - Each criterion corresponds to a range lookup into the index, so we only
357// need O(log N) string comparisons to determine scores.
358//
359// Apart from path proximity signals, also takes file extensions into account
360// when scoring the candidates.
361class FileIndex {
362public:
363 FileIndex(std::vector<std::string> Files)
364 : OriginalPaths(std::move(Files)), Strings(Arena) {
365 // Sort commands by filename for determinism (index is a tiebreaker later).
366 llvm::sort(OriginalPaths);
367 Paths.reserve(OriginalPaths.size());
368 Types.reserve(OriginalPaths.size());
369 Stems.reserve(OriginalPaths.size());
370 for (size_t I = 0; I < OriginalPaths.size(); ++I) {
371 StringRef Path = Strings.save(StringRef(OriginalPaths[I]).lower());
372
373 Paths.emplace_back(Path, I);
374 Types.push_back(foldType(guessType(OriginalPaths[I])));
375 Stems.emplace_back(sys::path::stem(Path), I);
376 auto Dir = ++sys::path::rbegin(Path), DirEnd = sys::path::rend(Path);
377 for (int J = 0; J < DirectorySegmentsIndexed && Dir != DirEnd; ++J, ++Dir)
378 if (Dir->size() > ShortDirectorySegment) // not trivial ones
379 Components.emplace_back(*Dir, I);
380 }
381 llvm::sort(Paths);
382 llvm::sort(Stems);
383 llvm::sort(Components);
384 }
385
386 bool empty() const { return Paths.empty(); }
387
388 // Returns the path for the file that best fits OriginalFilename.
389 // Candidates with extensions matching PreferLanguage will be chosen over
390 // others (unless it's TY_INVALID, or all candidates are bad).
391 StringRef chooseProxy(StringRef OriginalFilename,
392 types::ID PreferLanguage) const {
393 assert(!empty() && "need at least one candidate!");
394 std::string Filename = OriginalFilename.lower();
395 auto Candidates = scoreCandidates(Filename);
396 std::pair<size_t, int> Best =
397 pickWinner(Candidates, Filename, PreferLanguage);
398
399 DEBUG_WITH_TYPE(
400 "interpolate",
401 llvm::dbgs() << "interpolate: chose " << OriginalPaths[Best.first]
402 << " as proxy for " << OriginalFilename << " preferring "
403 << (PreferLanguage == types::TY_INVALID
404 ? "none"
405 : types::getTypeName(PreferLanguage))
406 << " score=" << Best.second << "\n");
407 return OriginalPaths[Best.first];
408 }
409
410private:
411 using SubstringAndIndex = std::pair<StringRef, size_t>;
412 // Directory matching parameters: we look at the last two segments of the
413 // parent directory (usually the semantically significant ones in practice).
414 // We search only the last four of each candidate (for efficiency).
415 constexpr static int DirectorySegmentsIndexed = 4;
416 constexpr static int DirectorySegmentsQueried = 2;
417 constexpr static int ShortDirectorySegment = 1; // Only look at longer names.
418
419 // Award points to candidate entries that should be considered for the file.
420 // Returned keys are indexes into paths, and the values are (nonzero) scores.
421 DenseMap<size_t, int> scoreCandidates(StringRef Filename) const {
422 // Decompose Filename into the parts we care about.
423 // /some/path/complicated/project/Interesting.h
424 // [-prefix--][---dir---] [-dir-] [--stem---]
425 StringRef Stem = sys::path::stem(Filename);
426 llvm::SmallVector<StringRef, DirectorySegmentsQueried> Dirs;
427 llvm::StringRef Prefix;
428 auto Dir = ++sys::path::rbegin(Filename),
429 DirEnd = sys::path::rend(Filename);
430 for (int I = 0; I < DirectorySegmentsQueried && Dir != DirEnd; ++I, ++Dir) {
431 if (Dir->size() > ShortDirectorySegment)
432 Dirs.push_back(*Dir);
433 Prefix = Filename.substr(0, Dir - DirEnd);
434 }
435
436 // Now award points based on lookups into our various indexes.
437 DenseMap<size_t, int> Candidates; // Index -> score.
438 auto Award = [&](int Points, ArrayRef<SubstringAndIndex> Range) {
439 for (const auto &Entry : Range)
440 Candidates[Entry.second] += Points;
441 };
442 // Award one point if the file's basename is a prefix of the candidate,
443 // and another if it's an exact match (so exact matches get two points).
444 Award(1, indexLookup</*Prefix=*/true>(Stem, Stems));
445 Award(1, indexLookup</*Prefix=*/false>(Stem, Stems));
446 // For each of the last few directories in the Filename, award a point
447 // if it's present in the candidate.
448 for (StringRef Dir : Dirs)
449 Award(1, indexLookup</*Prefix=*/false>(Dir, Components));
450 // Award one more point if the whole rest of the path matches.
451 if (sys::path::root_directory(Prefix) != Prefix)
452 Award(1, indexLookup</*Prefix=*/true>(Prefix, Paths));
453 return Candidates;
454 }
455
456 // Pick a single winner from the set of scored candidates.
457 // Returns (index, score).
458 std::pair<size_t, int> pickWinner(const DenseMap<size_t, int> &Candidates,
459 StringRef Filename,
460 types::ID PreferredLanguage) const {
461 struct ScoredCandidate {
462 size_t Index;
463 bool Preferred;
464 int Points;
465 size_t PrefixLength;
466 };
467 // Choose the best candidate by (preferred, points, prefix length, alpha).
468 ScoredCandidate Best = {size_t(-1), false, 0, 0};
469 for (const auto &Candidate : Candidates) {
470 ScoredCandidate S;
471 S.Index = Candidate.first;
472 S.Preferred = PreferredLanguage == types::TY_INVALID ||
473 PreferredLanguage == Types[S.Index];
474 S.Points = Candidate.second;
475 if (!S.Preferred && Best.Preferred)
476 continue;
477 if (S.Preferred == Best.Preferred) {
478 if (S.Points < Best.Points)
479 continue;
480 if (S.Points == Best.Points) {
481 S.PrefixLength = matchingPrefix(Filename, Paths[S.Index].first);
482 if (S.PrefixLength < Best.PrefixLength)
483 continue;
484 // hidden heuristics should at least be deterministic!
485 if (S.PrefixLength == Best.PrefixLength)
486 if (S.Index > Best.Index)
487 continue;
488 }
489 }
490 // PrefixLength was only set above if actually needed for a tiebreak.
491 // But it definitely needs to be set to break ties in the future.
492 S.PrefixLength = matchingPrefix(Filename, Paths[S.Index].first);
493 Best = S;
494 }
495 // Edge case: no candidate got any points.
496 // We ignore PreferredLanguage at this point (not ideal).
497 if (Best.Index == size_t(-1))
498 return {longestMatch(Filename, Paths).second, 0};
499 return {Best.Index, Best.Points};
500 }
501
502 // Returns the range within a sorted index that compares equal to Key.
503 // If Prefix is true, it's instead the range starting with Key.
504 template <bool Prefix>
505 ArrayRef<SubstringAndIndex>
506 indexLookup(StringRef Key, ArrayRef<SubstringAndIndex> Idx) const {
507 // Use pointers as iteratiors to ease conversion of result to ArrayRef.
508 auto Range = std::equal_range(Idx.data(), Idx.data() + Idx.size(), Key,
509 Less<Prefix>());
510 return {Range.first, Range.second};
511 }
512
513 // Performs a point lookup into a nonempty index, returning a longest match.
514 SubstringAndIndex longestMatch(StringRef Key,
515 ArrayRef<SubstringAndIndex> Idx) const {
516 assert(!Idx.empty());
517 // Longest substring match will be adjacent to a direct lookup.
518 auto It = llvm::lower_bound(Idx, SubstringAndIndex{Key, 0});
519 if (It == Idx.begin())
520 return *It;
521 if (It == Idx.end())
522 return *--It;
523 // Have to choose between It and It-1
524 size_t Prefix = matchingPrefix(Key, It->first);
525 size_t PrevPrefix = matchingPrefix(Key, (It - 1)->first);
526 return Prefix > PrevPrefix ? *It : *--It;
527 }
528
529 // Original paths, everything else is in lowercase.
530 std::vector<std::string> OriginalPaths;
531 BumpPtrAllocator Arena;
532 StringSaver Strings;
533 // Indexes of candidates by certain substrings.
534 // String is lowercase and sorted, index points into OriginalPaths.
535 std::vector<SubstringAndIndex> Paths; // Full path.
536 // Lang types obtained by guessing on the corresponding path. I-th element is
537 // a type for the I-th path.
538 std::vector<types::ID> Types;
539 std::vector<SubstringAndIndex> Stems; // Basename, without extension.
540 std::vector<SubstringAndIndex> Components; // Last path components.
541};
542
543// The actual CompilationDatabase wrapper delegates to its inner database.
544// If no match, looks up a proxy file in FileIndex and transfers its
545// command to the requested file.
546class InterpolatingCompilationDatabase : public CompilationDatabase {
547public:
548 InterpolatingCompilationDatabase(std::unique_ptr<CompilationDatabase> Inner)
549 : Inner(std::move(Inner)), Index(this->Inner->getAllFiles()) {}
550
551 std::vector<CompileCommand>
552 getCompileCommands(StringRef Filename) const override {
553 auto Known = Inner->getCompileCommands(Filename);
554 if (Index.empty() || !Known.empty())
555 return Known;
556 bool TypeCertain;
557 auto Lang = guessType(Filename, &TypeCertain);
558 if (!TypeCertain)
559 Lang = types::TY_INVALID;
560 auto ProxyCommands =
561 Inner->getCompileCommands(Index.chooseProxy(Filename, foldType(Lang)));
562 if (ProxyCommands.empty())
563 return {};
564 return {transferCompileCommand(std::move(ProxyCommands.front()), Filename)};
565 }
566
567 std::vector<std::string> getAllFiles() const override {
568 return Inner->getAllFiles();
569 }
570
571 std::vector<CompileCommand> getAllCompileCommands() const override {
572 return Inner->getAllCompileCommands();
573 }
574
575private:
576 std::unique_ptr<CompilationDatabase> Inner;
577 FileIndex Index;
578};
579
580} // namespace
581
582std::unique_ptr<CompilationDatabase>
583inferMissingCompileCommands(std::unique_ptr<CompilationDatabase> Inner) {
584 return std::make_unique<InterpolatingCompilationDatabase>(std::move(Inner));
585}
586
588 StringRef Filename) {
589 return TransferableCommand(std::move(Cmd)).transferTo(Filename);
590}
591
592} // namespace tooling
593} // namespace clang
#define V(N, I)
__SIZE_TYPE__ size_t
The unsigned integer type of the result of the sizeof operator.
Interface for compilation databases.
llvm::StringRef getDriverMode(StringRef ProgName, ArrayRef< const char * > Args)
Returns the driver mode option's value, i.e.
Definition Driver.cpp:7184
bool IsClangCL(StringRef DriverMode)
Checks whether the value produced by getDriverMode is for CL mode.
Definition Driver.cpp:7199
tooling::CompileCommand transferCompileCommand(tooling::CompileCommand, StringRef Filename)
Transforms a compile command so that it applies the same configuration to a different file.
std::unique_ptr< CompilationDatabase > inferMissingCompileCommands(std::unique_ptr< CompilationDatabase >)
Returns a wrapped CompilationDatabase that defers to the provided one, but getCompileCommands() will ...
The JSON file list parser is used to communicate input to InstallAPI.
Language
The language for the input, used to select and validate the language standard and possible actions.
@ C
Languages that the frontend can parse and compile.
@ Result
The result type of a method or function.
Definition TypeBase.h:905
const llvm::opt::OptTable & getDriverOptTable()
static const LangStandard & getLangStandardForKind(Kind K)
const char * getName() const
getName - Get the name of this standard.
static Kind getLangKind(StringRef Name)
Specifies the working directory and command of a compilation.