forked from OSchip/llvm-project
				
			
		
			
				
	
	
		
			148 lines
		
	
	
		
			5.7 KiB
		
	
	
	
		
			C++
		
	
	
	
			
		
		
	
	
			148 lines
		
	
	
		
			5.7 KiB
		
	
	
	
		
			C++
		
	
	
	
// RUN: %clang_cc1 -fsyntax-only -verify %s -std=c++14
 | 
						|
 | 
						|
namespace access_control {
 | 
						|
class Private {
 | 
						|
  void check(int *) __attribute__((enable_if(false, "")));
 | 
						|
  void check(double *) __attribute__((enable_if(true, "")));
 | 
						|
 | 
						|
  static void checkStatic(int *) __attribute__((enable_if(false, "")));
 | 
						|
  static void checkStatic(double *) __attribute__((enable_if(true, "")));
 | 
						|
};
 | 
						|
 | 
						|
auto Priv = reinterpret_cast<void (Private::*)(char *)>(&Private::check); // expected-error{{'check' is a private member of 'access_control::Private'}} expected-note@6{{implicitly declared private here}}
 | 
						|
 | 
						|
auto PrivStatic = reinterpret_cast<void (*)(char *)>(&Private::checkStatic); // expected-error{{'checkStatic' is a private member of 'access_control::Private'}} expected-note@9{{implicitly declared private here}}
 | 
						|
 | 
						|
class Protected {
 | 
						|
protected:
 | 
						|
  void check(int *) __attribute__((enable_if(false, "")));
 | 
						|
  void check(double *) __attribute__((enable_if(true, "")));
 | 
						|
 | 
						|
  static void checkStatic(int *) __attribute__((enable_if(false, "")));
 | 
						|
  static void checkStatic(double *) __attribute__((enable_if(true, "")));
 | 
						|
};
 | 
						|
 | 
						|
auto Prot = reinterpret_cast<void (Protected::*)(char *)>(&Protected::check); // expected-error{{'check' is a protected member of 'access_control::Protected'}} expected-note@19{{declared protected here}}
 | 
						|
 | 
						|
auto ProtStatic = reinterpret_cast<void (*)(char *)>(&Protected::checkStatic); // expected-error{{'checkStatic' is a protected member of 'access_control::Protected'}} expected-note@22{{declared protected here}}
 | 
						|
}
 | 
						|
 | 
						|
namespace unavailable {
 | 
						|
// Ensure that we check that the function can be called
 | 
						|
void foo() __attribute__((unavailable("don't call this")));
 | 
						|
void foo(int) __attribute__((enable_if(false, "")));
 | 
						|
 | 
						|
void *Ptr = reinterpret_cast<void*>(foo); // expected-error{{'foo' is unavailable: don't call this}} expected-note@-3{{explicitly marked unavailable here}}
 | 
						|
}
 | 
						|
 | 
						|
namespace template_deduction {
 | 
						|
void foo() __attribute__((enable_if(false, "")));
 | 
						|
 | 
						|
void bar() __attribute__((enable_if(true, "")));
 | 
						|
void bar() __attribute__((enable_if(false, "")));
 | 
						|
 | 
						|
void baz(int a) __attribute__((enable_if(true, "")));
 | 
						|
void baz(int a) __attribute__((enable_if(a, "")));
 | 
						|
void baz(int a) __attribute__((enable_if(false, "")));
 | 
						|
 | 
						|
void qux(int a) __attribute__((enable_if(1, "")));
 | 
						|
void qux(int a) __attribute__((enable_if(true, "")));
 | 
						|
void qux(int a) __attribute__((enable_if(a, "")));
 | 
						|
void qux(int a) __attribute__((enable_if(false, "")));
 | 
						|
 | 
						|
template <typename Fn, typename... Args> void call(Fn F, Args... As) {
 | 
						|
  F(As...);
 | 
						|
}
 | 
						|
 | 
						|
void test() {
 | 
						|
  call(foo); // expected-error{{cannot take address of function 'foo'}}
 | 
						|
  call(bar);
 | 
						|
  call(baz, 0);
 | 
						|
  call(qux, 0); // expected-error{{no matching function for call to 'call'}} expected-note@53{{candidate template ignored: couldn't infer template argument 'Fn'}}
 | 
						|
 | 
						|
  auto Ptr1 = foo; // expected-error{{cannot take address of function 'foo'}}
 | 
						|
  auto Ptr2 = bar;
 | 
						|
  auto Ptr3 = baz;
 | 
						|
  auto Ptr4 = qux; // expected-error{{variable 'Ptr4' with type 'auto' has incompatible initializer of type '<overloaded function type>'}}
 | 
						|
}
 | 
						|
 | 
						|
template <typename Fn, typename T, typename... Args>
 | 
						|
void callMem(Fn F, T t, Args... As) {
 | 
						|
  (t.*F)(As...);
 | 
						|
}
 | 
						|
 | 
						|
class Foo {
 | 
						|
  void bar() __attribute__((enable_if(true, "")));
 | 
						|
  void bar() __attribute__((enable_if(false, "")));
 | 
						|
 | 
						|
  static void staticBar() __attribute__((enable_if(true, "")));
 | 
						|
  static void staticBar() __attribute__((enable_if(false, "")));
 | 
						|
};
 | 
						|
 | 
						|
void testAccess() {
 | 
						|
  callMem(&Foo::bar, Foo()); // expected-error{{'bar' is a private member of 'template_deduction::Foo'}} expected-note@-8{{implicitly declared private here}}
 | 
						|
  call(&Foo::staticBar); // expected-error{{'staticBar' is a private member of 'template_deduction::Foo'}} expected-note@-6{{implicitly declared private here}}
 | 
						|
}
 | 
						|
}
 | 
						|
 | 
						|
