@@ -423,120 +423,127 @@ static bool reportClangErrors(std::istream &is, const std::function<void(const E
423423 return false ;
424424}
425425
426- unsigned int CppCheck::check (const std::string &path)
426+ unsigned int CppCheck::checkClang (const std::string &path)
427427{
428- if (mSettings .clang ) {
429- if (! mSettings . quiet )
430- mErrorLogger . reportOut ( std::string ( " Checking " ) + path + " ... " , Color::FgGreen);
431-
432- const std::string lang = Path::isCPP (path) ? " -x c++" : " -x c" ;
433- const std::string analyzerInfo = mSettings .buildDir .empty () ? std::string () : AnalyzerInformation::getAnalyzerInfoFile (mSettings .buildDir , path, emptyString);
434- const std::string clangcmd = analyzerInfo + " .clang-cmd" ;
435- const std::string clangStderr = analyzerInfo + " .clang-stderr" ;
436- const std::string clangAst = analyzerInfo + " .clang-ast" ;
437- std::string exe = mSettings .clangExecutable ;
428+ if (! mSettings .quiet )
429+ mErrorLogger . reportOut ( std::string ( " Checking " ) + path + " ... " , Color::FgGreen);
430+
431+ // TODO: this ignores the configured language
432+ const std::string lang = Path::isCPP (path) ? " -x c++" : " -x c" ;
433+ const std::string analyzerInfo = mSettings .buildDir .empty () ? std::string () : AnalyzerInformation::getAnalyzerInfoFile (mSettings .buildDir , path, emptyString);
434+ const std::string clangcmd = analyzerInfo + " .clang-cmd" ;
435+ const std::string clangStderr = analyzerInfo + " .clang-stderr" ;
436+ const std::string clangAst = analyzerInfo + " .clang-ast" ;
437+ std::string exe = mSettings .clangExecutable ;
438438#ifdef _WIN32
439- // append .exe if it is not a path
440- if (Path::fromNativeSeparators (mSettings .clangExecutable ).find (' /' ) == std::string::npos) {
441- exe += " .exe" ;
442- }
439+ // append .exe if it is not a path
440+ if (Path::fromNativeSeparators (mSettings .clangExecutable ).find (' /' ) == std::string::npos) {
441+ exe += " .exe" ;
442+ }
443443#endif
444444
445- std::string flags (lang + " " );
446- if (Path::isCPP (path) && !mSettings .standards .stdValue .empty ())
447- flags += " -std=" + mSettings .standards .stdValue + " " ;
445+ std::string flags (lang + " " );
446+ // TODO: does not apply C standard
447+ if (Path::isCPP (path) && !mSettings .standards .stdValue .empty ())
448+ flags += " -std=" + mSettings .standards .stdValue + " " ;
448449
449- for (const std::string &i: mSettings .includePaths )
450- flags += " -I" + i + " " ;
450+ for (const std::string &i: mSettings .includePaths )
451+ flags += " -I" + i + " " ;
451452
452- flags += getDefinesFlags (mSettings .userDefines );
453+ flags += getDefinesFlags (mSettings .userDefines );
453454
454- const std::string args2 = " -fsyntax-only -Xclang -ast-dump -fno-color-diagnostics " + flags + path;
455- const std::string redirect2 = analyzerInfo.empty () ? std::string (" 2>&1" ) : (" 2> " + clangStderr);
456- if (!mSettings .buildDir .empty ()) {
457- std::ofstream fout (clangcmd);
458- fout << exe << " " << args2 << " " << redirect2 << std::endl;
459- } else if (mSettings .verbose && !mSettings .quiet ) {
460- mErrorLogger .reportOut (exe + " " + args2);
461- }
455+ const std::string args2 = " -fsyntax-only -Xclang -ast-dump -fno-color-diagnostics " + flags + path;
456+ const std::string redirect2 = analyzerInfo.empty () ? std::string (" 2>&1" ) : (" 2> " + clangStderr);
457+ if (!mSettings .buildDir .empty ()) {
458+ std::ofstream fout (clangcmd);
459+ fout << exe << " " << args2 << " " << redirect2 << std::endl;
460+ } else if (mSettings .verbose && !mSettings .quiet ) {
461+ mErrorLogger .reportOut (exe + " " + args2);
462+ }
462463
463- std::string output2;
464- if (mExecuteCommand (exe,split (args2),redirect2,output2) != EXIT_SUCCESS || output2.find (" TranslationUnitDecl" ) == std::string::npos) {
465- std::cerr << " Failed to execute '" << exe << " " << args2 << " " << redirect2 << " '" << std::endl;
464+ std::string output2;
465+ if (mExecuteCommand (exe,split (args2),redirect2,output2) != EXIT_SUCCESS || output2.find (" TranslationUnitDecl" ) == std::string::npos) {
466+ std::cerr << " Failed to execute '" << exe << " " << args2 << " " << redirect2 << " '" << std::endl;
467+ return 0 ;
468+ }
469+
470+ // Ensure there are not syntax errors...
471+ std::vector<ErrorMessage> compilerWarnings;
472+ if (!mSettings .buildDir .empty ()) {
473+ std::ifstream fin (clangStderr);
474+ auto reportError = [this ](const ErrorMessage& errorMessage) {
475+ reportErr (errorMessage);
476+ };
477+ if (reportClangErrors (fin, reportError, compilerWarnings))
466478 return 0 ;
467- }
479+ } else {
480+ std::istringstream istr (output2);
481+ auto reportError = [this ](const ErrorMessage& errorMessage) {
482+ reportErr (errorMessage);
483+ };
484+ if (reportClangErrors (istr, reportError, compilerWarnings))
485+ return 0 ;
486+ }
468487
469- // Ensure there are not syntax errors...
470- std::vector<ErrorMessage> compilerWarnings;
471- if (!mSettings .buildDir .empty ()) {
472- std::ifstream fin (clangStderr);
473- auto reportError = [this ](const ErrorMessage& errorMessage) {
474- reportErr (errorMessage);
475- };
476- if (reportClangErrors (fin, reportError, compilerWarnings))
477- return 0 ;
478- } else {
479- std::istringstream istr (output2);
480- auto reportError = [this ](const ErrorMessage& errorMessage) {
481- reportErr (errorMessage);
482- };
483- if (reportClangErrors (istr, reportError, compilerWarnings))
484- return 0 ;
485- }
488+ if (!mSettings .buildDir .empty ()) {
489+ std::ofstream fout (clangAst);
490+ fout << output2 << std::endl;
491+ }
486492
487- if (!mSettings .buildDir .empty ()) {
488- std::ofstream fout (clangAst);
489- fout << output2 << std::endl;
493+ try {
494+ std::istringstream ast (output2);
495+ Tokenizer tokenizer (&mSettings , this );
496+ tokenizer.list .appendFileIfNew (path);
497+ clangimport::parseClangAstDump (&tokenizer, ast);
498+ ValueFlow::setValues (tokenizer.list ,
499+ const_cast <SymbolDatabase&>(*tokenizer.getSymbolDatabase ()),
500+ this ,
501+ &mSettings ,
502+ &s_timerResults);
503+ if (mSettings .debugnormal )
504+ tokenizer.printDebugOutput (1 );
505+ checkNormalTokens (tokenizer);
506+
507+ // create dumpfile
508+ std::ofstream fdump;
509+ std::string dumpFile;
510+ createDumpFile (mSettings , path, fdump, dumpFile);
511+ if (fdump.is_open ()) {
512+ // TODO: use tinyxml2 to create XML
513+ fdump << " <dump cfg=\"\" >\n " ;
514+ for (const ErrorMessage& errmsg: compilerWarnings)
515+ fdump << " <clang-warning file=\" " << toxml (errmsg.callStack .front ().getfile ()) << " \" line=\" " << errmsg.callStack .front ().line << " \" column=\" " << errmsg.callStack .front ().column << " \" message=\" " << toxml (errmsg.shortMessage ()) << " \" />\n " ;
516+ fdump << " <standards>\n " ;
517+ fdump << " <c version=\" " << mSettings .standards .getC () << " \" />\n " ;
518+ fdump << " <cpp version=\" " << mSettings .standards .getCPP () << " \" />\n " ;
519+ fdump << " </standards>\n " ;
520+ tokenizer.dump (fdump);
521+ fdump << " </dump>\n " ;
522+ fdump << " </dumps>\n " ;
523+ fdump.close ();
490524 }
491525
492- try {
493- std::istringstream ast (output2);
494- Tokenizer tokenizer (&mSettings , this );
495- tokenizer.list .appendFileIfNew (path);
496- clangimport::parseClangAstDump (&tokenizer, ast);
497- ValueFlow::setValues (tokenizer.list ,
498- const_cast <SymbolDatabase&>(*tokenizer.getSymbolDatabase ()),
499- this ,
500- &mSettings ,
501- &s_timerResults);
502- if (mSettings .debugnormal )
503- tokenizer.printDebugOutput (1 );
504- checkNormalTokens (tokenizer);
505-
506- // create dumpfile
507- std::ofstream fdump;
508- std::string dumpFile;
509- createDumpFile (mSettings , path, fdump, dumpFile);
510- if (fdump.is_open ()) {
511- fdump << " <dump cfg=\"\" >\n " ;
512- for (const ErrorMessage& errmsg: compilerWarnings)
513- fdump << " <clang-warning file=\" " << toxml (errmsg.callStack .front ().getfile ()) << " \" line=\" " << errmsg.callStack .front ().line << " \" column=\" " << errmsg.callStack .front ().column << " \" message=\" " << toxml (errmsg.shortMessage ()) << " \" />\n " ;
514- fdump << " <standards>\n " ;
515- fdump << " <c version=\" " << mSettings .standards .getC () << " \" />\n " ;
516- fdump << " <cpp version=\" " << mSettings .standards .getCPP () << " \" />\n " ;
517- fdump << " </standards>\n " ;
518- tokenizer.dump (fdump);
519- fdump << " </dump>\n " ;
520- fdump << " </dumps>\n " ;
521- fdump.close ();
522- }
523-
524- // run addons
525- executeAddons (dumpFile, path);
526-
527- } catch (const InternalError &e) {
528- const ErrorMessage errmsg = ErrorMessage::fromInternalError (e, nullptr , path, " Bailing out from analysis: Processing Clang AST dump failed" );
529- reportErr (errmsg);
530- } catch (const TerminateException &) {
531- // Analysis is terminated
532- return mExitCode ;
533- } catch (const std::exception &e) {
534- internalError (path, std::string (" Processing Clang AST dump failed: " ) + e.what ());
535- }
526+ // run addons
527+ executeAddons (dumpFile, path);
536528
529+ } catch (const InternalError &e) {
530+ const ErrorMessage errmsg = ErrorMessage::fromInternalError (e, nullptr , path, " Bailing out from analysis: Processing Clang AST dump failed" );
531+ reportErr (errmsg);
532+ } catch (const TerminateException &) {
533+ // Analysis is terminated
537534 return mExitCode ;
535+ } catch (const std::exception &e) {
536+ internalError (path, std::string (" Processing Clang AST dump failed: " ) + e.what ());
538537 }
539538
539+ return mExitCode ;
540+ }
541+
542+ unsigned int CppCheck::check (const std::string &path)
543+ {
544+ if (mSettings .clang )
545+ return checkClang (path);
546+
540547 return checkFile (Path::simplifyPath (path), emptyString);
541548}
542549
0 commit comments