// basic_test.cc -- a test case for gold // Copyright (C) 2006-2024 Free Software Foundation, Inc. // Written by Ian Lance Taylor . // This file is part of gold. // This program 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 3 of the License, or // (at your option) any later version. // This program 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 this program; if not, write to the Free Software // Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, // MA 02110-1301, USA. // The goal of this program is to produce as many different types of // relocations as we can in a stand-alone program that does not use // TLS. This program is compiled without optimization. // 1 Code reference to global data. // 2 Code reference to static data. // 3 Code reference to BSS data. // 4 Code reference to offset within global data. // 5 Code reference to offset within static data. // 6 Code reference to offset within BSS data. // 7 Switch statement with a table of destinations. // 8 Taking the address of a label (a gcc extension). // 9 Taking the address of a nested function (a gcc extension). // 10 Data reference to global data. // 11 Data reference to static data. // 12 Data reference to BSS data. // 13 Data reference to offset within global data. // 14 Data reference to offset within static data. // 15 Data reference to offset within BSS data. // 16 Virtual table. // 17 Inline function. // 18 Call through pointer to method. // 19 Initialize variable to pointer to method. // 20 Global constructor and destructor. // 1 Code reference to global data. int t1 = 11; // 2 Code reference to static data. static int t2 = 22; // 3 Code reference to BSS data (initialized after program starts, to // 33). int t3; // 4 Code reference to offset within global data. char t4[] = "Hello, world"; // 5 Code reference to offset within static data. static char t5[] = "Hello, world"; // 6 Code reference to offset within BSS data (initialized after // program starts, to contents of t4). char t6[13]; // Test cases 1 through 6. bool t1_6() { return (t1 == 11 && t2 == 22 && t3 == 33 && t4[5] == ',' && t5[7] == 'w' && t6[9] == 'r'); } // 7 Switch statement with a table of destinations. int t7(int i) { switch (i) { case 0: return 12; case 1: return 34; case 2: return 56; case 3: return 78; case 4: return 90; case 5: return 13; case 6: return 0; case 7: return 57; case 8: return 79; case 9: return 81; default: return 144; } } // 8 Taking the address of a label (a gcc extension). int t8(int i) { for (int j = 0; j < 10; ++j) { void* p; if (i + j > 6) p = &&lab1; else p = &&lab2; if (j == 7) goto *p; } return 15; lab1: return 0; lab2: return 12; } // 9 Taking the address of a nested function (a gcc extension). // Disabled because this is only supported in C, not C++. int t9a(int (*pfn)(int)) { return (*pfn)(10) - 10; } int t9(int i) { #if 0 int t9c(int j) { return i + j; } return t9a(&t9c); #else return i; #endif } // 10 Data reference to global data. int* t10 = &t1; // 11 Data reference to static data. int* t11 = &t2; // 12 Data reference to BSS data. int* t12 = &t3; // 13 Data reference to offset within global data. char* t13 = &t4[6]; // 14 Data reference to offset within static data. char* t14 = &t5[8]; // 15 Data reference to offset within BSS data. char* t15 = &t6[10]; // Test cases 10 through 15. bool t10_15() { return (*t10 == 11 && *t11 == 22 && *t12 == 33 && *t13 == ' ' && *t14 == 'o' && *t15 == 'l'); } // 16 Virtual table. class t16a { public: virtual ~t16a() { } virtual int t() { return 83; } }; class t16b : public t16a { public: virtual int t() { return 92; } }; t16b t16v; bool t16() { return t16v.t() == 92; } // 17 Inline function. inline int t17a() { return 74; } bool t17() { return t17a() == 74; } // 18 Call through pointer to method. class t18a { public: int ta() { return 65; } int tb() { return 90; } }; t18a t18v; int t18f(int (t18a::* p)()) { return (t18v.*p)(); } bool t18() { return t18f(&t18a::ta) == 65; } // 19 Initialize variable to pointer to method. int (t18a::* t19v)() = &t18a::tb; bool t19() { return (t18v.*t19v)() == 90; } // 20 Global constructor and destructor. class t20a { public: t20a() : i(96) { } ~t20a() { } int get() const { return this->i; } private: int i; }; t20a t20v; bool t20() { return t20v.get() == 96; } // Main function. Initialize variables and call test functions. int main() { t3 = 33; for (int i = 0; i < 13; ++i) t6[i] = t4[i]; if (t1_6() && t7(6) == 0 && t8(0) == 0 && t9(5) == 5 && t10_15() && t16() && t17() && t18() && t19() && t20()) return 0; else return 1; }