clang: lib/CrossTU/CrossTranslationUnit.cpp Source File (original) (raw)

1

2

3

4

5

6

7

8

9

10

11

22#include "llvm/ADT/Statistic.h"

23#include "llvm/Option/ArgList.h"

24#include "llvm/Support/ErrorHandling.h"

25#include "llvm/Support/ManagedStatic.h"

26#include "llvm/Support/Path.h"

27#include "llvm/Support/YAMLParser.h"

28#include "llvm/Support/raw_ostream.h"

29#include "llvm/TargetParser/Triple.h"

30#include

31#include

32#include

33#include

34#include

35

37namespace cross_tu {

38

39namespace {

40

41#define DEBUG_TYPE "CrossTranslationUnit"

42STATISTIC(NumGetCTUCalled, "The # of getCTUDefinition function called");

44 NumNotInOtherTU,

45 "The # of getCTUDefinition called but the function is not in any other TU");

47 "The # of getCTUDefinition successfully returned the "

48 "requested function's body");

49STATISTIC(NumUnsupportedNodeFound, "The # of imports when the ASTImporter "

50 "encountered an unsupported AST Node");

51STATISTIC(NumNameConflicts, "The # of imports when the ASTImporter "

52 "encountered an ODR error");

53STATISTIC(NumTripleMismatch, "The # of triple mismatches");

54STATISTIC(NumLangMismatch, "The # of language mismatches");

55STATISTIC(NumLangDialectMismatch, "The # of language dialect mismatches");

56STATISTIC(NumASTLoadThresholdReached,

57 "The # of ASTs not loaded because of threshold");

58

59

60

61bool hasEqualKnownFields(const llvm::Triple &Lhs, const llvm::Triple &Rhs) {

62 using llvm::Triple;

63 if (Lhs.getArch() != Triple::UnknownArch &&

64 Rhs.getArch() != Triple::UnknownArch && Lhs.getArch() != Rhs.getArch())

65 return false;

66 if (Lhs.getSubArch() != Triple::NoSubArch &&

67 Rhs.getSubArch() != Triple::NoSubArch &&

68 Lhs.getSubArch() != Rhs.getSubArch())

69 return false;

70 if (Lhs.getVendor() != Triple::UnknownVendor &&

71 Rhs.getVendor() != Triple::UnknownVendor &&

72 Lhs.getVendor() != Rhs.getVendor())

73 return false;

74 if (!Lhs.isOSUnknown() && !Rhs.isOSUnknown() &&

75 Lhs.getOS() != Rhs.getOS())

76 return false;

77 if (Lhs.getEnvironment() != Triple::UnknownEnvironment &&

78 Rhs.getEnvironment() != Triple::UnknownEnvironment &&

79 Lhs.getEnvironment() != Rhs.getEnvironment())

80 return false;

81 if (Lhs.getObjectFormat() != Triple::UnknownObjectFormat &&

82 Rhs.getObjectFormat() != Triple::UnknownObjectFormat &&

83 Lhs.getObjectFormat() != Rhs.getObjectFormat())

84 return false;

85 return true;

86}

87

88

89class IndexErrorCategory : public std::error_category {

90public:

91 const char *name() const noexcept override { return "clang.index"; }

92

93 std::string message(int Condition) const override {

96

97

98 break;

100 return "An unknown error has occurred.";

102 return "The index file is missing.";

104 return "Invalid index file format.";

106 return "Multiple definitions in the index file.";

108 return "Missing definition from the index file.";

110 return "Failed to import the definition.";

112 return "Failed to load external AST source.";

114 return "Failed to generate USR.";

116 return "Triple mismatch";

118 return "Language mismatch";

120 return "Language dialect mismatch";

122 return "Load threshold reached";

124 return "Invocation list file contains multiple references to the same "

125 "source file.";

127 return "Invocation list file is not found.";

129 return "Invocation list file is empty.";

131 return "Invocation list file is in wrong format.";

133 return "Invocation list file does not contain the requested source file.";

134 }

135 llvm_unreachable("Unrecognized index_error_code.");

136 }

137};

138

139static llvm::ManagedStatic Category;

140}

141

143

145 OS << Category->message(static_cast<int>(Code)) << '\n';

