static IntrusiveRefCntPtr<DiagnosticsEngine> createDiagnostics(unsigned int argc, char **argv) { IntrusiveRefCntPtr<DiagnosticIDs> DiagIDs(new DiagnosticIDs()); // Buffer diagnostics from argument parsing so that we can output them using a // well formed diagnostic object. TextDiagnosticBuffer *DiagsBuffer = new TextDiagnosticBuffer; IntrusiveRefCntPtr<DiagnosticsEngine> InterimDiags( new DiagnosticsEngine(DiagIDs, new DiagnosticOptions(), DiagsBuffer)); // Try to build a CompilerInvocation. OwningPtr<CompilerInvocation> Invocation( createInvocationFromCommandLine(ArrayRef<const char *>(argv, argc), InterimDiags)); if (!Invocation) return NULL; // Build the diagnostics parser IntrusiveRefCntPtr<DiagnosticsEngine> FinalDiags = CompilerInstance::createDiagnostics(&Invocation->getDiagnosticOpts(), argc, argv); if (!FinalDiags) return NULL; // Flush any errors created when initializing everything. This could happen // for invalid command lines, which will probably give non-sensical results. DiagsBuffer->FlushDiagnostics(*FinalDiags); return FinalDiags; }
/// CheckResults - This compares the expected results to those that /// were actually reported. It emits any discrepencies. Return "true" if there /// were problems. Return "false" otherwise. static unsigned CheckResults(DiagnosticsEngine &Diags, SourceManager &SourceMgr, const TextDiagnosticBuffer &Buffer, ExpectedData &ED) { // We want to capture the delta between what was expected and what was // seen. // // Expected \ Seen - set expected but not seen // Seen \ Expected - set seen but not expected unsigned NumProblems = 0; const DiagnosticLevelMask DiagMask = Diags.getDiagnosticOptions().getVerifyIgnoreUnexpected(); // See if there are error mismatches. NumProblems += CheckLists(Diags, SourceMgr, "error", ED.Errors, Buffer.err_begin(), Buffer.err_end(), bool(DiagnosticLevelMask::Error & DiagMask)); // See if there are warning mismatches. NumProblems += CheckLists(Diags, SourceMgr, "warning", ED.Warnings, Buffer.warn_begin(), Buffer.warn_end(), bool(DiagnosticLevelMask::Warning & DiagMask)); // See if there are remark mismatches. NumProblems += CheckLists(Diags, SourceMgr, "remark", ED.Remarks, Buffer.remark_begin(), Buffer.remark_end(), bool(DiagnosticLevelMask::Remark & DiagMask)); // See if there are note mismatches. NumProblems += CheckLists(Diags, SourceMgr, "note", ED.Notes, Buffer.note_begin(), Buffer.note_end(), bool(DiagnosticLevelMask::Note & DiagMask)); return NumProblems; }
int main(int argc, const char **argv) { // Only do front-end stuff llvm::SmallVector<const char *, 16> Args(argv + 1, argv + argc); Args.push_back("-fsyntax-only"); std::unique_ptr<CompilerInstance> Clang(new CompilerInstance()); llvm::IntrusiveRefCntPtr<DiagnosticIDs> DiagID(new DiagnosticIDs()); DiagnosticOptions *DiagOpts = new DiagnosticOptions; // Buffer diagnostics from argument parsing so that we can output them using a // well formed diagnostic object. TextDiagnosticBuffer *DiagsBuffer = new TextDiagnosticBuffer; DiagnosticsEngine Diags(DiagID, DiagOpts, DiagsBuffer); CompilerInvocation::CreateFromArgs(Clang->getInvocation(), Args.begin(), Args.end(), Diags); // Infer the builtin include path if unspecified. if (Clang->getHeaderSearchOpts().UseBuiltinIncludes && Clang->getHeaderSearchOpts().ResourceDir.empty()) Clang->getHeaderSearchOpts().ResourceDir = CompilerInvocation::GetResourcesPath(argv[0], (void*) (intptr_t) foo); // Create the actual diagnostics engine. ASTTextDiagnosticPrinter *DiagPrinter = new ASTTextDiagnosticPrinter(llvm::errs(), &Clang->getDiagnosticOpts()); Clang->createDiagnostics(DiagPrinter); if (!Clang->hasDiagnostics()) { return EXIT_FAILURE; } DiagsBuffer->FlushDiagnostics(Clang->getDiagnostics()); // If there were errors in processing arguments, don't do anything else. if (Clang->getDiagnostics().hasErrorOccurred()) { return EXIT_FAILURE; } // We can emit custom diagnostic messages that must be registered here. registerCustomDiagnostics(Clang->getDiagnostics()); std::unique_ptr<FrontendAction> WalkAct(new ASTWalkerAction(Clang->getDiagnostics())); if(!Clang->ExecuteAction(*WalkAct)) { return EXIT_FAILURE; } return EXIT_SUCCESS; }
int csabase::run(int argc_, const char **argv_) { sys::PrintStackTraceOnErrorSignal(); PrettyStackTraceProgram X(argc_, argv_); SmallVector<const char *, 1024> argv; SpecificBumpPtrAllocator<char> ArgAllocator; StringSetSaver Saver; sys::Process::GetArgumentVector(argv, ArrayRef<const char *>(argv_, argc_), ArgAllocator); cl::ExpandResponseFiles(Saver, cl::TokenizeGNUCommandLine, argv); argv.insert(argv.begin() == argv.end() ? argv.begin() : argv.begin() + 1, "-xc++"); llvm::InitializeNativeTarget(); llvm::InitializeNativeTargetAsmParser(); CompilerInstance Clang; TextDiagnosticBuffer DiagsBuffer; IntrusiveRefCntPtr<DiagnosticIDs> DiagID(new DiagnosticIDs()); IntrusiveRefCntPtr<DiagnosticOptions> DiagOpts(new DiagnosticOptions()); DiagnosticsEngine Diags(DiagID, &*DiagOpts, &DiagsBuffer, false); bool Success = CompilerInvocation::CreateFromArgs( Clang.getInvocation(), argv.data() + 1, argv.data() + argv.size(), Diags); Clang.createDiagnostics(); install_fatal_error_handler(LLVMErrorHandler, &Clang.getDiagnostics()); DiagsBuffer.FlushDiagnostics(Clang.getDiagnostics()); if (Success) { Success = ExecuteCompilerInvocation(&Clang); } remove_fatal_error_handler(); llvm::llvm_shutdown(); return !Success; }
/// This compares the expected results to those that were actually reported. /// It emits any discrepencies. Return "true" if there were problems. Return /// "false" otherwise. static unsigned CheckResults(DiagnosticsEngine &Diags, llvm::SourceMgr &SourceMgr, const TextDiagnosticBuffer &Buffer, ExpectedData &ED) { // We want to capture the delta between what was expected and what was // seen. // // Expected \ Seen - set expected but not seen // Seen \ Expected - set seen but not expected unsigned NumProblems = 0; // See if there are error mismatches. NumProblems += CheckLists(Diags, SourceMgr, "error", ED.Errors, Buffer.err_begin(), Buffer.err_end()); // See if there are note mismatches. NumProblems += CheckLists(Diags, SourceMgr, "note", ED.Notes, Buffer.note_begin(), Buffer.note_end()); return NumProblems; }
CXRemapping clang_getRemappingsFromFileList(const char **filePaths, unsigned numFiles) { bool Logging = ::getenv("LIBCLANG_LOGGING"); std::unique_ptr<Remap> remap(new Remap()); if (numFiles == 0) { if (Logging) llvm::errs() << "clang_getRemappingsFromFileList was called with " "numFiles=0\n"; return remap.release(); } if (!filePaths) { if (Logging) llvm::errs() << "clang_getRemappingsFromFileList was called with " "NULL filePaths\n"; return 0; } TextDiagnosticBuffer diagBuffer; SmallVector<StringRef, 32> Files; for (unsigned i = 0; i != numFiles; ++i) Files.push_back(filePaths[i]); bool err = arcmt::getFileRemappingsFromFileList(remap->Vec, Files, &diagBuffer); if (err) { if (Logging) { llvm::errs() << "Error by clang_getRemappingsFromFileList\n"; for (TextDiagnosticBuffer::const_iterator I = diagBuffer.err_begin(), E = diagBuffer.err_end(); I != E; ++I) llvm::errs() << I->second << '\n'; } return remap.release(); } return remap.release(); }
CXRemapping clang_getRemappings(const char *migrate_dir_path) { bool Logging = ::getenv("LIBCLANG_LOGGING"); if (!migrate_dir_path) { if (Logging) llvm::errs() << "clang_getRemappings was called with NULL parameter\n"; return 0; } bool exists = false; llvm::sys::fs::exists(migrate_dir_path, exists); if (!exists) { if (Logging) { llvm::errs() << "Error by clang_getRemappings(\"" << migrate_dir_path << "\")\n"; llvm::errs() << "\"" << migrate_dir_path << "\" does not exist\n"; } return 0; } TextDiagnosticBuffer diagBuffer; llvm::OwningPtr<Remap> remap(new Remap()); bool err = arcmt::getFileRemappings(remap->Vec, migrate_dir_path,&diagBuffer); if (err) { if (Logging) { llvm::errs() << "Error by clang_getRemappings(\"" << migrate_dir_path << "\")\n"; for (TextDiagnosticBuffer::const_iterator I = diagBuffer.err_begin(), E = diagBuffer.err_end(); I != E; ++I) llvm::errs() << I->second << '\n'; } return 0; } return remap.take(); }
int cc1_main(const char **ArgBegin, const char **ArgEnd, const char *Argv0, void *MainAddr) { llvm::OwningPtr<CompilerInstance> Clang(new CompilerInstance()); llvm::IntrusiveRefCntPtr<DiagnosticIDs> DiagID(new DiagnosticIDs()); // Run clang -cc1 test. if (ArgBegin != ArgEnd && StringRef(ArgBegin[0]) == "-cc1test") { Diagnostic Diags(DiagID, new TextDiagnosticPrinter(llvm::errs(), DiagnosticOptions())); return cc1_test(Diags, ArgBegin + 1, ArgEnd); } // Initialize targets first, so that --version shows registered targets. llvm::InitializeAllTargets(); llvm::InitializeAllTargetMCs(); llvm::InitializeAllAsmPrinters(); llvm::InitializeAllAsmParsers(); // Buffer diagnostics from argument parsing so that we can output them using a // well formed diagnostic object. TextDiagnosticBuffer *DiagsBuffer = new TextDiagnosticBuffer; Diagnostic Diags(DiagID, DiagsBuffer); CompilerInvocation::CreateFromArgs(Clang->getInvocation(), ArgBegin, ArgEnd, Diags); // Infer the builtin include path if unspecified. if (Clang->getHeaderSearchOpts().UseBuiltinIncludes && Clang->getHeaderSearchOpts().ResourceDir.empty()) Clang->getHeaderSearchOpts().ResourceDir = CompilerInvocation::GetResourcesPath(Argv0, MainAddr); // Create the actual diagnostics engine. Clang->createDiagnostics(ArgEnd - ArgBegin, const_cast<char**>(ArgBegin)); if (!Clang->hasDiagnostics()) return 1; // Set an error handler, so that any LLVM backend diagnostics go through our // error handler. llvm::install_fatal_error_handler(LLVMErrorHandler, static_cast<void*>(&Clang->getDiagnostics())); DiagsBuffer->FlushDiagnostics(Clang->getDiagnostics()); // Execute the frontend actions. bool Success = ExecuteCompilerInvocation(Clang.get()); // If any timers were active but haven't been destroyed yet, print their // results now. This happens in -disable-free mode. llvm::TimerGroup::printAll(llvm::errs()); // Our error handler depends on the Diagnostics object, which we're // potentially about to delete. Uninstall the handler now so that any // later errors use the default handling behavior instead. llvm::remove_fatal_error_handler(); // When running with -disable-free, don't do any destruction or shutdown. if (Clang->getFrontendOpts().DisableFree) { if (llvm::AreStatisticsEnabled() || Clang->getFrontendOpts().ShowStats) llvm::PrintStatistics(); Clang.take(); return !Success; } // Managed static deconstruction. Useful for making things like // -time-passes usable. llvm::llvm_shutdown(); return !Success; }
static int CompileSubprocess(const char **argv, int argc, sys::Path &ResourceDir, bool bugreport, bool versionOnly, sys::Path &apiMapPath) { std::vector<char*> llvmArgs; char apim[] = "-clam-apimap"; llvmArgs.push_back((char*)argv[0]); llvmArgs.push_back(apim); llvmArgs.push_back((char*)apiMapPath.c_str()); // Split args into cc1 and LLVM args, separator is -- int cc1_argc; for (cc1_argc=1;cc1_argc<argc;cc1_argc++) { if (StringRef(argv[cc1_argc]) == "--") { for (int i=cc1_argc+1;i<argc;i++) { llvmArgs.push_back((char*)argv[i]); } break; } } // Initialize CompilerInstance from commandline args CompilerInstance Clang; Clang.setLLVMContext(new llvm::LLVMContext); LLVMInitializeClamBCTargetInfo(); LLVMInitializeClamBCTarget(); TextDiagnosticBuffer DiagsBuffer; Diagnostic Diags(&DiagsBuffer); CompilerInvocation::CreateFromArgs(Clang.getInvocation(), argv+1, argv+cc1_argc, Diags); FrontendOptions &FrontendOpts = Clang.getInvocation().getFrontendOpts(); // Handle --version if (FrontendOpts.ShowVersion || versionOnly) { printVersion(outs(), true); exit(0); } DiagnosticOptions &DiagOpts = Clang.getInvocation().getDiagnosticOpts(); DiagOpts.ShowOptionNames = DiagOpts.ShowColors = 1; DiagOpts.MessageLength = 80;// we are writing to a file DiagOpts.Warnings.push_back("all"); DiagOpts.Warnings.push_back("no-pointer-sign"); Clang.createDiagnostics(argc-1, const_cast<char**>(argv+1)); if (!Clang.hasDiagnostics()) return 2; Clang.getInvocation().getHeaderSearchOpts().ResourceDir = ResourceDir.str(); // Set default options LangOptions &LangOpts = Clang.getInvocation().getLangOpts(); // This is a freestanding environment, without libc, etc. LangOpts.Freestanding = 1; HeaderSearchOptions &HeaderSearchOpts = Clang.getInvocation().getHeaderSearchOpts(); HeaderSearchOpts.UseStandardIncludes = 0; if (bugreport) HeaderSearchOpts.Verbose = 1; if (FrontendOpts.ProgramAction != frontend::PrintPreprocessedInput) FrontendOpts.ProgramAction = frontend::EmitBC; if (bugreport) FrontendOpts.ProgramAction = frontend::PrintPreprocessedInput; // Don't bother freeing of memory on exit FrontendOpts.DisableFree = 1; CodeGenOptions &Opts = Clang.getInvocation().getCodeGenOpts(); Opts.Inlining = CodeGenOptions::OnlyAlwaysInlining; // always generate debug info, so that ClamBC backend can output sourcelevel // diagnostics. Opts.DebugInfo = true; // FIXME: once the verifier can work w/o targetdata, and targetdate opts set // DisableLLVMOpts to true! // This is needed to avoid target-specific optimizations Opts.DisableLLVMOpts = false; AnalyzerOptions &AOpts = Clang.getInvocation().getAnalyzerOpts(); AOpts.AnalysisList.push_back(WarnDeadStores); AOpts.AnalysisList.push_back(WarnUninitVals); AOpts.AnalysisList.push_back(SecuritySyntacticChecks); AOpts.AnalysisList.push_back(WarnSizeofPointer); // Set triple Clang.getInvocation().getTargetOpts().Triple = "clambc-generic-generic"; // Set default include Clang.getInvocation().getPreprocessorOpts().Includes.push_back("bytecode.h"); // Set an LLVM error handler. llvm::llvm_install_error_handler(LLVMErrorHandler, static_cast<void*>(&Clang.getDiagnostics())); DiagsBuffer.FlushDiagnostics(Clang.getDiagnostics()); // If there were any errors in processing arguments, exit now. if (Clang.getDiagnostics().getNumErrors()) return 1; // Create the target instance. //TODO: directly create a clambc target Clang.setTarget(TargetInfo::CreateTargetInfo(Clang.getDiagnostics(), Clang.getTargetOpts())); if (!Clang.hasTarget()) return 1; // Inform the target of the language options Clang.getTarget().setForcedLangOptions(Clang.getLangOpts()); if (Clang.getHeaderSearchOpts().Verbose) { llvm::errs() << "clang -cc1 version " CLANG_VERSION_STRING << " based upon " << PACKAGE_STRING << " hosted on " << llvm::sys::getHostTriple() << "\n"; // Convert the invocation back to argument strings. std::vector<std::string> InvocationArgs; Clang.getInvocation().toArgs(InvocationArgs); // Dump the converted arguments. llvm::SmallVector<const char*, 32> Invocation2Args; llvm::errs() << "invocation argv :"; for (unsigned i = 0, e = InvocationArgs.size(); i != e; ++i) { Invocation2Args.push_back(InvocationArgs[i].c_str()); llvm::errs() << " \"" << InvocationArgs[i] << '"'; } llvm::errs() << "\n"; } std::string Input = FrontendOpts.Inputs[0].second; if (Input == "-" && bugreport) return 2; raw_fd_ostream *fd = 0; if (FrontendOpts.ProgramAction == frontend::EmitBC) { // replace output file of compiler with a tempfile, // and save the final output filename. std::string FinalOutput = FrontendOpts.OutputFile; if (FinalOutput.empty()) { if (Input == "-") FinalOutput = "-"; else { sys::Path P(sys::Path(Input).getBasename()); P.appendSuffix("cbc"); FinalOutput = P.str(); } } llvm::raw_fd_ostream *tmpfd; std::string Err2; fd = Clang.createOutputFile(FinalOutput, Err2, false); if (!fd) { Clang.getDiagnostics().Report(clang::diag::err_drv_unable_to_make_temp) << Err2; return 1; } sys::Path P = sys::Path(FinalOutput); P.eraseSuffix(); P.appendSuffix("tmp.bc"); FrontendOpts.OutputFile = P.str(); tmpfd = Clang.createOutputFile(P.str(), Err2, true); if (!tmpfd) { Clang.getDiagnostics().Report(clang::diag::err_drv_unable_to_make_temp) << Err2; return 1; } delete tmpfd; sys::RemoveFileOnSignal(sys::Path(FrontendOpts.OutputFile)); } if (!FrontendOpts.Inputs.empty()) { char srcp[] = "-clambc-src"; llvmArgs.push_back(srcp); llvmArgs.push_back(strdup(Input.c_str())); } // Parse LLVM commandline args cl::ParseCommandLineOptions(llvmArgs.size(), &llvmArgs[0]); std::string re2cpath = getTmpDir(); if (re2cpath.empty()) { llvm::errs()<< "Failed to create temporary file for re2c-out!\n"; return 2; } re2cpath += "/clambc-compiler-re2c-out"; sys::Path TmpRe2C(re2cpath); if (!FrontendOpts.Inputs.empty()) { char re2c_args[] = "--no-generation-date"; char re2c_o[] = "-o"; char name[] = ""; char *args[6] = { name, re2c_args, re2c_o, NULL, NULL, NULL }; args[4] = strdup(Input.c_str()); std::string ErrMsg(""); if (TmpRe2C.createTemporaryFileOnDisk(true, &ErrMsg)) { Clang.getDiagnostics().Report(clang::diag::err_drv_unable_to_make_temp) << ErrMsg; return 1; } sys::RemoveFileOnSignal(TmpRe2C); args[3] = strdup(TmpRe2C.str().c_str()); int ret = re2c_main(5, args); if (ret) { Clang.getDiagnostics().Report(clang::diag::err_drv_command_failed) << "re2c" << ret; return 1; } Input = TmpRe2C.str(); } // Create a file manager object to provide access to and cache the // filesystem. Clang.createFileManager(); // Create the source manager. Clang.createSourceManager(); // Create the preprocessor. Clang.createPreprocessor(); llvm::OwningPtr<FrontendAction> Act(CreateFrontendAction(Clang)); if (Act && Act->BeginSourceFile(Clang, Input, false)) { Act->Execute(); Act->EndSourceFile(); } TmpRe2C.eraseFromDisk();// erase tempfile int ret = Clang.getDiagnostics().getNumErrors() != 0; if (ret) return ret; if (FrontendOpts.ProgramAction != frontend::EmitBC) { // stop processing if not compiling a final .cbc file return 0; } ret = compileInternal(FrontendOpts.OutputFile.c_str(), Opts.OptimizationLevel, Opts.OptimizeSize, argv[0], fd, Clang); // Erase temp file, we need to do this here since OutputFile is a tempfile // only if action was EmitBC sys::Path(FrontendOpts.OutputFile).eraseFromDisk(); return ret; }
int cc1_main(const char **ArgBegin, const char **ArgEnd, const char *Argv0, void *MainAddr) { CompilerInstance Clang; Clang.setLLVMContext(new llvm::LLVMContext); // Run clang -cc1 test. if (ArgBegin != ArgEnd && llvm::StringRef(ArgBegin[0]) == "-cc1test") { TextDiagnosticPrinter DiagClient(llvm::errs(), DiagnosticOptions()); Diagnostic Diags(&DiagClient); return cc1_test(Diags, ArgBegin + 1, ArgEnd); } // Initialize targets first, so that --version shows registered targets. llvm::InitializeAllTargets(); llvm::InitializeAllAsmPrinters(); // Buffer diagnostics from argument parsing so that we can output them using a // well formed diagnostic object. TextDiagnosticBuffer DiagsBuffer; Diagnostic Diags(&DiagsBuffer); CompilerInvocation::CreateFromArgs(Clang.getInvocation(), ArgBegin, ArgEnd, Diags); // Infer the builtin include path if unspecified. if (Clang.getHeaderSearchOpts().UseBuiltinIncludes && Clang.getHeaderSearchOpts().ResourceDir.empty()) Clang.getHeaderSearchOpts().ResourceDir = CompilerInvocation::GetResourcesPath(Argv0, MainAddr); // Honor -help. if (Clang.getFrontendOpts().ShowHelp) { llvm::OwningPtr<driver::OptTable> Opts(driver::createCC1OptTable()); Opts->PrintHelp(llvm::outs(), "clang -cc1", "LLVM 'Clang' Compiler: http://clang.llvm.org"); return 0; } // Honor -version. // // FIXME: Use a better -version message? if (Clang.getFrontendOpts().ShowVersion) { llvm::cl::PrintVersionMessage(); return 0; } // Create the actual diagnostics engine. Clang.createDiagnostics(ArgEnd - ArgBegin, const_cast<char**>(ArgBegin)); if (!Clang.hasDiagnostics()) return 1; // Set an error handler, so that any LLVM backend diagnostics go through our // error handler. llvm::llvm_install_error_handler(LLVMErrorHandler, static_cast<void*>(&Clang.getDiagnostics())); DiagsBuffer.FlushDiagnostics(Clang.getDiagnostics()); // Load any requested plugins. for (unsigned i = 0, e = Clang.getFrontendOpts().Plugins.size(); i != e; ++i) { const std::string &Path = Clang.getFrontendOpts().Plugins[i]; std::string Error; if (llvm::sys::DynamicLibrary::LoadLibraryPermanently(Path.c_str(), &Error)) Diags.Report(diag::err_fe_unable_to_load_plugin) << Path << Error; } // If there were errors in processing arguments, don't do anything else. bool Success = false; if (!Clang.getDiagnostics().getNumErrors()) { // Create and execute the frontend action. llvm::OwningPtr<FrontendAction> Act(CreateFrontendAction(Clang)); if (Act) Success = Clang.ExecuteAction(*Act); } // Managed static deconstruction. Useful for making things like // -time-passes usable. llvm::llvm_shutdown(); return !Success; }
int cc1_main(const char **ArgBegin, const char **ArgEnd, const char *Argv0, void *MainAddr) { llvm::sys::PrintStackTraceOnErrorSignal(); llvm::PrettyStackTraceProgram X(ArgBegin - ArgEnd, ArgBegin); CompilerInstance Clang(&llvm::getGlobalContext(), false); // Run clang -cc1 test. if (ArgBegin != ArgEnd && llvm::StringRef(ArgBegin[0]) == "-cc1test") { TextDiagnosticPrinter DiagClient(llvm::errs(), DiagnosticOptions()); Diagnostic Diags(&DiagClient); return cc1_test(Diags, ArgBegin + 1, ArgEnd); } // Initialize targets first, so that --version shows registered targets. llvm::InitializeAllTargets(); llvm::InitializeAllAsmPrinters(); // Buffer diagnostics from argument parsing so that we can output them using a // well formed diagnostic object. TextDiagnosticBuffer DiagsBuffer; Diagnostic Diags(&DiagsBuffer); CompilerInvocation::CreateFromArgs(Clang.getInvocation(), ArgBegin, ArgEnd, Diags); // Infer the builtin include path if unspecified. if (Clang.getInvocation().getHeaderSearchOpts().UseBuiltinIncludes && Clang.getInvocation().getHeaderSearchOpts().ResourceDir.empty()) Clang.getInvocation().getHeaderSearchOpts().ResourceDir = CompilerInvocation::GetResourcesPath(Argv0, MainAddr); // Honor -help. if (Clang.getInvocation().getFrontendOpts().ShowHelp) { llvm::OwningPtr<driver::OptTable> Opts(driver::createCC1OptTable()); Opts->PrintHelp(llvm::outs(), "clang -cc1", "LLVM 'Clang' Compiler: http://clang.llvm.org"); return 0; } // Honor -version. // // FIXME: Use a better -version message? if (Clang.getInvocation().getFrontendOpts().ShowVersion) { llvm::cl::PrintVersionMessage(); return 0; } // Create the actual diagnostics engine. Clang.createDiagnostics(ArgEnd - ArgBegin, const_cast<char**>(ArgBegin)); if (!Clang.hasDiagnostics()) return 1; // Set an error handler, so that any LLVM backend diagnostics go through our // error handler. llvm::llvm_install_error_handler(LLVMErrorHandler, static_cast<void*>(&Clang.getDiagnostics())); DiagsBuffer.FlushDiagnostics(Clang.getDiagnostics()); // Load any requested plugins. for (unsigned i = 0, e = Clang.getFrontendOpts().Plugins.size(); i != e; ++i) { const std::string &Path = Clang.getFrontendOpts().Plugins[i]; std::string Error; if (llvm::sys::DynamicLibrary::LoadLibraryPermanently(Path.c_str(), &Error)) Diags.Report(diag::err_fe_unable_to_load_plugin) << Path << Error; } // If there were any errors in processing arguments, exit now. if (Clang.getDiagnostics().getNumErrors()) return 1; // Create the target instance. Clang.setTarget(TargetInfo::CreateTargetInfo(Clang.getDiagnostics(), Clang.getTargetOpts())); if (!Clang.hasTarget()) return 1; // Inform the target of the language options // // FIXME: We shouldn't need to do this, the target should be immutable once // created. This complexity should be lifted elsewhere. Clang.getTarget().setForcedLangOptions(Clang.getLangOpts()); // Validate/process some options if (Clang.getHeaderSearchOpts().Verbose) llvm::errs() << "clang -cc1 version " CLANG_VERSION_STRING << " based upon " << PACKAGE_STRING << " hosted on " << llvm::sys::getHostTriple() << "\n"; if (Clang.getFrontendOpts().ShowTimers) Clang.createFrontendTimer(); for (unsigned i = 0, e = Clang.getFrontendOpts().Inputs.size(); i != e; ++i) { const std::string &InFile = Clang.getFrontendOpts().Inputs[i].second; // If we aren't using an AST file, setup the file and source managers and // the preprocessor. bool IsAST = Clang.getFrontendOpts().Inputs[i].first == FrontendOptions::IK_AST; if (!IsAST) { if (!i) { // Create a file manager object to provide access to and cache the // filesystem. Clang.createFileManager(); // Create the source manager. Clang.createSourceManager(); } else { // Reset the ID tables if we are reusing the SourceManager. Clang.getSourceManager().clearIDTables(); } // Create the preprocessor. Clang.createPreprocessor(); } llvm::OwningPtr<FrontendAction> Act(CreateFrontendAction(Clang)); if (!Act) break; if (Act->BeginSourceFile(Clang, InFile, IsAST)) { Act->Execute(); Act->EndSourceFile(); } } if (Clang.getDiagnosticOpts().ShowCarets) if (unsigned NumDiagnostics = Clang.getDiagnostics().getNumDiagnostics()) fprintf(stderr, "%d diagnostic%s generated.\n", NumDiagnostics, (NumDiagnostics == 1 ? "" : "s")); if (Clang.getFrontendOpts().ShowStats) { Clang.getFileManager().PrintStats(); fprintf(stderr, "\n"); } // Return the appropriate status when verifying diagnostics. // // FIXME: If we could make getNumErrors() do the right thing, we wouldn't need // this. if (Clang.getDiagnosticOpts().VerifyDiagnostics) return static_cast<VerifyDiagnosticsClient&>( Clang.getDiagnosticClient()).HadErrors(); // Managed static deconstruction. Useful for making things like // -time-passes usable. llvm::llvm_shutdown(); return (Clang.getDiagnostics().getNumErrors() != 0); }