forked from OSchip/llvm-project
Correctly refer to element CVR qualifications when determining if a type is
more or less cv-qualified than another during implicit conversion and overload resolution ([basic.type.qualifier] p5). Factors the logic out of template deduction and into the ASTContext so it can be shared. This fixes several aspects of PR5542, but not all of them. llvm-svn: 92248
This commit is contained in:
parent
5d3b077111
commit
607f38e05f
|
@ -898,12 +898,29 @@ public:
|
||||||
return getCanonicalType(T1) == getCanonicalType(T2);
|
return getCanonicalType(T1) == getCanonicalType(T2);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// \brief Returns this type as a completely-unqualified array type, capturing
|
||||||
|
/// the qualifiers in Quals. This only operates on canonical types in order
|
||||||
|
/// to ensure the ArrayType doesn't itself have qualifiers.
|
||||||
|
///
|
||||||
|
/// \param T is the canonicalized QualType, which may be an ArrayType
|
||||||
|
///
|
||||||
|
/// \param Quals will receive the full set of qualifiers that were
|
||||||
|
/// applied to the element type of the array.
|
||||||
|
///
|
||||||
|
/// \returns if this is an array type, the completely unqualified array type
|
||||||
|
/// that corresponds to it. Otherwise, returns this->getUnqualifiedType().
|
||||||
|
QualType getUnqualifiedArrayType(QualType T, Qualifiers &Quals);
|
||||||
|
|
||||||
/// \brief Determine whether the given types are equivalent after
|
/// \brief Determine whether the given types are equivalent after
|
||||||
/// cvr-qualifiers have been removed.
|
/// cvr-qualifiers have been removed.
|
||||||
bool hasSameUnqualifiedType(QualType T1, QualType T2) {
|
bool hasSameUnqualifiedType(QualType T1, QualType T2) {
|
||||||
CanQualType CT1 = getCanonicalType(T1);
|
CanQualType CT1 = getCanonicalType(T1);
|
||||||
CanQualType CT2 = getCanonicalType(T2);
|
CanQualType CT2 = getCanonicalType(T2);
|
||||||
return CT1.getUnqualifiedType() == CT2.getUnqualifiedType();
|
|
||||||
|
Qualifiers Quals;
|
||||||
|
QualType UnqualT1 = getUnqualifiedArrayType(CT1, Quals);
|
||||||
|
QualType UnqualT2 = getUnqualifiedArrayType(CT2, Quals);
|
||||||
|
return UnqualT1 == UnqualT2;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// \brief Retrieves the "canonical" declaration of
|
/// \brief Retrieves the "canonical" declaration of
|
||||||
|
|
|
@ -2372,6 +2372,36 @@ CanQualType ASTContext::getCanonicalType(QualType T) {
|
||||||
VAT->getBracketsRange()));
|
VAT->getBracketsRange()));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
QualType ASTContext::getUnqualifiedArrayType(QualType T,
|
||||||
|
Qualifiers &Quals) {
|
||||||
|
assert(T.isCanonical() && "Only operates on canonical types");
|
||||||
|
if (!isa<ArrayType>(T)) {
|
||||||
|
Quals = T.getLocalQualifiers();
|
||||||
|
return T.getLocalUnqualifiedType();
|
||||||
|
}
|
||||||
|
|
||||||
|
assert(!T.hasQualifiers() && "canonical array type has qualifiers!");
|
||||||
|
const ArrayType *AT = cast<ArrayType>(T);
|
||||||
|
QualType Elt = AT->getElementType();
|
||||||
|
QualType UnqualElt = getUnqualifiedArrayType(Elt, Quals);
|
||||||
|
if (Elt == UnqualElt)
|
||||||
|
return T;
|
||||||
|
|
||||||
|
if (const ConstantArrayType *CAT = dyn_cast<ConstantArrayType>(T)) {
|
||||||
|
return getConstantArrayType(UnqualElt, CAT->getSize(),
|
||||||
|
CAT->getSizeModifier(), 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (const IncompleteArrayType *IAT = dyn_cast<IncompleteArrayType>(T)) {
|
||||||
|
return getIncompleteArrayType(UnqualElt, IAT->getSizeModifier(), 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
const DependentSizedArrayType *DSAT = cast<DependentSizedArrayType>(T);
|
||||||
|
return getDependentSizedArrayType(UnqualElt, DSAT->getSizeExpr()->Retain(),
|
||||||
|
DSAT->getSizeModifier(), 0,
|
||||||
|
SourceRange());
|
||||||
|
}
|
||||||
|
|
||||||
DeclarationName ASTContext::getNameForTemplate(TemplateName Name) {
|
DeclarationName ASTContext::getNameForTemplate(TemplateName Name) {
|
||||||
if (TemplateDecl *TD = Name.getAsTemplateDecl())
|
if (TemplateDecl *TD = Name.getAsTemplateDecl())
|
||||||
return TD->getDeclName();
|
return TD->getDeclName();
|
||||||
|
|
|
@ -4206,7 +4206,7 @@ Sema::CompleteConstructorCall(CXXConstructorDecl *Constructor,
|
||||||
/// type, and the first type (T1) is the pointee type of the reference
|
/// type, and the first type (T1) is the pointee type of the reference
|
||||||
/// type being initialized.
|
/// type being initialized.
|
||||||
Sema::ReferenceCompareResult
|
Sema::ReferenceCompareResult
|
||||||
Sema::CompareReferenceRelationship(SourceLocation Loc,
|
Sema::CompareReferenceRelationship(SourceLocation Loc,
|
||||||
QualType OrigT1, QualType OrigT2,
|
QualType OrigT1, QualType OrigT2,
|
||||||
bool& DerivedToBase) {
|
bool& DerivedToBase) {
|
||||||
assert(!OrigT1->isReferenceType() &&
|
assert(!OrigT1->isReferenceType() &&
|
||||||
|
@ -4215,8 +4215,9 @@ Sema::CompareReferenceRelationship(SourceLocation Loc,
|
||||||
|
|
||||||
QualType T1 = Context.getCanonicalType(OrigT1);
|
QualType T1 = Context.getCanonicalType(OrigT1);
|
||||||
QualType T2 = Context.getCanonicalType(OrigT2);
|
QualType T2 = Context.getCanonicalType(OrigT2);
|
||||||
QualType UnqualT1 = T1.getLocalUnqualifiedType();
|
Qualifiers T1Quals, T2Quals;
|
||||||
QualType UnqualT2 = T2.getLocalUnqualifiedType();
|
QualType UnqualT1 = Context.getUnqualifiedArrayType(T1, T1Quals);
|
||||||
|
QualType UnqualT2 = Context.getUnqualifiedArrayType(T2, T2Quals);
|
||||||
|
|
||||||
// C++ [dcl.init.ref]p4:
|
// C++ [dcl.init.ref]p4:
|
||||||
// Given types "cv1 T1" and "cv2 T2," "cv1 T1" is
|
// Given types "cv1 T1" and "cv2 T2," "cv1 T1" is
|
||||||
|
@ -4234,6 +4235,13 @@ Sema::CompareReferenceRelationship(SourceLocation Loc,
|
||||||
// At this point, we know that T1 and T2 are reference-related (at
|
// At this point, we know that T1 and T2 are reference-related (at
|
||||||
// least).
|
// least).
|
||||||
|
|
||||||
|
// If the type is an array type, promote the element qualifiers to the type
|
||||||
|
// for comparison.
|
||||||
|
if (isa<ArrayType>(T1) && T1Quals)
|
||||||
|
T1 = Context.getQualifiedType(UnqualT1, T1Quals);
|
||||||
|
if (isa<ArrayType>(T2) && T2Quals)
|
||||||
|
T2 = Context.getQualifiedType(UnqualT2, T2Quals);
|
||||||
|
|
||||||
// C++ [dcl.init.ref]p4:
|
// C++ [dcl.init.ref]p4:
|
||||||
// "cv1 T1" is reference-compatible with "cv2 T2" if T1 is
|
// "cv1 T1" is reference-compatible with "cv2 T2" if T1 is
|
||||||
// reference-related to T2 and cv1 is the same cv-qualification
|
// reference-related to T2 and cv1 is the same cv-qualification
|
||||||
|
@ -4241,7 +4249,7 @@ Sema::CompareReferenceRelationship(SourceLocation Loc,
|
||||||
// overload resolution, cases for which cv1 is greater
|
// overload resolution, cases for which cv1 is greater
|
||||||
// cv-qualification than cv2 are identified as
|
// cv-qualification than cv2 are identified as
|
||||||
// reference-compatible with added qualification (see 13.3.3.2).
|
// reference-compatible with added qualification (see 13.3.3.2).
|
||||||
if (T1.getCVRQualifiers() == T2.getCVRQualifiers())
|
if (T1Quals.getCVRQualifiers() == T2Quals.getCVRQualifiers())
|
||||||
return Ref_Compatible;
|
return Ref_Compatible;
|
||||||
else if (T1.isMoreQualifiedThan(T2))
|
else if (T1.isMoreQualifiedThan(T2))
|
||||||
return Ref_Compatible_With_Added_Qualification;
|
return Ref_Compatible_With_Added_Qualification;
|
||||||
|
|
|
@ -1802,7 +1802,16 @@ Sema::CompareStandardConversionSequences(const StandardConversionSequence& SCS1,
|
||||||
QualType T2 = QualType::getFromOpaquePtr(SCS2.ToTypePtr);
|
QualType T2 = QualType::getFromOpaquePtr(SCS2.ToTypePtr);
|
||||||
T1 = Context.getCanonicalType(T1);
|
T1 = Context.getCanonicalType(T1);
|
||||||
T2 = Context.getCanonicalType(T2);
|
T2 = Context.getCanonicalType(T2);
|
||||||
if (Context.hasSameUnqualifiedType(T1, T2)) {
|
Qualifiers T1Quals, T2Quals;
|
||||||
|
QualType UnqualT1 = Context.getUnqualifiedArrayType(T1, T1Quals);
|
||||||
|
QualType UnqualT2 = Context.getUnqualifiedArrayType(T2, T2Quals);
|
||||||
|
if (UnqualT1 == UnqualT2) {
|
||||||
|
// If the type is an array type, promote the element qualifiers to the type
|
||||||
|
// for comparison.
|
||||||
|
if (isa<ArrayType>(T1) && T1Quals)
|
||||||
|
T1 = Context.getQualifiedType(UnqualT1, T1Quals);
|
||||||
|
if (isa<ArrayType>(T2) && T2Quals)
|
||||||
|
T2 = Context.getQualifiedType(UnqualT2, T2Quals);
|
||||||
if (T2.isMoreQualifiedThan(T1))
|
if (T2.isMoreQualifiedThan(T1))
|
||||||
return ImplicitConversionSequence::Better;
|
return ImplicitConversionSequence::Better;
|
||||||
else if (T1.isMoreQualifiedThan(T2))
|
else if (T1.isMoreQualifiedThan(T2))
|
||||||
|
@ -1835,12 +1844,22 @@ Sema::CompareQualificationConversions(const StandardConversionSequence& SCS1,
|
||||||
QualType T2 = QualType::getFromOpaquePtr(SCS2.ToTypePtr);
|
QualType T2 = QualType::getFromOpaquePtr(SCS2.ToTypePtr);
|
||||||
T1 = Context.getCanonicalType(T1);
|
T1 = Context.getCanonicalType(T1);
|
||||||
T2 = Context.getCanonicalType(T2);
|
T2 = Context.getCanonicalType(T2);
|
||||||
|
Qualifiers T1Quals, T2Quals;
|
||||||
|
QualType UnqualT1 = Context.getUnqualifiedArrayType(T1, T1Quals);
|
||||||
|
QualType UnqualT2 = Context.getUnqualifiedArrayType(T2, T2Quals);
|
||||||
|
|
||||||
// If the types are the same, we won't learn anything by unwrapped
|
// If the types are the same, we won't learn anything by unwrapped
|
||||||
// them.
|
// them.
|
||||||
if (Context.hasSameUnqualifiedType(T1, T2))
|
if (UnqualT1 == UnqualT2)
|
||||||
return ImplicitConversionSequence::Indistinguishable;
|
return ImplicitConversionSequence::Indistinguishable;
|
||||||
|
|
||||||
|
// If the type is an array type, promote the element qualifiers to the type
|
||||||
|
// for comparison.
|
||||||
|
if (isa<ArrayType>(T1) && T1Quals)
|
||||||
|
T1 = Context.getQualifiedType(UnqualT1, T1Quals);
|
||||||
|
if (isa<ArrayType>(T2) && T2Quals)
|
||||||
|
T2 = Context.getQualifiedType(UnqualT2, T2Quals);
|
||||||
|
|
||||||
ImplicitConversionSequence::CompareKind Result
|
ImplicitConversionSequence::CompareKind Result
|
||||||
= ImplicitConversionSequence::Indistinguishable;
|
= ImplicitConversionSequence::Indistinguishable;
|
||||||
while (UnwrapSimilarPointerTypes(T1, T2)) {
|
while (UnwrapSimilarPointerTypes(T1, T2)) {
|
||||||
|
|
|
@ -337,58 +337,6 @@ DeduceTemplateArguments(ASTContext &Context,
|
||||||
return Sema::TDK_Success;
|
return Sema::TDK_Success;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// \brief Returns a completely-unqualified array type, capturing the
|
|
||||||
/// qualifiers in Quals.
|
|
||||||
///
|
|
||||||
/// \param Context the AST context in which the array type was built.
|
|
||||||
///
|
|
||||||
/// \param T a canonical type that may be an array type.
|
|
||||||
///
|
|
||||||
/// \param Quals will receive the full set of qualifiers that were
|
|
||||||
/// applied to the element type of the array.
|
|
||||||
///
|
|
||||||
/// \returns if \p T is an array type, the completely unqualified array type
|
|
||||||
/// that corresponds to T. Otherwise, returns T.
|
|
||||||
static QualType getUnqualifiedArrayType(ASTContext &Context, QualType T,
|
|
||||||
Qualifiers &Quals) {
|
|
||||||
assert(T.isCanonical() && "Only operates on canonical types");
|
|
||||||
if (!isa<ArrayType>(T)) {
|
|
||||||
Quals = T.getLocalQualifiers();
|
|
||||||
return T.getLocalUnqualifiedType();
|
|
||||||
}
|
|
||||||
|
|
||||||
assert(!T.hasQualifiers() && "canonical array type has qualifiers!");
|
|
||||||
|
|
||||||
if (const ConstantArrayType *CAT = dyn_cast<ConstantArrayType>(T)) {
|
|
||||||
QualType Elt = getUnqualifiedArrayType(Context, CAT->getElementType(),
|
|
||||||
Quals);
|
|
||||||
if (Elt == CAT->getElementType())
|
|
||||||
return T;
|
|
||||||
|
|
||||||
return Context.getConstantArrayType(Elt, CAT->getSize(),
|
|
||||||
CAT->getSizeModifier(), 0);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (const IncompleteArrayType *IAT = dyn_cast<IncompleteArrayType>(T)) {
|
|
||||||
QualType Elt = getUnqualifiedArrayType(Context, IAT->getElementType(),
|
|
||||||
Quals);
|
|
||||||
if (Elt == IAT->getElementType())
|
|
||||||
return T;
|
|
||||||
|
|
||||||
return Context.getIncompleteArrayType(Elt, IAT->getSizeModifier(), 0);
|
|
||||||
}
|
|
||||||
|
|
||||||
const DependentSizedArrayType *DSAT = cast<DependentSizedArrayType>(T);
|
|
||||||
QualType Elt = getUnqualifiedArrayType(Context, DSAT->getElementType(),
|
|
||||||
Quals);
|
|
||||||
if (Elt == DSAT->getElementType())
|
|
||||||
return T;
|
|
||||||
|
|
||||||
return Context.getDependentSizedArrayType(Elt, DSAT->getSizeExpr()->Retain(),
|
|
||||||
DSAT->getSizeModifier(), 0,
|
|
||||||
SourceRange());
|
|
||||||
}
|
|
||||||
|
|
||||||
/// \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]).
|
||||||
///
|
///
|
||||||
|
@ -459,7 +407,7 @@ DeduceTemplateArguments(ASTContext &Context,
|
||||||
// FIXME: address spaces, ObjC GC qualifiers
|
// FIXME: address spaces, ObjC GC qualifiers
|
||||||
if (isa<ArrayType>(Arg)) {
|
if (isa<ArrayType>(Arg)) {
|
||||||
Qualifiers Quals;
|
Qualifiers Quals;
|
||||||
Arg = getUnqualifiedArrayType(Context, Arg, Quals);
|
Arg = Context.getUnqualifiedArrayType(Arg, Quals);
|
||||||
if (Quals) {
|
if (Quals) {
|
||||||
Arg = Context.getQualifiedType(Arg, Quals);
|
Arg = Context.getQualifiedType(Arg, Quals);
|
||||||
RecanonicalizeArg = true;
|
RecanonicalizeArg = true;
|
||||||
|
|
|
@ -21,3 +21,14 @@ void test_mquals(int A::*p, int A::* A::*pp, int A::* A::* A::*ppp) {
|
||||||
mquals2(pp);
|
mquals2(pp);
|
||||||
mquals3(ppp); // expected-error {{no matching}}
|
mquals3(ppp); // expected-error {{no matching}}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void aquals1(int const (*p)[1]);
|
||||||
|
void aquals2(int * const (*pp)[1]);
|
||||||
|
void aquals2a(int const * (*pp2)[1]); // expected-note{{candidate function}}
|
||||||
|
|
||||||
|
void test_aquals(int (*p)[1], int * (*pp)[1], int * (*pp2)[1]) {
|
||||||
|
int const (*p2)[1] = p;
|
||||||
|
aquals1(p);
|
||||||
|
aquals2(pp);
|
||||||
|
aquals2a(pp2); // expected-error {{no matching}}
|
||||||
|
}
|
||||||
|
|
Loading…
Reference in New Issue