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

1

2

3

4

5

6

7

8

9

10

11

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

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

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

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

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

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

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

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

32#include

33#include

34#include

35#include

36#include

37

40

41namespace {

42

43#define DEBUG_TYPE "CrossTranslationUnit"

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

46 NumNotInOtherTU,

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

49 "The # of getCTUDefinition successfully returned the "

50 "requested function's body");

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

52 "encountered an unsupported AST Node");

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

54 "encountered an ODR error");

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

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

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

58STATISTIC(NumASTLoadThresholdReached,

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

60

61

62

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

64 using llvm::Triple;

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

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

67 return false;

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

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

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

71 return false;

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

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

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

75 return false;

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

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

78 return false;

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

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

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

82 return false;

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

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

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

86 return false;

87 return true;

88}

89

90

91class IndexErrorCategory : public std::error_category {

92public:

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

94

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

98

99

100 break;

102 return "An unknown error has occurred.";

104 return "The index file is missing.";

106 return "Invalid index file format.";

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

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

112 return "Failed to import the definition.";

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

116 return "Failed to generate USR.";

118 return "Triple mismatch";

120 return "Language mismatch";

122 return "Language dialect mismatch";

124 return "Load threshold reached";

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

127 "source file.";

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

131 return "Invocation list file is empty.";

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

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

136 }

137 llvm_unreachable("Unrecognized index_error_code.");

138 }

139};

140

141static llvm::ManagedStatic Category;

142}

143

145

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

148}

149

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

152}

153

154

155

156

157

158

159

161 StringRef &FilePath) {

162

163

164 size_t USRLength = 0;

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

166 return false;

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

168

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

170 return false;

171

172

173

174

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

176 return false;

177

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

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

180 return true;

181}

182

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

186 if (!ExternalMapFile)

188 IndexPath.str());

189

190 llvm::StringMapstd::string Result;

191 std::string Line;

192 unsigned LineNo = 1;

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

194

195 StringRef LookupName, FilePathInIndex;

197 return llvm::make_error(

199

200

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

203

204 bool InsertionOccured;

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

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

207 if (!InsertionOccured)

208 return llvm::make_error(

210

211 ++LineNo;

212 }

214}

215

216std::string

218 std::ostringstream Result;

219 for (const auto &E : Index)

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

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

223}

224

229

240

242 : Context(CI.getASTContext()), ASTStorage(CI) {

245 auto S = CI.getVirtualFileSystem().status(CI.getAnalyzerOpts().CTUDir);

246 if (!S || S->getType() != llvm::sys::fs::file_type::directory_file)

247 CI.getDiagnostics().Report(diag::err_analyzer_config_invalid_input)

248 << "ctu-dir"

249 << "a filename";

250 }

251}

252

254

255std::optionalstd::string

259 if (Ret)

260 return {};

261 return std::string(DeclUSR);

262}

263

264

265

266template

267const T *

268CrossTranslationUnitContext::findDefInDeclContext(const DeclContext *DC,

269 StringRef LookupName) {

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

271 for (const Decl *D : DC->decls()) {

272 const auto *SubDC = dyn_cast(D);

273 if (SubDC)

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

275 return ND;

276

277 const auto *ND = dyn_cast(D);

278 const T *ResultDecl;

280 continue;

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

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

283 continue;

284 return ResultDecl;

285 }

286 return nullptr;

287}

288

289template

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

292 bool DisplayCTUProgress) {

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

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

296 ++NumGetCTUCalled;

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

298 if (!LookupName)

299 return llvm::make_error(

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

303 if (!ASTUnitOrError)

304 return ASTUnitOrError.takeError();

305 ASTUnit *Unit = *ASTUnitOrError;

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

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

308

309 const llvm::Triple &TripleTo = Context.getTargetInfo().getTriple();

310 const llvm::Triple &TripleFrom =

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

312

313

314

315

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

317

318

319 ++NumTripleMismatch;

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

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

323 }

324

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

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

327

328

329

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

331 ++NumLangMismatch;

333 }

334

335

336

337

338

339

340

341

342

343

344

345

346

347

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

349 LangTo.CPlusPlus14 != LangFrom.CPlusPlus14 ||

350 LangTo.CPlusPlus17 != LangFrom.CPlusPlus17 ||

351 LangTo.CPlusPlus20 != LangFrom.CPlusPlus20) {

352 ++NumLangDialectMismatch;

353 return llvm::make_error(

355 }

356

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

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

361}

362

363llvm::Expected<const FunctionDecl *>

365 StringRef CrossTUDir,