146}

147

149 return std::error_code(static_cast<int>(Code), *Category);

150}

151

152

153

154

155

156

157

159 StringRef &FilePath) {

160

161

162 size_t USRLength = 0;

163 if (LineRef.consumeInteger(10, USRLength))

164 return false;

165 assert(USRLength && "USRLength should be greater than zero.");

166

167 if (!LineRef.consume_front(":"))

168 return false;

169

170

171

172

173 if (USRLength >= LineRef.size() || ' ' != LineRef[USRLength])

174 return false;

175

176 LookupName = LineRef.substr(0, USRLength);

177 FilePath = LineRef.substr(USRLength + 1);

178 return true;

179}

180

183 std::ifstream ExternalMapFile{std::string(IndexPath)};

184 if (!ExternalMapFile)

186 IndexPath.str());

187

188 llvm::StringMapstd::string Result;

189 std::string Line;

190 unsigned LineNo = 1;

191 while (std::getline(ExternalMapFile, Line)) {

192

193 StringRef LookupName, FilePathInIndex;

195 return llvm::make_error(

197

198

200 llvm::sys::path::native(FilePath, llvm::sys::path::Style::posix);

201

202 bool InsertionOccured;

203 std::tie(std::ignore, InsertionOccured) =

204 Result.try_emplace(LookupName, FilePath.begin(), FilePath.end());

205 if (!InsertionOccured)

206 return llvm::make_error(

208

209 ++LineNo;

210 }

212}

213

214std::string

216 std::ostringstream Result;

217 for (const auto &E : Index)

218 Result << E.getKey().size() << ':' << E.getKey().str() << ' '

219 << E.getValue() << '\n';

221}

222

226}

227

229 return D->hasBody(DefD);

230}

232 return D->getAnyInitializer(DefD);

233}

237}

238

240 : Context(CI.getASTContext()), ASTStorage(CI) {}

241

243

244std::optionalstd::string

248 if (Ret)

249 return {};

250 return std::string(DeclUSR);

251}

252

253

254

255template

256const T *

257CrossTranslationUnitContext::findDefInDeclContext(const DeclContext *DC,

258 StringRef LookupName) {

259 assert(DC && "Declaration Context must not be null");

261 const auto *SubDC = dyn_cast(D);

262 if (SubDC)

263 if (const auto *ND = findDefInDeclContext(SubDC, LookupName))

264 return ND;

265

266 const auto *ND = dyn_cast(D);

267 const T *ResultDecl;

269 continue;

270 std::optionalstd::string ResultLookupName = getLookupName(ResultDecl);

271 if (!ResultLookupName || *ResultLookupName != LookupName)

272 continue;

273 return ResultDecl;

274 }

275 return nullptr;

276}

277

278template

280 const T *D, StringRef CrossTUDir, StringRef IndexName,

281 bool DisplayCTUProgress) {

282 assert(D && "D is missing, bad call to this function!");

284 "D has a body or init in current translation unit!");

285 ++NumGetCTUCalled;

286 const std::optionalstd::string LookupName = getLookupName(D);

287 if (!LookupName)

288 return llvm::make_error(

291 loadExternalAST(*LookupName, CrossTUDir, IndexName, DisplayCTUProgress);

292 if (!ASTUnitOrError)

293 return ASTUnitOrError.takeError();

294 ASTUnit *Unit = *ASTUnitOrError;

295 assert(&Unit->getFileManager() ==

296 &Unit->getASTContext().getSourceManager().getFileManager());

297

299 const llvm::Triple &TripleFrom =

300 Unit->getASTContext().getTargetInfo().getTriple();

301

302

303

304

305 if (!hasEqualKnownFields(TripleTo, TripleFrom)) {

306

307

308 ++NumTripleMismatch;

310 std::string(Unit->getMainFileName()),

311 TripleTo.str(), TripleFrom.str());

312 }

313

314 const auto &LangTo = Context.getLangOpts();

315 const auto &LangFrom = Unit->getASTContext().getLangOpts();

316

317

318

319 if (LangTo.CPlusPlus != LangFrom.CPlusPlus) {

320 ++NumLangMismatch;

322 }

323

324

325

326

327

328

