зеркало из 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));
|
(((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; }
|
||||||
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.
|
/// ASTContext::getUnqualifiedArrayType.
|
||||||
inline SplitQualType getSplitUnqualifiedType() const;
|
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;
|
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;
|
bool isAtLeastAsQualifiedAs(QualType Other) const;
|
||||||
|
|
||||||
QualType getNonReferenceType() const;
|
QualType getNonReferenceType() const;
|
||||||
|
|
||||||
/// \brief Determine the type of a (typically non-lvalue) expression with the
|
/// \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);
|
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
|
/// isMoreQualifiedThan - Determine whether this type is more
|
||||||
/// qualified than the Other type. For example, "const volatile int"
|
/// qualified than the Other type. For example, "const volatile int"
|
||||||
/// is more qualified than "const int", "volatile int", and
|
/// is more qualified than "const int", "volatile int", and
|
||||||
|
|
|
@ -270,11 +270,11 @@ GetBestOverloadCandidateSimple(
|
||||||
|
|
||||||
unsigned Best = 0, N = Cands.size();
|
unsigned Best = 0, N = Cands.size();
|
||||||
for (unsigned I = 1; I != N; ++I)
|
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;
|
Best = I;
|
||||||
|
|
||||||
for (unsigned I = 1; I != N; ++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 0;
|
||||||
|
|
||||||
return Cands[Best].first;
|
return Cands[Best].first;
|
||||||
|
|
|
@ -800,6 +800,32 @@ DeduceTemplateArguments(Sema &S,
|
||||||
return Sema::TDK_Success;
|
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
|
/// \brief Deduce the template arguments by comparing the parameter type and
|
||||||
/// the argument type (C++ [temp.deduct.type]).
|
/// 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
|
// The argument type can not be less qualified than the parameter
|
||||||
// type.
|
// type.
|
||||||
if (Param.isMoreQualifiedThan(Arg) && !(TDF & TDF_IgnoreQualifiers)) {
|
if (!(TDF & TDF_IgnoreQualifiers) &&
|
||||||
|
hasInconsistentOrSupersetQualifiersOf(Param, Arg)) {
|
||||||
Info.Param = cast<TemplateTypeParmDecl>(TemplateParams->getParam(Index));
|
Info.Param = cast<TemplateTypeParmDecl>(TemplateParams->getParam(Index));
|
||||||
Info.FirstArg = TemplateArgument(Param);
|
Info.FirstArg = TemplateArgument(Param);
|
||||||
Info.SecondArg = TemplateArgument(Arg);
|
Info.SecondArg = TemplateArgument(Arg);
|
||||||
|
@ -971,8 +998,18 @@ DeduceTemplateArguments(Sema &S,
|
||||||
assert(Arg != S.Context.OverloadTy && "Unresolved overloaded function");
|
assert(Arg != S.Context.OverloadTy && "Unresolved overloaded function");
|
||||||
QualType DeducedType = Arg;
|
QualType DeducedType = Arg;
|
||||||
|
|
||||||
// local manipulation is okay because it's canonical
|
// Remove any qualifiers on the parameter from the deduced type.
|
||||||
DeducedType.removeLocalCVRQualifiers(Param.getCVRQualifiers());
|
// 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)
|
if (RecanonicalizeArg)
|
||||||
DeducedType = S.Context.getCanonicalType(DeducedType);
|
DeducedType = S.Context.getCanonicalType(DeducedType);
|
||||||
|
|
||||||
|
@ -1005,7 +1042,7 @@ DeduceTemplateArguments(Sema &S,
|
||||||
// Check the cv-qualifiers on the parameter and argument types.
|
// Check the cv-qualifiers on the parameter and argument types.
|
||||||
if (!(TDF & TDF_IgnoreQualifiers)) {
|
if (!(TDF & TDF_IgnoreQualifiers)) {
|
||||||
if (TDF & TDF_ParamWithReferenceType) {
|
if (TDF & TDF_ParamWithReferenceType) {
|
||||||
if (Param.isMoreQualifiedThan(Arg))
|
if (hasInconsistentOrSupersetQualifiersOf(Param, Arg))
|
||||||
return Sema::TDK_NonDeducedMismatch;
|
return Sema::TDK_NonDeducedMismatch;
|
||||||
} else if (!IsPossiblyOpaquelyQualifiedType(Param)) {
|
} else if (!IsPossiblyOpaquelyQualifiedType(Param)) {
|
||||||
if (Param.getCVRQualifiers() != Arg.getCVRQualifiers())
|
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_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_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];
|
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
|
// Check that we maintain address spaces through template argument
|
||||||
// deduction for a call.
|
// deduction for a call.
|
||||||
template<typename T>
|
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}}
|
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);
|
||||||
|
}
|
||||||
|
|
Загрузка…
Ссылка в новой задаче