366 StringRef IndexName,

367 bool DisplayCTUProgress) {

368 return getCrossTUDefinitionImpl(FD, CrossTUDir, IndexName,

369 DisplayCTUProgress);

370}

371

374 StringRef CrossTUDir,

375 StringRef IndexName,

376 bool DisplayCTUProgress) {

377 return getCrossTUDefinitionImpl(VD, CrossTUDir, IndexName,

378 DisplayCTUProgress);

379}

380

384 Context.getDiagnostics().Report(diag::err_ctu_error_opening)

386 break;

388 Context.getDiagnostics().Report(diag::err_extdefmap_parsing)

390 break;

392 Context.getDiagnostics().Report(diag::err_multiple_def_index)

394 break;

396 Context.getDiagnostics().Report(diag::warn_ctu_incompat_triple)

398 break;

399 default:

400 break;

401 }

402}

403

404CrossTranslationUnitContext::ASTUnitStorage::ASTUnitStorage(

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

407 CI.getAnalyzerOpts().CTUInvocationList),

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

409 ? CI.getAnalyzerOpts().CTUImportCppThreshold

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

411

413CrossTranslationUnitContext::ASTUnitStorage::getASTUnitForFile(

414 StringRef FileName, bool DisplayCTUProgress) {

415

416 auto ASTCacheEntry = FileASTUnitMap.find(FileName);

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

418

419

420 if (!LoadGuard) {

421 ++NumASTLoadThresholdReached;

422 return llvm::make_error(

424 }

425

426 auto LoadAttempt = Loader.load(FileName);

427

428 if (!LoadAttempt)

429 return LoadAttempt.takeError();

430

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

432

433

434 ASTUnit *Unit = LoadedUnit.get();

435

436

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

438

439 LoadGuard.indicateLoadSuccess();

440

441 if (DisplayCTUProgress)

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

443

444 return Unit;

445

446 } else {

447

448 return ASTCacheEntry->second.get();

449 }

450}

451

452llvm::Expected<ASTUnit *>

453CrossTranslationUnitContext::ASTUnitStorage::getASTUnitForFunction(

454 StringRef FunctionName, StringRef CrossTUDir, StringRef IndexName,

455 bool DisplayCTUProgress) {

456

457 auto ASTCacheEntry = NameASTUnitMap.find(FunctionName);

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

459

460

461

462 if (llvm::Error IndexLoadError =

463 ensureCTUIndexLoaded(CrossTUDir, IndexName))

464 return std::move(IndexLoadError);

465

466

467 auto It = NameFileMap.find(FunctionName);

468 if (It == NameFileMap.end()) {

469 ++NumNotInOtherTU;

471 }

472

473

474

475 if (llvm::Expected<ASTUnit *> FoundForFile =

476 getASTUnitForFile(It->second, DisplayCTUProgress)) {

477

478

479 NameASTUnitMap[FunctionName] = *FoundForFile;

480 return *FoundForFile;

481

482 } else {

483 return FoundForFile.takeError();

484 }

485 } else {

486

487 return ASTCacheEntry->second;

488 }

489}

490

491llvm::Expectedstd::string

492CrossTranslationUnitContext::ASTUnitStorage::getFileForFunction(

493 StringRef FunctionName, StringRef CrossTUDir, StringRef IndexName) {

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

495 return std::move(IndexLoadError);

496 return NameFileMap[FunctionName];

497}

498

499llvm::Error CrossTranslationUnitContext::ASTUnitStorage::ensureCTUIndexLoaded(

500 StringRef CrossTUDir, StringRef IndexName) {

501

502 if (!NameFileMap.empty())

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

504

505

506 SmallString<256> IndexFile = CrossTUDir;

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

508 IndexFile = IndexName;

509 else

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

511

513

514 NameFileMap = *IndexMapping;

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

516 } else {

517

518 return IndexMapping.takeError();

519 };

520}

521

523 StringRef LookupName, StringRef CrossTUDir, StringRef IndexName,

524 bool DisplayCTUProgress) {

525

526

527

528

529

530

532 LookupName, CrossTUDir, IndexName, DisplayCTUProgress);

533

534 if (!Unit)

535 return Unit.takeError();

536

537

538 if (!*Unit)

539 return llvm::make_error(

541

542 return Unit;

543}

544

545CrossTranslationUnitContext::ASTLoader::ASTLoader(

546 CompilerInstance &CI, StringRef CTUDir, StringRef InvocationListFilePath)

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

548

549CrossTranslationUnitContext::LoadResultTy

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

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