329

330

331

332

333

334

335

336

337 if (LangTo.CPlusPlus11 != LangFrom.CPlusPlus11 ||

338 LangTo.CPlusPlus14 != LangFrom.CPlusPlus14 ||

339 LangTo.CPlusPlus17 != LangFrom.CPlusPlus17 ||

340 LangTo.CPlusPlus20 != LangFrom.CPlusPlus20) {

341 ++NumLangDialectMismatch;

342 return llvm::make_error(

344 }

345

346 TranslationUnitDecl *TU = Unit->getASTContext().getTranslationUnitDecl();

347 if (const T *ResultDecl = findDefInDeclContext(TU, *LookupName))

350}

351

354 StringRef CrossTUDir,

355 StringRef IndexName,

356 bool DisplayCTUProgress) {

357 return getCrossTUDefinitionImpl(FD, CrossTUDir, IndexName,

358 DisplayCTUProgress);

359}

360

363 StringRef CrossTUDir,

364 StringRef IndexName,

365 bool DisplayCTUProgress) {

366 return getCrossTUDefinitionImpl(VD, CrossTUDir, IndexName,

367 DisplayCTUProgress);

368}

369

375 break;

379 break;

383 break;

387 break;

388 default:

389 break;

390 }

391}

392

393CrossTranslationUnitContext::ASTUnitStorage::ASTUnitStorage(

395 : Loader(CI, CI.getAnalyzerOpts().CTUDir,

396 CI.getAnalyzerOpts().CTUInvocationList),

397 LoadGuard(CI.getASTContext().getLangOpts().CPlusPlus

398 ? CI.getAnalyzerOpts().CTUImportCppThreshold

399 : CI.getAnalyzerOpts().CTUImportThreshold) {}

400

402CrossTranslationUnitContext::ASTUnitStorage::getASTUnitForFile(

403 StringRef FileName, bool DisplayCTUProgress) {

404

405 auto ASTCacheEntry = FileASTUnitMap.find(FileName);

406 if (ASTCacheEntry == FileASTUnitMap.end()) {

407

408

409 if (!LoadGuard) {

410 ++NumASTLoadThresholdReached;

411 return llvm::make_error(

413 }

414

415 auto LoadAttempt = Loader.load(FileName);

416

417 if (!LoadAttempt)

418 return LoadAttempt.takeError();

419

420 std::unique_ptr LoadedUnit = std::move(LoadAttempt.get());

421

422

423 ASTUnit *Unit = LoadedUnit.get();

424

425

426 FileASTUnitMap[FileName] = std::move(LoadedUnit);

427

428 LoadGuard.indicateLoadSuccess();

429

430 if (DisplayCTUProgress)

431 llvm::errs() << "CTU loaded AST file: " << FileName << "\n";

432

433 return Unit;

434

435 } else {

436

437 return ASTCacheEntry->second.get();

438 }

439}

440

442CrossTranslationUnitContext::ASTUnitStorage::getASTUnitForFunction(

443 StringRef FunctionName, StringRef CrossTUDir, StringRef IndexName,

444 bool DisplayCTUProgress) {

445

446 auto ASTCacheEntry = NameASTUnitMap.find(FunctionName);

447 if (ASTCacheEntry == NameASTUnitMap.end()) {

448

449

450

451 if (llvm::Error IndexLoadError =

452 ensureCTUIndexLoaded(CrossTUDir, IndexName))

453 return std::move(IndexLoadError);

454

455

456 if (!NameFileMap.count(FunctionName)) {

457 ++NumNotInOtherTU;

459 }

460

461

462

464 getASTUnitForFile(NameFileMap[FunctionName], DisplayCTUProgress)) {

465

466

467 NameASTUnitMap[FunctionName] = *FoundForFile;

468 return *FoundForFile;

469

470 } else {

471 return FoundForFile.takeError();

472 }

473 } else {

474

475 return ASTCacheEntry->second;

476 }

477}

478

480CrossTranslationUnitContext::ASTUnitStorage::getFileForFunction(

481 StringRef FunctionName, StringRef CrossTUDir, StringRef IndexName) {

482 if (llvm::Error IndexLoadError = ensureCTUIndexLoaded(CrossTUDir, IndexName))

483 return std::move(IndexLoadError);

484 return NameFileMap[FunctionName];

485}

486

487llvm::Error CrossTranslationUnitContext::ASTUnitStorage::ensureCTUIndexLoaded(

488 StringRef CrossTUDir, StringRef IndexName) {

489

490 if (!NameFileMap.empty())

491 return llvm::Error::success();

492

493

494 SmallString<256> IndexFile = CrossTUDir;

495 if (llvm::sys::path::is_absolute(IndexName))

496 IndexFile = IndexName;

497 else

498 llvm::sys::path::append(IndexFile, IndexName);

499

501

502 NameFileMap = *IndexMapping;

503 return llvm::Error::success();

504 } else {

505

506 return IndexMapping.takeError();

507 };

508}

