// 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++ -dynamiclib \
// 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 -dynamiclib \
// 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 T> class Simple {
public:
virtual void foo() {}
};
extern template class Simple<int>;
} // 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 <class T> int foo1(T a) { return 1; }
template <> int foo1<int>(int a);
extern template int foo1<short>(short a);
template <class T> int foo2(T a);
// Partial specialization.
template <class A, class B> class Partial {
static int run(A a, B b) { return a + b; }
};
template <class A> class Partial<A, int> {
static int run(A a, int b) { return a - b; }
};
template <class T> class Foo {
public:
Foo();
~Foo();
};
template <class T> class Bar {
public:
Bar();
~Bar() {}
inline int bazinga() { return 7; }
};
extern template class Bar<int>;
class Bazz {
public:
Bazz() {}
template <class T> int buzz(T a);
float implicit() const { return foo1(0.0f); }
};
template <class T> int Bazz::buzz(T a) { return sizeof(T); }
template <class T> struct S { static int x; };
template <class T> int S<T>::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
}