553 Path = Identifier;

554 } else {

555 Path = CTUDir;

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

557 }

558

559

560

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

562

563

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

565

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

567 return loadFromDump(Path);

568 else

569 return loadFromSource(Path);

570}

571

572CrossTranslationUnitContext::LoadResultTy

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

574 auto DiagOpts = std::make_shared();

575 TextDiagnosticPrinter *DiagClient =

576 new TextDiagnosticPrinter(llvm::errs(), *DiagOpts);

577 auto Diags = llvm::makeIntrusiveRefCnt(

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

582 CI.getFileSystemOpts(), CI.getHeaderSearchOpts());

583}

584

585

586

587

588

589

590

591

592

593

594

595

596CrossTranslationUnitContext::LoadResultTy

597CrossTranslationUnitContext::ASTLoader::loadFromSource(

598 StringRef SourceFilePath) {

599

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

601 return std::move(InitError);

602 assert(InvocationList);

603

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

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

606 return llvm::make_error(

608

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

610

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

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

613 CommandLineArgs.begin(),

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

615

616 auto DiagOpts = std::make_shared(CI.getDiagnosticOpts());

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

618 IntrusiveRefCntPtr DiagID{

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

620 auto Diags = llvm::makeIntrusiveRefCnt(DiagID, *DiagOpts,

621 DiagClient);

622

624 CommandLineArgs.begin(), (CommandLineArgs.end()),

625 CI.getPCHContainerOperations(), DiagOpts, Diags,

626 CI.getHeaderSearchOpts().ResourceDir);

627}

628

629llvm::Expected

632

633

634 llvm::SourceMgr SM;

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

636

637

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

639

640

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

642 return llvm::make_error(

644

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

646 if (!DocumentRoot)

647 return llvm::make_error(

649

650

651

652

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

654 if (!Mappings)

655 return llvm::make_error(

657

658 for (auto &NextMapping : *Mappings) {

659

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

661 if (!Key)

662 return llvm::make_error(

664

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

667

668

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

671

672 StringRef InvocationKey = NativeSourcePath;

673

674 if (InvocationList.contains(InvocationKey))

675 return llvm::make_error(

677

678

679

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

681 if (!Args)

682 return llvm::make_error(

684

685 for (auto &Arg : *Args) {

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

687 if (!CmdString)

688 return llvm::make_error(

690

691

692 ValueStorage.clear();

693 InvocationList[InvocationKey].emplace_back(

694 CmdString->getValue(ValueStorage));

695 }

696

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

698 return llvm::make_error(

700 }

701

702 return InvocationList;

703}

704

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

706

707 if (InvocationList)

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

710 return llvm::make_error(PreviousParsingResult);

711

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

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

714 if (!FileContent) {

716 return llvm::make_error(PreviousParsingResult);

717 }

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

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

720 "should not be nullptr.");

721

724

725

726 if (!ExpectedInvocationList) {

727 llvm::handleAllErrors(

728 ExpectedInvocationList.takeError(),

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

730 return llvm::make_error(PreviousParsingResult);

731 }

732

733 InvocationList = *ExpectedInvocationList;

734

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

736}

737

738template

739llvm::Expected<const T *>

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

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

742

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

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

745 ASTImporter &Importer = getOrCreateASTImporter(Unit);

746

747 auto ToDeclOrError = Importer.Import(D);

748 if (!ToDeclOrError) {

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

750 switch (IE.Error) {

751 case ASTImportError::NameConflict:

752 ++NumNameConflicts;

753 break;

754 case ASTImportError::UnsupportedConstruct:

755 ++NumUnsupportedNodeFound;

756 break;

757 case ASTImportError::Unknown:

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

759 break;

760 }

761 });

763 }

764 auto *ToDecl = cast(*ToDeclOrError);

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

766 ++NumGetCTUSuccess;

767

768

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

770

771 return ToDecl;

772}

773

774llvm::Expected<const FunctionDecl *>

777 return importDefinitionImpl(FD, Unit);

778}

779

783 return importDefinitionImpl(VD, Unit);

784}

785

786void CrossTranslationUnitContext::lazyInitImporterSharedSt(

788 if (!ImporterSharedSt)

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

790}

791

793CrossTranslationUnitContext::getOrCreateASTImporter(ASTUnit *Unit) {

795

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

798 return *I->second;

799 lazyInitImporterSharedSt(Context.getTranslationUnitDecl());

801 Context, Context.getSourceManager().getFileManager(), From,

804 return *NewImporter;

805}

806

807std::optionalclang::MacroExpansionContext

810

811 return std::nullopt;

812}

813

815 if (!ImporterSharedSt)

816 return false;

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

818}