509

511 StringRef LookupName, StringRef CrossTUDir, StringRef IndexName,

512 bool DisplayCTUProgress) {

513

514

515

516

517

518

520 LookupName, CrossTUDir, IndexName, DisplayCTUProgress);

521

522 if (!Unit)

523 return Unit.takeError();

524

525

526 if (!*Unit)

527 return llvm::make_error(

529

530 return Unit;

531}

532

533CrossTranslationUnitContext::ASTLoader::ASTLoader(

534 CompilerInstance &CI, StringRef CTUDir, StringRef InvocationListFilePath)

535 : CI(CI), CTUDir(CTUDir), InvocationListFilePath(InvocationListFilePath) {}

536

537CrossTranslationUnitContext::LoadResultTy

538CrossTranslationUnitContext::ASTLoader::load(StringRef Identifier) {

540 if (llvm::sys::path::is_absolute(Identifier, PathStyle)) {

542 } else {

543 Path = CTUDir;

544 llvm::sys::path::append(Path, PathStyle, Identifier);

545 }

546

547

548

549 llvm::sys::path::native(Path, PathStyle);

550

551

552 llvm::sys::path::remove_dots(Path, true, PathStyle);

553

554 if (Path.ends_with(".ast"))

555 return loadFromDump(Path);

556 else

557 return loadFromSource(Path);

558}

559

560CrossTranslationUnitContext::LoadResultTy

561CrossTranslationUnitContext::ASTLoader::loadFromDump(StringRef ASTDumpPath) {

562 IntrusiveRefCntPtr DiagOpts = new DiagnosticOptions();

563 TextDiagnosticPrinter *DiagClient =

564 new TextDiagnosticPrinter(llvm::errs(), &*DiagOpts);

565 IntrusiveRefCntPtr DiagID(new DiagnosticIDs());

566 IntrusiveRefCntPtr Diags(

567 new DiagnosticsEngine(DiagID, &*DiagOpts, DiagClient));

569 ASTDumpPath, CI.getPCHContainerOperations()->getRawReader(),

571 CI.getHeaderSearchOptsPtr());

572}

573

574

575

576

577

578

579

580

581

582

583

584

585CrossTranslationUnitContext::LoadResultTy

586CrossTranslationUnitContext::ASTLoader::loadFromSource(

587 StringRef SourceFilePath) {

588

589 if (llvm::Error InitError = lazyInitInvocationList())

590 return std::move(InitError);

591 assert(InvocationList);

592

593 auto Invocation = InvocationList->find(SourceFilePath);

594 if (Invocation == InvocationList->end())

595 return llvm::make_error(

597

598 const InvocationListTy::mapped_type &InvocationCommand = Invocation->second;

599

600 SmallVector<const char *, 32> CommandLineArgs(InvocationCommand.size());

601 std::transform(InvocationCommand.begin(), InvocationCommand.end(),

602 CommandLineArgs.begin(),

603 [](auto &&CmdPart) { return CmdPart.c_str(); });

604

605 IntrusiveRefCntPtr DiagOpts{&CI.getDiagnosticOpts()};

606 auto *DiagClient = new ForwardingDiagnosticConsumer{CI.getDiagnosticClient()};

607 IntrusiveRefCntPtr DiagID{

608 CI.getDiagnostics().getDiagnosticIDs()};

609 IntrusiveRefCntPtr Diags(

610 new DiagnosticsEngine{DiagID, &*DiagOpts, DiagClient});

611

613 (CommandLineArgs.end()),

614 CI.getPCHContainerOperations(), Diags,

615 CI.getHeaderSearchOpts().ResourceDir);

616}

617

621

622

623 llvm::SourceMgr SM;

624 llvm::yaml::Stream InvocationFile(FileContent, SM);

625

626

627 llvm::yaml::document_iterator FirstInvocationFile = InvocationFile.begin();

628

629

630 if (FirstInvocationFile == InvocationFile.end())

631 return llvm::make_error(

633

634 llvm::yaml::Node *DocumentRoot = FirstInvocationFile->getRoot();

635 if (!DocumentRoot)

636 return llvm::make_error(

638

639

640

641

642 auto *Mappings = dyn_castllvm::yaml::MappingNode(DocumentRoot);

643 if (!Mappings)

644 return llvm::make_error(

646

647 for (auto &NextMapping : *Mappings) {

648

649 auto *Key = dyn_castllvm::yaml::ScalarNode(NextMapping.getKey());

650 if (!Key)

651 return llvm::make_error(

653

655 StringRef SourcePath = Key->getValue(ValueStorage);

656

657

659 llvm::sys::path::native(NativeSourcePath, PathStyle);

660

661 StringRef InvocationKey = NativeSourcePath;

662

663 if (InvocationList.contains(InvocationKey))

664 return llvm::make_error(

666

667

668

669 auto *Args = dyn_castllvm::yaml::SequenceNode(NextMapping.getValue());

670 if (!Args)

671 return llvm::make_error(

673

674 for (auto &Arg : *Args) {

675 auto *CmdString = dyn_castllvm::yaml::ScalarNode(&Arg);

676 if (!CmdString)

677 return llvm::make_error(

679

680

681 ValueStorage.clear();

682 InvocationList[InvocationKey].emplace_back(

683 CmdString->getValue(ValueStorage));

684 }

685

686 if (InvocationList[InvocationKey].empty())

687 return llvm::make_error(

689 }

690

691 return InvocationList;

692}

693

694llvm::Error CrossTranslationUnitContext::ASTLoader::lazyInitInvocationList() {

695

696 if (InvocationList)

697 return llvm::Error::success();

699 return llvm::make_error(PreviousParsingResult);

700

701 llvm::ErrorOr<std::unique_ptrllvm::MemoryBuffer> FileContent =

702 llvm::MemoryBuffer::getFile(InvocationListFilePath);

703 if (!FileContent) {

705 return llvm::make_error(PreviousParsingResult);

706 }

707 std::unique_ptrllvm::MemoryBuffer ContentBuffer = std::move(*FileContent);

708 assert(ContentBuffer && "If no error was produced after loading, the pointer "

709 "should not be nullptr.");

710

713

714

715 if (!ExpectedInvocationList) {

716 llvm::handleAllErrors(

717 ExpectedInvocationList.takeError(),

718 [&](const IndexError &E) { PreviousParsingResult = E.getCode(); });

719 return llvm::make_error(PreviousParsingResult);

720 }

721

722 InvocationList = *ExpectedInvocationList;

723

724 return llvm::Error::success();

725}

726

727template

729CrossTranslationUnitContext::importDefinitionImpl(const T *D, ASTUnit *Unit) {

730 assert(hasBodyOrInit(D) && "Decls to be imported should have body or init.");

731

732 assert(&D->getASTContext() == &Unit->getASTContext() &&

733 "ASTContext of Decl and the unit should match.");

734 ASTImporter &Importer = getOrCreateASTImporter(Unit);

735

736 auto ToDeclOrError = Importer.Import(D);

737 if (!ToDeclOrError) {

738 handleAllErrors(ToDeclOrError.takeError(), [&](const ASTImportError &IE) {

739 switch (IE.Error) {

740 case ASTImportError::NameConflict:

741 ++NumNameConflicts;

742 break;

743 case ASTImportError::UnsupportedConstruct:

744 ++NumUnsupportedNodeFound;

745 break;

746 case ASTImportError::Unknown:

747 llvm_unreachable("Unknown import error happened.");

748 break;

749 }

750 });

752 }

753 auto *ToDecl = cast(*ToDeclOrError);

754 assert(hasBodyOrInit(ToDecl) && "Imported Decl should have body or init.");

755 ++NumGetCTUSuccess;

756

757

758 ToDecl->getASTContext().getParentMapContext().clear();

759

760 return ToDecl;

761}

762

764CrossTranslationUnitContext::importDefinition(const FunctionDecl *FD,

766 return importDefinitionImpl(FD, Unit);

767}

768

770CrossTranslationUnitContext::importDefinition(const VarDecl *VD,

772 return importDefinitionImpl(VD, Unit);

773}

774

775void CrossTranslationUnitContext::lazyInitImporterSharedSt(

777 if (!ImporterSharedSt)

778 ImporterSharedSt = std::make_shared(*ToTU);

779}

780

782CrossTranslationUnitContext::getOrCreateASTImporter(ASTUnit *Unit) {

784

786 if (I != ASTUnitImporterMap.end())

787 return *I->second;

793 return *NewImporter;

794}

795

796std::optionalclang::MacroExpansionContext

797CrossTranslationUnitContext::getMacroExpansionContextForSourceLocation(

799

800 return std::nullopt;

801}

802

803bool CrossTranslationUnitContext::isImportedAsNew(const Decl *ToDecl) const {

804 if (!ImporterSharedSt)

805 return false;

806 return ImporterSharedSt->isNewDecl(const_cast<Decl *>(ToDecl));

807}

808

809bool CrossTranslationUnitContext::hasError(const Decl *ToDecl) const {

810 if (!ImporterSharedSt)

811 return false;

812 return static_cast<bool>(

813 ImporterSharedSt->getImportDeclErrorIfAny(const_cast<Decl *>(ToDecl)));

814}

815

816}

817}

STATISTIC(NumObjCCallEdges, "Number of Objective-C method call edges")

Holds long-lived AST nodes (such as types and decls) that can be referred to throughout the semantic ...

SourceManager & getSourceManager()

TranslationUnitDecl * getTranslationUnitDecl() const

CanQualType getCanonicalType(QualType T) const

Return the canonical (structural) type corresponding to the specified potentially non-canonical type ...

const LangOptions & getLangOpts() const

DiagnosticsEngine & getDiagnostics() const

const TargetInfo & getTargetInfo() const

Imports selected nodes from one AST context into another context, merging AST nodes where appropriate...

Utility class for loading a ASTContext from an AST file.

static std::unique_ptr< ASTUnit > LoadFromCommandLine(const char **ArgBegin, const char **ArgEnd, std::shared_ptr< PCHContainerOperations > PCHContainerOps, IntrusiveRefCntPtr< DiagnosticsEngine > Diags, StringRef ResourceFilesPath, bool StorePreamblesInMemory=false, StringRef PreambleStoragePath=StringRef(), bool OnlyLocalDecls=false, CaptureDiagsKind CaptureDiagnostics=CaptureDiagsKind::None, ArrayRef< RemappedFile > RemappedFiles={}, bool RemappedFilesKeepOriginalName=true, unsigned PrecompilePreambleAfterNParses=0, TranslationUnitKind TUKind=TU_Complete, bool CacheCodeCompletionResults=false, bool IncludeBriefCommentsInCodeCompletion=false, bool AllowPCHWithCompilerErrors=false, SkipFunctionBodiesScope SkipFunctionBodies=SkipFunctionBodiesScope::None, bool SingleFileParse=false, bool UserFilesAreVolatile=false, bool ForSerialization=false, bool RetainExcludedConditionalBlocks=false, std::optional< StringRef > ModuleFormat=std::nullopt, std::unique_ptr< ASTUnit > *ErrAST=nullptr, IntrusiveRefCntPtr< llvm::vfs::FileSystem > VFS=nullptr)

LoadFromCommandLine - Create an ASTUnit from a vector of command line arguments, which must specify e...

@ LoadEverything

Load everything, including Sema.

static std::unique_ptr< ASTUnit > LoadFromASTFile(StringRef Filename, const PCHContainerReader &PCHContainerRdr, WhatToLoad ToLoad, IntrusiveRefCntPtr< DiagnosticsEngine > Diags, const FileSystemOptions &FileSystemOpts, std::shared_ptr< HeaderSearchOptions > HSOpts, std::shared_ptr< LangOptions > LangOpts=nullptr, bool OnlyLocalDecls=false, CaptureDiagsKind CaptureDiagnostics=CaptureDiagsKind::None, bool AllowASTWithCompilerErrors=false, bool UserFilesAreVolatile=false, IntrusiveRefCntPtr< llvm::vfs::FileSystem > VFS=llvm::vfs::getRealFileSystem())

Create a ASTUnit from an AST file.

const ASTContext & getASTContext() const

bool isConstQualified() const

CompilerInstance - Helper class for managing a single instance of the Clang compiler.

DeclContext - This is used only as base class of specific decl types that can act as declaration cont...

decl_range decls() const

decls_begin/decls_end - Iterate over the declarations stored in this context.

Decl - This represents one declaration (or definition), e.g.

DiagnosticBuilder Report(SourceLocation Loc, unsigned DiagID)

Issue the message to the client.

Represents a function declaration or definition.

This represents a decl that may have a name.

bool isTrivialType(const ASTContext &Context) const

Return true if this is a trivial type per (C++0x [basic.types]p9)

Encodes a location in the source.

FileManager & getFileManager() const

const llvm::Triple & getTriple() const

Returns the target triple of the primary target.

The top declaration context.

Represents a variable declaration or definition.

void emitCrossTUDiagnostics(const IndexError &IE)

Emit diagnostics for the user for potential configuration errors.

llvm::Expected< const FunctionDecl * > getCrossTUDefinition(const FunctionDecl *FD, StringRef CrossTUDir, StringRef IndexName, bool DisplayCTUProgress=false)

This function loads a function or variable definition from an external AST file and merges it into th...

llvm::Expected< const FunctionDecl * > importDefinition(const FunctionDecl *FD, ASTUnit *Unit)

This function merges a definition from a separate AST Unit into the current one which was created by ...

CrossTranslationUnitContext(CompilerInstance &CI)

static std::optional< std::string > getLookupName(const NamedDecl *ND)

Get a name to identify a named decl.

~CrossTranslationUnitContext()

llvm::Expected< ASTUnit * > loadExternalAST(StringRef LookupName, StringRef CrossTUDir, StringRef IndexName, bool DisplayCTUProgress=false)

This function loads a definition from an external AST file.

index_error_code getCode() const

std::string getTripleToName() const

std::error_code convertToErrorCode() const override

void log(raw_ostream &OS) const override

std::string getTripleFromName() const

std::string getFileName() const

Defines the clang::TargetInfo interface.

bool shouldImport(const VarDecl *VD, const ASTContext &ACtx)

Returns true if it makes sense to import a foreign variable definition.

llvm::StringMap< llvm::SmallVector< std::string, 32 > > InvocationListTy

llvm::Expected< llvm::StringMap< std::string > > parseCrossTUIndex(StringRef IndexPath)

This function parses an index file that determines which translation unit contains which definition.

std::string createCrossTUIndexString(const llvm::StringMap< std::string > &Index)

llvm::Expected< InvocationListTy > parseInvocationList(StringRef FileContent, llvm::sys::path::Style PathStyle=llvm::sys::path::Style::posix)

Parse the YAML formatted invocation list file content FileContent.

static bool hasBodyOrInit(const FunctionDecl *D, const FunctionDecl *&DefD)

@ invocation_list_wrong_format

@ invocation_list_file_not_found

@ invocation_list_lookup_unsuccessful

@ failed_to_get_external_ast

@ invocation_list_ambiguous

static bool parseCrossTUIndexItem(StringRef LineRef, StringRef &LookupName, StringRef &FilePath)

Parse one line of the input CTU index file.

bool generateUSRForDecl(const Decl *D, SmallVectorImpl< char > &Buf)

Generate a USR for a Decl, including the USR prefix.

RangeSelector name(std::string ID)

Given a node with a "name", (like NamedDecl, DeclRefExpr, CxxCtorInitializer, and TypeLoc) selects th...

The JSON file list parser is used to communicate input to InstallAPI.

@ Result

The result type of a method or function.

const FunctionProtoType * T