コード例 #1
0
ファイル: LibclangTest.cpp プロジェクト: CODECOMMUNITY/clang
TEST_F(LibclangReparseTest, ReparseWithModule) {
  const char *HeaderTop = "#ifndef H\n#define H\nstruct Foo { int bar;";
  const char *HeaderBottom = "\n};\n#endif\n";
  const char *MFile = "#include \"HeaderFile.h\"\nint main() {"
                         " struct Foo foo; foo.bar = 7; foo.baz = 8; }\n";
  const char *ModFile = "module A { header \"HeaderFile.h\" }\n";
  std::string HeaderName = "HeaderFile.h";
  std::string MName = "MFile.m";
  std::string ModName = "module.modulemap";
  WriteFile(MName, MFile);
  WriteFile(HeaderName, std::string(HeaderTop) + HeaderBottom);
  WriteFile(ModName, ModFile);

  std::string ModulesCache = std::string("-fmodules-cache-path=") + TestDir;
  const char *Args[] = { "-fmodules", ModulesCache.c_str(),
                         "-I", TestDir.c_str() };
  int NumArgs = sizeof(Args) / sizeof(Args[0]);
  ClangTU = clang_parseTranslationUnit(Index, MName.c_str(), Args, NumArgs,
                                       nullptr, 0, TUFlags);
  EXPECT_EQ(1U, clang_getNumDiagnostics(ClangTU));
  DisplayDiagnostics();

  // Immedaitely reparse.
  ASSERT_TRUE(ReparseTU(0, nullptr /* No unsaved files. */));
  EXPECT_EQ(1U, clang_getNumDiagnostics(ClangTU));

  std::string NewHeaderContents =
      std::string(HeaderTop) + "int baz;" + HeaderBottom;
  WriteFile(HeaderName, NewHeaderContents);

  // Reparse after fix.
  ASSERT_TRUE(ReparseTU(0, nullptr /* No unsaved files. */));
  EXPECT_EQ(0U, clang_getNumDiagnostics(ClangTU));
}
コード例 #2
0
ファイル: LibclangTest.cpp プロジェクト: CODECOMMUNITY/clang
TEST_F(LibclangReparseTest, Reparse) {
  const char *HeaderTop = "#ifndef H\n#define H\nstruct Foo { int bar;";
  const char *HeaderBottom = "\n};\n#endif\n";
  const char *CppFile = "#include \"HeaderFile.h\"\nint main() {"
                         " Foo foo; foo.bar = 7; foo.baz = 8; }\n";
  std::string HeaderName = "HeaderFile.h";
  std::string CppName = "CppFile.cpp";
  WriteFile(CppName, CppFile);
  WriteFile(HeaderName, std::string(HeaderTop) + HeaderBottom);

  ClangTU = clang_parseTranslationUnit(Index, CppName.c_str(), nullptr, 0,
                                       nullptr, 0, TUFlags);
  EXPECT_EQ(1U, clang_getNumDiagnostics(ClangTU));
  DisplayDiagnostics();

  // Immedaitely reparse.
  ASSERT_TRUE(ReparseTU(0, nullptr /* No unsaved files. */));
  EXPECT_EQ(1U, clang_getNumDiagnostics(ClangTU));

  std::string NewHeaderContents =
      std::string(HeaderTop) + "int baz;" + HeaderBottom;
  WriteFile(HeaderName, NewHeaderContents);

  // Reparse after fix.
  ASSERT_TRUE(ReparseTU(0, nullptr /* No unsaved files. */));
  EXPECT_EQ(0U, clang_getNumDiagnostics(ClangTU));
}
コード例 #3
0
ファイル: ClangInstanceTest.cpp プロジェクト: BlackMac/mo
void ClangInstanceTest::testGetTranslationUnit() {
  const char * const argv[] = { "test/samples/HelloWorld.m" };
  _instance->compileSourceFileToTranslationUnit(argv, 1);
  CXTranslationUnit translationUnit = _instance->getTranslationUnit();
  TS_ASSERT(translationUnit);
  TS_ASSERT(!clang_getNumDiagnostics(translationUnit));
}
コード例 #4
0
/* Handle syntax checking request, message format:
       source_length: [#src_length#]
       <# SOURCE CODE #>
*/
void completion_doSyntaxCheck(completion_Session *session, FILE *fp)
{
    unsigned int i_diag = 0, n_diag;
    CXDiagnostic diag;
    CXString     dmsg;

    /* get a copy of fresh source file */
    completion_readSourcefile(session, fp);

    /* reparse the source to retrieve diagnostic message */
    completion_reparseTranslationUnit(session);

    /* dump all diagnostic messages to fp */
    n_diag = clang_getNumDiagnostics(session->cx_tu);
    for ( ; i_diag < n_diag; i_diag++)
    {
        diag = clang_getDiagnostic(session->cx_tu, i_diag);
        dmsg = clang_formatDiagnostic(diag, clang_defaultDiagnosticDisplayOptions());
        fprintf(stdout, "%s\n", clang_getCString(dmsg));
        clang_disposeString(dmsg);
        clang_disposeDiagnostic(diag);
    }

    fprintf(stdout, "$"); fflush(stdout);    /* end of output */
}
コード例 #5
0
    std::vector<diagnostic> translation_unit::diagnose() {
        // Get all the diagnostics
        uint32_t n = clang_getNumDiagnostics(mUnit);

        if (n == 0)
            return {};

        std::vector<diagnostic> ret;
        ret.reserve(n);

        for (uint32_t i = 0; i < n; ++i) {
            CXFile file;
            uint32_t row = 0, col = 0, offset = 0;

            CXDiagnostic diag = clang_getDiagnostic(mUnit, i);
            CXSourceLocation loc = clang_getDiagnosticLocation(diag);
            clang_getExpansionLocation( loc, &file, &row, &col, &offset );

            ret.push_back({
                { cx2std(clang_getFileName(file)), row, col },
                clang_getDiagnosticSeverity(diag),
                diagnostic_text(diag),
                diagnostic_summary(diag)
            });

            clang_disposeDiagnostic(diag);
        }

        return ret;
    }
