Index: include/llvm-c/Core.h =================================================================== --- include/llvm-c/Core.h +++ include/llvm-c/Core.h @@ -400,6 +400,16 @@ void *DiagnosticContext); /** + * Get the diagnostic handler of this context. + */ +LLVMDiagnosticHandler LLVMContextGetDiagnosticHandler(LLVMContextRef C); + +/** + * Get the diagnostic context of this context. + */ +void *LLVMContextGetDiagnosticContext(LLVMContextRef C); + +/** * Set the yield callback function for this context. * * @see LLVMContext::setYieldCallback() Index: lib/IR/Core.cpp =================================================================== --- lib/IR/Core.cpp +++ lib/IR/Core.cpp @@ -85,10 +85,20 @@ LLVMDiagnosticHandler Handler, void *DiagnosticContext) { unwrap(C)->setDiagnosticHandler( - LLVM_EXTENSION reinterpret_cast(Handler), + LLVM_EXTENSION reinterpret_cast( + Handler), DiagnosticContext); } +LLVMDiagnosticHandler LLVMContextGetDiagnosticHandler(LLVMContextRef C) { + return LLVM_EXTENSION reinterpret_cast( + unwrap(C)->getDiagnosticHandler()); +} + +void *LLVMContextGetDiagnosticContext(LLVMContextRef C) { + return unwrap(C)->getDiagnosticContext(); +} + void LLVMContextSetYieldCallback(LLVMContextRef C, LLVMYieldCallback Callback, void *OpaqueHandle) { auto YieldCallback = Index: test/Bindings/llvm-c/empty.ll =================================================================== --- test/Bindings/llvm-c/empty.ll +++ test/Bindings/llvm-c/empty.ll @@ -1,3 +1,5 @@ ; RUN: llvm-as < %s | llvm-dis > %t.orig ; RUN: llvm-as < %s | llvm-c-test --echo > %t.echo ; RUN: diff -w %t.orig %t.echo +; RUN: llvm-as < %s | llvm-c-test --test-diagnostic-handler 2>&1 | FileCheck %s +; CHECK: Diagnostic handler was not called while loading module Index: test/Bindings/llvm-c/invalid-bitcode.test =================================================================== --- test/Bindings/llvm-c/invalid-bitcode.test +++ test/Bindings/llvm-c/invalid-bitcode.test @@ -8,3 +8,9 @@ ; RUN: not llvm-c-test --lazy-new-module-dump < %S/Inputs/invalid.ll.bc 2>&1 | FileCheck --check-prefix=NEW %s NEW: Error with new bitcode parser: Unknown attribute kind (52) + +; RUN: llvm-c-test --test-diagnostic-handler < %S/Inputs/invalid.ll.bc 2>&1 | FileCheck --check-prefix=DIAGNOSTIC %s + +DIAGNOSTIC: Executing diagnostic handler +DIAGNOSTIC: Diagnostic severity is of type error +DIAGNOSTIC: Diagnostic handler was called while loading module Index: tools/llvm-c-test/CMakeLists.txt =================================================================== --- tools/llvm-c-test/CMakeLists.txt +++ tools/llvm-c-test/CMakeLists.txt @@ -37,6 +37,7 @@ add_llvm_tool(llvm-c-test calc.c + diagnostic.c disassemble.c echo.cpp helpers.c Index: tools/llvm-c-test/diagnostic.c =================================================================== --- tools/llvm-c-test/diagnostic.c +++ tools/llvm-c-test/diagnostic.c @@ -0,0 +1,89 @@ +//===-- diagnostic.cpp - tool for testing libLLVM and llvm-c API ----------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file implements the --test-diagnostic-handler command in llvm-c-test. +// +// This command uses the C API to read a module with a custom diagnostic +// handler set to test the diagnostic handler functionality. +// +//===----------------------------------------------------------------------===// + +#include "llvm-c-test.h" +#include "llvm-c/BitReader.h" +#include "llvm-c/Core.h" + +#include + +static void diagnosticHandler(LLVMDiagnosticInfoRef DI, void *C) { + fprintf(stderr, "Executing diagnostic handler\n"); + + fprintf(stderr, "Diagnostic severity is of type "); + switch (LLVMGetDiagInfoSeverity(DI)) { + case LLVMDSError: + fprintf(stderr, "error"); + break; + case LLVMDSWarning: + fprintf(stderr, "warning"); + break; + case LLVMDSRemark: + fprintf(stderr, "remark"); + break; + case LLVMDSNote: + fprintf(stderr, "note"); + break; + } + fprintf(stderr, "\n"); + + (*(int *)C) = 1; +} + +static int handlerCalled = 0; + +int llvm_test_diagnostic_handler(void) { + LLVMContextRef C = LLVMGetGlobalContext(); + LLVMContextSetDiagnosticHandler(C, diagnosticHandler, &handlerCalled); + + if (LLVMContextGetDiagnosticHandler(C) != diagnosticHandler) { + fprintf(stderr, "LLVMContext{Set,Get}DiagnosticHandler failed\n"); + return 1; + } + + int *DC = (int *)LLVMContextGetDiagnosticContext(C); + if (DC != &handlerCalled || *DC) { + fprintf(stderr, "LLVMContextGetDiagnosticContext failed\n"); + return 1; + } + + LLVMMemoryBufferRef MB; + char *msg = NULL; + if (LLVMCreateMemoryBufferWithSTDIN(&MB, &msg)) { + fprintf(stderr, "Error reading file: %s\n", msg); + LLVMDisposeMessage(msg); + return 1; + } + + + LLVMModuleRef M; + int Ret = LLVMGetBitcodeModule2(MB, &M); + if (Ret) { + // We do not return if the bitcode was invalid, as we want to test whether + // the diagnostic handler was executed. + fprintf(stderr, "Error parsing bitcode: %s\n", msg); + } + + LLVMDisposeMemoryBuffer(MB); + + if (handlerCalled) { + fprintf(stderr, "Diagnostic handler was called while loading module\n"); + } else { + fprintf(stderr, "Diagnostic handler was not called while loading module\n"); + } + + return 0; +} Index: tools/llvm-c-test/echo.cpp =================================================================== --- tools/llvm-c-test/echo.cpp +++ tools/llvm-c-test/echo.cpp @@ -7,7 +7,7 @@ // //===----------------------------------------------------------------------===// // -// This file implements the --echo commands in llvm-c-test. +// This file implements the --echo command in llvm-c-test. // // This command uses the C API to read a module and output an exact copy of it // as output. It is used to check that the resulting module matches the input Index: tools/llvm-c-test/llvm-c-test.h =================================================================== --- tools/llvm-c-test/llvm-c-test.h +++ tools/llvm-c-test/llvm-c-test.h @@ -49,6 +49,9 @@ // echo.c int llvm_echo(void); +// diagnostic.c +int llvm_test_diagnostic_handler(void); + #ifdef __cplusplus } #endif /* !defined(__cplusplus) */ Index: tools/llvm-c-test/main.c =================================================================== --- tools/llvm-c-test/main.c +++ tools/llvm-c-test/main.c @@ -21,20 +21,20 @@ fprintf(stderr, "llvm-c-test command\n\n"); fprintf(stderr, " Commands:\n"); fprintf(stderr, " * --module-dump\n"); - fprintf(stderr, " Read bytecode from stdin - print disassembly\n\n"); + fprintf(stderr, " Read bitcode from stdin - print disassembly\n\n"); fprintf(stderr, " * --lazy-module-dump\n"); fprintf(stderr, - " Lazily read bytecode from stdin - print disassembly\n\n"); + " Lazily read bitcode from stdin - print disassembly\n\n"); fprintf(stderr, " * --new-module-dump\n"); - fprintf(stderr, " Read bytecode from stdin - print disassembly\n\n"); + fprintf(stderr, " Read bitcode from stdin - print disassembly\n\n"); fprintf(stderr, " * --lazy-new-module-dump\n"); fprintf(stderr, - " Lazily read bytecode from stdin - print disassembly\n\n"); + " Lazily read bitcode from stdin - print disassembly\n\n"); fprintf(stderr, " * --module-list-functions\n"); fprintf(stderr, - " Read bytecode from stdin - list summary of functions\n\n"); + " Read bitcode from stdin - list summary of functions\n\n"); fprintf(stderr, " * --module-list-globals\n"); - fprintf(stderr, " Read bytecode from stdin - list summary of globals\n\n"); + fprintf(stderr, " Read bitcode from stdin - list summary of globals\n\n"); fprintf(stderr, " * --targets-list\n"); fprintf(stderr, " List available targets\n\n"); fprintf(stderr, " * --object-list-sections\n"); @@ -46,12 +46,15 @@ fprintf(stderr, " Read lines of triple, hex ascii machine code from stdin " "- print disassembly\n\n"); fprintf(stderr, " * --calc\n"); - fprintf(stderr, " * --echo\n"); - fprintf(stderr, - " Read object file form stdin - and print it back out\n\n"); fprintf( stderr, " Read lines of name, rpn from stdin - print generated module\n\n"); + fprintf(stderr, " * --echo\n"); + fprintf(stderr, + " Read bitcode file form stdin - print it back out\n\n"); + fprintf(stderr, " * --test-diagnostic-handler\n"); + fprintf(stderr, + " Read bitcode file form stdin with a diagnostic handler set\n\n"); } int main(int argc, char **argv) { @@ -87,6 +90,8 @@ return llvm_set_metadata(); } else if (argc == 2 && !strcmp(argv[1], "--echo")) { return llvm_echo(); + } else if (argc == 2 && !strcmp(argv[1], "--test-diagnostic-handler")) { + return llvm_test_diagnostic_handler(); } else { print_usage(); }