예제 #1
0
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;
}
예제 #2
0
/// 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;
}
예제 #3
0
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;
}
예제 #4
0
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;
}
예제 #5
0
/// 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;
}
예제 #6
0
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();
}
예제 #7
0
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();
}
예제 #8
0
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;
}
예제 #11
0
파일: cc1_main.cpp 프로젝트: aaasz/SHP
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);
}