コード例 #6
0
ファイル: c-index-test.c プロジェクト: albertz/clang
void PrintDiagnostics(CXTranslationUnit TU) {
  int i, n = clang_getNumDiagnostics(TU);
  for (i = 0; i != n; ++i) {
    CXDiagnostic Diag = clang_getDiagnostic(TU, i);
    PrintDiagnostic(Diag);
    clang_disposeDiagnostic(Diag);
  }
}
コード例 #7
0
void TranslationUnit::updateDiagnostic()
{
    for (auto i = 0u, last = clang_getNumDiagnostics(m_unit); i < last; ++i)
    {
        clang::DCXDiagnostic diag = {clang_getDiagnostic(m_unit, i)};
        appendDiagnostic(diag);
    }
}
コード例 #8
0
ファイル: clic_add.cpp プロジェクト: gurjeet/clang_indexer
int main(int argc, const char* argv[]) {
    if (argc < 4) {
        std::cerr << "Usage:\n"
            << "    " << argv[0] << " <dbFilename> <indexFilename> [<options>] <sourceFilename>\n";
        return 1;
    }

    const char* dbFilename = argv[1];
    const char* indexFilename = argv[2];
    const char* sourceFilename = argv[argc-1];

    // Set up the clang translation unit
    CXIndex cxindex = clang_createIndex(0, 0);
    CXTranslationUnit tu = clang_parseTranslationUnit(
        cxindex, 0,
        argv + 3, argc - 3, // Skip over dbFilename and indexFilename
        0, 0,
        CXTranslationUnit_None);

    // Print any errors or warnings
    int n = clang_getNumDiagnostics(tu);
    if (n > 0) {
        int nErrors = 0;
        for (unsigned i = 0; i != n; ++i) {
            CXDiagnostic diag = clang_getDiagnostic(tu, i);
            CXString string = clang_formatDiagnostic(diag, clang_defaultDiagnosticDisplayOptions());
            fprintf(stderr, "%s\n", clang_getCString(string));
            if (clang_getDiagnosticSeverity(diag) == CXDiagnostic_Error
                    || clang_getDiagnosticSeverity(diag) == CXDiagnostic_Fatal)
                nErrors++;
        }
    }

    // Create the index
    EverythingIndexer visitor(sourceFilename);
    clang_visitChildren(
            clang_getTranslationUnitCursor(tu),
            &visitorFunction,
            &visitor);
    ClicIndex& index = visitor.usrToReferences;

    // OK, now write the index to a compressed file
    std::ofstream fout(indexFilename);
    boost::iostreams::filtering_stream<boost::iostreams::output> zout;
    zout.push(boost::iostreams::gzip_compressor());
    zout.push(fout);
    printIndex(zout, index);

    // Now open the database and add the index to it
    ClicDb db(dbFilename);

    BOOST_FOREACH(const ClicIndex::value_type& it, index) {
        const std::string& usr = it.first;
        db.addMultiple(usr, it.second);
    }

    return 0;
}
コード例 #9
0
ファイル: LibclangTest.cpp プロジェクト: CODECOMMUNITY/clang
 void DisplayDiagnostics() {
   unsigned NumDiagnostics = clang_getNumDiagnostics(ClangTU);
   for (unsigned i = 0; i < NumDiagnostics; ++i) {
     auto Diag = clang_getDiagnostic(ClangTU, i);
     DEBUG(llvm::dbgs() << clang_getCString(clang_formatDiagnostic(
         Diag, clang_defaultDiagnosticDisplayOptions())) << "\n");
     clang_disposeDiagnostic(Diag);
   }
 }
