/// enumeration types.
class BuiltinCandidateTypeSet {
/// TypeSet - A set of types.
- typedef llvm::SmallPtrSet<QualType, 8> TypeSet;
+ typedef llvm::SetVector<QualType, SmallVector<QualType, 8>,
+ llvm::SmallPtrSet<QualType, 8>> TypeSet;
/// PointerTypes - The set of pointer types that will be used in the
/// built-in candidates.
const Qualifiers &VisibleQuals) {
// Insert this type.
- if (!PointerTypes.insert(Ty).second)
+ if (!PointerTypes.insert(Ty))
return false;
QualType PointeeTy;
BuiltinCandidateTypeSet::AddMemberPointerWithMoreQualifiedTypeVariants(
QualType Ty) {
// Insert this type.
- if (!MemberPointerTypes.insert(Ty).second)
+ if (!MemberPointerTypes.insert(Ty))
return false;
const MemberPointerType *PointerTy = Ty->getAs<MemberPointerType>();
// 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> struct Error { typedef typename T::error error; };
-struct X { template<typename T> friend typename Error<T>::error f(X, T); };
-struct Y { template<typename T> friend typename Error<T>::error f(T, Y); };
+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());
// 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 'Y'
// 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 *>'