Diagnostic won't emit

Hi,

hopefully a straightforward issue.

I have written a standalone cfe tool to catch some project-specific bugs in a code base.

I am now replacing my cout << “ERROR…” messages with clang::Diagnostics by following this example:

https://github.com/peter-can-talk/cppnow-2017/blob/master/code/mccabe/mccabe.cpp#L46-L54

However I don’t see anything being printed when I run it (except my own cout << “error…” messages)…

I’ve seen the mcabbe example generate diagnostics on a youtube presentation and both it and my app use clang::Tool. mccabbe uses ast_matcher::MatchFinder whereas I use several classes derived from RecursiveASTVisitor. Presumably MatchFinder sets up a DiagnosticsConsumer that finally emits the diagnostics??

But I couldn’t really find out how to set up a DiagnosticsConsumer - if that is indeed what I need to do.

Thanks,
Billy.

Hi Billy,

It's a bit tricky to help without seeing the code :slight_smile: Are you using any specific/custom diagnostic consumer? Is your properly DiagnosticBuilder destroyed? AFAIK, that's when the message is printed.

Here's a bit more up-to-date example:

Hi Andrzej,

thanks for the reply. My code is basically identical to the mccabe example:

454 const clang::BinaryOperator *binOp = parents[0].getclang::BinaryOperator();
455 if (!binOp || binOp->getOpcodeStr() != std::string(“=”)) // TODO check for isAssignmentOp
456 {
457 auto& Diagnostics = mContext->getDiagnostics();
458 const auto ID = Diagnostics.getCustomDiagID(clang::DiagnosticsEngine::Error,
459 “Return value from ‘%0’ is not assigned”);
460 auto Builder = Diagnostics.Report(fnDecl->getLocation(), ID);
461 Builder.AddString(fnDecl->getNameAsString());
462
463 cout << “ERROR: Return val from API call not assigned '” << Diagnostics.getClient() << " " << fnDecl->getNameAsString()
464 return true;
465 }

I know that my DiagnosticsEngine does have a DiagnosticConsumer as Diagnostics.getClient() returns non-null.

My understanding is that when the Build object is destroyed after the return that the diagnostic should be emitted.

I will have a look at those samples.

Thanks,
Billy.

The code in those the CodeSytleChecker example looks more or less identical to my code above, so it must be something to do with setting up a DiagnosticConsumer or overriding a method somewhere in a derived class.

Thanks for maintaining those examples - they look really useful - I wish I’d seen them sooner :slight_smile:

I’ll download them and see if I can get them to run. Where is main() for the CodeCheckerApp by the way - it’s not in CodeChecker.cpp?

Can you check the DiagnosticConsumer in your example? AFAIK, TextDiagnosticBuffer will not print the diagnostics unless they are flushed. By default, the compiler driver (e.g. clang) creates TextDiagnosticPrinter and that's what you want to use. In a standalone example you are the one implementing the driver and _you_ need to make sure that your DiagnosticConsumer does what you expect :slight_smile:

As for the examples in clang-tutor, those are mostly dynamically loaded plugins. Here's how you can run the one that I pointed you to (you can also check the RUN command in the test that I referred to):

bin/clang -cc1  -load <clang-tutor-build-dir>/lib/libCodeStyleChecker.dylib -plugin code-style-checker -fcolor-diagnostics <clang-tutor-dir>/test/CodeStyleCheckerMacro.cpp

As this is a dynamically loaded plugin, there's no `main` (more specifically - clang's `main` drives this).

If you prefer a stand-alone example that implements `main`:

Can you check the DiagnosticConsumer in your example? AFAIK, TextDiagnosticBuffer will not print the diagnostics unless they are flushed. By default, the compiler driver (e.g. clang) creates TextDiagnosticPrinter and that's what you want to use. In a standalone example you are the one implementing the driver and _you_ need to make sure that your DiagnosticConsumer does what you expect :slight_smile:

As for the examples in clang-tutor, those are mostly dynamically loaded plugins. Here's how you can run the one that I pointed you to (you can also check the RUN command in the test that I referred to):

bin/clang -cc1  -load <clang-tutor-build-dir>/lib/libCodeStyleChecker.dylib -plugin code-style-checker -fcolor-diagnostics <clang-tutor-dir>/test/CodeStyleCheckerMacro.cpp

As this is a dynamically loaded plugin, there's no `main` (more specifically - clang's `main` drives this).

If you prefer a stand-alone example that implements `main`: