|  | // RUN: not %clang_cc1 -std=c++11 %s -fsyntax-only 2>&1 | FileCheck %s | 
|  | // RUN: %clang_cc1 -std=c++11 %s -fsyntax-only -DWARN 2>&1 | FileCheck %s --check-prefix=CHECK-WARN | 
|  |  | 
|  | #ifndef WARN | 
|  |  | 
|  | // Ensure that the diagnostics we produce for this situation appear in a | 
|  | // deterministic order. This requires ADL to provide lookup results in a | 
|  | // deterministic order. | 
|  | template<typename T, typename> struct Error { typedef typename T::error error; }; | 
|  | struct X { template<typename T> friend typename Error<X, T>::error f(X, T); }; | 
|  | struct Y { template<typename T> friend typename Error<Y, T>::error f(T, Y); }; | 
|  |  | 
|  | void g() { | 
|  | f(X(), Y()); | 
|  | } | 
|  |  | 
|  | // We don't really care which order these two diagnostics appear (although the | 
|  | // order below is source order, which seems best). The crucial fact is that | 
|  | // there is one single order that is stable across multiple runs of clang. | 
|  | // | 
|  | // CHECK: no type named 'error' in 'X' | 
|  | // CHECK: no type named 'error' in 'Y' | 
|  | // CHECK: no matching function for call to 'f' | 
|  |  | 
|  |  | 
|  | struct Oper { | 
|  | template<typename T, typename U = typename Error<Oper, T>::error> operator T(); | 
|  |  | 
|  | operator int*(); | 
|  | operator float*(); | 
|  | operator X*(); | 
|  | operator Y*(); | 
|  |  | 
|  | operator int(*[1])(); | 
|  | operator int(*[2])(); | 
|  | operator int(*[3])(); | 
|  | operator int(*[4])(); | 
|  | operator int(*[5])(); | 
|  | operator int(*[6])(); | 
|  | operator int(*[7])(); | 
|  | operator int(*[8])(); | 
|  | operator float(*[1])(); | 
|  | operator float(*[2])(); | 
|  | operator float(*[3])(); | 
|  | operator float(*[4])(); | 
|  | operator float(*[5])(); | 
|  | operator float(*[6])(); | 
|  | operator float(*[7])(); | 
|  | operator float(*[8])(); | 
|  | }; | 
|  | int *p = Oper() + 0; | 
|  |  | 
|  | // CHECK: no type named 'error' in 'Oper' | 
|  | // CHECK: in instantiation of template class 'Error<Oper, int *>' | 
|  | // CHECK: no type named 'error' in 'Oper' | 
|  | // CHECK: in instantiation of template class 'Error<Oper, float *>' | 
|  | // CHECK: no type named 'error' in 'Oper' | 
|  | // CHECK: in instantiation of template class 'Error<Oper, X *>' | 
|  | // CHECK: no type named 'error' in 'Oper' | 
|  | // CHECK: in instantiation of template class 'Error<Oper, Y *>' | 
|  |  | 
|  | #endif | 
|  |  | 
|  | template<typename T> struct UndefButUsed { | 
|  | static inline int f(); | 
|  | static int g() { return f(); } | 
|  | }; | 
|  | int undef_but_used = UndefButUsed<int>::g() + UndefButUsed<float>::g() + UndefButUsed<char>::g() + UndefButUsed<void>::g(); | 
|  |  | 
|  | // CHECK-WARN: inline function 'UndefButUsed<int>::f' is not defined | 
|  | // CHECK-WARN: inline function 'UndefButUsed<float>::f' is not defined | 
|  | // CHECK-WARN: inline function 'UndefButUsed<char>::f' is not defined | 
|  | // CHECK-WARN: inline function 'UndefButUsed<void>::f' is not defined |