コード例 #10
0
ファイル: Irony.cpp プロジェクト: Aionios/irony-mode
void Irony::check(const std::string &file,
                  const std::vector<std::string> &flags,
                  const std::vector<CXUnsavedFile> &unsavedFiles) {
  std::cout << "(";

  unsigned numDiag = 0;
  int fatals = 0;
  int errors = 0;
  int warnings = 0;

  CXTranslationUnit tu = tuManager_.parse(file, flags, unsavedFiles);

  if (tu) {
    numDiag = clang_getNumDiagnostics(tu);
  } else {
    fatals = 1;
  }

  for (unsigned i = 0; i < numDiag; ++i) {
    CXDiagnostic diagnostic = clang_getDiagnostic(tu, i);

    switch (clang_getDiagnosticSeverity(diagnostic)) {
    case CXDiagnostic_Fatal:
      fatals++;
      break;

    case CXDiagnostic_Error:
      errors++;
      break;

    case CXDiagnostic_Warning:
      warnings++;
      break;

    default:
      break;
    }

    clang_disposeDiagnostic(diagnostic);
  }

  if (fatals > 0)
    std::cout << " :fatals " << fatals;

  if (errors > 0)
    std::cout << " :errors " << errors;

  if (warnings > 0)
    std::cout << " :warnings " << warnings;

  std::cout << ")\n";
}
コード例 #11
0
ファイル: ffigen.c プロジェクト: iamaaditya/cshore
int main(int argc, const char* const argv[]){
  if (argc < 2) {
    printf("Usage: %s header.h\n", argv[0]);
    printf("Standard clang arguments (-I, -D, etc.) may be used\n");
    exit(1);
  }
  unsigned i;

  char filename[] = "ffigen.tmp.XXXXXX";
  int fd = mkstemp(filename);
  FILE* file = fdopen(fd, "w");
  fprintf(file, "#define _SIZE_T\n");
  fprintf(file, "#define _PTRDIFF_T\n");
  fprintf(file, "typedef __SIZE_TYPE__ size_t;\n");
  fprintf(file, "typedef __PTRDIFF_TYPE__ ptrdiff_t;\n");
  fprintf(file, "#include <%s>\n", argv[1]);
  fclose(file);

  int clang_argc = argc + 1;
  const char** clang_argv = malloc(sizeof(char*) * clang_argc);
  clang_argv[0] = "-x";
  clang_argv[1] = "c";
  clang_argv[2] = filename;
  for (i=3; i < clang_argc; i++) {
    clang_argv[i] = argv[i-1];
  }

  CXIndex Index = clang_createIndex(0, 0);
  TU = clang_parseTranslationUnit(Index, 0, clang_argv, clang_argc,
                                  0, 0, CXTranslationUnit_DetailedPreprocessingRecord);
  json_t* json = json_object();
  clang_visitChildren(clang_getTranslationUnitCursor(TU), visit_program, (CXClientData)json);


  json_dumpf(json, stdout, JSON_INDENT(2) | JSON_PRESERVE_ORDER);
  printf("\n");
  json_decref(json);


  for (i=0; i<clang_getNumDiagnostics(TU); i++) {
    putstring(clang_formatDiagnostic(clang_getDiagnostic(TU, i), clang_defaultDiagnosticDisplayOptions()));
  }


  clang_disposeTranslationUnit(TU);
  clang_disposeIndex(Index);
  free(clang_argv);
  unlink(filename);

  return 0;
}
コード例 #12
0
ファイル: Irony.cpp プロジェクト: cahlbin/irony-mode
static void dumpDiagnostics(const CXTranslationUnit &tu) {
  std::cout << "(\n";

  std::string file;

  for (unsigned i = 0, diagnosticCount = clang_getNumDiagnostics(tu);
       i < diagnosticCount;
       ++i) {
    CXDiagnostic diagnostic = clang_getDiagnostic(tu, i);

    CXSourceLocation location = clang_getDiagnosticLocation(diagnostic);

    unsigned line, column, offset;
    if (clang_equalLocations(location, clang_getNullLocation())) {
      file.clear();
      line = 0;
      column = 0;
      offset = 0;
    } else {
      CXFile cxFile;

// clang_getInstantiationLocation() has been marked deprecated and
// is aimed to be replaced by clang_getExpansionLocation().
#if CINDEX_VERSION >= 6
      clang_getExpansionLocation(location, &cxFile, &line, &column, &offset);
#else
      clang_getInstantiationLocation(location, &cxFile, &line, &column, &offset);
#endif

      file = cxStringToStd(clang_getFileName(cxFile));
    }

    const char *severity = diagnosticSeverity(diagnostic);

    std::string message =
        cxStringToStd(clang_getDiagnosticSpelling(diagnostic));

    std::cout << '(' << support::quoted(file)    //
              << ' ' << line                     //
              << ' ' << column                   //
              << ' ' << offset                   //
              << ' ' << severity                 //
              << ' ' << support::quoted(message) //
              << ")\n";

    clang_disposeDiagnostic(diagnostic);
  }

  std::cout << ")\n";
}
コード例 #13
0
ファイル: clang_utils.cpp プロジェクト: AndrianDTR/codelite
void ClangUtils::printDiagnosticsToLog(CXTranslationUnit& TU)
{
	//// Report diagnostics to the log file
	const unsigned diagCount = clang_getNumDiagnostics(TU);
	for(unsigned i=0; i<diagCount; i++) {
		CXDiagnostic diag     = clang_getDiagnostic(TU, i);
		CXString diagStr      = clang_formatDiagnostic(diag, clang_defaultDiagnosticDisplayOptions());
		wxString wxDiagString = wxString(clang_getCString(diagStr), wxConvUTF8);
		if(!wxDiagString.Contains(wxT("'dllimport' attribute"))) {
			CL_DEBUG(wxT("Diagnostic: %s"), wxDiagString.c_str());

		}
		clang_disposeString(diagStr);
		clang_disposeDiagnostic(diag);
	}
}
コード例 #14
0
void TranslationUnit::UpdateLatestDiagnostics() {
  unique_lock< mutex > lock1( clang_access_mutex_ );
  unique_lock< mutex > lock2( diagnostics_mutex_ );

  latest_diagnostics_.clear();
  size_t num_diagnostics = clang_getNumDiagnostics( clang_translation_unit_ );
  latest_diagnostics_.reserve( num_diagnostics );

  for ( size_t i = 0; i < num_diagnostics; ++i ) {
    Diagnostic diagnostic =
      BuildDiagnostic(
        DiagnosticWrap( clang_getDiagnostic( clang_translation_unit_, i ),
                        clang_disposeDiagnostic ),
        clang_translation_unit_ );

    if ( diagnostic.kind_ != INFORMATION )
      latest_diagnostics_.push_back( diagnostic );
  }
}
コード例 #15
0
ファイル: Highlighter.cpp プロジェクト: animatedb/oovaide
OovStringVec Tokenizer::getDiagResults()
    {
    OovStringVec diagResults;
    if(mTransUnit)
        {
        int numDiags = clang_getNumDiagnostics(mTransUnit);
        for (int i = 0; i<numDiags && diagResults.size() < 10; i++)
            {
            CXDiagnostic diag = clang_getDiagnostic(mTransUnit, i);
//          CXDiagnosticSeverity sev = clang_getDiagnosticSeverity(diag);
//          if(sev >= CXDiagnostic_Error)
            OovString diagStr = getDisposedString(clang_formatDiagnostic(diag,
                clang_defaultDiagnosticDisplayOptions()));
            if(diagStr.find(mSourceFilename) != std::string::npos)
                {
                diagResults.push_back(diagStr);
                }
            }
        }
    return diagResults;
    }
