// Copyright 2008, Google Inc. // All rights reserved. // // Redistribution and use in source and binary forms, with or without // modification, are permitted provided that the following conditions are // met: // // * Redistributions of source code must retain the above copyright // notice, this list of conditions and the following disclaimer. // * Redistributions in binary form must reproduce the above // copyright notice, this list of conditions and the following disclaimer // in the documentation and/or other materials provided with the // distribution. // * Neither the name of Google Inc. nor the names of its // contributors may be used to endorse or promote products derived from // this software without specific prior written permission. // // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. // Google Mock - a framework for writing C++ mock classes. // // This file tests the built-in matchers generated by a script. #include "gmock/gmock-generated-matchers.h" #include #include #include #include #include #include #include #include "gmock/gmock.h" #include "gtest/gtest.h" #include "gtest/gtest-spi.h" namespace { using std::list; using std::map; using std::pair; using std::set; using std::stringstream; using std::vector; using testing::get; using testing::make_tuple; using testing::tuple; using testing::_; using testing::Args; using testing::Contains; using testing::ElementsAre; using testing::ElementsAreArray; using testing::Eq; using testing::Ge; using testing::Gt; using testing::Le; using testing::Lt; using testing::MakeMatcher; using testing::Matcher; using testing::MatcherInterface; using testing::MatchResultListener; using testing::Ne; using testing::Not; using testing::Pointee; using testing::PrintToString; using testing::Ref; using testing::StaticAssertTypeEq; using testing::StrEq; using testing::Value; using testing::internal::ElementsAreArrayMatcher; using testing::internal::string; // Returns the description of the given matcher. template string Describe(const Matcher& m) { stringstream ss; m.DescribeTo(&ss); return ss.str(); } // Returns the description of the negation of the given matcher. template string DescribeNegation(const Matcher& m) { stringstream ss; m.DescribeNegationTo(&ss); return ss.str(); } // Returns the reason why x matches, or doesn't match, m. template string Explain(const MatcherType& m, const Value& x) { stringstream ss; m.ExplainMatchResultTo(x, &ss); return ss.str(); } // Tests Args(m). TEST(ArgsTest, AcceptsZeroTemplateArg) { const tuple t(5, true); EXPECT_THAT(t, Args<>(Eq(tuple<>()))); EXPECT_THAT(t, Not(Args<>(Ne(tuple<>())))); } TEST(ArgsTest, AcceptsOneTemplateArg) { const tuple t(5, true); EXPECT_THAT(t, Args<0>(Eq(make_tuple(5)))); EXPECT_THAT(t, Args<1>(Eq(make_tuple(true)))); EXPECT_THAT(t, Not(Args<1>(Eq(make_tuple(false))))); } TEST(ArgsTest, AcceptsTwoTemplateArgs) { const tuple t(4, 5, 6L); // NOLINT EXPECT_THAT(t, (Args<0, 1>(Lt()))); EXPECT_THAT(t, (Args<1, 2>(Lt()))); EXPECT_THAT(t, Not(Args<0, 2>(Gt()))); } TEST(ArgsTest, AcceptsRepeatedTemplateArgs) { const tuple t(4, 5, 6L); // NOLINT EXPECT_THAT(t, (Args<0, 0>(Eq()))); EXPECT_THAT(t, Not(Args<1, 1>(Ne()))); } TEST(ArgsTest, AcceptsDecreasingTemplateArgs) { const tuple t(4, 5, 6L); // NOLINT EXPECT_THAT(t, (Args<2, 0>(Gt()))); EXPECT_THAT(t, Not(Args<2, 1>(Lt()))); } // The MATCHER*() macros trigger warning C4100 (unreferenced formal // parameter) in MSVC with -W4. Unfortunately they cannot be fixed in // the macro definition, as the warnings are generated when the macro // is expanded and macro expansion cannot contain #pragma. Therefore // we suppress them here. #ifdef _MSC_VER # pragma warning(push) # pragma warning(disable:4100) #endif MATCHER(SumIsZero, "") { return get<0>(arg) + get<1>(arg) + get<2>(arg) == 0; } TEST(ArgsTest, AcceptsMoreTemplateArgsThanArityOfOriginalTuple) { EXPECT_THAT(make_tuple(-1, 2), (Args<0, 0, 1>(SumIsZero()))); EXPECT_THAT(make_tuple(1, 2), Not(Args<0, 0, 1>(SumIsZero()))); } TEST(ArgsTest, CanBeNested) { const tuple t(4, 5, 6L, 6); // NOLINT EXPECT_THAT(t, (Args<1, 2, 3>(Args<1, 2>(Eq())))); EXPECT_THAT(t, (Args<0, 1, 3>(Args<0, 2>(Lt())))); } TEST(ArgsTest, CanMatchTupleByValue) { typedef tuple Tuple3; const Matcher m = Args<1, 2>(Lt()); EXPECT_TRUE(m.Matches(Tuple3('a', 1, 2))); EXPECT_FALSE(m.Matches(Tuple3('b', 2, 2))); } TEST(ArgsTest, CanMatchTupleByReference) { typedef tuple Tuple3; const Matcher m = Args<0, 1>(Lt()); EXPECT_TRUE(m.Matches(Tuple3('a', 'b', 2))); EXPECT_FALSE(m.Matches(Tuple3('b', 'b', 2))); } // Validates that arg is printed as str. MATCHER_P(PrintsAs, str, "") { return testing::PrintToString(arg) == str; } TEST(ArgsTest, AcceptsTenTemplateArgs) { EXPECT_THAT(make_tuple(0, 1L, 2, 3L, 4, 5, 6, 7, 8, 9), (Args<9, 8, 7, 6, 5, 4, 3, 2, 1, 0>( PrintsAs("(9, 8, 7, 6, 5, 4, 3, 2, 1, 0)")))); EXPECT_THAT(make_tuple(0, 1L, 2, 3L, 4, 5, 6, 7, 8, 9), Not(Args<9, 8, 7, 6, 5, 4, 3, 2, 1, 0>( PrintsAs("(0, 8, 7, 6, 5, 4, 3, 2, 1, 0)")))); } TEST(ArgsTest, DescirbesSelfCorrectly) { const Matcher > m = Args<2, 0>(Lt()); EXPECT_EQ("are a tuple whose fields (#2, #0) are a pair where " "the first < the second", Describe(m)); } TEST(ArgsTest, DescirbesNestedArgsCorrectly) { const Matcher&> m = Args<0, 2, 3>(Args<2, 0>(Lt())); EXPECT_EQ("are a tuple whose fields (#0, #2, #3) are a tuple " "whose fields (#2, #0) are a pair where the first < the second", Describe(m)); } TEST(ArgsTest, DescribesNegationCorrectly) { const Matcher > m = Args<1, 0>(Gt()); EXPECT_EQ("are a tuple whose fields (#1, #0) aren't a pair " "where the first > the second", DescribeNegation(m)); } TEST(ArgsTest, ExplainsMatchResultWithoutInnerExplanation) { const Matcher > m = Args<1, 2>(Eq()); EXPECT_EQ("whose fields (#1, #2) are (42, 42)", Explain(m, make_tuple(false, 42, 42))); EXPECT_EQ("whose fields (#1, #2) are (42, 43)", Explain(m, make_tuple(false, 42, 43))); } // For testing Args<>'s explanation. class LessThanMatcher : public MatcherInterface > { public: virtual void DescribeTo(::std::ostream* os) const {} virtual bool MatchAndExplain(tuple value, MatchResultListener* listener) const { const int diff = get<0>(value) - get<1>(value); if (diff > 0) { *listener << "where the first value is " << diff << " more than the second"; } return diff < 0; } }; Matcher > LessThan() { return MakeMatcher(new LessThanMatcher); } TEST(ArgsTest, ExplainsMatchResultWithInnerExplanation) { const Matcher > m = Args<0, 2>(LessThan()); EXPECT_EQ("whose fields (#0, #2) are ('a' (97, 0x61), 42), " "where the first value is 55 more than the second", Explain(m, make_tuple('a', 42, 42))); EXPECT_EQ("whose fields (#0, #2) are ('\\0', 43)", Explain(m, make_tuple('\0', 42, 43))); } // For testing ExplainMatchResultTo(). class GreaterThanMatcher : public MatcherInterface { public: explicit GreaterThanMatcher(int rhs) : rhs_(rhs) {} virtual void DescribeTo(::std::ostream* os) const { *os << "is greater than " << rhs_; } virtual bool MatchAndExplain(int lhs, MatchResultListener* listener) const { const int diff = lhs - rhs_; if (diff > 0) { *listener << "which is " << diff << " more than " << rhs_; } else if (diff == 0) { *listener << "which is the same as " << rhs_; } else { *listener << "which is " << -diff << " less than " << rhs_; } return lhs > rhs_; } private: int rhs_; }; Matcher GreaterThan(int n) { return MakeMatcher(new GreaterThanMatcher(n)); } // Tests for ElementsAre(). TEST(ElementsAreTest, CanDescribeExpectingNoElement) { Matcher&> m = ElementsAre(); EXPECT_EQ("is empty", Describe(m)); } TEST(ElementsAreTest, CanDescribeExpectingOneElement) { Matcher > m = ElementsAre(Gt(5)); EXPECT_EQ("has 1 element that is > 5", Describe(m)); } TEST(ElementsAreTest, CanDescribeExpectingManyElements) { Matcher > m = ElementsAre(StrEq("one"), "two"); EXPECT_EQ("has 2 elements where\n" "element #0 is equal to \"one\",\n" "element #1 is equal to \"two\"", Describe(m)); } TEST(ElementsAreTest, CanDescribeNegationOfExpectingNoElement) { Matcher > m = ElementsAre(); EXPECT_EQ("isn't empty", DescribeNegation(m)); } TEST(ElementsAreTest, CanDescribeNegationOfExpectingOneElment) { Matcher& > m = ElementsAre(Gt(5)); EXPECT_EQ("doesn't have 1 element, or\n" "element #0 isn't > 5", DescribeNegation(m)); } TEST(ElementsAreTest, CanDescribeNegationOfExpectingManyElements) { Matcher& > m = ElementsAre("one", "two"); EXPECT_EQ("doesn't have 2 elements, or\n" "element #0 isn't equal to \"one\", or\n" "element #1 isn't equal to \"two\"", DescribeNegation(m)); } TEST(ElementsAreTest, DoesNotExplainTrivialMatch) { Matcher& > m = ElementsAre(1, Ne(2)); list test_list; test_list.push_back(1); test_list.push_back(3); EXPECT_EQ("", Explain(m, test_list)); // No need to explain anything. } TEST(ElementsAreTest, ExplainsNonTrivialMatch) { Matcher& > m = ElementsAre(GreaterThan(1), 0, GreaterThan(2)); const int a[] = { 10, 0, 100 }; vector test_vector(a, a + GTEST_ARRAY_SIZE_(a)); EXPECT_EQ("whose element #0 matches, which is 9 more than 1,\n" "and whose element #2 matches, which is 98 more than 2", Explain(m, test_vector)); } TEST(ElementsAreTest, CanExplainMismatchWrongSize) { Matcher& > m = ElementsAre(1, 3); list test_list; // No need to explain when the container is empty. EXPECT_EQ("", Explain(m, test_list)); test_list.push_back(1); EXPECT_EQ("which has 1 element", Explain(m, test_list)); } TEST(ElementsAreTest, CanExplainMismatchRightSize) { Matcher& > m = ElementsAre(1, GreaterThan(5)); vector v; v.push_back(2); v.push_back(1); EXPECT_EQ("whose element #0 doesn't match", Explain(m, v)); v[0] = 1; EXPECT_EQ("whose element #1 doesn't match, which is 4 less than 5", Explain(m, v)); } TEST(ElementsAreTest, MatchesOneElementVector) { vector test_vector; test_vector.push_back("test string"); EXPECT_THAT(test_vector, ElementsAre(StrEq("test string"))); } TEST(ElementsAreTest, MatchesOneElementList) { list test_list; test_list.push_back("test string"); EXPECT_THAT(test_list, ElementsAre("test string")); } TEST(ElementsAreTest, MatchesThreeElementVector) { vector test_vector; test_vector.push_back("one"); test_vector.push_back("two"); test_vector.push_back("three"); EXPECT_THAT(test_vector, ElementsAre("one", StrEq("two"), _)); } TEST(ElementsAreTest, MatchesOneElementEqMatcher) { vector test_vector; test_vector.push_back(4); EXPECT_THAT(test_vector, ElementsAre(Eq(4))); } TEST(ElementsAreTest, MatchesOneElementAnyMatcher) { vector test_vector; test_vector.push_back(4); EXPECT_THAT(test_vector, ElementsAre(_)); } TEST(ElementsAreTest, MatchesOneElementValue) { vector test_vector; test_vector.push_back(4); EXPECT_THAT(test_vector, ElementsAre(4)); } TEST(ElementsAreTest, MatchesThreeElementsMixedMatchers) { vector test_vector; test_vector.push_back(1); test_vector.push_back(2); test_vector.push_back(3); EXPECT_THAT(test_vector, ElementsAre(1, Eq(2), _)); } TEST(ElementsAreTest, MatchesTenElementVector) { const int a[] = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 }; vector test_vector(a, a + GTEST_ARRAY_SIZE_(a)); EXPECT_THAT(test_vector, // The element list can contain values and/or matchers // of different types. ElementsAre(0, Ge(0), _, 3, 4, Ne(2), Eq(6), 7, 8, _)); } TEST(ElementsAreTest, DoesNotMatchWrongSize) { vector test_vector; test_vector.push_back("test string"); test_vector.push_back("test string"); Matcher > m = ElementsAre(StrEq("test string")); EXPECT_FALSE(m.Matches(test_vector)); } TEST(ElementsAreTest, DoesNotMatchWrongValue) { vector test_vector; test_vector.push_back("other string"); Matcher > m = ElementsAre(StrEq("test string")); EXPECT_FALSE(m.Matches(test_vector)); } TEST(ElementsAreTest, DoesNotMatchWrongOrder) { vector test_vector; test_vector.push_back("one"); test_vector.push_back("three"); test_vector.push_back("two"); Matcher > m = ElementsAre( StrEq("one"), StrEq("two"), StrEq("three")); EXPECT_FALSE(m.Matches(test_vector)); } TEST(ElementsAreTest, WorksForNestedContainer) { const char* strings[] = { "Hi", "world" }; vector > nested; for (size_t i = 0; i < GTEST_ARRAY_SIZE_(strings); i++) { nested.push_back(list(strings[i], strings[i] + strlen(strings[i]))); } EXPECT_THAT(nested, ElementsAre(ElementsAre('H', Ne('e')), ElementsAre('w', 'o', _, _, 'd'))); EXPECT_THAT(nested, Not(ElementsAre(ElementsAre('H', 'e'), ElementsAre('w', 'o', _, _, 'd')))); } TEST(ElementsAreTest, WorksWithByRefElementMatchers) { int a[] = { 0, 1, 2 }; vector v(a, a + GTEST_ARRAY_SIZE_(a)); EXPECT_THAT(v, ElementsAre(Ref(v[0]), Ref(v[1]), Ref(v[2]))); EXPECT_THAT(v, Not(ElementsAre(Ref(v[0]), Ref(v[1]), Ref(a[2])))); } TEST(ElementsAreTest, WorksWithContainerPointerUsingPointee) { int a[] = { 0, 1, 2 }; vector v(a, a + GTEST_ARRAY_SIZE_(a)); EXPECT_THAT(&v, Pointee(ElementsAre(0, 1, _))); EXPECT_THAT(&v, Not(Pointee(ElementsAre(0, _, 3)))); } TEST(ElementsAreTest, WorksWithNativeArrayPassedByReference) { int array[] = { 0, 1, 2 }; EXPECT_THAT(array, ElementsAre(0, 1, _)); EXPECT_THAT(array, Not(ElementsAre(1, _, _))); EXPECT_THAT(array, Not(ElementsAre(0, _))); } class NativeArrayPassedAsPointerAndSize { public: NativeArrayPassedAsPointerAndSize() {} MOCK_METHOD2(Helper, void(int* array, int size)); private: GTEST_DISALLOW_COPY_AND_ASSIGN_(NativeArrayPassedAsPointerAndSize); }; TEST(ElementsAreTest, WorksWithNativeArrayPassedAsPointerAndSize) { int array[] = { 0, 1 }; ::testing::tuple array_as_tuple(array, 2); EXPECT_THAT(array_as_tuple, ElementsAre(0, 1)); EXPECT_THAT(array_as_tuple, Not(ElementsAre(0))); NativeArrayPassedAsPointerAndSize helper; EXPECT_CALL(helper, Helper(_, _)) .With(ElementsAre(0, 1)); helper.Helper(array, 2); } TEST(ElementsAreTest, WorksWithTwoDimensionalNativeArray) { const char a2[][3] = { "hi", "lo" }; EXPECT_THAT(a2, ElementsAre(ElementsAre('h', 'i', '\0'), ElementsAre('l', 'o', '\0'))); EXPECT_THAT(a2, ElementsAre(StrEq("hi"), StrEq("lo"))); EXPECT_THAT(a2, ElementsAre(Not(ElementsAre('h', 'o', '\0')), ElementsAre('l', 'o', '\0'))); } TEST(ElementsAreTest, AcceptsStringLiteral) { string array[] = { "hi", "one", "two" }; EXPECT_THAT(array, ElementsAre("hi", "one", "two")); EXPECT_THAT(array, Not(ElementsAre("hi", "one", "too"))); } #ifndef _MSC_VER // The following test passes a value of type const char[] to a // function template that expects const T&. Some versions of MSVC // generates a compiler error C2665 for that. We believe it's a bug // in MSVC. Therefore this test is #if-ed out for MSVC. // Declared here with the size unknown. Defined AFTER the following test. extern const char kHi[]; TEST(ElementsAreTest, AcceptsArrayWithUnknownSize) { // The size of kHi is not known in this test, but ElementsAre() should // still accept it. string array1[] = { "hi" }; EXPECT_THAT(array1, ElementsAre(kHi)); string array2[] = { "ho" }; EXPECT_THAT(array2, Not(ElementsAre(kHi))); } const char kHi[] = "hi"; #endif // _MSC_VER TEST(ElementsAreTest, MakesCopyOfArguments) { int x = 1; int y = 2; // This should make a copy of x and y. ::testing::internal::ElementsAreMatcher > polymorphic_matcher = ElementsAre(x, y); // Changing x and y now shouldn't affect the meaning of the above matcher. x = y = 0; const int array1[] = { 1, 2 }; EXPECT_THAT(array1, polymorphic_matcher); const int array2[] = { 0, 0 }; EXPECT_THAT(array2, Not(polymorphic_matcher)); } // Tests for ElementsAreArray(). Since ElementsAreArray() shares most // of the implementation with ElementsAre(), we don't test it as // thoroughly here. TEST(ElementsAreArrayTest, CanBeCreatedWithValueArray) { const int a[] = { 1, 2, 3 }; vector test_vector(a, a + GTEST_ARRAY_SIZE_(a)); EXPECT_THAT(test_vector, ElementsAreArray(a)); test_vector[2] = 0; EXPECT_THAT(test_vector, Not(ElementsAreArray(a))); } TEST(ElementsAreArrayTest, CanBeCreatedWithArraySize) { const char* a[] = { "one", "two", "three" }; vector test_vector(a, a + GTEST_ARRAY_SIZE_(a)); EXPECT_THAT(test_vector, ElementsAreArray(a, GTEST_ARRAY_SIZE_(a))); const char** p = a; test_vector[0] = "1"; EXPECT_THAT(test_vector, Not(ElementsAreArray(p, GTEST_ARRAY_SIZE_(a)))); } TEST(ElementsAreArrayTest, CanBeCreatedWithoutArraySize) { const char* a[] = { "one", "two", "three" }; vector test_vector(a, a + GTEST_ARRAY_SIZE_(a)); EXPECT_THAT(test_vector, ElementsAreArray(a)); test_vector[0] = "1"; EXPECT_THAT(test_vector, Not(ElementsAreArray(a))); } TEST(ElementsAreArrayTest, CanBeCreatedWithMatcherArray) { const Matcher kMatcherArray[] = { StrEq("one"), StrEq("two"), StrEq("three") }; vector test_vector; test_vector.push_back("one"); test_vector.push_back("two"); test_vector.push_back("three"); EXPECT_THAT(test_vector, ElementsAreArray(kMatcherArray)); test_vector.push_back("three"); EXPECT_THAT(test_vector, Not(ElementsAreArray(kMatcherArray))); } TEST(ElementsAreArrayTest, CanBeCreatedWithVector) { const int a[] = { 1, 2, 3 }; vector test_vector(a, a + GTEST_ARRAY_SIZE_(a)); const vector expected(a, a + GTEST_ARRAY_SIZE_(a)); EXPECT_THAT(test_vector, ElementsAreArray(expected)); test_vector.push_back(4); EXPECT_THAT(test_vector, Not(ElementsAreArray(expected))); } #if GTEST_HAS_STD_INITIALIZER_LIST_ TEST(ElementsAreArrayTest, TakesInitializerList) { const int a[5] = { 1, 2, 3, 4, 5 }; EXPECT_THAT(a, ElementsAreArray({ 1, 2, 3, 4, 5 })); EXPECT_THAT(a, Not(ElementsAreArray({ 1, 2, 3, 5, 4 }))); EXPECT_THAT(a, Not(ElementsAreArray({ 1, 2, 3, 4, 6 }))); } TEST(ElementsAreArrayTest, TakesInitializerListOfCStrings) { const string a[5] = { "a", "b", "c", "d", "e" }; EXPECT_THAT(a, ElementsAreArray({ "a", "b", "c", "d", "e" })); EXPECT_THAT(a, Not(ElementsAreArray({ "a", "b", "c", "e", "d" }))); EXPECT_THAT(a, Not(ElementsAreArray({ "a", "b", "c", "d", "ef" }))); } TEST(ElementsAreArrayTest, TakesInitializerListOfSameTypedMatchers) { const int a[5] = { 1, 2, 3, 4, 5 }; EXPECT_THAT(a, ElementsAreArray( { Eq(1), Eq(2), Eq(3), Eq(4), Eq(5) })); EXPECT_THAT(a, Not(ElementsAreArray( { Eq(1), Eq(2), Eq(3), Eq(4), Eq(6) }))); } TEST(ElementsAreArrayTest, TakesInitializerListOfDifferentTypedMatchers) { const int a[5] = { 1, 2, 3, 4, 5 }; // The compiler cannot infer the type of the initializer list if its // elements have different types. We must explicitly specify the // unified element type in this case. EXPECT_THAT(a, ElementsAreArray >( { Eq(1), Ne(-2), Ge(3), Le(4), Eq(5) })); EXPECT_THAT(a, Not(ElementsAreArray >( { Eq(1), Ne(-2), Ge(3), Le(4), Eq(6) }))); } #endif // GTEST_HAS_STD_INITIALIZER_LIST_ TEST(ElementsAreArrayTest, CanBeCreatedWithMatcherVector) { const int a[] = { 1, 2, 3 }; const Matcher kMatchers[] = { Eq(1), Eq(2), Eq(3) }; vector test_vector(a, a + GTEST_ARRAY_SIZE_(a)); const vector > expected( kMatchers, kMatchers + GTEST_ARRAY_SIZE_(kMatchers)); EXPECT_THAT(test_vector, ElementsAreArray(expected)); test_vector.push_back(4); EXPECT_THAT(test_vector, Not(ElementsAreArray(expected))); } TEST(ElementsAreArrayTest, CanBeCreatedWithIteratorRange) { const int a[] = { 1, 2, 3 }; const vector test_vector(a, a + GTEST_ARRAY_SIZE_(a)); const vector expected(a, a + GTEST_ARRAY_SIZE_(a)); EXPECT_THAT(test_vector, ElementsAreArray(expected.begin(), expected.end())); // Pointers are iterators, too. EXPECT_THAT(test_vector, ElementsAreArray(a, a + GTEST_ARRAY_SIZE_(a))); // The empty range of NULL pointers should also be okay. int* const null_int = NULL; EXPECT_THAT(test_vector, Not(ElementsAreArray(null_int, null_int))); EXPECT_THAT((vector()), ElementsAreArray(null_int, null_int)); } // Since ElementsAre() and ElementsAreArray() share much of the // implementation, we only do a sanity test for native arrays here. TEST(ElementsAreArrayTest, WorksWithNativeArray) { ::std::string a[] = { "hi", "ho" }; ::std::string b[] = { "hi", "ho" }; EXPECT_THAT(a, ElementsAreArray(b)); EXPECT_THAT(a, ElementsAreArray(b, 2)); EXPECT_THAT(a, Not(ElementsAreArray(b, 1))); } TEST(ElementsAreArrayTest, SourceLifeSpan) { const int a[] = { 1, 2, 3 }; vector test_vector(a, a + GTEST_ARRAY_SIZE_(a)); vector expect(a, a + GTEST_ARRAY_SIZE_(a)); ElementsAreArrayMatcher matcher_maker = ElementsAreArray(expect.begin(), expect.end()); EXPECT_THAT(test_vector, matcher_maker); // Changing in place the values that initialized matcher_maker should not // affect matcher_maker anymore. It should have made its own copy of them. typedef vector::iterator Iter; for (Iter it = expect.begin(); it != expect.end(); ++it) { *it += 10; } EXPECT_THAT(test_vector, matcher_maker); test_vector.push_back(3); EXPECT_THAT(test_vector, Not(matcher_maker)); } // Tests for the MATCHER*() macro family. // Tests that a simple MATCHER() definition works. MATCHER(IsEven, "") { return (arg % 2) == 0; } TEST(MatcherMacroTest, Works) { const Matcher m = IsEven(); EXPECT_TRUE(m.Matches(6)); EXPECT_FALSE(m.Matches(7)); EXPECT_EQ("is even", Describe(m)); EXPECT_EQ("not (is even)", DescribeNegation(m)); EXPECT_EQ("", Explain(m, 6)); EXPECT_EQ("", Explain(m, 7)); } // This also tests that the description string can reference 'negation'. MATCHER(IsEven2, negation ? "is odd" : "is even") { if ((arg % 2) == 0) { // Verifies that we can stream to result_listener, a listener // supplied by the MATCHER macro implicitly. *result_listener << "OK"; return true; } else { *result_listener << "% 2 == " << (arg % 2); return false; } } // This also tests that the description string can reference matcher // parameters. MATCHER_P2(EqSumOf, x, y, string(negation ? "doesn't equal" : "equals") + " the sum of " + PrintToString(x) + " and " + PrintToString(y)) { if (arg == (x + y)) { *result_listener << "OK"; return true; } else { // Verifies that we can stream to the underlying stream of // result_listener. if (result_listener->stream() != NULL) { *result_listener->stream() << "diff == " << (x + y - arg); } return false; } } // Tests that the matcher description can reference 'negation' and the // matcher parameters. TEST(MatcherMacroTest, DescriptionCanReferenceNegationAndParameters) { const Matcher m1 = IsEven2(); EXPECT_EQ("is even", Describe(m1)); EXPECT_EQ("is odd", DescribeNegation(m1)); const Matcher m2 = EqSumOf(5, 9); EXPECT_EQ("equals the sum of 5 and 9", Describe(m2)); EXPECT_EQ("doesn't equal the sum of 5 and 9", DescribeNegation(m2)); } // Tests explaining match result in a MATCHER* macro. TEST(MatcherMacroTest, CanExplainMatchResult) { const Matcher m1 = IsEven2(); EXPECT_EQ("OK", Explain(m1, 4)); EXPECT_EQ("% 2 == 1", Explain(m1, 5)); const Matcher m2 = EqSumOf(1, 2); EXPECT_EQ("OK", Explain(m2, 3)); EXPECT_EQ("diff == -1", Explain(m2, 4)); } // Tests that the body of MATCHER() can reference the type of the // value being matched. MATCHER(IsEmptyString, "") { StaticAssertTypeEq< ::std::string, arg_type>(); return arg == ""; } MATCHER(IsEmptyStringByRef, "") { StaticAssertTypeEq(); return arg == ""; } TEST(MatcherMacroTest, CanReferenceArgType) { const Matcher< ::std::string> m1 = IsEmptyString(); EXPECT_TRUE(m1.Matches("")); const Matcher m2 = IsEmptyStringByRef(); EXPECT_TRUE(m2.Matches("")); } // Tests that MATCHER() can be used in a namespace. namespace matcher_test { MATCHER(IsOdd, "") { return (arg % 2) != 0; } } // namespace matcher_test TEST(MatcherMacroTest, WorksInNamespace) { Matcher m = matcher_test::IsOdd(); EXPECT_FALSE(m.Matches(4)); EXPECT_TRUE(m.Matches(5)); } // Tests that Value() can be used to compose matchers. MATCHER(IsPositiveOdd, "") { return Value(arg, matcher_test::IsOdd()) && arg > 0; } TEST(MatcherMacroTest, CanBeComposedUsingValue) { EXPECT_THAT(3, IsPositiveOdd()); EXPECT_THAT(4, Not(IsPositiveOdd())); EXPECT_THAT(-1, Not(IsPositiveOdd())); } // Tests that a simple MATCHER_P() definition works. MATCHER_P(IsGreaterThan32And, n, "") { return arg > 32 && arg > n; } TEST(MatcherPMacroTest, Works) { const Matcher m = IsGreaterThan32And(5); EXPECT_TRUE(m.Matches(36)); EXPECT_FALSE(m.Matches(5)); EXPECT_EQ("is greater than 32 and 5", Describe(m)); EXPECT_EQ("not (is greater than 32 and 5)", DescribeNegation(m)); EXPECT_EQ("", Explain(m, 36)); EXPECT_EQ("", Explain(m, 5)); } // Tests that the description is calculated correctly from the matcher name. MATCHER_P(_is_Greater_Than32and_, n, "") { return arg > 32 && arg > n; } TEST(MatcherPMacroTest, GeneratesCorrectDescription) { const Matcher m = _is_Greater_Than32and_(5); EXPECT_EQ("is greater than 32 and 5", Describe(m)); EXPECT_EQ("not (is greater than 32 and 5)", DescribeNegation(m)); EXPECT_EQ("", Explain(m, 36)); EXPECT_EQ("", Explain(m, 5)); } // Tests that a MATCHER_P matcher can be explicitly instantiated with // a reference parameter type. class UncopyableFoo { public: explicit UncopyableFoo(char value) : value_(value) {} private: UncopyableFoo(const UncopyableFoo&); void operator=(const UncopyableFoo&); char value_; }; MATCHER_P(ReferencesUncopyable, variable, "") { return &arg == &variable; } TEST(MatcherPMacroTest, WorksWhenExplicitlyInstantiatedWithReference) { UncopyableFoo foo1('1'), foo2('2'); const Matcher m = ReferencesUncopyable(foo1); EXPECT_TRUE(m.Matches(foo1)); EXPECT_FALSE(m.Matches(foo2)); // We don't want the address of the parameter printed, as most // likely it will just annoy the user. If the address is // interesting, the user should consider passing the parameter by // pointer instead. EXPECT_EQ("references uncopyable 1-byte object <31>", Describe(m)); } // Tests that the body of MATCHER_Pn() can reference the parameter // types. MATCHER_P3(ParamTypesAreIntLongAndChar, foo, bar, baz, "") { StaticAssertTypeEq(); StaticAssertTypeEq(); // NOLINT StaticAssertTypeEq(); return arg == 0; } TEST(MatcherPnMacroTest, CanReferenceParamTypes) { EXPECT_THAT(0, ParamTypesAreIntLongAndChar(10, 20L, 'a')); } // Tests that a MATCHER_Pn matcher can be explicitly instantiated with // reference parameter types. MATCHER_P2(ReferencesAnyOf, variable1, variable2, "") { return &arg == &variable1 || &arg == &variable2; } TEST(MatcherPnMacroTest, WorksWhenExplicitlyInstantiatedWithReferences) { UncopyableFoo foo1('1'), foo2('2'), foo3('3'); const Matcher m = ReferencesAnyOf(foo1, foo2); EXPECT_TRUE(m.Matches(foo1)); EXPECT_TRUE(m.Matches(foo2)); EXPECT_FALSE(m.Matches(foo3)); } TEST(MatcherPnMacroTest, GeneratesCorretDescriptionWhenExplicitlyInstantiatedWithReferences) { UncopyableFoo foo1('1'), foo2('2'); const Matcher m = ReferencesAnyOf(foo1, foo2); // We don't want the addresses of the parameters printed, as most // likely they will just annoy the user. If the addresses are // interesting, the user should consider passing the parameters by // pointers instead. EXPECT_EQ("references any of (1-byte object <31>, 1-byte object <32>)", Describe(m)); } // Tests that a simple MATCHER_P2() definition works. MATCHER_P2(IsNotInClosedRange, low, hi, "") { return arg < low || arg > hi; } TEST(MatcherPnMacroTest, Works) { const Matcher m = IsNotInClosedRange(10, 20); // NOLINT EXPECT_TRUE(m.Matches(36L)); EXPECT_FALSE(m.Matches(15L)); EXPECT_EQ("is not in closed range (10, 20)", Describe(m)); EXPECT_EQ("not (is not in closed range (10, 20))", DescribeNegation(m)); EXPECT_EQ("", Explain(m, 36L)); EXPECT_EQ("", Explain(m, 15L)); } // Tests that MATCHER*() definitions can be overloaded on the number // of parameters; also tests MATCHER_Pn() where n >= 3. MATCHER(EqualsSumOf, "") { return arg == 0; } MATCHER_P(EqualsSumOf, a, "") { return arg == a; } MATCHER_P2(EqualsSumOf, a, b, "") { return arg == a + b; } MATCHER_P3(EqualsSumOf, a, b, c, "") { return arg == a + b + c; } MATCHER_P4(EqualsSumOf, a, b, c, d, "") { return arg == a + b + c + d; } MATCHER_P5(EqualsSumOf, a, b, c, d, e, "") { return arg == a + b + c + d + e; } MATCHER_P6(EqualsSumOf, a, b, c, d, e, f, "") { return arg == a + b + c + d + e + f; } MATCHER_P7(EqualsSumOf, a, b, c, d, e, f, g, "") { return arg == a + b + c + d + e + f + g; } MATCHER_P8(EqualsSumOf, a, b, c, d, e, f, g, h, "") { return arg == a + b + c + d + e + f + g + h; } MATCHER_P9(EqualsSumOf, a, b, c, d, e, f, g, h, i, "") { return arg == a + b + c + d + e + f + g + h + i; } MATCHER_P10(EqualsSumOf, a, b, c, d, e, f, g, h, i, j, "") { return arg == a + b + c + d + e + f + g + h + i + j; } TEST(MatcherPnMacroTest, CanBeOverloadedOnNumberOfParameters) { EXPECT_THAT(0, EqualsSumOf()); EXPECT_THAT(1, EqualsSumOf(1)); EXPECT_THAT(12, EqualsSumOf(10, 2)); EXPECT_THAT(123, EqualsSumOf(100, 20, 3)); EXPECT_THAT(1234, EqualsSumOf(1000, 200, 30, 4)); EXPECT_THAT(12345, EqualsSumOf(10000, 2000, 300, 40, 5)); EXPECT_THAT("abcdef", EqualsSumOf(::std::string("a"), 'b', 'c', "d", "e", 'f')); EXPECT_THAT("abcdefg", EqualsSumOf(::std::string("a"), 'b', 'c', "d", "e", 'f', 'g')); EXPECT_THAT("abcdefgh", EqualsSumOf(::std::string("a"), 'b', 'c', "d", "e", 'f', 'g', "h")); EXPECT_THAT("abcdefghi", EqualsSumOf(::std::string("a"), 'b', 'c', "d", "e", 'f', 'g', "h", 'i')); EXPECT_THAT("abcdefghij", EqualsSumOf(::std::string("a"), 'b', 'c', "d", "e", 'f', 'g', "h", 'i', ::std::string("j"))); EXPECT_THAT(1, Not(EqualsSumOf())); EXPECT_THAT(-1, Not(EqualsSumOf(1))); EXPECT_THAT(-12, Not(EqualsSumOf(10, 2))); EXPECT_THAT(-123, Not(EqualsSumOf(100, 20, 3))); EXPECT_THAT(-1234, Not(EqualsSumOf(1000, 200, 30, 4))); EXPECT_THAT(-12345, Not(EqualsSumOf(10000, 2000, 300, 40, 5))); EXPECT_THAT("abcdef ", Not(EqualsSumOf(::std::string("a"), 'b', 'c', "d", "e", 'f'))); EXPECT_THAT("abcdefg ", Not(EqualsSumOf(::std::string("a"), 'b', 'c', "d", "e", 'f', 'g'))); EXPECT_THAT("abcdefgh ", Not(EqualsSumOf(::std::string("a"), 'b', 'c', "d", "e", 'f', 'g', "h"))); EXPECT_THAT("abcdefghi ", Not(EqualsSumOf(::std::string("a"), 'b', 'c', "d", "e", 'f', 'g', "h", 'i'))); EXPECT_THAT("abcdefghij ", Not(EqualsSumOf(::std::string("a"), 'b', 'c', "d", "e", 'f', 'g', "h", 'i', ::std::string("j")))); } // Tests that a MATCHER_Pn() definition can be instantiated with any // compatible parameter types. TEST(MatcherPnMacroTest, WorksForDifferentParameterTypes) { EXPECT_THAT(123, EqualsSumOf(100L, 20, static_cast(3))); EXPECT_THAT("abcd", EqualsSumOf(::std::string("a"), "b", 'c', "d")); EXPECT_THAT(124, Not(EqualsSumOf(100L, 20, static_cast(3)))); EXPECT_THAT("abcde", Not(EqualsSumOf(::std::string("a"), "b", 'c', "d"))); } // Tests that the matcher body can promote the parameter types. MATCHER_P2(EqConcat, prefix, suffix, "") { // The following lines promote the two parameters to desired types. std::string prefix_str(prefix); char suffix_char = static_cast(suffix); return arg == prefix_str + suffix_char; } TEST(MatcherPnMacroTest, SimpleTypePromotion) { Matcher no_promo = EqConcat(std::string("foo"), 't'); Matcher promo = EqConcat("foo", static_cast('t')); EXPECT_FALSE(no_promo.Matches("fool")); EXPECT_FALSE(promo.Matches("fool")); EXPECT_TRUE(no_promo.Matches("foot")); EXPECT_TRUE(promo.Matches("foot")); } // Verifies the type of a MATCHER*. TEST(MatcherPnMacroTest, TypesAreCorrect) { // EqualsSumOf() must be assignable to a EqualsSumOfMatcher variable. EqualsSumOfMatcher a0 = EqualsSumOf(); // EqualsSumOf(1) must be assignable to a EqualsSumOfMatcherP variable. EqualsSumOfMatcherP a1 = EqualsSumOf(1); // EqualsSumOf(p1, ..., pk) must be assignable to a EqualsSumOfMatcherPk // variable, and so on. EqualsSumOfMatcherP2 a2 = EqualsSumOf(1, '2'); EqualsSumOfMatcherP3 a3 = EqualsSumOf(1, 2, '3'); EqualsSumOfMatcherP4 a4 = EqualsSumOf(1, 2, 3, '4'); EqualsSumOfMatcherP5 a5 = EqualsSumOf(1, 2, 3, 4, '5'); EqualsSumOfMatcherP6 a6 = EqualsSumOf(1, 2, 3, 4, 5, '6'); EqualsSumOfMatcherP7 a7 = EqualsSumOf(1, 2, 3, 4, 5, 6, '7'); EqualsSumOfMatcherP8 a8 = EqualsSumOf(1, 2, 3, 4, 5, 6, 7, '8'); EqualsSumOfMatcherP9 a9 = EqualsSumOf(1, 2, 3, 4, 5, 6, 7, 8, '9'); EqualsSumOfMatcherP10 a10 = EqualsSumOf(1, 2, 3, 4, 5, 6, 7, 8, 9, '0'); // Avoid "unused variable" warnings. (void)a0; (void)a1; (void)a2; (void)a3; (void)a4; (void)a5; (void)a6; (void)a7; (void)a8; (void)a9; (void)a10; } // Tests that matcher-typed parameters can be used in Value() inside a // MATCHER_Pn definition. // Succeeds if arg matches exactly 2 of the 3 matchers. MATCHER_P3(TwoOf, m1, m2, m3, "") { const int count = static_cast(Value(arg, m1)) + static_cast(Value(arg, m2)) + static_cast(Value(arg, m3)); return count == 2; } TEST(MatcherPnMacroTest, CanUseMatcherTypedParameterInValue) { EXPECT_THAT(42, TwoOf(Gt(0), Lt(50), Eq(10))); EXPECT_THAT(0, Not(TwoOf(Gt(-1), Lt(1), Eq(0)))); } // Tests Contains(). TEST(ContainsTest, ListMatchesWhenElementIsInContainer) { list some_list; some_list.push_back(3); some_list.push_back(1); some_list.push_back(2); EXPECT_THAT(some_list, Contains(1)); EXPECT_THAT(some_list, Contains(Gt(2.5))); EXPECT_THAT(some_list, Contains(Eq(2.0f))); list another_list; another_list.push_back("fee"); another_list.push_back("fie"); another_list.push_back("foe"); another_list.push_back("fum"); EXPECT_THAT(another_list, Contains(string("fee"))); } TEST(ContainsTest, ListDoesNotMatchWhenElementIsNotInContainer) { list some_list; some_list.push_back(3); some_list.push_back(1); EXPECT_THAT(some_list, Not(Contains(4))); } TEST(ContainsTest, SetMatchesWhenElementIsInContainer) { set some_set; some_set.insert(3); some_set.insert(1); some_set.insert(2); EXPECT_THAT(some_set, Contains(Eq(1.0))); EXPECT_THAT(some_set, Contains(Eq(3.0f))); EXPECT_THAT(some_set, Contains(2)); set another_set; another_set.insert("fee"); another_set.insert("fie"); another_set.insert("foe"); another_set.insert("fum"); EXPECT_THAT(another_set, Contains(Eq(string("fum")))); } TEST(ContainsTest, SetDoesNotMatchWhenElementIsNotInContainer) { set some_set; some_set.insert(3); some_set.insert(1); EXPECT_THAT(some_set, Not(Contains(4))); set c_string_set; c_string_set.insert("hello"); EXPECT_THAT(c_string_set, Not(Contains(string("hello").c_str()))); } TEST(ContainsTest, ExplainsMatchResultCorrectly) { const int a[2] = { 1, 2 }; Matcher m = Contains(2); EXPECT_EQ("whose element #1 matches", Explain(m, a)); m = Contains(3); EXPECT_EQ("", Explain(m, a)); m = Contains(GreaterThan(0)); EXPECT_EQ("whose element #0 matches, which is 1 more than 0", Explain(m, a)); m = Contains(GreaterThan(10)); EXPECT_EQ("", Explain(m, a)); } TEST(ContainsTest, DescribesItselfCorrectly) { Matcher > m = Contains(1); EXPECT_EQ("contains at least one element that is equal to 1", Describe(m)); Matcher > m2 = Not(m); EXPECT_EQ("doesn't contain any element that is equal to 1", Describe(m2)); } TEST(ContainsTest, MapMatchesWhenElementIsInContainer) { map my_map; const char* bar = "a string"; my_map[bar] = 2; EXPECT_THAT(my_map, Contains(pair(bar, 2))); map another_map; another_map["fee"] = 1; another_map["fie"] = 2; another_map["foe"] = 3; another_map["fum"] = 4; EXPECT_THAT(another_map, Contains(pair(string("fee"), 1))); EXPECT_THAT(another_map, Contains(pair("fie", 2))); } TEST(ContainsTest, MapDoesNotMatchWhenElementIsNotInContainer) { map some_map; some_map[1] = 11; some_map[2] = 22; EXPECT_THAT(some_map, Not(Contains(pair(2, 23)))); } TEST(ContainsTest, ArrayMatchesWhenElementIsInContainer) { const char* string_array[] = { "fee", "fie", "foe", "fum" }; EXPECT_THAT(string_array, Contains(Eq(string("fum")))); } TEST(ContainsTest, ArrayDoesNotMatchWhenElementIsNotInContainer) { int int_array[] = { 1, 2, 3, 4 }; EXPECT_THAT(int_array, Not(Contains(5))); } TEST(ContainsTest, AcceptsMatcher) { const int a[] = { 1, 2, 3 }; EXPECT_THAT(a, Contains(Gt(2))); EXPECT_THAT(a, Not(Contains(Gt(4)))); } TEST(ContainsTest, WorksForNativeArrayAsTuple) { const int a[] = { 1, 2 }; const int* const pointer = a; EXPECT_THAT(make_tuple(pointer, 2), Contains(1)); EXPECT_THAT(make_tuple(pointer, 2), Not(Contains(Gt(3)))); } TEST(ContainsTest, WorksForTwoDimensionalNativeArray) { int a[][3] = { { 1, 2, 3 }, { 4, 5, 6 } }; EXPECT_THAT(a, Contains(ElementsAre(4, 5, 6))); EXPECT_THAT(a, Contains(Contains(5))); EXPECT_THAT(a, Not(Contains(ElementsAre(3, 4, 5)))); EXPECT_THAT(a, Contains(Not(Contains(5)))); } TEST(AllOfTest, HugeMatcher) { // Verify that using AllOf with many arguments doesn't cause // the compiler to exceed template instantiation depth limit. EXPECT_THAT(0, testing::AllOf(_, _, _, _, _, _, _, _, _, testing::AllOf(_, _, _, _, _, _, _, _, _, _))); } TEST(AnyOfTest, HugeMatcher) { // Verify that using AnyOf with many arguments doesn't cause // the compiler to exceed template instantiation depth limit. EXPECT_THAT(0, testing::AnyOf(_, _, _, _, _, _, _, _, _, testing::AnyOf(_, _, _, _, _, _, _, _, _, _))); } namespace adl_test { // Verifies that the implementation of ::testing::AllOf and ::testing::AnyOf // don't issue unqualified recursive calls. If they do, the argument dependent // name lookup will cause AllOf/AnyOf in the 'adl_test' namespace to be found // as a candidate and the compilation will break due to an ambiguous overload. // The matcher must be in the same namespace as AllOf/AnyOf to make argument // dependent lookup find those. MATCHER(M, "") { return true; } template bool AllOf(const T1& t1, const T2& t2) { return true; } TEST(AllOfTest, DoesNotCallAllOfUnqualified) { EXPECT_THAT(42, testing::AllOf( M(), M(), M(), M(), M(), M(), M(), M(), M(), M())); } template bool AnyOf(const T1& t1, const T2& t2) { return true; } TEST(AnyOfTest, DoesNotCallAnyOfUnqualified) { EXPECT_THAT(42, testing::AnyOf( M(), M(), M(), M(), M(), M(), M(), M(), M(), M())); } } // namespace adl_test #ifdef _MSC_VER # pragma warning(pop) #endif } // namespace /a> 1147 1148 1149 1150 1151 1152 1153 1154 1155 1156 1157 1158 1159 1160 1161 1162 1163 1164 1165 1166 1167 1168 1169 1170 1171 1172 1173 1174 1175 1176 1177 1178 1179 1180 1181 1182 1183 1184 1185 1186 1187 1188 1189 1190 1191 1192 1193
--  LLVM binding
--  Copyright (C) 2014 Tristan Gingold
--
--  GHDL is free software; you can redistribute it and/or modify it under
--  the terms of the GNU General Public License as published by the Free
--  Software Foundation; either version 2, or (at your option) any later
--  version.
--
--  GHDL is distributed in the hope that it will be useful, but WITHOUT ANY
--  WARRANTY; without even the implied warranty of MERCHANTABILITY or
--  FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
--  for more details.
--
--  You should have received a copy of the GNU General Public License
--  along with GHDL; see the file COPYING.  If not, write to the Free
--  Software Foundation, 59 Temple Place - Suite 330, Boston, MA
--  02111-1307, USA.
with System;
with Interfaces.C; use Interfaces.C;
use Interfaces;