819

821 if (!ImporterSharedSt)

822 return false;

823 return static_cast<bool>(

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

825}

826

827}

828}

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

static CanQualType getCanonicalType(QualType T)

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

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 > LoadFromASTFile(StringRef Filename, const PCHContainerReader &PCHContainerRdr, WhatToLoad ToLoad, IntrusiveRefCntPtr< llvm::vfs::FileSystem > VFS, std::shared_ptr< DiagnosticOptions > DiagOpts, IntrusiveRefCntPtr< DiagnosticsEngine > Diags, const FileSystemOptions &FileSystemOpts, const HeaderSearchOptions &HSOpts, const LangOptions *LangOpts=nullptr, bool OnlyLocalDecls=false, CaptureDiagsKind CaptureDiagnostics=CaptureDiagsKind::None, bool AllowASTWithCompilerErrors=false, bool UserFilesAreVolatile=false)

Create a ASTUnit from an AST file.

@ LoadEverything

Load everything, including Sema.

const ASTContext & getASTContext() const

unsigned ShouldEmitErrorsOnInvalidConfigValue

bool isConstQualified() const

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

AnalyzerOptions & getAnalyzerOpts()

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.

static llvm::IntrusiveRefCntPtr< DiagnosticIDs > create()

Represents a function declaration or definition.

bool hasBody(const FunctionDecl *&Definition) const

Returns true if the function has a body.

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

The top declaration context.

Represents a variable declaration or definition.

const Expr * getAnyInitializer() const

Get the initializer for this variable, no matter which declaration it is attached to.

void emitCrossTUDiagnostics(const IndexError &IE)

Emit diagnostics for the user for potential configuration errors.

Definition CrossTranslationUnit.cpp:381

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...

Definition CrossTranslationUnit.cpp:364

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 ...

Definition CrossTranslationUnit.cpp:775

CrossTranslationUnitContext(CompilerInstance &CI)

Definition CrossTranslationUnit.cpp:241

static std::optional< std::string > getLookupName(const Decl *D)

Get a name to identify a decl.

Definition CrossTranslationUnit.cpp:256

std::optional< clang::MacroExpansionContext > getMacroExpansionContextForSourceLocation(const clang::SourceLocation &ToLoc) const

Returns the MacroExpansionContext for the imported TU to which the given source-location corresponds.

Definition CrossTranslationUnit.cpp:808

bool hasError(const Decl *ToDecl) const

Returns true if the given Decl is mapped (or created) during an import but there was an unrecoverable...

Definition CrossTranslationUnit.cpp:820

bool isImportedAsNew(const Decl *ToDecl) const

Returns true if the given Decl is newly created during the import.

Definition CrossTranslationUnit.cpp:814

~CrossTranslationUnitContext()

Definition CrossTranslationUnit.cpp:253

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

This function loads a definition from an external AST file.

Definition CrossTranslationUnit.cpp:522

index_error_code getCode() const

std::string getTripleToName() const

std::error_code convertToErrorCode() const override

Definition CrossTranslationUnit.cpp:150

void log(raw_ostream &OS) const override

Definition CrossTranslationUnit.cpp:146

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.

Definition CrossTranslationUnit.cpp:225

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

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

Definition CrossTranslationUnit.cpp:184

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

Definition CrossTranslationUnit.cpp:217

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.

Definition CrossTranslationUnit.cpp:630

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

Definition CrossTranslationUnit.cpp:230

@ 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.

Definition CrossTranslationUnit.cpp:160

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

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.

CanQual< Type > CanQualType

Represents a canonical, potentially-qualified type.

std::unique_ptr< ASTUnit > CreateASTUnitFromCommandLine(const char **ArgBegin, const char **ArgEnd, std::shared_ptr< PCHContainerOperations > PCHContainerOps, std::shared_ptr< DiagnosticOptions > DiagOpts, IntrusiveRefCntPtr< DiagnosticsEngine > Diags, StringRef ResourceFilesPath, bool StorePreamblesInMemory=false, StringRef PreambleStoragePath=StringRef(), bool OnlyLocalDecls=false, CaptureDiagsKind CaptureDiagnostics=CaptureDiagsKind::None, ArrayRef< ASTUnit::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)

Create an ASTUnit from a vector of command line arguments, which must specify exactly one source file...

@ Result

The result type of a method or function.

const FunctionProtoType * T

U cast(CodeGen::Address addr)