// RUN: rm -rf %t // RUN: split-file %s %t // RUN: sed -e "s|DSTROOT|%/t|g" %t/inputs.json.in > %t/inputs.json // Invoke C++ with no-rtti. // RUN: clang-installapi -target arm64-apple-macos13.1 \ // RUN: -I%t/usr/include -I%t/usr/local/include -x c++ \ // RUN: -install_name @rpath/lib/libcpp.dylib -fno-rtti \ // RUN: %t/inputs.json -o %t/no-rtti.tbd 2>&1 | FileCheck %s --allow-empty // RUN: llvm-readtapi -compare %t/no-rtti.tbd \ // RUN: %t/expected-no-rtti.tbd 2>&1 | FileCheck %s --allow-empty // Invoke C++ with rtti. // RUN: clang-installapi -target arm64-apple-macos13.1 \ // RUN: -I%t/usr/include -I%t/usr/local/include -x c++ \ // RUN: -install_name @rpath/lib/libcpp.dylib -frtti \ // RUN: %t/inputs.json -o %t/rtti.tbd 2>&1 | FileCheck %s --allow-empty // RUN: llvm-readtapi -compare %t/rtti.tbd \ // RUN: %t/expected-rtti.tbd 2>&1 | FileCheck %s --allow-empty // CHECK-NOT: error: // CHECK-NOT: warning: //--- usr/include/basic.h #ifndef CPP_H #define CPP_H inline int foo(int x) { return x + 1; } extern int bar(int x) { return x + 1; } inline int baz(int x) { static const int a[] = {1, 2, 3}; return a[x]; } extern "C" { int cFunc(const char*); } class Bar { public: static const int x = 0; static int y; inline int func1(int x) { return x + 2; } inline int func2(int x); int func3(int x); }; class __attribute__((visibility("hidden"))) BarI { static const int x = 0; static int y; inline int func1(int x) { return x + 2; } inline int func2(int x); int func3(int x); }; int Bar::func2(int x) { return x + 3; } inline int Bar::func3(int x) { return x + 4; } int BarI::func2(int x) { return x + 3; } inline int BarI::func3(int x) { return x + 4; } #endif //--- usr/local/include/vtable.h // Simple test class with no virtual functions. There should be no vtable or // RTTI. namespace test1 { class Simple { public: void run(); }; } // end namespace test1 // Simple test class with virtual function. There should be an external vtable // and RTTI. namespace test2 { class Simple { public: virtual void run(); }; } // end namespace test2 // Abstract class with no sub classes. There should be no vtable or RTTI. namespace test3 { class Abstract { public: virtual ~Abstract() {} virtual void run() = 0; }; } // end namespace test3 // Abstract base class with a sub class. There should be weak-def RTTI for the // abstract base class. // The sub-class should have vtable and RTTI. namespace test4 { class Base { public: virtual ~Base() {} virtual void run() = 0; }; class Sub : public Base { public: void run() override; }; } // end namespace test4 // Abstract base class with a sub class. Same as above, but with a user defined // inlined destructor. namespace test5 { class Base { public: virtual ~Base() {} virtual void run() = 0; }; class Sub : public Base { public: virtual ~Sub() {} void run() override; }; } // end namespace test5 // Abstract base class with a sub class. Same as above, but with a different // inlined key method. namespace test6 { class Base { public: virtual ~Base() {} virtual void run() = 0; }; class Sub : public Base { public: virtual void foo() {} void run() override; }; } // end namespace test6 // Abstract base class with a sub class. Overloaded method is implemented // inline. No vtable or RTTI. namespace test7 { class Base { public: virtual ~Base() {} virtual bool run() = 0; }; class Sub : public Base { public: bool run() override { return true; } }; } // end namespace test7 // Abstract base class with a sub class. Overloaded method has no inline // attribute and is recognized as key method, // but is later implemented inline. Weak-def RTTI only. namespace test8 { class Base { public: virtual ~Base() {} virtual void run() = 0; }; class Sub : public Base { public: void run() override; }; inline void Sub::run() {} } // end namespace test8 namespace test9 { class Base { public: virtual ~Base() {} virtual void run1() = 0; virtual void run2() = 0; }; class Sub : public Base { public: void run1() override {} void run2() override; }; inline void Sub::run2() {} } // end namespace test9 namespace test10 { class Base { public: virtual ~Base() {} virtual void run1() = 0; virtual void run2() = 0; }; class Sub : public Base { public: void run1() override {} inline void run2() override; }; void Sub::run2() {} } // end namespace test10 namespace test11 { class Base { public: virtual ~Base() {} virtual void run1() = 0; virtual void run2() = 0; virtual void run3() = 0; }; class Sub : public Base { public: void run1() override {} void run2() override; void run3() override; }; inline void Sub::run2() {} } // end namespace test11 namespace test12 { template class Simple { public: virtual void foo() {} }; extern template class Simple; } // end namespace test12 namespace test13 { class Base { public: virtual ~Base() {} virtual void run1() = 0; virtual void run2() {}; virtual void run3(); // key function. }; class Sub : public Base { public: void run1() override {} void run2() override {} }; } // end namespace test13 namespace test14 { class __attribute__((visibility("hidden"))) Base { public: Base() {} virtual ~Base(); // keyfunction. virtual void run1() const = 0; }; class Sub : public Base { public: Sub(); virtual ~Sub(); virtual void run1() const; void run2() const {} }; } // end namespace test14 namespace test15 { class Base { public: virtual ~Base() {} virtual void run() {}; }; class Base1 { public: virtual ~Base1() {} virtual void run1() {}; }; class Sub : public Base, public Base1 { public: Sub() {} ~Sub(); void run() override; void run1() override; }; class Sub1 : public Base, public Base1 { public: Sub1() {} ~Sub1() = default; void run() override; void run1() override; }; } // end namespace test15 //--- usr/local/include/templates.h #ifndef TEMPLATES_H #define TEMPLATES_H namespace templates { // Full specialization. template int foo1(T a) { return 1; } template <> int foo1(int a); extern template int foo1(short a); template int foo2(T a); // Partial specialization. template class Partial { static int run(A a, B b) { return a + b; } }; template class Partial { static int run(A a, int b) { return a - b; } }; template class Foo { public: Foo(); ~Foo(); }; template class Bar { public: Bar(); ~Bar() {} inline int bazinga() { return 7; } }; extern template class Bar; class Bazz { public: Bazz() {} template int buzz(T a); float implicit() const { return foo1(0.0f); } }; template int Bazz::buzz(T a) { return sizeof(T); } template struct S { static int x; }; template int S::x = 0; } // end namespace templates. #endif //--- inputs.json.in { "headers": [ { "path" : "DSTROOT/usr/include/basic.h", "type" : "public" }, { "path" : "DSTROOT/usr/local/include/vtable.h", "type" : "private" }, { "path" : "DSTROOT/usr/local/include/templates.h", "type" : "private" } ], "version": "3" } //--- expected-no-rtti.tbd { "main_library": { "compatibility_versions": [ { "version": "0" } ], "current_versions": [ { "version": "0" } ], "exported_symbols": [ { "data": { "global": [ "__ZTVN6test143SubE", "__ZTVN6test113SubE", "__ZTVN5test26SimpleE", "__ZTVN5test53SubE", "__ZTVN6test154Sub1E", "__ZTVN6test153SubE", "__ZN3Bar1yE", "__ZTVN5test43SubE", "__ZTVN5test63SubE", "__ZTVN6test134BaseE" ], "weak": [ "__ZTVN6test126SimpleIiEE" ] }, "text": { "global": [ "__ZN6test153Sub3runEv", "__ZN6test154Sub13runEv", "__Z3bari", "__ZThn8_N6test153SubD1Ev", "__ZNK6test143Sub4run1Ev", "__ZN6test154Sub14run1Ev", "__ZThn8_N6test153Sub4run1Ev", "__ZN6test143SubD1Ev", "__ZN6test134Base4run3Ev", "__ZN5test16Simple3runEv", "__ZN5test43Sub3runEv", "__ZN6test113Sub4run3Ev", "__ZN6test153SubD2Ev", "__ZN5test53Sub3runEv", "__ZN6test153SubD1Ev", "__ZN6test143SubC1Ev", "__ZN9templates4foo1IiEEiT_", "__ZN6test143SubC2Ev", "__ZN5test63Sub3runEv", "__ZN5test26Simple3runEv", "__ZN6test153SubD0Ev", "__ZN6test143SubD2Ev", "__ZN6test153Sub4run1Ev", "__ZN6test143SubD0Ev", "__ZThn8_N6test153SubD0Ev", "__ZThn8_N6test154Sub14run1Ev", "_cFunc" ], "weak": [ "__ZN9templates3BarIiED2Ev", "__ZN9templates3BarIiEC2Ev", "__ZN9templates3BarIiEC1Ev", "__ZN9templates3BarIiED1Ev", "__ZN6test126SimpleIiE3fooEv", "__ZN9templates3BarIiE7bazingaEv", "__ZN9templates4foo1IsEEiT_" ] } } ], "flags": [ { "attributes": [ "not_app_extension_safe" ] } ], "install_names": [ { "name": "@rpath/lib/libcpp.dylib" } ], "target_info": [ { "min_deployment": "13.1", "target": "arm64-macos" } ] }, "tapi_tbd_version": 5 } //--- expected-rtti.tbd { "main_library": { "compatibility_versions": [ { "version": "0" } ], "current_versions": [ { "version": "0" } ], "exported_symbols": [ { "data": { "global": [ "__ZTVN6test143SubE", "__ZTIN5test63SubE", "__ZTSN5test26SimpleE", "__ZTIN6test153SubE", "__ZTVN6test113SubE", "__ZTIN5test43SubE", "__ZTIN6test134BaseE", "__ZTVN5test26SimpleE", "__ZTIN5test26SimpleE", "__ZTSN6test134BaseE", "__ZTVN6test154Sub1E", "__ZTVN5test43SubE", "__ZTVN5test63SubE", "__ZTSN5test43SubE", "__ZTSN6test113SubE", "__ZTIN6test154Sub1E", "__ZTSN6test153SubE", "__ZTSN5test63SubE", "__ZTSN6test154Sub1E", "__ZTIN6test113SubE", "__ZTSN6test143SubE", "__ZTVN5test53SubE", "__ZTIN6test143SubE", "__ZTVN6test153SubE", "__ZTIN5test53SubE", "__ZN3Bar1yE", "__ZTVN6test134BaseE", "__ZTSN5test53SubE" ], "weak": [ "__ZTVN6test126SimpleIiEE" ] }, "text": { "global": [ "__ZN6test154Sub13runEv", "__ZN6test153Sub3runEv", "__ZNK6test143Sub4run1Ev", "__ZN6test134Base4run3Ev", "__ZN5test16Simple3runEv", "__ZN6test153SubD2Ev", "__ZN6test143SubC2Ev", "__ZN5test63Sub3runEv", "__ZN6test153SubD0Ev", "__ZN6test143SubD2Ev", "__ZThn8_N6test154Sub14run1Ev", "__ZThn8_N6test153SubD0Ev", "__Z3bari", "__ZThn8_N6test153SubD1Ev", "__ZN6test154Sub14run1Ev", "__ZThn8_N6test153Sub4run1Ev", "__ZN6test143SubD1Ev", "__ZN5test43Sub3runEv", "__ZN6test113Sub4run3Ev", "__ZN5test53Sub3runEv", "__ZN6test143SubC1Ev", "__ZN6test153SubD1Ev", "__ZN9templates4foo1IiEEiT_", "__ZN5test26Simple3runEv", "__ZN6test153Sub4run1Ev", "__ZN6test143SubD0Ev", "_cFunc" ], "weak": [ "__ZN9templates3BarIiEC2Ev", "__ZN9templates3BarIiEC1Ev", "__ZN9templates3BarIiED1Ev", "__ZN6test126SimpleIiE3fooEv", "__ZN9templates4foo1IsEEiT_", "__ZN9templates3BarIiED2Ev", "__ZN9templates3BarIiE7bazingaEv" ] } } ], "flags": [ { "attributes": [ "not_app_extension_safe" ] } ], "install_names": [ { "name": "@rpath/lib/libcpp.dylib" } ], "target_info": [ { "min_deployment": "13.1", "target": "arm64-macos" } ] }, "tapi_tbd_version": 5 }