package LLVM.Core is

   subtype Cstring is System.Address;
   function "=" (L, R : Cstring) return Boolean renames System."=";
   --  Null_Cstring : constant Cstring := Null_Address;
   Nul : constant String := (1 => Character'Val (0));
   Empty_Cstring : constant Cstring := Nul'Address;

   --  The top-level container for all LLVM global data. See the LLVMContext
   --  class.
   type ContextRef is new System.Address;

   --  The top-level container for all other LLVM Intermediate
   --  Representation (IR) objects. See the llvm::Module class.
   type ModuleRef is new System.Address;

   subtype Bool is int;

   --  Each value in the LLVM IR has a type, an LLVMTypeRef. See the llvm::Type
   --  class.
   type TypeRef is new System.Address;
   Null_TypeRef : constant TypeRef := TypeRef (System.Null_Address);
   type TypeRefArray is array (unsigned range <>) of TypeRef;
   pragma Convention (C, TypeRefArray);

   type ValueRef is new System.Address;
   Null_ValueRef : constant ValueRef := ValueRef (System.Null_Address);
   type ValueRefArray is array (unsigned range <>) of ValueRef; -- Ada
   pragma Convention (C, ValueRefArray);

   type BasicBlockRef is new System.Address;
   Null_BasicBlockRef : constant BasicBlockRef :=
     BasicBlockRef (System.Null_Address);
   type BasicBlockRefArray is
     array (unsigned range <>) of BasicBlockRef; -- Ada
   pragma Convention (C, BasicBlockRefArray);

   type BuilderRef is new System.Address;

   --  Used to provide a module to JIT or interpreter.
   --  See the llvm::MemoryBuffer class.
   type MemoryBufferRef is new System.Address;

   --  See the llvm::PassManagerBase class.
   type PassManagerRef is new System.Address;

   type Attribute is new unsigned;
   ZExtAttribute            : constant Attribute := 2**0;
   SExtAttribute            : constant Attribute := 2**1;
   NoReturnAttribute        : constant Attribute := 2**2;
   InRegAttribute           : constant Attribute := 2**3;
   StructRetAttribute       : constant Attribute := 2**4;
   NoUnwindAttribute        : constant Attribute := 2**5;
   NoAliasAttribute         : constant Attribute := 2**6;
   ByValAttribute           : constant Attribute := 2**7;
   NestAttribute            : constant Attribute := 2**8;
   ReadNoneAttribute        : constant Attribute := 2**9;
   ReadOnlyAttribute        : constant Attribute := 2**10;
   NoInlineAttribute        : constant Attribute := 2**11;
   AlwaysInlineAttribute    : constant Attribute := 2**12;
   OptimizeForSizeAttribute : constant Attribute := 2**13;
   StackProtectAttribute    : constant Attribute := 2**14;
   StackProtectReqAttribute : constant Attribute := 2**15;
   Alignment                : constant Attribute := 31 * 2**16;
   NoCaptureAttribute       : constant Attribute := 2**21;
   NoRedZoneAttribute       : constant Attribute := 2**22;
   NoImplicitFloatAttribute : constant Attribute := 2**23;
   NakedAttribute           : constant Attribute := 2**24;
   InlineHintAttribute      : constant Attribute := 2**25;
   StackAlignment           : constant Attribute := 7 * 2**26;
   ReturnsTwice             : constant Attribute := 2**29;
   UWTable                  : constant Attribute := 2**30;
   NonLazyBind              : constant Attribute := 2**31;

   type TypeKind is
     (
      VoidTypeKind,        --  type with no size
      HalfTypeKind,        --  16 bit floating point type
      FloatTypeKind,       --  32 bit floating point type
      DoubleTypeKind,      --  64 bit floating point type
      X86_FP80TypeKind,    --  80 bit floating point type (X87)
      FP128TypeKind,       --  128 bit floating point type (112-bit mantissa)
      PPC_FP128TypeKind,   --  128 bit floating point type (two 64-bits)
      LabelTypeKind,       --  Labels
      IntegerTypeKind,     --  Arbitrary bit width integers
      FunctionTypeKind,    --  Functions
      StructTypeKind,      --  Structures
      ArrayTypeKind,       --  Arrays
      PointerTypeKind,     --  Pointers
      VectorTypeKind,      --  SIMD 'packed' format, or other vector type
      MetadataTypeKind,    --  Metadata
      X86_MMXTypeKind      --  X86 MMX
     );
   pragma Convention (C, TypeKind);

   type Linkage is
     (
      ExternalLinkage,    --  Externally visible function
      AvailableExternallyLinkage,
      LinkOnceAnyLinkage, --  Keep one copy of function when linking (inline)
      LinkOnceODRLinkage, --  Same, but only replaced by someth equivalent.
      LinkOnceODRAutoHideLinkage, --  Obsolete
      WeakAnyLinkage,     --  Keep one copy of function when linking (weak)
      WeakODRLinkage,     --  Same, but only replaced by someth equivalent.
      AppendingLinkage,   --  Special purpose, only applies to global arrays
      InternalLinkage,    --  Rename collisions when linking (static func)
      PrivateLinkage,     --  Like Internal, but omit from symbol table
      DLLImportLinkage,   --  Obsolete
      DLLExportLinkage,   --  Obsolete
      ExternalWeakLinkage,--  ExternalWeak linkage description
      GhostLinkage,       --  Obsolete
      CommonLinkage,      --  Tentative definitions
      LinkerPrivateLinkage, --  Like Private, but linker removes.
      LinkerPrivateWeakLinkage --  Like LinkerPrivate, but is weak.
     );
   pragma Convention (C, Linkage);

   type Visibility is
     (
      DefaultVisibility,  --  The GV is visible
      HiddenVisibility,   --  The GV is hidden
      ProtectedVisibility --  The GV is protected
     );
   pragma Convention (C, Visibility);

   type CallConv is new unsigned;
   CCallConv           : constant CallConv := 0;
   FastCallConv        : constant CallConv := 8;
   ColdCallConv        : constant CallConv := 9;
   X86StdcallCallConv  : constant CallConv := 64;
   X86FastcallCallConv : constant CallConv := 6;

   type IntPredicate is new unsigned;
   IntEQ  : constant IntPredicate := 32; -- equal
   IntNE  : constant IntPredicate := 33; -- not equal
   IntUGT : constant IntPredicate := 34; -- unsigned greater than
   IntUGE : constant IntPredicate := 35; -- unsigned greater or equal
   IntULT : constant IntPredicate := 36; -- unsigned less than
   IntULE : constant IntPredicate := 37; -- unsigned less or equal
   IntSGT : constant IntPredicate := 38; -- signed greater than
   IntSGE : constant IntPredicate := 39; -- signed greater or equal
   IntSLT : constant IntPredicate := 40; -- signed less than
   IntSLE : constant IntPredicate := 41; -- signed less or equal

   type RealPredicate is
     (
      RealPredicateFalse, --  Always false (always folded)
      RealOEQ,            --  True if ordered and equal
      RealOGT,            --  True if ordered and greater than
      RealOGE,            --  True if ordered and greater than or equal
      RealOLT,            --  True if ordered and less than
      RealOLE,            --  True if ordered and less than or equal
      RealONE,            --  True if ordered and operands are unequal
      RealORD,            --  True if ordered (no nans)
      RealUNO,            --  True if unordered: isnan(X) | isnan(Y)
      RealUEQ,            --  True if unordered or equal
      RealUGT,            --  True if unordered or greater than
      RealUGE,            --  True if unordered, greater than, or equal
      RealULT,            --  True if unordered or less than
      RealULE,            --  True if unordered, less than, or equal
      RealUNE,            --  True if unordered or not equal
      RealPredicateTrue   --  Always true (always folded)
     );

   -- Error handling ----------------------------------------------------

   procedure DisposeMessage (Message : Cstring);


   --  Context

   --  Create a new context.
   --  Every call to this function should be paired with a call to
   -- LLVMContextDispose() or the context will leak memory.
   function ContextCreate return ContextRef;

   --  Obtain the global context instance.
   function GetGlobalContext return ContextRef;

   --  Destroy a context instance.
   --  This should be called for every call to LLVMContextCreate() or memory
   --  will be leaked.
   procedure ContextDispose (C : ContextRef);

   -- Modules -----------------------------------------------------------

   -- Create and destroy modules.
   -- See llvm::Module::Module.
   function ModuleCreateWithName (ModuleID : Cstring) return ModuleRef;

   -- See llvm::Module::~Module.
   procedure DisposeModule (M : ModuleRef);

   -- Data layout. See Module::getDataLayout.
   function GetDataLayout(M : ModuleRef) return Cstring;
   procedure SetDataLayout(M : ModuleRef; Triple : Cstring);

   -- Target triple. See Module::getTargetTriple.
   function GetTarget (M : ModuleRef) return Cstring;
   procedure SetTarget (M : ModuleRef; Triple : Cstring);

   -- See Module::dump.
   procedure DumpModule(M : ModuleRef);

   --  Print a representation of a module to a file. The ErrorMessage needs to
   --  be disposed with LLVMDisposeMessage. Returns 0 on success, 1 otherwise.
   --
   --  @see Module::print()
   function PrintModuleToFile(M : ModuleRef;
                              Filename : Cstring;
                              ErrorMessage : access Cstring) return Bool;


   -- Types -------------------------------------------------------------

   -- LLVM types conform to the following hierarchy:
   --
   --   types:
   --     integer type
   --     real type
   --     function type
   --     sequence types:
   --       array type
   --       pointer type
   --       vector type
   --     void type
   --     label type
   --     opaque type

   -- See llvm::LLVMTypeKind::getTypeID.
   function GetTypeKind (Ty : TypeRef) return TypeKind;

   -- Operations on integer types
   function Int1Type return TypeRef;
   function Int8Type return TypeRef;
   function Int16Type return TypeRef;
   function Int32Type return TypeRef;
   function Int64Type return TypeRef;
   function IntType(NumBits : unsigned) return TypeRef;
   function GetIntTypeWidth(IntegerTy : TypeRef) return unsigned;

   function MetadataType return TypeRef;

   -- Operations on real types
   function FloatType return TypeRef;
   function DoubleType return TypeRef;
   function X86FP80Type return TypeRef;
   function FP128Type return TypeRef;
   function PPCFP128Type return TypeRef;

   -- Operations on function types
   function FunctionType(ReturnType : TypeRef;
                         ParamTypes : TypeRefArray;
                         ParamCount : unsigned;
                         IsVarArg : int) return TypeRef;

   function IsFunctionVarArg(FunctionTy : TypeRef) return int;
   function GetReturnType(FunctionTy : TypeRef) return TypeRef;
   function CountParamTypes(FunctionTy : TypeRef) return unsigned;
   procedure GetParamTypes(FunctionTy : TypeRef; Dest : out TypeRefArray);

   -- Operations on struct types
   function StructType(ElementTypes : TypeRefArray;
                       ElementCount : unsigned;
                       Packed : Bool) return TypeRef;
   function StructCreateNamed(C : ContextRef; Name : Cstring) return TypeRef;
   procedure StructSetBody(StructTy : TypeRef;
                           ElementTypes : TypeRefArray;
                           ElementCount : unsigned;
                           Packed : Bool);
   function CountStructElementTypes(StructTy : TypeRef) return unsigned;
   procedure GetStructElementTypes(StructTy : TypeRef;
                                   Dest : out TypeRefArray);
   function IsPackedStruct(StructTy : TypeRef) return Bool;


   -- Operations on array, pointer, and vector types (sequence types)
   function ArrayType(ElementType : TypeRef; ElementCount : unsigned)
                     return TypeRef;
   function PointerType(ElementType : TypeRef; AddressSpace : unsigned := 0)
                       return TypeRef;
   function VectorType(ElementType : TypeRef; ElementCount : unsigned)
                      return TypeRef;

   function GetElementType(Ty : TypeRef) return TypeRef;
   function GetArrayLength(ArrayTy : TypeRef) return unsigned;
   function GetPointerAddressSpace(PointerTy : TypeRef) return unsigned;
   function GetVectorSize(VectorTy : TypeRef) return unsigned;

   -- Operations on other types.
   function VoidType return TypeRef;
   function LabelType return TypeRef;

   -- See Module::dump.
   procedure DumpType(T : TypeRef);

   -- Values ------------------------------------------------------------
   -- The bulk of LLVM's object model consists of values, which comprise a very
   -- rich type hierarchy.
   --
   --   values:
   --     constants:
   --       scalar constants
   --       composite contants
   --       globals:
   --         global variable
   --         function
   --         alias
   --       basic blocks

   -- Operations on all values
   function TypeOf(Val : ValueRef) return TypeRef;
   function GetValueName(Val : ValueRef) return Cstring;
   procedure SetValueName(Val : ValueRef; Name : Cstring);
   procedure DumpValue(Val : ValueRef);

   -- Operations on constants of any type
   function ConstNull(Ty : TypeRef) return ValueRef; --  All zero
   function ConstAllOnes(Ty : TypeRef) return ValueRef; -- Int or Vec
   function GetUndef(Ty : TypeRef) return ValueRef;
   function IsConstant(Val : ValueRef) return int;
   function IsNull(Val : ValueRef) return int;
   function IsUndef(Val : ValueRef) return int;

   --  Convert value instances between types.
   --
   --  Internally, an LLVMValueRef is "pinned" to a specific type. This
   --  series of functions allows you to cast an instance to a specific
   --  type.
   --
   --  If the cast is not valid for the specified type, NULL is returned.
   --
   -- @see llvm::dyn_cast_or_null<>
   function IsAInstruction (Val : ValueRef) return ValueRef;

   -- Operations on scalar constants
   function ConstInt(IntTy : TypeRef; N : Unsigned_64; SignExtend : int)
                    return ValueRef;
   function ConstReal(RealTy : TypeRef; N : double) return ValueRef;
   function ConstRealOfString(RealTy : TypeRef; Text : Cstring)
                             return ValueRef;


   -- Obtain the zero extended value for an integer constant value.
   -- @see llvm::ConstantInt::getZExtValue()
   function ConstIntGetZExtValue (ConstantVal : ValueRef) return Unsigned_64;

   -- Operations on composite constants
   function ConstString(Str : Cstring;
                        Length : unsigned; DontNullTerminate : int)
                       return ValueRef;
   function ConstArray(ElementTy : TypeRef;
                       ConstantVals : ValueRefArray; Length : unsigned)
                      return ValueRef;
   function ConstStruct(ConstantVals : ValueRefArray;
                        Count : unsigned; packed : int) return ValueRef;

   --  Create a non-anonymous ConstantStruct from values.
   --  @see llvm::ConstantStruct::get()
   function ConstNamedStruct(StructTy : TypeRef;
                             ConstantVals : ValueRefArray;
                             Count : unsigned) return ValueRef;

   function ConstVector(ScalarConstantVals : ValueRefArray; Size : unsigned)
                       return ValueRef;

   -- Constant expressions
   function SizeOf(Ty : TypeRef) return ValueRef;
   function AlignOf(Ty : TypeRef) return ValueRef;

   function ConstNeg(ConstantVal : ValueRef) return ValueRef;
   function ConstNot(ConstantVal : ValueRef) return ValueRef;
   function ConstAdd(LHSConstant : ValueRef; RHSConstant : ValueRef)
                    return ValueRef;
   function ConstSub(LHSConstant : ValueRef; RHSConstant : ValueRef)
                    return ValueRef;
   function ConstMul(LHSConstant : ValueRef; RHSConstant : ValueRef)
                    return ValueRef;
   function ConstUDiv(LHSConstant : ValueRef; RHSConstant : ValueRef)
                     return ValueRef;
   function ConstSDiv(LHSConstant : ValueRef; RHSConstant : ValueRef)
                     return ValueRef;
   function ConstFDiv(LHSConstant : ValueRef; RHSConstant : ValueRef)
                     return ValueRef;
   function ConstURem(LHSConstant : ValueRef; RHSConstant : ValueRef)
                     return ValueRef;
   function ConstSRem(LHSConstant : ValueRef; RHSConstant : ValueRef)
                     return ValueRef;
   function ConstFRem(LHSConstant : ValueRef; RHSConstant : ValueRef)
                     return ValueRef;
   function ConstAnd(LHSConstant : ValueRef; RHSConstant : ValueRef)
                    return ValueRef;
   function ConstOr(LHSConstant : ValueRef; RHSConstant : ValueRef)
                   return ValueRef;
   function ConstXor(LHSConstant : ValueRef; RHSConstant : ValueRef)
                    return ValueRef;
   function ConstICmp(Predicate : IntPredicate;
                      LHSConstant : ValueRef; RHSConstant : ValueRef)
                     return ValueRef;
   function ConstFCmp(Predicate : RealPredicate;
                      LHSConstant : ValueRef; RHSConstant : ValueRef)
                     return ValueRef;
   function ConstShl(LHSConstant : ValueRef; RHSConstant : ValueRef)
                    return ValueRef;
   function ConstLShr(LHSConstant : ValueRef; RHSConstant : ValueRef)
                     return ValueRef;
   function ConstAShr(LHSConstant : ValueRef; RHSConstant : ValueRef)
                     return ValueRef;
   function ConstGEP(ConstantVal : ValueRef;
                     ConstantIndices : ValueRefArray; NumIndices : unsigned)
                    return ValueRef;
   function ConstTrunc(ConstantVal : ValueRef; ToType : TypeRef)
                      return ValueRef;
   function ConstSExt(ConstantVal : ValueRef; ToType : TypeRef)
                     return ValueRef;
   function ConstZExt(ConstantVal : ValueRef; ToType : TypeRef)
                     return ValueRef;
   function ConstFPTrunc(ConstantVal : ValueRef; ToType : TypeRef)
                        return ValueRef;
   function ConstFPExt(ConstantVal : ValueRef; ToType : TypeRef)
                      return ValueRef;
   function ConstUIToFP(ConstantVal : ValueRef; ToType : TypeRef)
                       return ValueRef;
   function ConstSIToFP(ConstantVal : ValueRef; ToType : TypeRef)
                       return ValueRef;
   function ConstFPToUI(ConstantVal : ValueRef; ToType : TypeRef)
                       return ValueRef;
   function ConstFPToSI(ConstantVal : ValueRef; ToType : TypeRef)
                       return ValueRef;
   function ConstPtrToInt(ConstantVal : ValueRef; ToType : TypeRef)
                         return ValueRef;
   function ConstIntToPtr(ConstantVal : ValueRef; ToType : TypeRef)
                         return ValueRef;
   function ConstBitCast(ConstantVal : ValueRef; ToType : TypeRef)
                        return ValueRef;

   function ConstTruncOrBitCast(ConstantVal : ValueRef; ToType : TypeRef)
                               return ValueRef;

   function ConstSelect(ConstantCondition : ValueRef;
                        ConstantIfTrue : ValueRef;
                        ConstantIfFalse : ValueRef) return ValueRef;
   function ConstExtractElement(VectorConstant : ValueRef;
                                IndexConstant : ValueRef) return ValueRef;
   function ConstInsertElement(VectorConstant : ValueRef;
                               ElementValueConstant : ValueRef;
                               IndexConstant : ValueRef) return ValueRef;
   function ConstShuffleVector(VectorAConstant : ValueRef;
                               VectorBConstant : ValueRef;
                               MaskConstant : ValueRef) return ValueRef;

   -- Operations on global variables, functions, and aliases (globals)
   function GetGlobalParent(Global : ValueRef) return ModuleRef;
   function IsDeclaration(Global : ValueRef) return int;
   function GetLinkage(Global : ValueRef) return Linkage;
   procedure SetLinkage(Global : ValueRef; Link : Linkage);
   function GetSection(Global : ValueRef) return Cstring;
   procedure SetSection(Global : ValueRef; Section : Cstring);
   function GetVisibility(Global : ValueRef) return Visibility;
   procedure SetVisibility(Global : ValueRef; Viz : Visibility);
   function GetAlignment(Global : ValueRef) return unsigned;
   procedure SetAlignment(Global : ValueRef; Bytes : unsigned);

   -- Operations on global variables
   function AddGlobal(M : ModuleRef; Ty : TypeRef; Name : Cstring)
                     return ValueRef;
   function GetNamedGlobal(M : ModuleRef; Name : Cstring) return ValueRef;
   function GetFirstGlobal(M : ModuleRef) return ValueRef;
   function GetLastGlobal(M : ModuleRef) return ValueRef;
   function GetNextGlobal(GlobalVar : ValueRef) return ValueRef;
   function GetPreviousGlobal(GlobalVar : ValueRef) return ValueRef;
   procedure DeleteGlobal(GlobalVar : ValueRef);
   function GetInitializer(GlobalVar : ValueRef) return ValueRef;
   procedure SetInitializer(GlobalVar : ValueRef; ConstantVal : ValueRef);
   function IsThreadLocal(GlobalVar : ValueRef) return int;
   procedure SetThreadLocal(GlobalVar : ValueRef; IsThreadLocal : int);
   function IsGlobalConstant(GlobalVar : ValueRef) return int;
   procedure SetGlobalConstant(GlobalVar : ValueRef; IsConstant : int);

   -- Operations on functions
   function AddFunction(M : ModuleRef; Name : Cstring; FunctionTy : TypeRef)
                       return ValueRef;
   function GetNamedFunction(M : ModuleRef; Name : Cstring) return ValueRef;
   function GetFirstFunction(M : ModuleRef) return ValueRef;
   function GetLastFunction(M : ModuleRef) return ValueRef;
   function GetNextFunction(Fn : ValueRef) return ValueRef;
   function GetPreviousFunction(Fn : ValueRef) return ValueRef;
   procedure DeleteFunction(Fn : ValueRef);
   function GetIntrinsicID(Fn : ValueRef) return unsigned;
   function GetFunctionCallConv(Fn : ValueRef) return CallConv;
   procedure SetFunctionCallConv(Fn : ValueRef; CC : CallConv);
   function GetGC(Fn : ValueRef) return Cstring;
   procedure SetGC(Fn : ValueRef; Name : Cstring);

   --  Add an attribute to a function.
   --  @see llvm::Function::addAttribute()
   procedure AddFunctionAttr (Fn : ValueRef; PA : Attribute);

   --  Add a target-dependent attribute to a fuction
   --  @see llvm::AttrBuilder::addAttribute()
   procedure AddTargetDependentFunctionAttr
     (Fn : ValueRef; A : Cstring; V : Cstring);

   --  Obtain an attribute from a function.
   --  @see llvm::Function::getAttributes()
   function GetFunctionAttr (Fn : ValueRef) return Attribute;

   --  Remove an attribute from a function.
   procedure RemoveFunctionAttr (Fn : ValueRef; PA : Attribute);

   -- Operations on parameters
   function CountParams(Fn : ValueRef) return unsigned;
   procedure GetParams(Fn : ValueRef; Params : ValueRefArray);
   function GetParam(Fn : ValueRef; Index : unsigned) return ValueRef;
   function GetParamParent(Inst : ValueRef) return ValueRef;
   function GetFirstParam(Fn : ValueRef) return ValueRef;
   function GetLastParam(Fn : ValueRef) return ValueRef;
   function GetNextParam(Arg : ValueRef) return ValueRef;
   function GetPreviousParam(Arg : ValueRef) return ValueRef;
   procedure AddAttribute(Arg : ValueRef; PA : Attribute);
   procedure RemoveAttribute(Arg : ValueRef; PA : Attribute);
   procedure SetParamAlignment(Arg : ValueRef; align : unsigned);

   -- Operations on basic blocks
   function BasicBlockAsValue(BB : BasicBlockRef) return ValueRef;
   function ValueIsBasicBlock(Val : ValueRef) return int;
   function ValueAsBasicBlock(Val : ValueRef) return BasicBlockRef;
   function GetBasicBlockParent(BB : BasicBlockRef) return ValueRef;
   function CountBasicBlocks(Fn : ValueRef) return unsigned;
   procedure GetBasicBlocks(Fn : ValueRef; BasicBlocks : BasicBlockRefArray);
   function GetFirstBasicBlock(Fn : ValueRef) return BasicBlockRef;
   function GetLastBasicBlock(Fn : ValueRef) return BasicBlockRef;
   function GetNextBasicBlock(BB : BasicBlockRef) return BasicBlockRef;
   function GetPreviousBasicBlock(BB : BasicBlockRef) return BasicBlockRef;
   function GetEntryBasicBlock(Fn : ValueRef) return BasicBlockRef;
   function AppendBasicBlock(Fn : ValueRef; Name : Cstring)
                            return BasicBlockRef;
   function InsertBasicBlock(InsertBeforeBB : BasicBlockRef;
                             Name : Cstring) return BasicBlockRef;
   procedure DeleteBasicBlock(BB : BasicBlockRef);

   -- Operations on instructions

   --  Determine whether an instruction has any metadata attached.
   function HasMetadata(Val: ValueRef) return Bool;

   --  Return metadata associated with an instruction value.
   function GetMetadata(Val : ValueRef; KindID : unsigned) return ValueRef;

   --  Set metadata associated with an instruction value.
   procedure SetMetadata(Val : ValueRef; KindID : unsigned; Node : ValueRef);

   function GetInstructionParent(Inst : ValueRef) return BasicBlockRef;
   function GetFirstInstruction(BB : BasicBlockRef) return ValueRef;
   function GetLastInstruction(BB : BasicBlockRef) return ValueRef;
   function GetNextInstruction(Inst : ValueRef) return ValueRef;
   function GetPreviousInstruction(Inst : ValueRef) return ValueRef;

   -- Operations on call sites
   procedure SetInstructionCallConv(Instr : ValueRef; CC : unsigned);
   function GetInstructionCallConv(Instr : ValueRef) return unsigned;
   procedure AddInstrAttribute(Instr : ValueRef;
                               index : unsigned; Attr : Attribute);
   procedure RemoveInstrAttribute(Instr : ValueRef;
                                 index : unsigned; Attr : Attribute);
   procedure SetInstrParamAlignment(Instr : ValueRef;
                                    index : unsigned; align : unsigned);

   -- Operations on call instructions (only)
   function IsTailCall(CallInst : ValueRef) return int;
   procedure SetTailCall(CallInst : ValueRef; IsTailCall : int);

   -- Operations on phi nodes
   procedure AddIncoming(PhiNode : ValueRef; IncomingValues : ValueRefArray;
                        IncomingBlocks : BasicBlockRefArray; Count : unsigned);
   function CountIncoming(PhiNode : ValueRef) return unsigned;
   function GetIncomingValue(PhiNode : ValueRef; Index : unsigned)
                            return ValueRef;
   function GetIncomingBlock(PhiNode : ValueRef; Index : unsigned)
                            return BasicBlockRef;

   -- Instruction builders ----------------------------------------------
   --  An instruction builder represents a point within a basic block,
   --  and is the exclusive means of building instructions using the C
   --  interface.

   function CreateBuilder return BuilderRef;
   procedure PositionBuilder(Builder : BuilderRef;
                             Block : BasicBlockRef; Instr : ValueRef);
   procedure PositionBuilderBefore(Builder : BuilderRef; Instr : ValueRef);
   procedure PositionBuilderAtEnd(Builder : BuilderRef; Block : BasicBlockRef);
   function GetInsertBlock(Builder : BuilderRef) return BasicBlockRef;
   procedure DisposeBuilder(Builder : BuilderRef);

   -- Terminators
   function BuildRetVoid(Builder : BuilderRef) return ValueRef;
   function BuildRet(Builder : BuilderRef; V : ValueRef) return ValueRef;
   function BuildBr(Builder : BuilderRef; Dest : BasicBlockRef)
                   return ValueRef;
   function BuildCondBr(Builder : BuilderRef;
                        If_Br : ValueRef;
                        Then_Br : BasicBlockRef; Else_Br : BasicBlockRef)
                       return ValueRef;
   function BuildSwitch(Builder : BuilderRef;
                        V : ValueRef;
                        Else_Br : BasicBlockRef; NumCases : unsigned)
                       return ValueRef;
   function BuildInvoke(Builder : BuilderRef;
                        Fn : ValueRef;
                        Args : ValueRefArray;
                        NumArgs : unsigned;
                        Then_Br : BasicBlockRef;
                        Catch : BasicBlockRef;
                        Name : Cstring) return ValueRef;
   function BuildUnwind(Builder : BuilderRef) return ValueRef;
   function BuildUnreachable(Builder : BuilderRef) return ValueRef;

   -- Add a case to the switch instruction
   procedure AddCase(Switch : ValueRef;
                     OnVal : ValueRef; Dest : BasicBlockRef);

   -- Arithmetic
   function BuildAdd(Builder : BuilderRef;
                     LHS : ValueRef; RHS : ValueRef; Name : Cstring)
                    return ValueRef;
   function BuildNSWAdd(Builder : BuilderRef;
                        LHS : ValueRef; RHS : ValueRef; Name : Cstring)
                       return ValueRef;
   function BuildNUWAdd(Builder : BuilderRef;
                        LHS : ValueRef; RHS : ValueRef; Name : Cstring)
                       return ValueRef;
   function BuildFAdd(Builder : BuilderRef;
                        LHS : ValueRef; RHS : ValueRef; Name : Cstring)
                       return ValueRef;

   function BuildSub(Builder : BuilderRef;
                     LHS : ValueRef; RHS : ValueRef; Name : Cstring)
                    return ValueRef;
   function BuildNSWSub(Builder : BuilderRef;
                        LHS : ValueRef; RHS : ValueRef; Name : Cstring)
                       return ValueRef;
   function BuildNUWSub(Builder : BuilderRef;
                        LHS : ValueRef; RHS : ValueRef; Name : Cstring)
                       return ValueRef;
   function BuildFSub(Builder : BuilderRef;
                      LHS : ValueRef; RHS : ValueRef; Name : Cstring)
                     return ValueRef;

   function BuildMul(Builder : BuilderRef;
                     LHS : ValueRef; RHS : ValueRef; Name : Cstring)
                    return ValueRef;
   function BuildFMul(Builder : BuilderRef;
                      LHS : ValueRef; RHS : ValueRef; Name : Cstring)
                     return ValueRef;

   function BuildUDiv(Builder : BuilderRef;
                      LHS : ValueRef; RHS : ValueRef; Name : Cstring)
                     return ValueRef;
   function BuildSDiv(Builder : BuilderRef;
                      LHS : ValueRef; RHS : ValueRef; Name : Cstring)
                     return ValueRef;
   function BuildFDiv(Builder : BuilderRef;
                      LHS : ValueRef; RHS : ValueRef; Name : Cstring)
                     return ValueRef;
   function BuildURem(Builder : BuilderRef;
                      LHS : ValueRef; RHS : ValueRef; Name : Cstring)
                     return ValueRef;
   function BuildSRem(Builder : BuilderRef;
                      LHS : ValueRef; RHS : ValueRef; Name : Cstring)
                     return ValueRef;
   function BuildFRem(Builder : BuilderRef;
                      LHS : ValueRef; RHS : ValueRef; Name : Cstring)
                     return ValueRef;
   function BuildShl(Builder : BuilderRef;
                     LHS : ValueRef; RHS : ValueRef; Name : Cstring)
                    return ValueRef;
   function BuildLShr(Builder : BuilderRef;
                      LHS : ValueRef; RHS : ValueRef; Name : Cstring)
                     return ValueRef;
   function BuildAShr(Builder : BuilderRef;
                      LHS : ValueRef; RHS : ValueRef; Name : Cstring)
                     return ValueRef;
   function BuildAnd(Builder : BuilderRef;
                     LHS : ValueRef; RHS : ValueRef; Name : Cstring)
                    return ValueRef;
   function BuildOr(Builder : BuilderRef;
                    LHS : ValueRef; RHS : ValueRef; Name : Cstring)
                   return ValueRef;
   function BuildXor(Builder : BuilderRef;
                     LHS : ValueRef; RHS : ValueRef; Name : Cstring)
                    return ValueRef;
   function BuildNeg(Builder : BuilderRef; V : ValueRef; Name : Cstring)
                    return ValueRef;
   function BuildFNeg(Builder : BuilderRef; V : ValueRef; Name : Cstring)
                    return ValueRef;
   function BuildNot(Builder : BuilderRef; V : ValueRef; Name : Cstring)
                    return ValueRef;

   -- Memory
   function BuildMalloc(Builder : BuilderRef; Ty : TypeRef; Name : Cstring)
                       return ValueRef;
   function BuildArrayMalloc(Builder : BuilderRef;
                             Ty : TypeRef; Val : ValueRef; Name : Cstring)
                            return ValueRef;
   function BuildAlloca(Builder : BuilderRef; Ty : TypeRef; Name : Cstring)
                       return ValueRef;
   function BuildArrayAlloca(Builder : BuilderRef;
                             Ty : TypeRef; Val : ValueRef; Name : Cstring)
                            return ValueRef;
   function BuildFree(Builder : BuilderRef; PointerVal : ValueRef)
                     return ValueRef;
   function BuildLoad(Builder : BuilderRef; PointerVal : ValueRef;
                           Name : Cstring) return ValueRef;
   function BuildStore(Builder : BuilderRef; Val : ValueRef; Ptr : ValueRef)
                      return ValueRef;
   function BuildGEP(Builder : BuilderRef;
                     Pointer : ValueRef;
                     Indices : ValueRefArray;
                     NumIndices : unsigned; Name : Cstring) return ValueRef;

   -- Casts
   function BuildTrunc(Builder : BuilderRef;
                       Val : ValueRef; DestTy : TypeRef; Name : Cstring)
                      return ValueRef;
   function BuildZExt(Builder : BuilderRef;
                      Val : ValueRef; DestTy : TypeRef; Name : Cstring)
                     return ValueRef;
   function BuildSExt(Builder : BuilderRef;
                      Val : ValueRef; DestTy : TypeRef; Name : Cstring)
                     return ValueRef;
   function BuildFPToUI(Builder : BuilderRef;
                        Val : ValueRef; DestTy : TypeRef; Name : Cstring)
                       return ValueRef;
   function BuildFPToSI(Builder : BuilderRef;
                        Val : ValueRef; DestTy : TypeRef; Name : Cstring)
                       return ValueRef;
   function BuildUIToFP(Builder : BuilderRef;
                        Val : ValueRef; DestTy : TypeRef; Name : Cstring)
                       return ValueRef;
   function BuildSIToFP(Builder : BuilderRef;
                        Val : ValueRef; DestTy : TypeRef; Name : Cstring)
                       return ValueRef;
   function BuildFPTrunc(Builder : BuilderRef;
                         Val : ValueRef; DestTy : TypeRef; Name : Cstring)
                        return ValueRef;
   function BuildFPExt(Builder : BuilderRef;
                       Val : ValueRef; DestTy : TypeRef; Name : Cstring)
                      return ValueRef;
   function BuildPtrToInt(Builder : BuilderRef;
                          Val : ValueRef; DestTy : TypeRef; Name : Cstring)
                         return ValueRef;
   function BuildIntToPtr(Builder : BuilderRef;
                          Val : ValueRef; DestTy : TypeRef; Name : Cstring)
                         return ValueRef;
   function BuildBitCast(Builder : BuilderRef;
                         Val : ValueRef; DestTy : TypeRef; Name : Cstring)
                        return ValueRef;

   -- Comparisons
   function BuildICmp(Builder : BuilderRef;
                      Op : IntPredicate;
                      LHS : ValueRef; RHS : ValueRef; Name : Cstring)
                     return ValueRef;
   function BuildFCmp(Builder : BuilderRef;
                      Op : RealPredicate;
                      LHS : ValueRef; RHS : ValueRef; Name : Cstring)
                     return ValueRef;

   -- Miscellaneous instructions
   function BuildPhi(Builder : BuilderRef; Ty : TypeRef; Name : Cstring)
                    return ValueRef;
   function BuildCall(Builder : BuilderRef;
                      Fn : ValueRef;
                      Args : ValueRefArray; NumArgs : unsigned; Name : Cstring)
                     return ValueRef;
   function BuildSelect(Builder : BuilderRef;
                        If_Sel : ValueRef;
                        Then_Sel : ValueRef;
                        Else_Sel : ValueRef;
                        Name : Cstring) return ValueRef;
   function BuildVAArg(Builder : BuilderRef;
                       List : ValueRef; Ty : TypeRef; Name : Cstring)
                      return ValueRef;
   function BuildExtractElement(Builder : BuilderRef;
                                VecVal : ValueRef;
                                Index : ValueRef;
                                Name : Cstring) return ValueRef;
   function BuildInsertElement(Builder : BuilderRef;
                               VecVal : ValueRef;
                               EltVal : ValueRef;
                               Index : ValueRef;
                               Name : Cstring) return ValueRef;
   function BuildShuffleVector(Builder : BuilderRef;
                               V1 : ValueRef;
                               V2 : ValueRef;
                               Mask : ValueRef;
                               Name : Cstring) return ValueRef;

   -- Memory buffers ----------------------------------------------------

   function CreateMemoryBufferWithContentsOfFile
     (Path : Cstring;
      OutMemBuf : access MemoryBufferRef;
      OutMessage : access Cstring) return int;
   function CreateMemoryBufferWithSTDIN
     (OutMemBuf : access MemoryBufferRef;
      OutMessage : access Cstring) return int;
   procedure DisposeMemoryBuffer(MemBuf : MemoryBufferRef);


   -- Pass Managers -----------------------------------------------------

   -- Constructs a new whole-module pass pipeline. This type of pipeline is
   -- suitable for link-time optimization and whole-module transformations.
   -- See llvm::PassManager::PassManager.
   function CreatePassManager return PassManagerRef;

   -- Constructs a new function-by-function pass pipeline over the module
   -- provider. It does not take ownership of the module provider. This type of
   -- pipeline is suitable for code generation and JIT compilation tasks.
   -- See llvm::FunctionPassManager::FunctionPassManager.
   function CreateFunctionPassManagerForModule(M : ModuleRef)
                                              return PassManagerRef;

   -- Initializes, executes on the provided module, and finalizes all of the
   -- passes scheduled in the pass manager. Returns 1 if any of the passes
   -- modified the module, 0 otherwise. See llvm::PassManager::run(Module&).
   function RunPassManager(PM : PassManagerRef; M : ModuleRef)
                          return int;

   -- Initializes all of the function passes scheduled in the function pass
   -- manager. Returns 1 if any of the passes modified the module, 0 otherwise.
   -- See llvm::FunctionPassManager::doInitialization.
   function InitializeFunctionPassManager(FPM : PassManagerRef)
                                         return int;

   --  Executes all of the function passes scheduled in the function
   --  pass manager on the provided function. Returns 1 if any of the
   --  passes modified the function, false otherwise.
   -- See llvm::FunctionPassManager::run(Function&).
   function RunFunctionPassManager (FPM : PassManagerRef; F : ValueRef)
                                   return int;

   -- Finalizes all of the function passes scheduled in in the function pass
   -- manager. Returns 1 if any of the passes modified the module, 0 otherwise.
   -- See llvm::FunctionPassManager::doFinalization.
   function FinalizeFunctionPassManager(FPM : PassManagerRef)
                                       return int;

   --  Frees the memory of a pass pipeline. For function pipelines,
   --  does not free the module provider.
   -- See llvm::PassManagerBase::~PassManagerBase.
   procedure DisposePassManager(PM : PassManagerRef);

private
   pragma Import (C, ContextCreate, "LLVMContextCreate");
   pragma Import (C, GetGlobalContext, "LLVMGetGlobalContext");
   pragma Import (C, ContextDispose, "LLVMContextDispose");

   pragma Import (C, DisposeMessage, "LLVMDisposeMessage");
   pragma Import (C, ModuleCreateWithName, "LLVMModuleCreateWithName");
   pragma Import (C, DisposeModule, "LLVMDisposeModule");
   pragma Import (C, GetDataLayout, "LLVMGetDataLayout");
   pragma Import (C, SetDataLayout, "LLVMSetDataLayout");
   pragma Import (C, GetTarget, "LLVMGetTarget");
   pragma Import (C, SetTarget, "LLVMSetTarget");
   pragma Import (C, DumpModule, "LLVMDumpModule");
   pragma Import (C, PrintModuleToFile, "LLVMPrintModuleToFile");
   pragma Import (C, GetTypeKind, "LLVMGetTypeKind");
   pragma Import (C, Int1Type, "LLVMInt1Type");
   pragma Import (C, Int8Type, "LLVMInt8Type");
   pragma Import (C, Int16Type, "LLVMInt16Type");
   pragma Import (C, Int32Type, "LLVMInt32Type");
   pragma Import (C, Int64Type, "LLVMInt64Type");
   pragma Import (C, IntType, "LLVMIntType");
   pragma Import (C, GetIntTypeWidth, "LLVMGetIntTypeWidth");
   pragma Import (C, MetadataType, "LLVMMetadataType_extra");

   pragma Import (C, FloatType, "LLVMFloatType");
   pragma Import (C, DoubleType, "LLVMDoubleType");
   pragma Import (C, X86FP80Type, "LLVMX86FP80Type");
   pragma Import (C, FP128Type, "LLVMFP128Type");
   pragma Import (C, PPCFP128Type, "LLVMPPCFP128Type");

   pragma Import (C, FunctionType, "LLVMFunctionType");
   pragma Import (C, IsFunctionVarArg, "LLVMIsFunctionVarArg");
   pragma Import (C, GetReturnType, "LLVMGetReturnType");
   pragma Import (C, CountParamTypes, "LLVMCountParamTypes");
   pragma Import (C, GetParamTypes, "LLVMGetParamTypes");

   pragma Import (C, StructType, "LLVMStructType");
   pragma Import (C, StructCreateNamed, "LLVMStructCreateNamed");
   pragma Import (C, StructSetBody, "LLVMStructSetBody");
   pragma Import (C, CountStructElementTypes, "LLVMCountStructElementTypes");
   pragma Import (C, GetStructElementTypes, "LLVMGetStructElementTypes");
   pragma Import (C, IsPackedStruct, "LLVMIsPackedStruct");

   pragma Import (C, ArrayType, "LLVMArrayType");
   pragma Import (C, PointerType, "LLVMPointerType");
   pragma Import (C, VectorType, "LLVMVectorType");
   pragma Import (C, GetElementType, "LLVMGetElementType");
   pragma Import (C, GetArrayLength, "LLVMGetArrayLength");
   pragma Import (C, GetPointerAddressSpace, "LLVMGetPointerAddressSpace");
   pragma Import (C, GetVectorSize, "LLVMGetVectorSize");

   pragma Import (C, VoidType, "LLVMVoidType");
   pragma Import (C, LabelType, "LLVMLabelType");
   pragma Import (C, DumpType, "LLVMDumpType");

   pragma Import (C, TypeOf, "LLVMTypeOf");
   pragma Import (C, GetValueName, "LLVMGetValueName");
   pragma Import (C, SetValueName, "LLVMSetValueName");
   pragma Import (C, DumpValue, "LLVMDumpValue");

   pragma Import (C, ConstNull, "LLVMConstNull");
   pragma Import (C, ConstAllOnes, "LLVMConstAllOnes");
   pragma Import (C, GetUndef, "LLVMGetUndef");
   pragma Import (C, IsConstant, "LLVMIsConstant");
   pragma Import (C, IsNull, "LLVMIsNull");
   pragma Import (C, IsUndef, "LLVMIsUndef");
   pragma Import (C, IsAInstruction, "LLVMIsAInstruction");

   pragma Import (C, ConstInt, "LLVMConstInt");
   pragma Import (C, ConstReal, "LLVMConstReal");
   pragma Import (C, ConstIntGetZExtValue, "LLVMConstIntGetZExtValue");
   pragma Import (C, ConstRealOfString, "LLVMConstRealOfString");
   pragma Import (C, ConstString, "LLVMConstString");
   pragma Import (C, ConstArray, "LLVMConstArray");
   pragma Import (C, ConstStruct, "LLVMConstStruct");
   pragma Import (C, ConstNamedStruct, "LLVMConstNamedStruct");
   pragma Import (C, ConstVector, "LLVMConstVector");

   pragma Import (C, SizeOf, "LLVMSizeOf");
   pragma Import (C, AlignOf, "LLVMAlignOf");
   pragma Import (C, ConstNeg, "LLVMConstNeg");
   pragma Import (C, ConstNot, "LLVMConstNot");
   pragma Import (C, ConstAdd, "LLVMConstAdd");
   pragma Import (C, ConstSub, "LLVMConstSub");
   pragma Import (C, ConstMul, "LLVMConstMul");
   pragma Import (C, ConstUDiv, "LLVMConstUDiv");
   pragma Import (C, ConstSDiv, "LLVMConstSDiv");
   pragma Import (C, ConstFDiv, "LLVMConstFDiv");
   pragma Import (C, ConstURem, "LLVMConstURem");
   pragma Import (C, ConstSRem, "LLVMConstSRem");
   pragma Import (C, ConstFRem, "LLVMConstFRem");
   pragma Import (C, ConstAnd, "LLVMConstAnd");
   pragma Import (C, ConstOr, "LLVMConstOr");
   pragma Import (C, ConstXor, "LLVMConstXor");
   pragma Import (C, ConstICmp, "LLVMConstICmp");
   pragma Import (C, ConstFCmp, "LLVMConstFCmp");
   pragma Import (C, ConstShl, "LLVMConstShl");
   pragma Import (C, ConstLShr, "LLVMConstLShr");
   pragma Import (C, ConstAShr, "LLVMConstAShr");
   pragma Import (C, ConstGEP, "LLVMConstGEP");
   pragma Import (C, ConstTrunc, "LLVMConstTrunc");
   pragma Import (C, ConstSExt, "LLVMConstSExt");
   pragma Import (C, ConstZExt, "LLVMConstZExt");
   pragma Import (C, ConstFPTrunc, "LLVMConstFPTrunc");
   pragma Import (C, ConstFPExt, "LLVMConstFPExt");
   pragma Import (C, ConstUIToFP, "LLVMConstUIToFP");
   pragma Import (C, ConstSIToFP, "LLVMConstSIToFP");
   pragma Import (C, ConstFPToUI, "LLVMConstFPToUI");
   pragma Import (C, ConstFPToSI, "LLVMConstFPToSI");
   pragma Import (C, ConstPtrToInt, "LLVMConstPtrToInt");
   pragma Import (C, ConstIntToPtr, "LLVMConstIntToPtr");
   pragma Import (C, ConstBitCast, "LLVMConstBitCast");
   pragma Import (C, ConstTruncOrBitCast, "LLVMConstTruncOrBitCast");
   pragma Import (C, ConstSelect, "LLVMConstSelect");
   pragma Import (C, ConstExtractElement, "LLVMConstExtractElement");
   pragma Import (C, ConstInsertElement, "LLVMConstInsertElement");
   pragma Import (C, ConstShuffleVector, "LLVMConstShuffleVector");

   pragma Import (C, GetGlobalParent, "LLVMGetGlobalParent");
   pragma Import (C, IsDeclaration, "LLVMIsDeclaration");
   pragma Import (C, GetLinkage, "LLVMGetLinkage");
   pragma Import (C, SetLinkage, "LLVMSetLinkage");
   pragma Import (C, GetSection, "LLVMGetSection");
   pragma Import (C, SetSection, "LLVMSetSection");
   pragma Import (C, GetVisibility, "LLVMGetVisibility");
   pragma Import (C, SetVisibility, "LLVMSetVisibility");
   pragma Import (C, GetAlignment, "LLVMGetAlignment");
   pragma Import (C, SetAlignment, "LLVMSetAlignment");

   pragma Import (C, AddGlobal, "LLVMAddGlobal");
   pragma Import (C, GetNamedGlobal, "LLVMGetNamedGlobal");
   pragma Import (C, GetFirstGlobal, "LLVMGetFirstGlobal");
   pragma Import (C, GetLastGlobal, "LLVMGetLastGlobal");
   pragma Import (C, GetNextGlobal, "LLVMGetNextGlobal");
   pragma Import (C, GetPreviousGlobal, "LLVMGetPreviousGlobal");
   pragma Import (C, DeleteGlobal, "LLVMDeleteGlobal");
   pragma Import (C, GetInitializer, "LLVMGetInitializer");
   pragma Import (C, SetInitializer, "LLVMSetInitializer");
   pragma Import (C, IsThreadLocal, "LLVMIsThreadLocal");
   pragma Import (C, SetThreadLocal, "LLVMSetThreadLocal");
   pragma Import (C, IsGlobalConstant, "LLVMIsGlobalConstant");
   pragma Import (C, SetGlobalConstant, "LLVMSetGlobalConstant");

   pragma Import (C, AddFunction, "LLVMAddFunction");
   pragma Import (C, GetNamedFunction, "LLVMGetNamedFunction");
   pragma Import (C, GetFirstFunction, "LLVMGetFirstFunction");
   pragma Import (C, GetLastFunction, "LLVMGetLastFunction");
   pragma Import (C, GetNextFunction, "LLVMGetNextFunction");
   pragma Import (C, GetPreviousFunction, "LLVMGetPreviousFunction");
   pragma Import (C, DeleteFunction, "LLVMDeleteFunction");
   pragma Import (C, GetIntrinsicID, "LLVMGetIntrinsicID");
   pragma Import (C, GetFunctionCallConv, "LLVMGetFunctionCallConv");
   pragma Import (C, SetFunctionCallConv, "LLVMSetFunctionCallConv");
   pragma Import (C, GetGC, "LLVMGetGC");
   pragma Import (C, SetGC, "LLVMSetGC");

   pragma Import (C, AddFunctionAttr, "LLVMAddFunctionAttr");
   pragma import (C, AddTargetDependentFunctionAttr,
                  "LLVMAddTargetDependentFunctionAttr");
   pragma Import (C, GetFunctionAttr, "LLVMGetFunctionAttr");
   pragma Import (C, RemoveFunctionAttr, "LLVMRemoveFunctionAttr");

   pragma Import (C, CountParams, "LLVMCountParams");
   pragma Import (C, GetParams, "LLVMGetParams");
   pragma Import (C, GetParam, "LLVMGetParam");
   pragma Import (C, GetParamParent, "LLVMGetParamParent");
   pragma Import (C, GetFirstParam, "LLVMGetFirstParam");
   pragma Import (C, GetLastParam, "LLVMGetLastParam");
   pragma Import (C, GetNextParam, "LLVMGetNextParam");
   pragma Import (C, GetPreviousParam, "LLVMGetPreviousParam");
   pragma Import (C, AddAttribute, "LLVMAddAttribute");
   pragma Import (C, RemoveAttribute, "LLVMRemoveAttribute");
   pragma Import (C, SetParamAlignment, "LLVMSetParamAlignment");

   pragma Import (C, BasicBlockAsValue, "LLVMBasicBlockAsValue");
   pragma Import (C, ValueIsBasicBlock, "LLVMValueIsBasicBlock");
   pragma Import (C, ValueAsBasicBlock, "LLVMValueAsBasicBlock");
   pragma Import (C, GetBasicBlockParent, "LLVMGetBasicBlockParent");
   pragma Import (C, CountBasicBlocks, "LLVMCountBasicBlocks");
   pragma Import (C, GetBasicBlocks, "LLVMGetBasicBlocks");
   pragma Import (C, GetFirstBasicBlock, "LLVMGetFirstBasicBlock");
   pragma Import (C, GetLastBasicBlock, "LLVMGetLastBasicBlock");
   pragma Import (C, GetNextBasicBlock, "LLVMGetNextBasicBlock");
   pragma Import (C, GetPreviousBasicBlock, "LLVMGetPreviousBasicBlock");
   pragma Import (C, GetEntryBasicBlock, "LLVMGetEntryBasicBlock");
   pragma Import (C, AppendBasicBlock, "LLVMAppendBasicBlock");
   pragma Import (C, InsertBasicBlock, "LLVMInsertBasicBlock");
   pragma Import (C, DeleteBasicBlock, "LLVMDeleteBasicBlock");

   pragma Import (C, HasMetadata, "LLVMHasMetadata");
   pragma Import (C, GetMetadata, "LLVMGetMetadata");
   pragma Import (C, SetMetadata, "LLVMSetMetadata");

   pragma Import (C, GetInstructionParent, "LLVMGetInstructionParent");
   pragma Import (C, GetFirstInstruction, "LLVMGetFirstInstruction");
   pragma Import (C, GetLastInstruction, "LLVMGetLastInstruction");
   pragma Import (C, GetNextInstruction, "LLVMGetNextInstruction");
   pragma Import (C, GetPreviousInstruction, "LLVMGetPreviousInstruction");

   pragma Import (C, SetInstructionCallConv, "LLVMSetInstructionCallConv");
   pragma Import (C, GetInstructionCallConv, "LLVMGetInstructionCallConv");
   pragma Import (C, AddInstrAttribute, "LLVMAddInstrAttribute");
   pragma Import (C, RemoveInstrAttribute, "LLVMRemoveInstrAttribute");
   pragma Import (C, SetInstrParamAlignment, "LLVMSetInstrParamAlignment");

   pragma Import (C, IsTailCall, "LLVMIsTailCall");
   pragma Import (C, SetTailCall, "LLVMSetTailCall");

   pragma Import (C, AddIncoming, "LLVMAddIncoming");
   pragma Import (C, CountIncoming, "LLVMCountIncoming");
   pragma Import (C, GetIncomingValue, "LLVMGetIncomingValue");
   pragma Import (C, GetIncomingBlock, "LLVMGetIncomingBlock");

   pragma Import (C, CreateBuilder, "LLVMCreateBuilder");
   pragma Import (C, PositionBuilder, "LLVMPositionBuilder");
   pragma Import (C, PositionBuilderBefore, "LLVMPositionBuilderBefore");
   pragma Import (C, PositionBuilderAtEnd, "LLVMPositionBuilderAtEnd");
   pragma Import (C, GetInsertBlock, "LLVMGetInsertBlock");