コード例 #16
0
ファイル: clangtest.c プロジェクト: HackerFoo/rtags
int main(int argc, char **argv)
{
    if (argc < 2)
        return 1;
    CXIndex index = clang_createIndex(1, 1);
    const char * const *args = 0;
    if (argc > 2)
        args = (const char *const *)&argv[2];

    CXTranslationUnit unit = clang_parseTranslationUnit(index, argv[1], args, argc - 2,
                                                        0, 0, clang_defaultEditingTranslationUnitOptions());
    if (unit) {
        int indent = 0;
        clang_visitChildren(clang_getTranslationUnitCursor(unit), visit, &indent);

        const unsigned int diagnosticCount = clang_getNumDiagnostics(unit);
        unsigned int i;
        for (i=0; i<diagnosticCount; ++i) {
            CXDiagnostic diagnostic = clang_getDiagnostic(unit, i);
            const unsigned int diagnosticOptions = (CXDiagnostic_DisplaySourceLocation|
                                                CXDiagnostic_DisplayColumn|
                                                CXDiagnostic_DisplaySourceRanges|
                                                CXDiagnostic_DisplayOption|
                                                CXDiagnostic_DisplayCategoryId|
                                                CXDiagnostic_DisplayCategoryName);
            CXString diagnosticText = clang_formatDiagnostic(diagnostic, diagnosticOptions);
            const char *cstr = clang_getCString(diagnosticText);
            if (cstr)
                printf("%s\n", cstr);
            clang_disposeString(diagnosticText);
        }
        clang_disposeTranslationUnit(unit);
    }
    clang_disposeIndex(index);
    return 0;
}
コード例 #17
0
ファイル: clangparser.cpp プロジェクト: Acidburn0zzz/doxygen
void ClangParser::start(const char *fileName,QStrList &filesInTranslationUnit)
{
  static bool clangAssistedParsing = Config_getBool("CLANG_ASSISTED_PARSING");
  static QStrList &includePath = Config_getList("INCLUDE_PATH");
  static QStrList clangOptions = Config_getList("CLANG_OPTIONS");
  if (!clangAssistedParsing) return;
  //printf("ClangParser::start(%s)\n",fileName);
  p->fileName = fileName;
  p->index    = clang_createIndex(0, 0);
  p->curLine  = 1;
  p->curToken = 0;
  char **argv = (char**)malloc(sizeof(char*)*(4+Doxygen::inputPaths.count()+includePath.count()+clangOptions.count()));
  QDictIterator<void> di(Doxygen::inputPaths);
  int argc=0;
  // add include paths for input files
  for (di.toFirst();di.current();++di,++argc)
  {
    QCString inc = QCString("-I")+di.currentKey();
    argv[argc]=strdup(inc.data());
    //printf("argv[%d]=%s\n",argc,argv[argc]);
  }
  // add external include paths
  for (uint i=0;i<includePath.count();i++)
  {
    QCString inc = QCString("-I")+includePath.at(i);
    argv[argc++]=strdup(inc.data());
  }
  // user specified options
  for (uint i=0;i<clangOptions.count();i++)
  {
    argv[argc++]=strdup(clangOptions.at(i));
  }
  // extra options
  argv[argc++]=strdup("-ferror-limit=0");
  argv[argc++]=strdup("-x");

  // Since we can be presented with a .h file that can contain C/C++ or
  // Objective C code and we need to configure the parser before knowing this,
  // we use the source file to detected the language. Detection will fail if you
  // pass a bunch of .h files containing ObjC code, and no sources :-(
  SrcLangExt lang = getLanguageFromFileName(fileName);
  if (lang==SrcLangExt_ObjC || p->detectedLang!=ClangParser::Private::Detected_Cpp)
  {
    QCString fn = fileName;
    if (p->detectedLang==ClangParser::Private::Detected_Cpp && 
        (fn.right(4).lower()==".cpp" || fn.right(4).lower()==".cxx" ||
         fn.right(3).lower()==".cc" || fn.right(2).lower()==".c"))
    { // fall back to C/C++ once we see an extension that indicates this
      p->detectedLang = ClangParser::Private::Detected_Cpp;
    }
    else if (fn.right(3).lower()==".mm") // switch to Objective C++
    {
      p->detectedLang = ClangParser::Private::Detected_ObjCpp;
    }
    else if (fn.right(2).lower()==".m") // switch to Objective C
    {
      p->detectedLang = ClangParser::Private::Detected_ObjC;
    }
  }
  switch(p->detectedLang)
  {
    case ClangParser::Private::Detected_Cpp: 
      argv[argc++]=strdup("c++"); 
      break;
    case ClangParser::Private::Detected_ObjC: 
      argv[argc++]=strdup("objective-c"); 
      break;
    case ClangParser::Private::Detected_ObjCpp: 
      argv[argc++]=strdup("objective-c++"); 
      break;
  }

  // provide the input and and its dependencies as unsaved files so we can
  // pass the filtered versions
  argv[argc++]=strdup(fileName);
  static bool filterSourceFiles = Config_getBool("FILTER_SOURCE_FILES");
  //printf("source %s ----------\n%s\n-------------\n\n",
  //    fileName,p->source.data());
  uint numUnsavedFiles = filesInTranslationUnit.count()+1;
  p->numFiles = numUnsavedFiles;
  p->sources = new QCString[numUnsavedFiles];
  p->ufs     = new CXUnsavedFile[numUnsavedFiles];
  p->sources[0]      = detab(fileToString(fileName,filterSourceFiles,TRUE));
  p->ufs[0].Filename = strdup(fileName);
  p->ufs[0].Contents = p->sources[0].data();
  p->ufs[0].Length   = p->sources[0].length();
  QStrListIterator it(filesInTranslationUnit);
  uint i=1;
  for (it.toFirst();it.current() && i<numUnsavedFiles;++it,i++)
  {
    p->fileMapping.insert(it.current(),new uint(i));
    p->sources[i]      = detab(fileToString(it.current(),filterSourceFiles,TRUE));
    p->ufs[i].Filename = strdup(it.current());
    p->ufs[i].Contents = p->sources[i].data();
    p->ufs[i].Length   = p->sources[i].length();
  }

  // let libclang do the actual parsing
  p->tu = clang_parseTranslationUnit(p->index, 0,
                                     argv, argc, p->ufs, numUnsavedFiles, 
                                     CXTranslationUnit_DetailedPreprocessingRecord);
  // free arguments
  for (int i=0;i<argc;++i)
  {
    free(argv[i]);
  }
  free(argv);

  if (p->tu)
  {
    // filter out any includes not found by the clang parser
    determineInputFilesInSameTu(filesInTranslationUnit);

    // show any warnings that the compiler produced
    for (uint i=0, n=clang_getNumDiagnostics(p->tu); i!=n; ++i) 
    {
      CXDiagnostic diag = clang_getDiagnostic(p->tu, i); 
      CXString string = clang_formatDiagnostic(diag,
          clang_defaultDiagnosticDisplayOptions()); 
      err("%s [clang]\n",clang_getCString(string));
      clang_disposeString(string);
      clang_disposeDiagnostic(diag);
    }

    // create a source range for the given file
    QFileInfo fi(fileName);
    CXFile f = clang_getFile(p->tu, fileName);
    CXSourceLocation fileBegin = clang_getLocationForOffset(p->tu, f, 0);
    CXSourceLocation fileEnd   = clang_getLocationForOffset(p->tu, f, p->ufs[0].Length);
    CXSourceRange    fileRange = clang_getRange(fileBegin, fileEnd);

    // produce a token stream for the file
    clang_tokenize(p->tu,fileRange,&p->tokens,&p->numTokens);

    // produce cursors for each token in the stream
    p->cursors=new CXCursor[p->numTokens];
    clang_annotateTokens(p->tu,p->tokens,p->numTokens,p->cursors);
  }
  else
  {
    p->tokens    = 0;
    p->numTokens = 0;
    p->cursors   = 0;
    err("clang: Failed to parse translation unit %s\n",fileName);
  }
}
コード例 #18
0
ファイル: IndexerJob.cpp プロジェクト: jbulow/rtags
bool IndexerJob::diagnose(int build, int *errorCount)
{
    if (errorCount)
        *errorCount = 0;
    if (!mUnits.at(build).second) {
        abort();
        return false;
    }

    List<String> compilationErrors;
    const unsigned diagnosticCount = clang_getNumDiagnostics(mUnits.at(build).second);
    const unsigned options = Server::instance()->options().options;

    for (unsigned i=0; i<diagnosticCount; ++i) {
        CXDiagnostic diagnostic = clang_getDiagnostic(mUnits.at(build).second, i);
        int logLevel = INT_MAX;
        const CXDiagnosticSeverity severity = clang_getDiagnosticSeverity(diagnostic);
        switch (severity) {
        case CXDiagnostic_Fatal:
        case CXDiagnostic_Error:
            if (errorCount)
                ++*errorCount;
            logLevel = Error;
            break;
        case CXDiagnostic_Warning:
            logLevel = Warning;
            break;
        case CXDiagnostic_Note:
            logLevel = Debug;
            break;
        case CXDiagnostic_Ignored:
            break;
        }

        const unsigned diagnosticOptions = (CXDiagnostic_DisplaySourceLocation|
                                            CXDiagnostic_DisplayColumn|
                                            CXDiagnostic_DisplaySourceRanges|
                                            CXDiagnostic_DisplayOption|
                                            CXDiagnostic_DisplayCategoryId|
                                            CXDiagnostic_DisplayCategoryName);
        const uint32_t fileId = createLocation(clang_getDiagnosticLocation(diagnostic), 0).fileId();
        if (mVisitedFiles.contains(fileId)) {
            const String text = RTags::eatString(clang_formatDiagnostic(diagnostic, diagnosticOptions));
            if (testLog(logLevel) || testLog(CompilationError)) {
                log(logLevel, "%s: %s => %s", mSourceInformation.sourceFile.constData(), mClangLines.at(build).constData(), text.constData());
                compilationErrors.append(text);
            }

            const unsigned fixItCount = clang_getDiagnosticNumFixIts(diagnostic);
            RegExp rx;
            if (options & Server::IgnorePrintfFixits) {
                rx = "^%[A-Za-z0-9]\\+$";
            }
            for (unsigned f=0; f<fixItCount; ++f) {
                CXSourceRange range;
                const String string = RTags::eatString(clang_getDiagnosticFixIt(diagnostic, f, &range));
                unsigned startOffset;
                CXFile file;
                clang_getSpellingLocation(clang_getRangeStart(range), &file, 0, 0, &startOffset);
                unsigned endOffset;
                clang_getSpellingLocation(clang_getRangeEnd(range), 0, 0, 0, &endOffset);
                const Location loc(file, startOffset);
                if (options & Server::IgnorePrintfFixits && rx.indexIn(string) == 0) {
                    error("Ignored fixit for %s: Replace %d-%d with [%s]", loc.path().constData(),
                          startOffset, endOffset, string.constData());
                } else {
                    error("Fixit for %s: Replace %d-%d with [%s]", loc.path().constData(),
                          startOffset, endOffset, string.constData());
                    compilationErrors.append(String::format<128>("Fixit for %s: Replace %d-%d with [%s]", loc.path().constData(),
                                                                 startOffset, endOffset, string.constData()));
                    mData->fixIts[loc.fileId()].insert(FixIt(startOffset, endOffset, string));
                }
            }
        }

        clang_disposeDiagnostic(diagnostic);
    }
    if (testLog(CompilationError))
        sendDiagnostics(compilationErrors);
    return !isAborted();
}
コード例 #19
0
ファイル: clang++.cpp プロジェクト: mythagel/cxxide
unsigned translation_unit::num_diagnostics()
{
    return clang_getNumDiagnostics(tu);
}
コード例 #20
0
ファイル: clangparser.cpp プロジェクト: bithium/doxygen
void ClangParser::start(const char *fileName,QStrList &filesInTranslationUnit)
{
  static bool clangAssistedParsing = Config_getBool(CLANG_ASSISTED_PARSING);
  static QStrList &includePath = Config_getList(INCLUDE_PATH);
  static QStrList clangOptions = Config_getList(CLANG_OPTIONS);
  static QCString clangCompileDatabase = Config_getList(CLANG_COMPILATION_DATABASE_PATH);
  if (!clangAssistedParsing) return;
  //printf("ClangParser::start(%s)\n",fileName);
  p->fileName = fileName;
  p->index    = clang_createIndex(0, 0);
  p->curLine  = 1;
  p->curToken = 0;
  QDictIterator<void> di(Doxygen::inputPaths);
  int argc=0;
  std::string error;
  // load a clang compilation database (https://clang.llvm.org/docs/JSONCompilationDatabase.html)
  // this only needs to be loaded once, and could be refactored to a higher level function
  static std::unique_ptr<clang::tooling::CompilationDatabase> db =
      clang::tooling::CompilationDatabase::loadFromDirectory(clangCompileDatabase.data(), error);
  int clang_option_len = 0;
  std::vector<clang::tooling::CompileCommand> command;
  if (strcmp(clangCompileDatabase, "0") != 0) {
      if (db == nullptr) {
          // user specified a path, but DB file was not found
          err("%s using clang compilation database path of: \"%s\"\n", error.c_str(),
              clangCompileDatabase.data());
      } else {
          // check if the file we are parsing is in the DB
          command = db->getCompileCommands(fileName);
          if (!command.empty() ) {
              // it's possible to have multiple entries for the same file, so use the last entry
              clang_option_len = command[command.size()-1].CommandLine.size();
          }
      }
  }
  char **argv = (char**)malloc(sizeof(char*)*(4+Doxygen::inputPaths.count()+includePath.count()+clangOptions.count()+clang_option_len));
  if (!command.empty() ) {
      std::vector<std::string> options = command[command.size()-1].CommandLine;
      // copy each compiler option used from the database. Skip the first which is compiler exe.
      for (auto option = options.begin()+1; option != options.end(); option++) {
          argv[argc++] = strdup(option->c_str());
      }
      // this extra addition to argv is accounted for as we are skipping the first entry in
      argv[argc++]=strdup("-w"); // finally, turn off warnings.
  } else {
  // add include paths for input files
  for (di.toFirst();di.current();++di,++argc)
  {
    QCString inc = QCString("-I")+di.currentKey();
    argv[argc]=strdup(inc.data());
    //printf("argv[%d]=%s\n",argc,argv[argc]);
  }
  // add external include paths
  for (uint i=0;i<includePath.count();i++)
  {
    QCString inc = QCString("-I")+includePath.at(i);
    argv[argc++]=strdup(inc.data());
  }
  // user specified options
  for (uint i=0;i<clangOptions.count();i++)
  {
    argv[argc++]=strdup(clangOptions.at(i));
  }
  // extra options
  argv[argc++]=strdup("-ferror-limit=0");
  argv[argc++]=strdup("-x");

  // Since we can be presented with a .h file that can contain C/C++ or
  // Objective C code and we need to configure the parser before knowing this,
  // we use the source file to detected the language. Detection will fail if you
  // pass a bunch of .h files containing ObjC code, and no sources :-(
  SrcLangExt lang = getLanguageFromFileName(fileName);
  if (lang==SrcLangExt_ObjC || p->detectedLang!=ClangParser::Private::Detected_Cpp)
  {
    QCString fn = fileName;
    if (p->detectedLang==ClangParser::Private::Detected_Cpp && 
        (fn.right(4).lower()==".cpp" || fn.right(4).lower()==".cxx" ||
         fn.right(3).lower()==".cc" || fn.right(2).lower()==".c"))
    { // fall back to C/C++ once we see an extension that indicates this
      p->detectedLang = ClangParser::Private::Detected_Cpp;
    }
    else if (fn.right(3).lower()==".mm") // switch to Objective C++
    {
      p->detectedLang = ClangParser::Private::Detected_ObjCpp;
    }
    else if (fn.right(2).lower()==".m") // switch to Objective C
    {
      p->detectedLang = ClangParser::Private::Detected_ObjC;
    }
  }
  switch(p->detectedLang)
  {
    case ClangParser::Private::Detected_Cpp: 
      argv[argc++]=strdup("c++"); 
      break;
    case ClangParser::Private::Detected_ObjC: 
      argv[argc++]=strdup("objective-c"); 
      break;
    case ClangParser::Private::Detected_ObjCpp: 
      argv[argc++]=strdup("objective-c++"); 
      break;
  }

  // provide the input and and its dependencies as unsaved files so we can
  // pass the filtered versions
  argv[argc++]=strdup(fileName);
  }
  static bool filterSourceFiles = Config_getBool(FILTER_SOURCE_FILES);
  //printf("source %s ----------\n%s\n-------------\n\n",
  //    fileName,p->source.data());
  uint numUnsavedFiles = filesInTranslationUnit.count()+1;
  p->numFiles = numUnsavedFiles;
  p->sources = new QCString[numUnsavedFiles];
  p->ufs     = new CXUnsavedFile[numUnsavedFiles];
  p->sources[0]      = detab(fileToString(fileName,filterSourceFiles,TRUE));
  p->ufs[0].Filename = strdup(fileName);
  p->ufs[0].Contents = p->sources[0].data();
  p->ufs[0].Length   = p->sources[0].length();
  QStrListIterator it(filesInTranslationUnit);
  uint i=1;
  for (it.toFirst();it.current() && i<numUnsavedFiles;++it,i++)
  {
    p->fileMapping.insert(it.current(),new uint(i));
    p->sources[i]      = detab(fileToString(it.current(),filterSourceFiles,TRUE));
    p->ufs[i].Filename = strdup(it.current());
    p->ufs[i].Contents = p->sources[i].data();
    p->ufs[i].Length   = p->sources[i].length();
  }

  // let libclang do the actual parsing
  p->tu = clang_parseTranslationUnit(p->index, 0,
                                     argv, argc, p->ufs, numUnsavedFiles, 
                                     CXTranslationUnit_DetailedPreprocessingRecord);
  // free arguments
  for (int i=0;i<argc;++i)
  {
    free(argv[i]);
  }
  free(argv);

  if (p->tu)
  {
    // filter out any includes not found by the clang parser
    determineInputFilesInSameTu(filesInTranslationUnit);

    // show any warnings that the compiler produced
    for (uint i=0, n=clang_getNumDiagnostics(p->tu); i!=n; ++i) 
    {
      CXDiagnostic diag = clang_getDiagnostic(p->tu, i); 
      CXString string = clang_formatDiagnostic(diag,
          clang_defaultDiagnosticDisplayOptions()); 
      err("%s [clang]\n",clang_getCString(string));
      clang_disposeString(string);
      clang_disposeDiagnostic(diag);
    }

    // create a source range for the given file
    QFileInfo fi(fileName);
    CXFile f = clang_getFile(p->tu, fileName);
    CXSourceLocation fileBegin = clang_getLocationForOffset(p->tu, f, 0);
    CXSourceLocation fileEnd   = clang_getLocationForOffset(p->tu, f, p->ufs[0].Length);
    CXSourceRange    fileRange = clang_getRange(fileBegin, fileEnd);

    // produce a token stream for the file
    clang_tokenize(p->tu,fileRange,&p->tokens,&p->numTokens);

    // produce cursors for each token in the stream
    p->cursors=new CXCursor[p->numTokens];
    clang_annotateTokens(p->tu,p->tokens,p->numTokens,p->cursors);
  }
  else
  {
    p->tokens    = 0;
    p->numTokens = 0;
    p->cursors   = 0;
    err("clang: Failed to parse translation unit %s\n",fileName);
  }
}
コード例 #21
0
ファイル: CppInstr.cpp プロジェクト: animatedb/oovaide
CppInstr::eErrorTypes CppInstr::parse(OovStringRef const srcFn, OovStringRef const srcRootDir,
        OovStringRef const outDir,
        char const * const clang_args[], int num_clang_args)
    {
    eErrorTypes errType = ET_None;

    mOutputFileContents.read(srcFn);
    mTopParseFn.setPath(srcFn, FP_File);
    FilePath rootDir(srcRootDir, FP_Dir);
    setFileDefine(mTopParseFn, rootDir);

    CXIndex index = clang_createIndex(1, 1);

// This doesn't appear to change anything.
//    clang_toggleCrashRecovery(true);
    // Get inclusion directives to be in AST.
    unsigned options = 0;
    CXTranslationUnit tu;
    CXErrorCode errCode = clang_parseTranslationUnit2(index, srcFn,
        clang_args, num_clang_args, 0, 0, options, &tu);
    if(errCode == CXError_Success)
        {
        CXCursor rootCursor = clang_getTranslationUnitCursor(tu);
        try
            {
            clang_visitChildren(rootCursor, ::visitTranslationUnit, this);
            }
        catch(...)
            {
            errType = ET_ParseError;
            sCrashDiagnostics.setCrashed();
            }

        std::string outFileName;
        for(int i=0; i<num_clang_args; i++)
            {
            std::string testArg = clang_args[i];
            if(testArg.compare("-o") == 0)
                {
                if(i+1 < num_clang_args)
                    outFileName = clang_args[i+1];
                }
            }
        try
            {
            mOutputFileContents.write(outFileName);
            }
        catch(...)
            {
            errType = ET_ParseError;
            }
        std::string outErrFileName = outFileName;
        outErrFileName += "-err.txt";
        size_t numDiags = clang_getNumDiagnostics(tu);
        if(numDiags > 0 || sCrashDiagnostics.hasCrashed())
            {
            FILE *fp = fopen(outErrFileName.c_str(), "w");
            if(fp)
                {
                sCrashDiagnostics.dumpCrashed(fp);
                for (size_t i = 0; i<numDiags; i++)
                    {
                    CXDiagnostic diag = clang_getDiagnostic(tu, i);
                    CXDiagnosticSeverity sev = clang_getDiagnosticSeverity(diag);
                    if(errType == ET_None || errType == ET_CompileWarnings)
                        {
                        if(sev >= CXDiagnostic_Error)
                            errType = ET_CompileErrors;
                        else
                            errType = ET_CompileWarnings;
                        }
                    CXStringDisposer diagStr = clang_formatDiagnostic(diag,
                        clang_defaultDiagnosticDisplayOptions());
                        fprintf(fp, "%s\n", diagStr.c_str());
                    }

                fprintf(fp, "Arguments: %s %s %s ", static_cast<char const *>(srcFn),
                        static_cast<char const *>(srcRootDir),
                        static_cast<char const *>(outDir));
                for(int i=0 ; i<num_clang_args; i++)
                    {
                    fprintf(fp, "%s ", clang_args[i]);
                    }
                fprintf(fp, "\n");

                fclose(fp);
                }
            }
        else
            {
            unlink(outErrFileName.c_str());
            }
        FilePath covDir(outDir, FP_Dir);
        updateCoverageHeader(mTopParseFn, covDir, mInstrCount);
        updateCoverageSource(mTopParseFn, covDir);
        }
    else
        {
        errType = ET_CLangError;
        }
    return errType;
    }
コード例 #22
0
unsigned TranslationUnit::getNumDiagnostics() {
    return clang_getNumDiagnostics(unit_);
}
コード例 #23
0
void ClangParser::start(const QString &fileName, QStringList &includeFiles)
{
   static QStringList includePath = Config::getList("include-path");    
   static QStringList clangFlags  = Config::getList("clang-flags");

   p->fileName = fileName;
   p->index    = clang_createIndex(0, 0);
   p->curLine  = 1;
   p->curToken = 0;

   char **argv = (char **)malloc(sizeof(char *) * (4 + Doxy_Globals::inputPaths.count() + includePath.count() + clangFlags.count()));
   int argc = 0;

   // add include paths for input files  
   for (auto item : Doxy_Globals::inputPaths) { 
      QString inc = "-I" + item;
      argv[argc] = strdup(inc.toUtf8());  

      ++argc;
   }

   // add external include paths
   for (uint i = 0; i < includePath.count(); i++) {  
      QString inc = "-I" + includePath.at(i);
      argv[argc++] = strdup(inc.toUtf8());  
   }

   // user specified options
   for (uint i = 0; i < clangFlags.count(); i++) {
      argv[argc++] = strdup(clangFlags.at(i).toUtf8());
   }

   // extra options
   argv[argc++] = strdup("-ferror-limit=0");
   argv[argc++] = strdup("-x");

   // Since we can be presented with an .h file that can contain C, C++, or Objective C,
   // we need to configure the parser before knowing this.
   // Use the source file to detected the language. Detection will fail if you
   // pass a bunch of .h files containing ObjC code and no source 

   SrcLangExt lang = getLanguageFromFileName(fileName);

   if (lang == SrcLangExt_ObjC || p->detectedLang != ClangParser::Private::Detected_Cpp) {
      QString fn = fileName;

      if (p->detectedLang == ClangParser::Private::Detected_Cpp &&
            (fn.right(4).toLower() == ".cpp" || fn.right(4).toLower() == ".cxx" ||
             fn.right(3).toLower() == ".cc" || fn.right(2).toLower() == ".c")) {

         // fall back to C/C++ once we see an extension that indicates this
         p->detectedLang = ClangParser::Private::Detected_Cpp;

      } else if (fn.right(3).toLower() == ".mm") { 
         // switch to Objective C++
         p->detectedLang = ClangParser::Private::Detected_ObjCpp;

      } else if (fn.right(2).toLower() == ".m") { 
         // switch to Objective C
         p->detectedLang = ClangParser::Private::Detected_ObjC;
      }
   }

   switch (p->detectedLang) {
      case ClangParser::Private::Detected_Cpp:
         argv[argc++] = strdup("c++");
         break;

      case ClangParser::Private::Detected_ObjC:
         argv[argc++] = strdup("objective-c");
         break;

      case ClangParser::Private::Detected_ObjCpp:
         argv[argc++] = strdup("objective-c++");
         break;
   }

   // provide the input and and its dependencies as unsaved files so we can pass the filtered versions
   static bool filterSourceFiles = Config::getBool("filter-source-files");

   argv[argc++] = strdup(fileName.toUtf8());
 
   uint numUnsavedFiles = includeFiles.count() + 1;

   p->numFiles = numUnsavedFiles;
   p->sources  = new QByteArray[numUnsavedFiles];
   p->ufs      = new CXUnsavedFile[numUnsavedFiles];

   p->sources[0]      = detab(fileToString(fileName, filterSourceFiles, true)).toUtf8();
   p->ufs[0].Filename = strdup(fileName.toUtf8());
   p->ufs[0].Contents = p->sources[0].constData();
   p->ufs[0].Length   = p->sources[0].length();

   //  
   uint i = 1;
   for (auto item : includeFiles) {       

      p->fileMapping.insert(item, i);

      p->sources[i]      = detab(fileToString(item, filterSourceFiles, true)).toUtf8();
      p->ufs[i].Filename = strdup(item.toUtf8());
      p->ufs[i].Contents = p->sources[i].constData();
      p->ufs[i].Length   = p->sources[i].length();

      i++;
   }

   // let libclang do the actual parsing
   CXErrorCode errorCode = clang_parseTranslationUnit2(p->index, 0, argv, argc, 0, 0, 
                  CXTranslationUnit_DetailedPreprocessingRecord, &(p->tu) );

   // free arguments
   for (int i = 0; i < argc; ++i) {
      free(argv[i]);
   }
   free(argv);

   if (p->tu) {
      // filter out any includes not found by the clang parser
      determineInputFiles(includeFiles);

      // show any warnings the compiler produced
      uint n = clang_getNumDiagnostics(p->tu);

      for (uint i = 0; i != n; ++i) {
         CXDiagnostic diag = clang_getDiagnostic(p->tu, i);
         CXString string   = clang_formatDiagnostic(diag, clang_defaultDiagnosticDisplayOptions());

         err("Clang parser warning -- %s\n", clang_getCString(string));
         clang_disposeString(string);

         clang_disposeDiagnostic(diag);
      }

      // create a source range for the given file
      QFileInfo fi(fileName);
      CXFile f = clang_getFile(p->tu, fileName.toUtf8());

      CXSourceLocation fileBegin = clang_getLocationForOffset(p->tu, f, 0);
      CXSourceLocation fileEnd   = clang_getLocationForOffset(p->tu, f, p->ufs[0].Length);
      CXSourceRange    fileRange = clang_getRange(fileBegin, fileEnd);

      // produce a token stream for the file
      clang_tokenize(p->tu, fileRange, &p->tokens, &p->numTokens);

      // produce cursors for each token in the stream
      p->cursors = new CXCursor[p->numTokens];
      clang_annotateTokens(p->tu, p->tokens, p->numTokens, p->cursors);

   } else {
      p->tokens    = 0;
      p->numTokens = 0;
      p->cursors   = 0;

      err("Clang failed to parse translation unit -- %s\n", qPrintable(fileName));
   }
}
コード例 #24
0
ファイル: ClangIndexer.cpp プロジェクト: clapautius/rtags
bool ClangIndexer::diagnose()
{
    if (!mClangUnit) {
        return false;
    }

    List<String> compilationErrors;
    const unsigned diagnosticCount = clang_getNumDiagnostics(mClangUnit);

    Map<Location, XmlEntry> xmlEntries;

    for (unsigned i=0; i<diagnosticCount; ++i) {
        CXDiagnostic diagnostic = clang_getDiagnostic(mClangUnit, i);
        const CXSourceLocation diagLoc = clang_getDiagnosticLocation(diagnostic);
        const Location loc = createLocation(diagLoc, 0);
        const uint32_t fileId = loc.fileId();
        if (mData->visited.value(fileId)) {
            const String msg = RTags::eatString(clang_getDiagnosticSpelling(diagnostic));
            const CXDiagnosticSeverity sev = clang_getDiagnosticSeverity(diagnostic);
            XmlEntry::Type type = XmlEntry::None;
            switch (sev) {
            case CXDiagnostic_Warning:
                type = XmlEntry::Warning;
                break;
            case CXDiagnostic_Error:
            case CXDiagnostic_Fatal:
                type = XmlEntry::Error;
                break;
            default:
                break;
            }
            if (type != XmlEntry::None) {
                const unsigned rangeCount = clang_getDiagnosticNumRanges(diagnostic);
                bool ok = false;
                for (unsigned rangePos = 0; rangePos < rangeCount; ++rangePos) {
                    const CXSourceRange range = clang_getDiagnosticRange(diagnostic, rangePos);
                    const CXSourceLocation start = clang_getRangeStart(range);
                    const CXSourceLocation end = clang_getRangeEnd(range);

                    unsigned startOffset, endOffset;
                    clang_getSpellingLocation(start, 0, 0, 0, &startOffset);
                    clang_getSpellingLocation(end, 0, 0, 0, &endOffset);
                    if (!rangePos && !startOffset && !endOffset) {
                        // huh, range invalid? fall back to diag location
                        break;
                    } else {
                        unsigned int line, column;
                        clang_getPresumedLocation(start, 0, &line, &column);
                        const Location key(loc.fileId(), line, column);
                        xmlEntries[key] = XmlEntry(type, msg, endOffset - startOffset);
                        ok = true;
                        break;
                    }
                }
                if (!ok) {
                    unsigned line, column;
                    clang_getPresumedLocation(diagLoc, 0, &line, &column);
                    const Location key(loc.fileId(), line, column);
                    xmlEntries[key] = XmlEntry(type, msg);
                    // no length
                }
            }
            // logDirect(RTags::CompilationError, msg.constData());

            const unsigned fixItCount = clang_getDiagnosticNumFixIts(diagnostic);
            for (unsigned f=0; f<fixItCount; ++f) {
                CXSourceRange range;
                const CXStringScope stringScope = clang_getDiagnosticFixIt(diagnostic, f, &range);
                CXSourceLocation start = clang_getRangeStart(range);

                unsigned line, column;
                CXString file;
                clang_getPresumedLocation(start, &file, &line, &column);
                CXStringScope fileScope(file);

                const Location loc = createLocation(clang_getCString(file), line, column);
                if (mData->visited.value(loc.fileId())) {
                    unsigned int startOffset, endOffset;
                    CXSourceLocation end = clang_getRangeEnd(range);
                    clang_getSpellingLocation(start, 0, 0, 0, &startOffset);
                    clang_getSpellingLocation(end, 0, 0, 0, &endOffset);
                    const char *string = clang_getCString(stringScope);
                    error("Fixit for %s:%d:%d: Replace %d characters with [%s]", loc.path().constData(),
                          line, column, endOffset - startOffset, string);
                    XmlEntry &entry = xmlEntries[Location(loc.fileId(), line, column)];
                    entry.type = XmlEntry::Fixit;
                    if (entry.message.isEmpty()) {
                        entry.message = String::format<64>("did you mean '%s'?", string);
                    }
                    entry.length = endOffset - startOffset;
                    mData->fixIts[loc.fileId()].insert(FixIt(line, column, endOffset - startOffset, string));
                }
            }
        }

        clang_disposeDiagnostic(diagnostic);
    }

    mData->xmlDiagnostics = "<?xml version=\"1.0\" encoding=\"utf-8\"?><checkstyle>";
    if (!xmlEntries.isEmpty()) {
        Map<Location, XmlEntry>::const_iterator entry = xmlEntries.begin();
        const Map<Location, XmlEntry>::const_iterator end = xmlEntries.end();

        const char *severities[] = { "none", "warning", "error", "fixit" };

        uint32_t lastFileId = 0;
        while (entry != end) {
            const Location &loc = entry->first;
            const XmlEntry &xmlEntry = entry->second;
            if (loc.fileId() != lastFileId) {
                if (lastFileId)
                    mData->xmlDiagnostics += "</file>";
                lastFileId = loc.fileId();
                mData->xmlDiagnostics += String::format<128>("<file name=\"%s\">", loc.path().constData());
            }
            mData->xmlDiagnostics += String::format("<error line=\"%d\" column=\"%d\" %sseverity=\"%s\" message=\"%s\"/>",
                                                    loc.line(), loc.column(),
                                                    (xmlEntry.length <= 0 ? ""
                                                     : String::format<32>("length=\"%d\" ", xmlEntry.length).constData()),
                                                    severities[xmlEntry.type], xmlEscape(xmlEntry.message).constData());
            ++entry;
        }
        if (lastFileId)
            mData->xmlDiagnostics += "</file>";
    }

    for (Hash<uint32_t, bool>::const_iterator it = mData->visited.begin(); it != mData->visited.end(); ++it) {
        if (it->second) {
            const Map<Location, XmlEntry>::const_iterator x = xmlEntries.lower_bound(Location(it->first, 0, 0));
            if (x == xmlEntries.end() || x->first.fileId() != it->first) {
                const String fn = Location::path(it->first);
                mData->xmlDiagnostics += String::format("<file name=\"%s\"/>", fn.constData());
            }
        }
    }

    mData->xmlDiagnostics += "</checkstyle>";
    return true;
}