llvm/clang/test/SemaCXX/vtable_pointer_authentication_attribute.cpp

// RUN: %clang_cc1 -fsyntax-only -triple arm64-apple-ios   -verify -fptrauth-calls -std=c++2a %s
// RUN: %clang_cc1 -fsyntax-only -triple aarch64-linux-gnu -verify -fptrauth-calls -std=c++2a %s

namespace basic {

#define authenticated(a, b, c...) [[clang::ptrauth_vtable_pointer(a, b, c)]]

// Basic sanity tests
#define TEST_AUTH(name, auth...)                        \
  struct [[clang::ptrauth_vtable_pointer(auth)]] name { \
    virtual ~name() {}                                  \
  }

TEST_AUTH(NoParams);
// expected-error@-1{{'ptrauth_vtable_pointer' attribute takes at least 3 arguments}}
TEST_AUTH(NoAuth, no_authentication, default_address_discrimination, default_extra_discrimination);
TEST_AUTH(InvalidKey, wat, default_address_discrimination, default_extra_discrimination);
// expected-error@-1{{invalid authentication key 'wat'}}
TEST_AUTH(InvalidAddressDiscrimination, no_authentication, wat, default_extra_discrimination);
// expected-error@-1{{invalid address discrimination mode 'wat'}}
TEST_AUTH(InvalidExtraDiscrimination, no_authentication, default_address_discrimination, wat);
// expected-error@-1{{invalid extra discrimination selection 'wat'}}
TEST_AUTH(InvalidNoCustomDiscrimination, no_authentication, default_address_discrimination, custom_discrimination);
// expected-error@-1{{missing custom discrimination}}
TEST_AUTH(InvalidCustomDiscrimination, no_authentication, default_address_discrimination, custom_discrimination, wat);
// expected-error@-1{{invalid custom discrimination}}
TEST_AUTH(Default, default_key, default_address_discrimination, default_extra_discrimination);
TEST_AUTH(InvalidDefaultExtra, default_key, default_address_discrimination, default_extra_discrimination, 1);
// expected-error@-1{{'ptrauth_vtable_pointer' attribute takes no more than 3 arguments}}
TEST_AUTH(ProcessDependentKey, process_dependent, default_address_discrimination, default_extra_discrimination);
TEST_AUTH(ProcessIndependentKey, process_independent, default_address_discrimination, default_extra_discrimination);
TEST_AUTH(DefaultAddressDiscrimination, process_independent, default_address_discrimination, default_extra_discrimination);
TEST_AUTH(NoAddressDiscrimination, process_independent, no_address_discrimination, default_extra_discrimination);
TEST_AUTH(AddressDiscrimination, process_independent, address_discrimination, default_extra_discrimination);
TEST_AUTH(DefaultExtraDiscrimination, process_independent, default_address_discrimination, default_extra_discrimination);
TEST_AUTH(NoExtraDiscrimination, process_independent, default_address_discrimination, no_extra_discrimination);
TEST_AUTH(TypeExtraDiscrimination, process_independent, default_address_discrimination, type_discrimination);
TEST_AUTH(InvalidCustomExtraDiscrimination, process_independent, default_address_discrimination, custom_discrimination);
// expected-error@-1{{missing custom discrimination}}
TEST_AUTH(ValidCustomExtraDiscrimination, process_independent, default_address_discrimination, custom_discrimination, 1);

// Basic valid authentication configuration
#define generic_authenticated \
  authenticated(process_independent, address_discrimination, type_discrimination)

struct generic_authenticated ForwardDecl;

struct generic_authenticated generic_authenticated InvalidDuplicateAttribute {
  // expected-error@-1{{multiple vtable pointer authentication policies on 'InvalidDuplicateAttribute'}}
  virtual ~InvalidDuplicateAttribute(){};
};
struct generic_authenticated ValidPolymorphic {
  virtual ~ValidPolymorphic(){};
};
struct generic_authenticated InvalidMonomorphic { // expected-error{{cannot set vtable pointer authentication on monomorphic type 'InvalidMonomorphic'}}
};
struct ValidMonomorphic {
};

struct ValidSubclass : ValidPolymorphic {};
struct generic_authenticated InvalidSubclass : ValidPolymorphic {}; // expected-error{{cannot set vtable pointer authentication on 'InvalidSubclass' which is a subclass of polymorphic type 'ValidPolymorphic'}}

// Awful template time
template <typename T>
struct generic_authenticated ExplicitlyAuthedMonomorphicTemplateClass : T {};
// expected-error@-1{{cannot set vtable pointer authentication on 'ExplicitlyAuthedMonomorphicTemplateClass<basic::ValidPolymorphic>' which is a subclass of polymorphic type 'ValidPolymorphic'}}
// expected-error@-2{{cannot set vtable pointer authentication on monomorphic type 'ExplicitlyAuthedMonomorphicTemplateClass<basic::ValidMonomorphic>'}}
template <typename T>
struct generic_authenticated ExplicitlyAuthedPolymorphicTemplateClass : T { // expected-error{{cannot set vtable pointer authentication on 'ExplicitlyAuthedPolymorphicTemplateClass<basic::ValidPolymorphic>' which is a subclass of polymorphic type 'ValidPolymorphic'}}
  virtual ~ExplicitlyAuthedPolymorphicTemplateClass(){};
};
template <typename T>
struct UnauthedMonomorphicTemplateClass : T {};
template <typename T>
struct UnauthedPolymorphicTemplateClass : T {
  virtual ~UnauthedPolymorphicTemplateClass(){};
};

ExplicitlyAuthedMonomorphicTemplateClass<ValidPolymorphic> test1;
// expected-note@-1{{in instantiation of template class 'basic::ExplicitlyAuthedMonomorphicTemplateClass<basic::ValidPolymorphic>' requested here}}
ExplicitlyAuthedMonomorphicTemplateClass<ValidMonomorphic> test2;
// expected-note@-1{{in instantiation of template class 'basic::ExplicitlyAuthedMonomorphicTemplateClass<basic::ValidMonomorphic>' requested here}}
ExplicitlyAuthedPolymorphicTemplateClass<ValidPolymorphic> test3;
// expected-note@-1{{in instantiation of template class 'basic::ExplicitlyAuthedPolymorphicTemplateClass<basic::ValidPolymorphic>' requested here}}
ExplicitlyAuthedPolymorphicTemplateClass<ValidMonomorphic> test4;

UnauthedMonomorphicTemplateClass<ValidPolymorphic> test5;
UnauthedMonomorphicTemplateClass<ValidMonomorphic> test6;
UnauthedPolymorphicTemplateClass<ValidPolymorphic> test7;
UnauthedPolymorphicTemplateClass<ValidMonomorphic> test8;

// Just use a different policy from the generic macro to verify we won't complain
// about the insanity
struct authenticated(process_independent, no_address_discrimination, type_discrimination) SecondAuthenticatedPolymorphic {
  virtual ~SecondAuthenticatedPolymorphic(){};
};
struct UnauthenticatedPolymorphic {
  virtual ~UnauthenticatedPolymorphic(){};
};

struct MultipleParents1 : ValidPolymorphic, SecondAuthenticatedPolymorphic, UnauthenticatedPolymorphic {};
struct MultipleParents2 : UnauthenticatedPolymorphic, ValidPolymorphic, SecondAuthenticatedPolymorphic {};
struct generic_authenticated InvalidMultipleParents : UnauthenticatedPolymorphic, ValidPolymorphic, SecondAuthenticatedPolymorphic {};
// expected-error@-1{{cannot set vtable pointer authentication on 'InvalidMultipleParents' which is a subclass of polymorphic type 'UnauthenticatedPolymorphic'}}

template <typename T>
struct generic_authenticated ExplicitlyAuthedPolymorphicTemplateClassNoBase {
  virtual ~ExplicitlyAuthedPolymorphicTemplateClassNoBase();
};

ExplicitlyAuthedPolymorphicTemplateClassNoBase<int> v;

struct ValidSubclassOfTemplate : ExplicitlyAuthedPolymorphicTemplateClassNoBase<int> {
};

struct generic_authenticated InvalidSubclassOfTemplate : ExplicitlyAuthedPolymorphicTemplateClassNoBase<int> {
  // expected-error@-1{{cannot set vtable pointer authentication on 'InvalidSubclassOfTemplate' which is a subclass of polymorphic type 'ExplicitlyAuthedPolymorphicTemplateClassNoBase<int>'}}
};

template <typename T>
struct generic_authenticated ExplicitlyAuthedMonomorphicTemplateClassNoBase {
  // expected-error@-1{{cannot set vtable pointer authentication on monomorphic type 'ExplicitlyAuthedMonomorphicTemplateClassNoBase'}}
  // expected-error@-2{{cannot set vtable pointer authentication on monomorphic type 'ExplicitlyAuthedMonomorphicTemplateClassNoBase<int>'}}
};

ExplicitlyAuthedMonomorphicTemplateClassNoBase<int> X;
// expected-note@-1{{in instantiation of template class 'basic::ExplicitlyAuthedMonomorphicTemplateClassNoBase<int>' requested here}}

template <typename T>
struct generic_authenticated ExplicitlyAuthedTemplateClassValidBase : ValidMonomorphic {
  // expected-error@-1{{cannot set vtable pointer authentication on monomorphic type 'ExplicitlyAuthedTemplateClassValidBase'}}
  // expected-error@-2{{cannot set vtable pointer authentication on monomorphic type 'ExplicitlyAuthedTemplateClassValidBase<int>'}}
};

ExplicitlyAuthedTemplateClassValidBase<int> Y;
// expected-note@-1{{in instantiation of template class 'basic::ExplicitlyAuthedTemplateClassValidBase<int>' requested here}}

template <typename T>
struct generic_authenticated ExplicitlyAuthedTemplateClassInvalidBase : ValidPolymorphic {
  // expected-error@-1{{cannot set vtable pointer authentication on 'ExplicitlyAuthedTemplateClassInvalidBase' which is a subclass of polymorphic type 'ValidPolymorphic'}}
  // expected-error@-2{{cannot set vtable pointer authentication on 'ExplicitlyAuthedTemplateClassInvalidBase<int>' which is a subclass of polymorphic type 'ValidPolymorphic'}}
};

ExplicitlyAuthedTemplateClassInvalidBase<int> Z;
// expected-note@-1{{in instantiation of template class 'basic::ExplicitlyAuthedTemplateClassInvalidBase<int>' requested here}}

template <class test1, class test2>
class generic_authenticated TestPolymorphicTemplateSpecialization;

template <>
class TestPolymorphicTemplateSpecialization<double, float> {
  MissingDecl *zl;
  // expected-error@-1 {{unknown type name 'MissingDecl'}}
public:
  virtual ~TestPolymorphicTemplateSpecialization();
};
template <class test1>
class generic_authenticated TestPolymorphicTemplateSpecialization<test1, double>
// expected-error@-1 {{cannot set vtable pointer authentication on monomorphic type 'TestPolymorphicTemplateSpecialization<test1, double>'}}
// expected-error@-2 {{cannot set vtable pointer authentication on monomorphic type 'TestPolymorphicTemplateSpecialization<double, double>'}}
{
};

TestPolymorphicTemplateSpecialization<double, float> b;
TestPolymorphicTemplateSpecialization<double, double> b2;
// expected-note@-1 {{in instantiation of template class 'basic::TestPolymorphicTemplateSpecialization<double, double>' requested here}}

template <typename A> class generic_authenticated TestMonomorphic {};
// expected-error@-1 {{cannot set vtable pointer authentication on monomorphic type 'TestMonomorphic'}}
// expected-error@-2 {{cannot set vtable pointer authentication on monomorphic type 'TestMonomorphic<double>'}}

template <> class generic_authenticated TestMonomorphic<int> {
public:
  virtual ~TestMonomorphic();
};

struct TestMonomorphicSubclass : TestMonomorphic<int> {
};
template <typename T> struct generic_authenticated TestMonomorphicSubclass2 : TestMonomorphic<T> {
  // expected-error@-1 {{cannot set vtable pointer authentication on 'TestMonomorphicSubclass2<int>' which is a subclass of polymorphic type 'TestMonomorphic<int>'}}
  // expected-error@-2 {{cannot set vtable pointer authentication on monomorphic type 'TestMonomorphicSubclass2<double>'}}
  // expected-note@-3 {{in instantiation of template class 'basic::TestMonomorphic<double>' requested here}}
};

TestMonomorphicSubclass tms_1;
TestMonomorphicSubclass2<int> tms2_1;
// expected-note@-1 {{in instantiation of template class 'basic::TestMonomorphicSubclass2<int>' requested here}}
TestMonomorphicSubclass2<double> tms2_2;
// expected-note@-1 {{in instantiation of template class 'basic::TestMonomorphicSubclass2<double>' requested here}}
// expected-note@-2 {{in instantiation of template class 'basic::TestMonomorphicSubclass2<double>' requested here}}

template <typename T>
class generic_authenticated dependent_type {
  // expected-error@-1 {{cannot set vtable pointer authentication on monomorphic type 'dependent_type'}}
  static constexpr unsigned small_object_size = 1;
  char _model[small_object_size];
};

template <typename... T>
class generic_authenticated dependent_type2 : public T... {
  // expected-error@-1 {{cannot set vtable pointer authentication on 'dependent_type2<basic::Foo>' which is a subclass of polymorphic type 'Foo'}}
  static constexpr unsigned small_object_size = 1;
  char _model[small_object_size];
};

struct Foo {
  virtual ~Foo();
};

dependent_type2<Foo> thing;
// expected-note@-1 {{in instantiation of template class 'basic::dependent_type2<basic::Foo>' requested here}}

template <class>
class task;
template <unsigned align> struct alignedthing {
  char buffer[align];
};

template <class R, class... Args>
class generic_authenticated task<R(Args...)> {
  // expected-error@-1 {{cannot set vtable pointer authentication on monomorphic type 'task<R (Args...)>'}}
  static constexpr __SIZE_TYPE__ small_object_size = 256;
  alignedthing<small_object_size> _model;
};

} // namespace basic