diff --git a/lib/Sema/SemaTemplateDeduction.cpp b/lib/Sema/SemaTemplateDeduction.cpp index 469118111146d92e6f97442190de26b63721bc53..87d9febfb13036a8e5127efca8bc00178c908cc9 100644 --- a/lib/Sema/SemaTemplateDeduction.cpp +++ b/lib/Sema/SemaTemplateDeduction.cpp @@ -350,6 +350,29 @@ DeduceTemplateArguments(Sema &S, return Sema::TDK_Success; } +/// \brief Determines whether the given type is an opaque type that +/// might be more qualified when instantiated. +static bool IsPossiblyOpaquelyQualifiedType(QualType T) { + switch (T->getTypeClass()) { + case Type::TypeOfExpr: + case Type::TypeOf: + case Type::DependentName: + case Type::Decltype: + case Type::UnresolvedUsing: + return true; + + case Type::ConstantArray: + case Type::IncompleteArray: + case Type::VariableArray: + case Type::DependentSizedArray: + return IsPossiblyOpaquelyQualifiedType( + cast<ArrayType>(T)->getElementType()); + + default: + return false; + } +} + /// \brief Deduce the template arguments by comparing the parameter type and /// the argument type (C++ [temp.deduct.type]). /// @@ -474,7 +497,7 @@ DeduceTemplateArguments(Sema &S, if (TDF & TDF_ParamWithReferenceType) { if (Param.isMoreQualifiedThan(Arg)) return Sema::TDK_NonDeducedMismatch; - } else { + } else if (!IsPossiblyOpaquelyQualifiedType(Param)) { if (Param.getCVRQualifiers() != Arg.getCVRQualifiers()) return Sema::TDK_NonDeducedMismatch; } diff --git a/test/SemaTemplate/deduction.cpp b/test/SemaTemplate/deduction.cpp index c4c668898f0fae312ae22c42a9afb7a7d87f5ecc..9400a0aba96be29b8b9df0b87e5f01e3af8d6312 100644 --- a/test/SemaTemplate/deduction.cpp +++ b/test/SemaTemplate/deduction.cpp @@ -121,3 +121,16 @@ namespace test1 { foo(a); } } + +// PR7708 +namespace test2 { + template<typename T> struct Const { typedef void const type; }; + + template<typename T> void f(T, typename Const<T>::type*); + template<typename T> void f(T, void const *); + + void test() { + void *p = 0; + f(0, p); + } +}