зеркало из https://github.com/microsoft/clang.git
More cleanup of template argument deduction and its handling of
non-CVR qualifiers. We can now properly match address-space--qualified references during template argument deduction. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@130365 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
Родитель
b93962532c
Коммит
61d0b6baf4
|
@ -299,8 +299,6 @@ public:
|
|||
(((Mask & CVRMask) | (other.Mask & CVRMask)) == (Mask & CVRMask));
|
||||
}
|
||||
|
||||
bool isSupersetOf(Qualifiers Other) const;
|
||||
|
||||
bool operator==(Qualifiers Other) const { return Mask == Other.Mask; }
|
||||
bool operator!=(Qualifiers Other) const { return Mask != Other.Mask; }
|
||||
|
||||
|
@ -606,8 +604,14 @@ public:
|
|||
/// ASTContext::getUnqualifiedArrayType.
|
||||
inline SplitQualType getSplitUnqualifiedType() const;
|
||||
|
||||
/// \brief Determine whether this type is more qualified than the other
|
||||
/// given type, requiring exact equality for non-CVR qualifiers.
|
||||
bool isMoreQualifiedThan(QualType Other) const;
|
||||
|
||||
/// \brief Determine whether this type is at least as qualified as the other
|
||||
/// given type, requiring exact equality for non-CVR qualifiers.
|
||||
bool isAtLeastAsQualifiedAs(QualType Other) const;
|
||||
|
||||
QualType getNonReferenceType() const;
|
||||
|
||||
/// \brief Determine the type of a (typically non-lvalue) expression with the
|
||||
|
@ -4154,12 +4158,6 @@ inline FunctionType::ExtInfo getFunctionExtInfo(QualType t) {
|
|||
return getFunctionExtInfo(*t);
|
||||
}
|
||||
|
||||
/// \brief Determine whether this set of qualifiers is a superset of the given
|
||||
/// set of qualifiers.
|
||||
inline bool Qualifiers::isSupersetOf(Qualifiers Other) const {
|
||||
return Mask != Other.Mask && (Mask | Other.Mask) == Mask;
|
||||
}
|
||||
|
||||
/// isMoreQualifiedThan - Determine whether this type is more
|
||||
/// qualified than the Other type. For example, "const volatile int"
|
||||
/// is more qualified than "const int", "volatile int", and
|
||||
|
|
|
@ -270,11 +270,11 @@ GetBestOverloadCandidateSimple(
|
|||
|
||||
unsigned Best = 0, N = Cands.size();
|
||||
for (unsigned I = 1; I != N; ++I)
|
||||
if (Cands[Best].second.isSupersetOf(Cands[I].second))
|
||||
if (Cands[Best].second.compatiblyIncludes(Cands[I].second))
|
||||
Best = I;
|
||||
|
||||
for (unsigned I = 1; I != N; ++I)
|
||||
if (Cands[Best].second.isSupersetOf(Cands[I].second))
|
||||
if (Cands[Best].second.compatiblyIncludes(Cands[I].second))
|
||||
return 0;
|
||||
|
||||
return Cands[Best].first;
|
||||
|
|
|
@ -800,6 +800,32 @@ DeduceTemplateArguments(Sema &S,
|
|||
return Sema::TDK_Success;
|
||||
}
|
||||
|
||||
/// \brief Determine whether the parameter has qualifiers that are either
|
||||
/// inconsistent with or a superset of the argument's qualifiers.
|
||||
static bool hasInconsistentOrSupersetQualifiersOf(QualType ParamType,
|
||||
QualType ArgType) {
|
||||
Qualifiers ParamQs = ParamType.getQualifiers();
|
||||
Qualifiers ArgQs = ArgType.getQualifiers();
|
||||
|
||||
if (ParamQs == ArgQs)
|
||||
return false;
|
||||
|
||||
// Mismatched (but not missing) Objective-C GC attributes.
|
||||
if (ParamQs.getObjCGCAttr() != ArgQs.getObjCGCAttr() &&
|
||||
ParamQs.hasObjCGCAttr())
|
||||
return true;
|
||||
|
||||
// Mismatched (but not missing) address spaces.
|
||||
if (ParamQs.getAddressSpace() != ArgQs.getAddressSpace() &&
|
||||
ParamQs.hasAddressSpace())
|
||||
return true;
|
||||
|
||||
// CVR qualifier superset.
|
||||
return (ParamQs.getCVRQualifiers() != ArgQs.getCVRQualifiers()) &&
|
||||
((ParamQs.getCVRQualifiers() | ArgQs.getCVRQualifiers())
|
||||
== ParamQs.getCVRQualifiers());
|
||||
}
|
||||
|
||||
/// \brief Deduce the template arguments by comparing the parameter type and
|
||||
/// the argument type (C++ [temp.deduct.type]).
|
||||
///
|
||||
|
@ -960,7 +986,8 @@ DeduceTemplateArguments(Sema &S,
|
|||
|
||||
// The argument type can not be less qualified than the parameter
|
||||
// type.
|
||||
if (Param.isMoreQualifiedThan(Arg) && !(TDF & TDF_IgnoreQualifiers)) {
|
||||
if (!(TDF & TDF_IgnoreQualifiers) &&
|
||||
hasInconsistentOrSupersetQualifiersOf(Param, Arg)) {
|
||||
Info.Param = cast<TemplateTypeParmDecl>(TemplateParams->getParam(Index));
|
||||
Info.FirstArg = TemplateArgument(Param);
|
||||
Info.SecondArg = TemplateArgument(Arg);
|
||||
|
@ -971,8 +998,18 @@ DeduceTemplateArguments(Sema &S,
|
|||
assert(Arg != S.Context.OverloadTy && "Unresolved overloaded function");
|
||||
QualType DeducedType = Arg;
|
||||
|
||||
// local manipulation is okay because it's canonical
|
||||
DeducedType.removeLocalCVRQualifiers(Param.getCVRQualifiers());
|
||||
// Remove any qualifiers on the parameter from the deduced type.
|
||||
// We checked the qualifiers for consistency above.
|
||||
Qualifiers DeducedQs = DeducedType.getQualifiers();
|
||||
Qualifiers ParamQs = Param.getQualifiers();
|
||||
DeducedQs.removeCVRQualifiers(ParamQs.getCVRQualifiers());
|
||||
if (ParamQs.hasObjCGCAttr())
|
||||
DeducedQs.removeObjCGCAttr();
|
||||
if (ParamQs.hasAddressSpace())
|
||||
DeducedQs.removeAddressSpace();
|
||||
DeducedType = S.Context.getQualifiedType(DeducedType.getUnqualifiedType(),
|
||||
DeducedQs);
|
||||
|
||||
if (RecanonicalizeArg)
|
||||
DeducedType = S.Context.getCanonicalType(DeducedType);
|
||||
|
||||
|
@ -1005,7 +1042,7 @@ DeduceTemplateArguments(Sema &S,
|
|||
// Check the cv-qualifiers on the parameter and argument types.
|
||||
if (!(TDF & TDF_IgnoreQualifiers)) {
|
||||
if (TDF & TDF_ParamWithReferenceType) {
|
||||
if (Param.isMoreQualifiedThan(Arg))
|
||||
if (hasInconsistentOrSupersetQualifiersOf(Param, Arg))
|
||||
return Sema::TDK_NonDeducedMismatch;
|
||||
} else if (!IsPossiblyOpaquelyQualifiedType(Param)) {
|
||||
if (Param.getCVRQualifiers() != Arg.getCVRQualifiers())
|
||||
|
|
|
@ -31,7 +31,21 @@ int check_remove0[is_same<remove_pointer<int_1_ptr>::type, int_1>::value? 1 : -1
|
|||
int check_remove1[is_same<remove_pointer<int_2_ptr>::type, int_2>::value? 1 : -1];
|
||||
int check_remove2[is_same<remove_pointer<int_2_ptr>::type, int>::value? -1 : 1];
|
||||
int check_remove3[is_same<remove_pointer<int_2_ptr>::type, int_1>::value? -1 : 1];
|
||||
|
||||
template<typename T>
|
||||
struct is_pointer_in_address_space_1 {
|
||||
static const bool value = false;
|
||||
};
|
||||
|
||||
template<typename T>
|
||||
struct is_pointer_in_address_space_1<T __attribute__((address_space(1))) *> {
|
||||
static const bool value = true;
|
||||
};
|
||||
|
||||
int check_ptr_in_as1[is_pointer_in_address_space_1<int_1_ptr>::value? 1 : -1];
|
||||
int check_ptr_in_as2[is_pointer_in_address_space_1<int_2_ptr>::value? -1 : 1];
|
||||
int check_ptr_in_as3[is_pointer_in_address_space_1<int*>::value? -1 : 1];
|
||||
|
||||
// Check that we maintain address spaces through template argument
|
||||
// deduction for a call.
|
||||
template<typename T>
|
||||
|
@ -46,3 +60,16 @@ void test_accept_any_pointer(int_1_ptr ip1, int_2_ptr ip2) {
|
|||
accept_any_pointer(array); // expected-note{{in instantiation of}}
|
||||
}
|
||||
|
||||
template<typename T> struct identity {};
|
||||
|
||||
template<typename T>
|
||||
identity<T> accept_arg_in_address_space_1(__attribute__((address_space(1))) T &ir1);
|
||||
|
||||
template<typename T>
|
||||
identity<T> accept_any_arg(T &ir1);
|
||||
|
||||
void test_arg_in_address_space_1() {
|
||||
static int __attribute__((address_space(1))) int_1;
|
||||
identity<int> ii = accept_arg_in_address_space_1(int_1);
|
||||
identity<int __attribute__((address_space(1)))> ii2 = accept_any_arg(int_1);
|
||||
}
|
||||
|
|
Загрузка…
Ссылка в новой задаче