CXString clang_getDeclObjCTypeEncoding(CXCursor C) { if (!clang_isDeclaration(C.kind)) return cxstring::createCXString(""); const Decl *D = static_cast<const Decl*>(C.data[0]); ASTUnit *AU = cxcursor::getCursorASTUnit(C); ASTContext &Ctx = AU->getASTContext(); std::string encoding; if (const ObjCMethodDecl *OMD = dyn_cast<ObjCMethodDecl>(D)) { if (Ctx.getObjCEncodingForMethodDecl(OMD, encoding)) return cxstring::createCXString("?"); } else if (const ObjCPropertyDecl *OPD = dyn_cast<ObjCPropertyDecl>(D)) Ctx.getObjCEncodingForPropertyDecl(OPD, NULL, encoding); else if (const FunctionDecl *FD = dyn_cast<FunctionDecl>(D)) Ctx.getObjCEncodingForFunctionDecl(FD, encoding); else { QualType Ty; if (const TypeDecl *TD = dyn_cast<TypeDecl>(D)) Ty = Ctx.getTypeDeclType(TD); if (const ValueDecl *VD = dyn_cast<ValueDecl>(D)) Ty = VD->getType(); else return cxstring::createCXString("?"); Ctx.getObjCEncodingForType(Ty, encoding); } return cxstring::createCXString(encoding); }
static bool findMacroRefsInFile(CXTranslationUnit TU, CXCursor Cursor, const FileEntry *File, CXCursorAndRangeVisitor Visitor) { if (Cursor.kind != CXCursor_MacroDefinition && Cursor.kind != CXCursor_MacroExpansion) return false; ASTUnit *Unit = cxtu::getASTUnit(TU); SourceManager &SM = Unit->getSourceManager(); FileID FID = SM.translateFile(File); const IdentifierInfo *Macro = 0; if (Cursor.kind == CXCursor_MacroDefinition) Macro = getCursorMacroDefinition(Cursor)->getName(); else Macro = getCursorMacroExpansion(Cursor).getName(); if (!Macro) return false; FindFileMacroRefVisitData data(*Unit, File, Macro, Visitor); SourceRange Range(SM.getLocForStartOfFile(FID), SM.getLocForEndOfFile(FID)); CursorVisitor FindMacroRefsVisitor(TU, findFileMacroRefVisit, &data, /*VisitPreprocessorLast=*/false, /*VisitIncludedEntities=*/false, Range); return FindMacroRefsVisitor.visitPreprocessedEntitiesInRegion(); }
ASTContext& CursorHelper::getASTContext(CXCursor node) { ASTUnit *astUnit = static_cast<ASTUnit *>( static_cast<CXTranslationUnit>(node.data[2])->TUData); return astUnit->getASTContext(); }
CXSourceLocation clang_getLocation(CXTranslationUnit TU, CXFile file, unsigned line, unsigned column) { if (cxtu::isNotUsableTU(TU)) { LOG_BAD_TU(TU); return clang_getNullLocation(); } if (!file) return clang_getNullLocation(); if (line == 0 || column == 0) return clang_getNullLocation(); LogRef Log = Logger::make(__func__); ASTUnit *CXXUnit = cxtu::getASTUnit(TU); ASTUnit::ConcurrencyCheck Check(*CXXUnit); const FileEntry *File = static_cast<const FileEntry *>(file); SourceLocation SLoc = CXXUnit->getLocation(File, line, column); if (SLoc.isInvalid()) { if (Log) *Log << llvm::format("(\"%s\", %d, %d) = invalid", File->getName().str().c_str(), line, column); return clang_getNullLocation(); } CXSourceLocation CXLoc = cxloc::translateSourceLocation(CXXUnit->getASTContext(), SLoc); if (Log) *Log << llvm::format("(\"%s\", %d, %d) = ", File->getName().str().c_str(), line, column) << CXLoc; return CXLoc; }
CXCompletionString clang_getCursorCompletionString(CXCursor cursor) { enum CXCursorKind kind = clang_getCursorKind(cursor); if (clang_isDeclaration(kind)) { const Decl *decl = getCursorDecl(cursor); if (const NamedDecl *namedDecl = dyn_cast_or_null<NamedDecl>(decl)) { ASTUnit *unit = getCursorASTUnit(cursor); CodeCompletionResult Result(namedDecl, CCP_Declaration); CodeCompletionString *String = Result.CreateCodeCompletionString(unit->getASTContext(), unit->getPreprocessor(), unit->getCodeCompletionTUInfo().getAllocator(), unit->getCodeCompletionTUInfo(), true); return String; } } else if (kind == CXCursor_MacroDefinition) { const MacroDefinition *definition = getCursorMacroDefinition(cursor); const IdentifierInfo *MacroInfo = definition->getName(); ASTUnit *unit = getCursorASTUnit(cursor); CodeCompletionResult Result(MacroInfo); CodeCompletionString *String = Result.CreateCodeCompletionString(unit->getASTContext(), unit->getPreprocessor(), unit->getCodeCompletionTUInfo().getAllocator(), unit->getCodeCompletionTUInfo(), false); return String; } return NULL; }
CXSourceLocation lfort_getLocation(CXProgram tu, CXFile file, unsigned line, unsigned column) { if (!tu || !file) return lfort_getNullLocation(); bool Logging = ::getenv("LIBLFORT_LOGGING"); ASTUnit *CXXUnit = static_cast<ASTUnit *>(tu->PgmData); ASTUnit::ConcurrencyCheck Check(*CXXUnit); const FileEntry *File = static_cast<const FileEntry *>(file); SourceLocation SLoc = CXXUnit->getLocation(File, line, column); if (SLoc.isInvalid()) { if (Logging) llvm::errs() << "lfort_getLocation(\"" << File->getName() << "\", " << line << ", " << column << ") = invalid\n"; return lfort_getNullLocation(); } if (Logging) llvm::errs() << "lfort_getLocation(\"" << File->getName() << "\", " << line << ", " << column << ") = " << SLoc.getRawEncoding() << "\n"; return cxloc::translateSourceLocation(CXXUnit->getASTContext(), SLoc); }
std::vector<ASTMemoryUsage> TranslationUnitManager::GetMemoryUsageForProjectFile(ProjectFile* file) { ASTUnit* tu = GetASTUnitForProjectFile(file); std::vector<ASTMemoryUsage> usages; if (tu) { //AST Context ASTContext& ctx = tu->getASTContext(); usages.emplace_back(AST_Nodes, ctx.getASTAllocatedMemory()); usages.emplace_back(AST_Identifiers, ctx.Idents.getAllocator().getTotalMemory()); usages.emplace_back(AST_Selectors, ctx.Selectors.getTotalMemory()); usages.emplace_back(AST_SideTables, ctx.getSideTableAllocatedMemory()); //Source Manager usages.emplace_back(SM_ContentCache, ctx.getSourceManager().getContentCacheSize()); const SourceManager::MemoryBufferSizes& srcBufs = tu->getSourceManager().getMemoryBufferSizes(); usages.emplace_back(SM_Malloc, srcBufs.malloc_bytes); usages.emplace_back(SM_Mmap, srcBufs.mmap_bytes); usages.emplace_back(SM_DataStructures, tu->getSourceManager().getDataStructureSizes()); // Preprocessor Preprocessor& PP = tu->getPreprocessor(); usages.emplace_back(PP_Total, PP.getTotalMemory()); usages.emplace_back(PP_HeaderSearch, PP.getHeaderSearchInfo().getTotalMemory()); if (PP.getPreprocessorOpts().DetailedRecord) usages.emplace_back(ASTMemoryUsage(PP_PreprocessingRecord, PP.getPreprocessingRecord()->getTotalMemory())); } return usages; }
static void indexPreprocessingRecord(ASTUnit &Unit, IndexingContext &IdxCtx) { Preprocessor &PP = Unit.getPreprocessor(); if (!PP.getPreprocessingRecord()) return; // FIXME: Only deserialize inclusion directives. PreprocessingRecord::iterator I, E; std::tie(I, E) = Unit.getLocalPreprocessingEntities(); bool isModuleFile = Unit.isModuleFile(); for (; I != E; ++I) { PreprocessedEntity *PPE = *I; if (InclusionDirective *ID = dyn_cast<InclusionDirective>(PPE)) { SourceLocation Loc = ID->getSourceRange().getBegin(); // Modules have synthetic main files as input, give an invalid location // if the location points to such a file. if (isModuleFile && Unit.isInMainFileID(Loc)) Loc = SourceLocation(); IdxCtx.ppIncludedFile(Loc, ID->getFileName(), ID->getFile(), ID->getKind() == InclusionDirective::Import, !ID->wasInQuotes(), ID->importedModule()); } } }
CXString clang_getDeclObjCTypeEncoding(CXCursor C) { if ((C.kind < CXCursor_FirstDecl) || (C.kind > CXCursor_LastDecl)) return cxstring::createCXString(""); Decl *D = static_cast<Decl*>(C.data[0]); CXTranslationUnit TU = static_cast<CXTranslationUnit>(C.data[2]); ASTUnit *AU = static_cast<ASTUnit*>(TU->TUData); ASTContext &Ctx = AU->getASTContext(); std::string encoding; if (ObjCMethodDecl *OMD = dyn_cast<ObjCMethodDecl>(D)) { if (Ctx.getObjCEncodingForMethodDecl(OMD, encoding)) return cxstring::createCXString("?"); } else if (ObjCPropertyDecl *OPD = dyn_cast<ObjCPropertyDecl>(D)) Ctx.getObjCEncodingForPropertyDecl(OPD, NULL, encoding); else if (FunctionDecl *FD = dyn_cast<FunctionDecl>(D)) Ctx.getObjCEncodingForFunctionDecl(FD, encoding); else { QualType Ty; if (TypeDecl *TD = dyn_cast<TypeDecl>(D)) Ty = Ctx.getTypeDeclType(TD); if (ValueDecl *VD = dyn_cast<ValueDecl>(D)) Ty = VD->getType(); else return cxstring::createCXString("?"); Ctx.getObjCEncodingForType(Ty, encoding); } return cxstring::createCXString(encoding); }
SourceRange cxcursor::getCursorPreprocessingDirective(CXCursor C) { assert(C.kind == CXCursor_PreprocessingDirective); SourceRange Range(SourceLocation::getFromPtrEncoding(C.data[0]), SourceLocation::getFromPtrEncoding(C.data[1])); ASTUnit *TU = getCursorASTUnit(C); return TU->mapRangeFromPreamble(Range); }
static void indexTranslationUnit(ASTUnit &Unit, IndexingContext &IdxCtx) { // FIXME: Only deserialize stuff from the last chained PCH, not the PCH/Module // that it depends on. bool OnlyLocal = !Unit.isMainFileAST() && Unit.getOnlyLocalDecls(); if (OnlyLocal) { for (ASTUnit::top_level_iterator TL = Unit.top_level_begin(), TLEnd = Unit.top_level_end(); TL != TLEnd; ++TL) { IdxCtx.indexTopLevelDecl(*TL); if (IdxCtx.shouldAbort()) return; } } else { TranslationUnitDecl *TUDecl = Unit.getASTContext().getTranslationUnitDecl(); for (TranslationUnitDecl::decl_iterator I = TUDecl->decls_begin(), E = TUDecl->decls_end(); I != E; ++I) { IdxCtx.indexTopLevelDecl(*I); if (IdxCtx.shouldAbort()) return; } } }
static void indexPreprocessingRecord(ASTUnit &Unit, IndexingContext &IdxCtx) { Preprocessor &PP = Unit.getPreprocessor(); if (!PP.getPreprocessingRecord()) return; PreprocessingRecord &PPRec = *PP.getPreprocessingRecord(); // FIXME: Only deserialize inclusion directives. // FIXME: Only deserialize stuff from the last chained PCH, not the PCH/Module // that it depends on. bool OnlyLocal = !Unit.isMainFileAST() && Unit.getOnlyLocalDecls(); PreprocessingRecord::iterator I, E; if (OnlyLocal) { I = PPRec.local_begin(); E = PPRec.local_end(); } else { I = PPRec.begin(); E = PPRec.end(); } for (; I != E; ++I) { PreprocessedEntity *PPE = *I; if (InclusionDirective *ID = dyn_cast<InclusionDirective>(PPE)) { IdxCtx.ppIncludedFile(ID->getSourceRange().getBegin(), ID->getFileName(), ID->getFile(), ID->getKind() == InclusionDirective::Import, !ID->wasInQuotes()); } } }
static void clang_indexTranslationUnit_Impl(void *UserData) { IndexTranslationUnitInfo *ITUI = static_cast<IndexTranslationUnitInfo*>(UserData); CXTranslationUnit TU = ITUI->TU; CXClientData client_data = ITUI->client_data; IndexerCallbacks *client_index_callbacks = ITUI->index_callbacks; unsigned index_callbacks_size = ITUI->index_callbacks_size; unsigned index_options = ITUI->index_options; ITUI->result = 1; // init as error. if (!TU) return; if (!client_index_callbacks || index_callbacks_size == 0) return; CIndexer *CXXIdx = (CIndexer*)TU->CIdx; if (CXXIdx->isOptEnabled(CXGlobalOpt_ThreadBackgroundPriorityForIndexing)) setThreadBackgroundPriority(); IndexerCallbacks CB; memset(&CB, 0, sizeof(CB)); unsigned ClientCBSize = index_callbacks_size < sizeof(CB) ? index_callbacks_size : sizeof(CB); memcpy(&CB, client_index_callbacks, ClientCBSize); OwningPtr<IndexingContext> IndexCtx; IndexCtx.reset(new IndexingContext(client_data, CB, index_options, TU)); // Recover resources if we crash before exiting this method. llvm::CrashRecoveryContextCleanupRegistrar<IndexingContext> IndexCtxCleanup(IndexCtx.get()); OwningPtr<IndexingConsumer> IndexConsumer; IndexConsumer.reset(new IndexingConsumer(*IndexCtx)); // Recover resources if we crash before exiting this method. llvm::CrashRecoveryContextCleanupRegistrar<IndexingConsumer> IndexConsumerCleanup(IndexConsumer.get()); ASTUnit *Unit = static_cast<ASTUnit *>(TU->TUData); if (!Unit) return; ASTUnit::ConcurrencyCheck Check(*Unit); FileManager &FileMgr = Unit->getFileManager(); if (Unit->getOriginalSourceFileName().empty()) IndexCtx->enteredMainFile(0); else IndexCtx->enteredMainFile(FileMgr.getFile(Unit->getOriginalSourceFileName())); IndexConsumer->Initialize(Unit->getASTContext()); indexPreprocessingRecord(*Unit, *IndexCtx); indexTranslationUnit(*Unit, *IndexCtx); indexDiagnostics(TU, *IndexCtx); ITUI->result = 0; }
CXDiagnostic clang_getDiagnostic(CXTranslationUnit Unit, unsigned Index) { ASTUnit *CXXUnit = static_cast<ASTUnit *>(Unit->TUData); if (!CXXUnit || Index >= CXXUnit->stored_diag_size()) return 0; return new CXStoredDiagnostic(CXXUnit->stored_diag_begin()[Index], CXXUnit->getASTContext().getLangOptions()); }
SourceRange cxcursor::getCursorPreprocessingDirective(CXCursor C) { assert(C.kind == CXCursor_PreprocessingDirective); SourceRange Range = SourceRange(SourceLocation::getFromRawEncoding( reinterpret_cast<uintptr_t> (C.data[0])), SourceLocation::getFromRawEncoding( reinterpret_cast<uintptr_t> (C.data[1]))); ASTUnit *TU = getCursorASTUnit(C); return TU->mapRangeFromPreamble(Range); }
unsigned clang_isPODType(CXType X) { QualType T = GetQualType(X); if (!T.getTypePtrOrNull()) return 0; CXTranslationUnit TU = GetTU(X); ASTUnit *AU = static_cast<ASTUnit*>(TU->TUData); return T.isPODType(AU->getASTContext()) ? 1 : 0; }
ASTUnit* TranslationUnitManager::ReparseProjectFile(ProjectFile* file) { { //if the file is already being parsed return immediately. std::lock_guard<std::mutex> lock(m_FilesBeingParsedMutex); auto it = std::find(m_FilesBeingParsed.begin(), m_FilesBeingParsed.end(), file); if (it != m_FilesBeingParsed.end()) return nullptr; m_FilesBeingParsed.push_back(file); } wxString fileName = file->file.GetFullPath(); ccEvent startEvent(ccEVT_REPARSE_START, fileName, nullptr, file); AddPendingEvent(startEvent); #ifdef CLANGCC_TIMING wxStopWatch watch; #endif // CLANGCC_TIMING cbStyledTextCtrl* control = Manager::Get()->GetEditorManager()->GetBuiltinEditor(fileName)->GetControl(); SmallVector<ASTUnit::RemappedFile,1> remappedFiles; if (control->GetModify()) { unsigned length = control->GetLength(); llvm::MemoryBuffer* membuf = llvm::MemoryBuffer::getNewUninitMemBuffer(length+1,wx2std(fileName)).release(); control->SendMsg(SCI_GETTEXT, length+1, (wxUIntPtr)membuf->getBufferStart()); ASTUnit::RemappedFile remap = std::make_pair(wx2std(fileName),membuf); remappedFiles.push_back(remap); } ASTUnit* tu = GetASTUnitForProjectFile(file); if (!tu) tu = ParseProjectFile(file); if (!tu || tu->Reparse(m_PCHContainerOps, remappedFiles)) LoggerAccess::Get()->Log("\t Reparsing Failed : "+ file->file.GetFullName()); #ifdef CLANGCC_TIMING LoggerAccess::Get()->Log(wxString::Format("Reparsing completed in %ldms", watch.Time()), Logger::info); #endif // CLANGCC_TIMING { //File is free again std::lock_guard<std::mutex> lock(m_FilesBeingParsedMutex); m_FilesBeingParsed.erase(std::remove(m_FilesBeingParsed.begin(), m_FilesBeingParsed.end(), file),m_FilesBeingParsed.end()); } ccEvent endEvent(ccEVT_REPARSE_END, fileName, tu, file); AddPendingEvent(endEvent); return tu; }
CXType clang_getCanonicalType(CXType CT) { if (CT.kind == CXType_Invalid) return CT; QualType T = GetQualType(CT); CXTranslationUnit TU = GetTU(CT); if (T.isNull()) return MakeCXType(QualType(), GetTU(CT)); ASTUnit *AU = static_cast<ASTUnit*>(TU->TUData); return MakeCXType(AU->getASTContext().getCanonicalType(T), TU); }
CXCompletionString clang_getCursorCompletionString(CXCursor cursor) { enum CXCursorKind kind = clang_getCursorKind(cursor); if (clang_isDeclaration(kind)) { Decl *decl = getCursorDecl(cursor); if (isa<NamedDecl>(decl)) { NamedDecl *namedDecl = (NamedDecl *)decl; ASTUnit *unit = getCursorASTUnit(cursor); if (unit->hasSema()) { Sema &S = unit->getSema(); CodeCompletionAllocator *Allocator = unit->getCursorCompletionAllocator().getPtr(); CodeCompletionResult Result(namedDecl); CodeCompletionString *String = Result.CreateCodeCompletionString(S, *Allocator); return String; } } } else if (kind == CXCursor_MacroDefinition) { MacroDefinition *definition = getCursorMacroDefinition(cursor); const IdentifierInfo *MacroInfo = definition->getName(); ASTUnit *unit = getCursorASTUnit(cursor); if (unit->hasSema()) { Sema &S = unit->getSema(); CodeCompletionAllocator *Allocator = unit->getCursorCompletionAllocator().getPtr(); CodeCompletionResult Result(const_cast<IdentifierInfo *>(MacroInfo)); CodeCompletionString *String = Result.CreateCodeCompletionString(S, *Allocator); return String; } } return NULL; }
CXSourceLocation lfort_getLocationForOffset(CXProgram tu, CXFile file, unsigned offset) { if (!tu || !file) return lfort_getNullLocation(); ASTUnit *CXXUnit = static_cast<ASTUnit *>(tu->PgmData); SourceLocation SLoc = CXXUnit->getLocation(static_cast<const FileEntry *>(file), offset); if (SLoc.isInvalid()) return lfort_getNullLocation(); return cxloc::translateSourceLocation(CXXUnit->getASTContext(), SLoc); }
void index::indexASTUnit(ASTUnit &Unit, std::shared_ptr<IndexDataConsumer> DataConsumer, IndexingOptions Opts) { IndexingContext IndexCtx(Opts, *DataConsumer); IndexCtx.setASTContext(Unit.getASTContext()); indexTranslationUnit(Unit, IndexCtx); }
static void getInclusions(const SrcMgr::SLocEntry &(SourceManager::*Getter)(unsigned, bool*) const, unsigned n, CXTranslationUnit TU, CXInclusionVisitor CB, CXClientData clientData) { ASTUnit *CXXUnit = cxtu::getASTUnit(TU); SourceManager &SM = CXXUnit->getSourceManager(); ASTContext &Ctx = CXXUnit->getASTContext(); SmallVector<CXSourceLocation, 10> InclusionStack; const bool HasPreamble = SM.getPreambleFileID().isValid(); for (unsigned i = 0 ; i < n ; ++i) { bool Invalid = false; const SrcMgr::SLocEntry &SL = (SM.*Getter)(i, &Invalid); if (!SL.isFile() || Invalid) continue; const SrcMgr::FileInfo &FI = SL.getFile(); if (!FI.getContentCache()->OrigEntry) continue; // If this is the main file, and there is a preamble, skip this SLoc. The // inclusions of the preamble already showed it. SourceLocation L = FI.getIncludeLoc(); if (HasPreamble && CXXUnit->isInMainFileID(L)) continue; // Build the inclusion stack. InclusionStack.clear(); while (L.isValid()) { PresumedLoc PLoc = SM.getPresumedLoc(L); InclusionStack.push_back(cxloc::translateSourceLocation(Ctx, L)); L = PLoc.isValid()? PLoc.getIncludeLoc() : SourceLocation(); } // If there is a preamble, the last entry is the "inclusion" of that // preamble into the main file, which has the bogus entry of main.c:1:1 if (HasPreamble && !InclusionStack.empty()) InclusionStack.pop_back(); // Callback to the client. // FIXME: We should have a function to construct CXFiles. CB(static_cast<CXFile>( const_cast<FileEntry *>(FI.getContentCache()->OrigEntry)), InclusionStack.data(), InclusionStack.size(), clientData); } }
CXDiagnosticSetImpl *cxdiag::lazyCreateDiags(CXTranslationUnit TU, bool checkIfChanged) { ASTUnit *AU = cxtu::getASTUnit(TU); if (TU->Diagnostics && checkIfChanged) { // In normal use, ASTUnit's diagnostics should not change unless we reparse. // Currently they can only change by using the internal testing flag // '-error-on-deserialized-decl' which will error during deserialization of // a declaration. What will happen is: // // -c-index-test gets a CXTranslationUnit // -checks the diagnostics, the diagnostics set is lazily created, // no errors are reported // -later does an operation, like annotation of tokens, that triggers // -error-on-deserialized-decl, that will emit a diagnostic error, // that ASTUnit will catch and add to its stored diagnostics vector. // -c-index-test wants to check whether an error occurred after performing // the operation but can only query the lazily created set. // // We check here if a new diagnostic was appended since the last time the // diagnostic set was created, in which case we reset it. CXDiagnosticSetImpl * Set = static_cast<CXDiagnosticSetImpl*>(TU->Diagnostics); if (AU->stored_diag_size() != Set->getNumDiagnostics()) { // Diagnostics in the ASTUnit were updated, reset the associated // diagnostics. delete Set; TU->Diagnostics = nullptr; } } if (!TU->Diagnostics) { CXDiagnosticSetImpl *Set = new CXDiagnosticSetImpl(); TU->Diagnostics = Set; IntrusiveRefCntPtr<DiagnosticOptions> DOpts = new DiagnosticOptions; CXDiagnosticRenderer Renderer(AU->getASTContext().getLangOpts(), &*DOpts, Set); for (ASTUnit::stored_diag_iterator it = AU->stored_diag_begin(), ei = AU->stored_diag_end(); it != ei; ++it) { Renderer.emitStoredDiagnostic(*it); } } return static_cast<CXDiagnosticSetImpl*>(TU->Diagnostics); }
void ASTMergeAction::ExecuteAction() { CompilerInstance &CI = getCompilerInstance(); CI.getDiagnostics().getClient()->BeginSourceFile( CI.getASTContext().getLangOpts()); CI.getDiagnostics().SetArgToStringFn(&FormatASTNodeDiagnosticArgument, &CI.getASTContext()); IntrusiveRefCntPtr<DiagnosticIDs> DiagIDs(CI.getDiagnostics().getDiagnosticIDs()); for (unsigned I = 0, N = ASTFiles.size(); I != N; ++I) { IntrusiveRefCntPtr<DiagnosticsEngine> Diags(new DiagnosticsEngine(DiagIDs, &CI.getDiagnosticOpts(), new ForwardingDiagnosticConsumer( *CI.getDiagnostics().getClient()), /*ShouldOwnClient=*/true)); ASTUnit *Unit = ASTUnit::LoadFromASTFile(ASTFiles[I], Diags, CI.getFileSystemOpts(), false); if (!Unit) continue; ASTImporter Importer(CI.getASTContext(), CI.getFileManager(), Unit->getASTContext(), Unit->getFileManager(), /*MinimalImport=*/false); TranslationUnitDecl *TU = Unit->getASTContext().getTranslationUnitDecl(); for (DeclContext::decl_iterator D = TU->decls_begin(), DEnd = TU->decls_end(); D != DEnd; ++D) { // Don't re-import __va_list_tag, __builtin_va_list. if (NamedDecl *ND = dyn_cast<NamedDecl>(*D)) if (IdentifierInfo *II = ND->getIdentifier()) if (II->isStr("__va_list_tag") || II->isStr("__builtin_va_list")) continue; Importer.Import(*D); } delete Unit; } AdaptedAction->ExecuteAction(); CI.getDiagnostics().getClient()->EndSourceFile(); }
void clang_getInclusions(CXTranslationUnit TU, CXInclusionVisitor CB, CXClientData clientData) { ASTUnit *CXXUnit = static_cast<ASTUnit *>(TU); SourceManager &SM = CXXUnit->getSourceManager(); ASTContext &Ctx = CXXUnit->getASTContext(); llvm::SmallVector<CXSourceLocation, 10> InclusionStack; unsigned i = SM.sloc_loaded_entry_size(); unsigned n = SM.sloc_entry_size(); // In the case where all the SLocEntries are in an external source, traverse // those SLocEntries as well. This is the case where we are looking // at the inclusion stack of an AST/PCH file. if (i >= n) i = 0; for ( ; i < n ; ++i) { const SrcMgr::SLocEntry &SL = SM.getSLocEntry(i); if (!SL.isFile()) continue; const SrcMgr::FileInfo &FI = SL.getFile(); if (!FI.getContentCache()->Entry) continue; // Build the inclusion stack. SourceLocation L = FI.getIncludeLoc(); InclusionStack.clear(); while (L.isValid()) { PresumedLoc PLoc = SM.getPresumedLoc(L); InclusionStack.push_back(cxloc::translateSourceLocation(Ctx, L)); L = PLoc.getIncludeLoc(); } // Callback to the client. // FIXME: We should have a function to construct CXFiles. CB((CXFile) FI.getContentCache()->Entry, InclusionStack.data(), InclusionStack.size(), clientData); } }
static bool findIncludesInFile(CXTranslationUnit TU, const FileEntry *File, CXCursorAndRangeVisitor Visitor) { assert(TU && File && Visitor.visit); ASTUnit *Unit = cxtu::getASTUnit(TU); SourceManager &SM = Unit->getSourceManager(); FileID FID = SM.translateFile(File); FindFileIncludesVisitor IncludesVisitor(*Unit, File, Visitor); SourceRange Range(SM.getLocForStartOfFile(FID), SM.getLocForEndOfFile(FID)); CursorVisitor InclusionCursorsVisitor(TU, FindFileIncludesVisitor::visit, &IncludesVisitor, /*VisitPreprocessorLast=*/false, /*VisitIncludedEntities=*/false, Range); return InclusionCursorsVisitor.visitPreprocessedEntitiesInRegion(); }
CXSourceLocation clang_getLocationForOffset(CXTranslationUnit TU, CXFile file, unsigned offset) { if (cxtu::isNotUsableTU(TU)) { LOG_BAD_TU(TU); return clang_getNullLocation(); } if (!file) return clang_getNullLocation(); ASTUnit *CXXUnit = cxtu::getASTUnit(TU); SourceLocation SLoc = CXXUnit->getLocation(static_cast<const FileEntry *>(file), offset); if (SLoc.isInvalid()) return clang_getNullLocation(); return cxloc::translateSourceLocation(CXXUnit->getASTContext(), SLoc); }
static void indexPreprocessingRecord(ASTUnit &Unit, IndexingContext &IdxCtx) { Preprocessor &PP = Unit.getPreprocessor(); if (!PP.getPreprocessingRecord()) return; // FIXME: Only deserialize inclusion directives. PreprocessingRecord::iterator I, E; llvm::tie(I, E) = Unit.getLocalPreprocessingEntities(); for (; I != E; ++I) { PreprocessedEntity *PPE = *I; if (InclusionDirective *ID = dyn_cast<InclusionDirective>(PPE)) { if (!ID->importedModule()) IdxCtx.ppIncludedFile(ID->getSourceRange().getBegin(),ID->getFileName(), ID->getFile(), ID->getKind() == InclusionDirective::Import, !ID->wasInQuotes()); } } }
static CXErrorCode clang_indexTranslationUnit_Impl( CXIndexAction idxAction, CXClientData client_data, IndexerCallbacks *client_index_callbacks, unsigned index_callbacks_size, unsigned index_options, CXTranslationUnit TU) { // Check arguments. if (isNotUsableTU(TU)) { LOG_BAD_TU(TU); return CXError_InvalidArguments; } if (!client_index_callbacks || index_callbacks_size == 0) { return CXError_InvalidArguments; } CIndexer *CXXIdx = TU->CIdx; if (CXXIdx->isOptEnabled(CXGlobalOpt_ThreadBackgroundPriorityForIndexing)) setThreadBackgroundPriority(); IndexerCallbacks CB; memset(&CB, 0, sizeof(CB)); unsigned ClientCBSize = index_callbacks_size < sizeof(CB) ? index_callbacks_size : sizeof(CB); memcpy(&CB, client_index_callbacks, ClientCBSize); auto DataConsumer = std::make_shared<CXIndexDataConsumer>(client_data, CB, index_options, TU); ASTUnit *Unit = cxtu::getASTUnit(TU); if (!Unit) return CXError_Failure; ASTUnit::ConcurrencyCheck Check(*Unit); if (const FileEntry *PCHFile = Unit->getPCHFile()) DataConsumer->importedPCH(PCHFile); FileManager &FileMgr = Unit->getFileManager(); if (Unit->getOriginalSourceFileName().empty()) DataConsumer->enteredMainFile(nullptr); else DataConsumer->enteredMainFile(FileMgr.getFile(Unit->getOriginalSourceFileName())); DataConsumer->setASTContext(Unit->getASTContext()); DataConsumer->startedTranslationUnit(); indexPreprocessingRecord(*Unit, *DataConsumer); indexASTUnit(*Unit, DataConsumer, getIndexingOptionsFromCXOptions(index_options)); DataConsumer->indexDiagnostics(); return CXError_Success; }
bool FrontendAction::BeginSourceFile(CompilerInstance &CI, const FrontendInputFile &Input) { assert(!Instance && "Already processing a source file!"); assert(!Input.isEmpty() && "Unexpected empty filename!"); setCurrentInput(Input); setCompilerInstance(&CI); StringRef InputFile = Input.getFile(); bool HasBegunSourceFile = false; if (!BeginInvocation(CI)) goto failure; // AST files follow a very different path, since they share objects via the // AST unit. if (Input.getKind() == IK_AST) { assert(!usesPreprocessorOnly() && "Attempt to pass AST file to preprocessor only action!"); assert(hasASTFileSupport() && "This action does not have AST file support!"); IntrusiveRefCntPtr<DiagnosticsEngine> Diags(&CI.getDiagnostics()); ASTUnit *AST = ASTUnit::LoadFromASTFile(InputFile, Diags, CI.getFileSystemOpts()); if (!AST) goto failure; setCurrentInput(Input, AST); // Inform the diagnostic client we are processing a source file. CI.getDiagnosticClient().BeginSourceFile(CI.getLangOpts(), 0); HasBegunSourceFile = true; // Set the shared objects, these are reset when we finish processing the // file, otherwise the CompilerInstance will happily destroy them. CI.setFileManager(&AST->getFileManager()); CI.setSourceManager(&AST->getSourceManager()); CI.setPreprocessor(&AST->getPreprocessor()); CI.setASTContext(&AST->getASTContext()); // Initialize the action. if (!BeginSourceFileAction(CI, InputFile)) goto failure; // Create the AST consumer. CI.setASTConsumer(CreateWrappedASTConsumer(CI, InputFile)); if (!CI.hasASTConsumer()) goto failure; return true; } // Set up the file and source managers, if needed. if (!CI.hasFileManager()) CI.createFileManager(); if (!CI.hasSourceManager()) CI.createSourceManager(CI.getFileManager()); // IR files bypass the rest of initialization. if (Input.getKind() == IK_LLVM_IR) { assert(hasIRSupport() && "This action does not have IR file support!"); // Inform the diagnostic client we are processing a source file. CI.getDiagnosticClient().BeginSourceFile(CI.getLangOpts(), 0); HasBegunSourceFile = true; // Initialize the action. if (!BeginSourceFileAction(CI, InputFile)) goto failure; return true; } // If the implicit PCH include is actually a directory, rather than // a single file, search for a suitable PCH file in that directory. if (!CI.getPreprocessorOpts().ImplicitPCHInclude.empty()) { FileManager &FileMgr = CI.getFileManager(); PreprocessorOptions &PPOpts = CI.getPreprocessorOpts(); StringRef PCHInclude = PPOpts.ImplicitPCHInclude; if (const DirectoryEntry *PCHDir = FileMgr.getDirectory(PCHInclude)) { llvm::error_code EC; SmallString<128> DirNative; llvm::sys::path::native(PCHDir->getName(), DirNative); bool Found = false; for (llvm::sys::fs::directory_iterator Dir(DirNative.str(), EC), DirEnd; Dir != DirEnd && !EC; Dir.increment(EC)) { // Check whether this is an acceptable AST file. if (ASTReader::isAcceptableASTFile(Dir->path(), FileMgr, CI.getLangOpts(), CI.getTargetOpts(), CI.getPreprocessorOpts())) { PPOpts.ImplicitPCHInclude = Dir->path(); Found = true; break; } } if (!Found) { CI.getDiagnostics().Report(diag::err_fe_no_pch_in_dir) << PCHInclude; return true; } } } // Set up the preprocessor. CI.createPreprocessor(); // Inform the diagnostic client we are processing a source file. CI.getDiagnosticClient().BeginSourceFile(CI.getLangOpts(), &CI.getPreprocessor()); HasBegunSourceFile = true; // Initialize the action. if (!BeginSourceFileAction(CI, InputFile)) goto failure; // Create the AST context and consumer unless this is a preprocessor only // action. if (!usesPreprocessorOnly()) { CI.createASTContext(); OwningPtr<ASTConsumer> Consumer( CreateWrappedASTConsumer(CI, InputFile)); if (!Consumer) goto failure; CI.getASTContext().setASTMutationListener(Consumer->GetASTMutationListener()); if (!CI.getPreprocessorOpts().ChainedIncludes.empty()) { // Convert headers to PCH and chain them. OwningPtr<ExternalASTSource> source; source.reset(ChainedIncludesSource::create(CI)); if (!source) goto failure; CI.setModuleManager(static_cast<ASTReader*>( &static_cast<ChainedIncludesSource*>(source.get())->getFinalReader())); CI.getASTContext().setExternalSource(source); } else if (!CI.getPreprocessorOpts().ImplicitPCHInclude.empty()) { // Use PCH. assert(hasPCHSupport() && "This action does not have PCH support!"); ASTDeserializationListener *DeserialListener = Consumer->GetASTDeserializationListener(); if (CI.getPreprocessorOpts().DumpDeserializedPCHDecls) DeserialListener = new DeserializedDeclsDumper(DeserialListener); if (!CI.getPreprocessorOpts().DeserializedPCHDeclsToErrorOn.empty()) DeserialListener = new DeserializedDeclsChecker(CI.getASTContext(), CI.getPreprocessorOpts().DeserializedPCHDeclsToErrorOn, DeserialListener); CI.createPCHExternalASTSource( CI.getPreprocessorOpts().ImplicitPCHInclude, CI.getPreprocessorOpts().DisablePCHValidation, CI.getPreprocessorOpts().AllowPCHWithCompilerErrors, DeserialListener); if (!CI.getASTContext().getExternalSource()) goto failure; } CI.setASTConsumer(Consumer.take()); if (!CI.hasASTConsumer()) goto failure; } // Initialize built-in info as long as we aren't using an external AST // source. if (!CI.hasASTContext() || !CI.getASTContext().getExternalSource()) { Preprocessor &PP = CI.getPreprocessor(); PP.getBuiltinInfo().InitializeBuiltins(PP.getIdentifierTable(), PP.getLangOpts()); } // If there is a layout overrides file, attach an external AST source that // provides the layouts from that file. if (!CI.getFrontendOpts().OverrideRecordLayoutsFile.empty() && CI.hasASTContext() && !CI.getASTContext().getExternalSource()) { OwningPtr<ExternalASTSource> Override(new LayoutOverrideSource( CI.getFrontendOpts().OverrideRecordLayoutsFile)); CI.getASTContext().setExternalSource(Override); } return true; // If we failed, reset state since the client will not end up calling the // matching EndSourceFile(). failure: if (isCurrentFileAST()) { CI.setASTContext(0); CI.setPreprocessor(0); CI.setSourceManager(0); CI.setFileManager(0); } if (HasBegunSourceFile) CI.getDiagnosticClient().EndSourceFile(); CI.clearOutputFiles(/*EraseFiles=*/true); setCurrentInput(FrontendInputFile()); setCompilerInstance(0); return false; }