Index: lib/IR/Core.cpp =================================================================== --- lib/IR/Core.cpp +++ lib/IR/Core.cpp @@ -1842,12 +1842,16 @@ unsigned LLVMGetAttributeCountAtIndex(LLVMValueRef F, LLVMAttributeIndex Idx) { auto *ASN = AttributeSetNode::get(unwrap(F)->getAttributes(), Idx); + if (!ASN) + return 0; return ASN->getNumAttributes(); } void LLVMGetAttributesAtIndex(LLVMValueRef F, LLVMAttributeIndex Idx, LLVMAttributeRef *Attrs) { auto *ASN = AttributeSetNode::get(unwrap(F)->getAttributes(), Idx); + if (!ASN) + return; for (auto A: make_range(ASN->begin(), ASN->end())) *Attrs++ = wrap(A); } @@ -2173,6 +2177,8 @@ LLVMAttributeIndex Idx) { auto CS = CallSite(unwrap(C)); auto *ASN = AttributeSetNode::get(CS.getAttributes(), Idx); + if (!ASN) + return 0; return ASN->getNumAttributes(); } @@ -2180,6 +2186,8 @@ LLVMAttributeRef *Attrs) { auto CS = CallSite(unwrap(C)); auto *ASN = AttributeSetNode::get(CS.getAttributes(), Idx); + if (!ASN) + return; for (auto A: make_range(ASN->begin(), ASN->end())) *Attrs++ = wrap(A); } Index: test/Bindings/llvm-c/callsite_attributes.ll =================================================================== --- /dev/null +++ test/Bindings/llvm-c/callsite_attributes.ll @@ -0,0 +1,12 @@ +; RUN: llvm-as %s -o %t.bc +; RUN: llvm-c-test --test-callsite-attributes < %t.bc +; This used to segfault + +define void @Y() { + ret void +} + +define void @X() { + call void @X() + ret void +} Index: test/Bindings/llvm-c/function_attributes.ll =================================================================== --- /dev/null +++ test/Bindings/llvm-c/function_attributes.ll @@ -0,0 +1,7 @@ +; RUN: llvm-as %s -o %t.bc +; RUN: llvm-c-test --test-function-attributes < %t.bc +; This used to segfault + +define void @X() { + ret void +} Index: tools/llvm-c-test/CMakeLists.txt =================================================================== --- tools/llvm-c-test/CMakeLists.txt +++ tools/llvm-c-test/CMakeLists.txt @@ -36,6 +36,7 @@ endif () add_llvm_tool(llvm-c-test + attributes.c calc.c diagnostic.c disassemble.c Index: tools/llvm-c-test/attributes.c =================================================================== --- /dev/null +++ tools/llvm-c-test/attributes.c @@ -0,0 +1,75 @@ +/*===-- attributes.c - 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-attributes and --test-callsite-attributes *| +|* commands in llvm-c-test. *| +|* *| +\*===----------------------------------------------------------------------===*/ + +#include "llvm-c-test.h" + +#include + +int llvm_test_function_attributes(void) { + LLVMEnablePrettyStackTrace(); + + LLVMModuleRef M = llvm_load_module(false, true); + + LLVMValueRef F = LLVMGetFirstFunction(M); + while (F) { + // Read attributes + for (int Idx = LLVMAttributeFunctionIndex, ParamCount = LLVMCountParams(F); + Idx <= ParamCount; ++Idx) { + int AttrCount = LLVMGetAttributeCountAtIndex(F, Idx); + LLVMAttributeRef *Attrs = + (LLVMAttributeRef *)malloc(AttrCount * sizeof(LLVMAttributeRef)); + LLVMGetAttributesAtIndex(F, Idx, Attrs); + free(Attrs); + } + F = LLVMGetNextFunction(F); + } + + LLVMDisposeModule(M); + + return 0; +} + +int llvm_test_callsite_attributes(void) { + LLVMEnablePrettyStackTrace(); + + LLVMModuleRef M = llvm_load_module(false, true); + + LLVMValueRef F = LLVMGetFirstFunction(M); + while (F) { + LLVMBasicBlockRef BB; + for (BB = LLVMGetFirstBasicBlock(F); BB; BB = LLVMGetNextBasicBlock(BB)) { + LLVMValueRef I; + for (I = LLVMGetFirstInstruction(BB); I; I = LLVMGetNextInstruction(I)) { + if (LLVMIsACallInst(I)) { + // Read attributes + for (int Idx = LLVMAttributeFunctionIndex, + ParamCount = LLVMCountParams(F); + Idx <= ParamCount; ++Idx) { + int AttrCount = LLVMGetCallSiteAttributeCount(I, Idx); + LLVMAttributeRef *Attrs = (LLVMAttributeRef *)malloc( + AttrCount * sizeof(LLVMAttributeRef)); + LLVMGetCallSiteAttributes(I, Idx, Attrs); + free(Attrs); + } + } + } + } + + F = LLVMGetNextFunction(F); + } + + LLVMDisposeModule(M); + + return 0; +} 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 @@ -52,6 +52,10 @@ // diagnostic.c int llvm_test_diagnostic_handler(void); +// attributes.c +int llvm_test_function_attributes(); +int llvm_test_callsite_attributes(); + #ifdef __cplusplus } #endif /* !defined(__cplusplus) */ Index: tools/llvm-c-test/main.c =================================================================== --- tools/llvm-c-test/main.c +++ tools/llvm-c-test/main.c @@ -88,6 +88,10 @@ return llvm_add_named_metadata_operand(); } else if (argc == 2 && !strcmp(argv[1], "--set-metadata")) { return llvm_set_metadata(); + } else if (argc == 2 && !strcmp(argv[1], "--test-function-attributes")) { + return llvm_test_function_attributes(); + } else if (argc == 2 && !strcmp(argv[1], "--test-callsite-attributes")) { + return llvm_test_callsite_attributes(); } else if (argc == 2 && !strcmp(argv[1], "--echo")) { return llvm_echo(); } else if (argc == 2 && !strcmp(argv[1], "--test-diagnostic-handler")) {