Skip to content

Commit 44ed533

Browse files
authored
CppCheck: extracted clang-specific code from check(const std::string&) into separate method (#5842)
1 parent bd9700b commit 44ed533

4 files changed

Lines changed: 110 additions & 97 deletions

File tree

lib/cppcheck.cpp

Lines changed: 104 additions & 97 deletions
Original file line numberDiff line numberDiff line change
@@ -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

lib/cppcheck.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -200,6 +200,8 @@ class CPPCHECKLIB CppCheck : ErrorLogger {
200200
void executeRules(const std::string &tokenlist, const Tokenizer &tokenizer);
201201
#endif
202202

203+
unsigned int checkClang(const std::string &path);
204+
203205
/**
204206
* @brief Errors and warnings are directed here.
205207
*

lib/filesettings.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -31,14 +31,17 @@ struct CPPCHECKLIB FileSettings {
3131
std::string cfg;
3232
std::string filename;
3333
std::string defines;
34+
// TODO: handle differently
3435
std::string cppcheckDefines() const {
3536
return defines + (msc ? ";_MSC_VER=1900" : "") + (useMfc ? ";__AFXWIN_H__=1" : "");
3637
}
3738
std::set<std::string> undefs;
3839
std::list<std::string> includePaths;
40+
// only used by clang mode
3941
std::list<std::string> systemIncludePaths;
4042
std::string standard;
4143
Platform::Type platformType = Platform::Type::Unspecified;
44+
// TODO: get rid of these
4245
bool msc{};
4346
bool useMfc{};
4447
};

lib/importproject.cpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -757,6 +757,7 @@ bool ImportProject::importVcxproj(const std::string &filename, std::map<std::str
757757
FileSettings fs;
758758
fs.filename = cfilename;
759759
fs.cfg = p.name;
760+
// TODO: detect actual MSC version
760761
fs.msc = true;
761762
fs.useMfc = useOfMfc;
762763
fs.defines = "_WIN32=1";

0 commit comments

Comments
 (0)