namespace template_template_deduction {
 | 
						|
void foo() __attribute__((enable_if(false, "")));
 | 
						|
template <typename T>
 | 
						|
T foo() __attribute__((enable_if(true, "")));
 | 
						|
 | 
						|
template <typename Fn, typename... Args> auto call(Fn F, Args... As) {
 | 
						|
  return F(As...);
 | 
						|
}
 | 
						|
 | 
						|
auto Ok = call(&foo<int>);
 | 
						|
auto Fail = call(&foo); // expected-error{{no matching function for call to 'call'}} expected-note@-5{{candidate template ignored: couldn't infer template argument 'Fn'}}
 | 
						|
 | 
						|
auto PtrOk = &foo<int>;
 | 
						|
auto PtrFail = &foo; // expected-error{{variable 'PtrFail' with type 'auto' has incompatible initializer of type '<overloaded function type>'}}
 | 
						|
}
 | 
						|
 | 
						|
namespace pointer_equality {
 | 
						|
  using FnTy = void (*)();
 | 
						|
 | 
						|
  void bothEnableIf() __attribute__((enable_if(false, "")));
 | 
						|
  void bothEnableIf() __attribute__((enable_if(true, "")));
 | 
						|
 | 
						|
  void oneEnableIf() __attribute__((enable_if(false, "")));
 | 
						|
  void oneEnableIf();
 | 
						|
 | 
						|
  void test() {
 | 
						|
    FnTy Fn;
 | 
						|
    (void)(Fn == bothEnableIf);
 | 
						|
    (void)(Fn == &bothEnableIf);
 | 
						|
    (void)(Fn == oneEnableIf);
 | 
						|
    (void)(Fn == &oneEnableIf);
 | 
						|
  }
 | 
						|
 | 
						|
  void unavailableEnableIf() __attribute__((enable_if(false, "")));
 | 
						|
  void unavailableEnableIf() __attribute__((unavailable("noooo"))); // expected-note 2{{marked unavailable here}}
 | 
						|
 | 
						|
  void testUnavailable() {
 | 
						|
    FnTy Fn;
 | 
						|
    (void)(Fn == unavailableEnableIf); // expected-error{{is unavailable}}
 | 
						|
    (void)(Fn == &unavailableEnableIf); // expected-error{{is unavailable}}
 | 
						|
  }
 | 
						|
 | 
						|
  class Foo {
 | 
						|
    static void staticAccessEnableIf(); // expected-note 2{{declared private here}}
 | 
						|
    void accessEnableIf(); // expected-note{{declared private here}}
 | 
						|
 | 
						|
  public:
 | 
						|
    static void staticAccessEnableIf() __attribute__((enable_if(false, "")));
 | 
						|
    void accessEnableIf() __attribute__((enable_if(false, "")));
 | 
						|
  };
 | 
						|
 | 
						|
  void testAccess() {
 | 
						|
    FnTy Fn;
 | 
						|
    (void)(Fn == Foo::staticAccessEnableIf); // expected-error{{is a private member}}
 | 
						|
    (void)(Fn == &Foo::staticAccessEnableIf); // expected-error{{is a private member}}
 | 
						|
 | 
						|
    void (Foo::*MemFn)();
 | 
						|
    (void)(MemFn == &Foo::accessEnableIf); // expected-error{{is a private member}}
 | 
						|
  }
 | 
						|
}
 |