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);
|
||||
}
|
||||
|
||||
/// \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
|
||||
/// cvr-qualifiers have been removed.
|
||||
bool hasSameUnqualifiedType(QualType T1, QualType T2) {
|
||||
CanQualType CT1 = getCanonicalType(T1);
|
||||
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
|
||||
|
|
|
@ -2372,6 +2372,36 @@ CanQualType ASTContext::getCanonicalType(QualType T) {
|
|||
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) {
|
||||
if (TemplateDecl *TD = Name.getAsTemplateDecl())
|
||||
return TD->getDeclName();
|
||||
|
|
|
@ -4215,8 +4215,9 @@ Sema::CompareReferenceRelationship(SourceLocation Loc,
|
|||
|
||||
QualType T1 = Context.getCanonicalType(OrigT1);
|
||||
QualType T2 = Context.getCanonicalType(OrigT2);
|
||||
QualType UnqualT1 = T1.getLocalUnqualifiedType();
|
||||
QualType UnqualT2 = T2.getLocalUnqualifiedType();
|
||||
Qualifiers T1Quals, T2Quals;
|
||||
QualType UnqualT1 = Context.getUnqualifiedArrayType(T1, T1Quals);
|
||||
QualType UnqualT2 = Context.getUnqualifiedArrayType(T2, T2Quals);
|
||||
|
||||
// C++ [dcl.init.ref]p4:
|
||||
// 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
|
||||
// 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:
|
||||
// "cv1 T1" is reference-compatible with "cv2 T2" if T1 is
|
||||
// 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
|
||||
// cv-qualification than cv2 are identified as
|
||||
// reference-compatible with added qualification (see 13.3.3.2).
|
||||
if (T1.getCVRQualifiers() == T2.getCVRQualifiers())
|
||||
if (T1Quals.getCVRQualifiers() == T2Quals.getCVRQualifiers())
|
||||
return Ref_Compatible;
|
||||
else if (T1.isMoreQualifiedThan(T2))
|
||||
return Ref_Compatible_With_Added_Qualification;
|
||||
|
|
|
@ -1802,7 +1802,16 @@ Sema::CompareStandardConversionSequences(const StandardConversionSequence& SCS1,
|
|||
QualType T2 = QualType::getFromOpaquePtr(SCS2.ToTypePtr);
|
||||
T1 = Context.getCanonicalType(T1);
|
||||
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))
|
||||
return ImplicitConversionSequence::Better;
|
||||
else if (T1.isMoreQualifiedThan(T2))
|
||||
|
@ -1835,12 +1844,22 @@ Sema::CompareQualificationConversions(const StandardConversionSequence& SCS1,
|
|||
QualType T2 = QualType::getFromOpaquePtr(SCS2.ToTypePtr);
|
||||
T1 = Context.getCanonicalType(T1);
|
||||
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
|
||||
// them.
|
||||
if (Context.hasSameUnqualifiedType(T1, T2))
|
||||
if (UnqualT1 == UnqualT2)
|
||||
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::Indistinguishable;
|
||||
while (UnwrapSimilarPointerTypes(T1, T2)) {
|
||||
|
|
|
@ -337,58 +337,6 @@ DeduceTemplateArguments(ASTContext &Context,
|
|||
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
|
||||
/// the argument type (C++ [temp.deduct.type]).
|
||||
///
|
||||
|
@ -459,7 +407,7 @@ DeduceTemplateArguments(ASTContext &Context,
|
|||
// FIXME: address spaces, ObjC GC qualifiers
|
||||
if (isa<ArrayType>(Arg)) {
|
||||
Qualifiers Quals;
|
||||
Arg = getUnqualifiedArrayType(Context, Arg, Quals);
|
||||
Arg = Context.getUnqualifiedArrayType(Arg, Quals);
|
||||
if (Quals) {
|
||||
Arg = Context.getQualifiedType(Arg, Quals);
|
||||
RecanonicalizeArg = true;
|
||||
|
|
|
@ -21,3 +21,14 @@ void test_mquals(int A::*p, int A::* A::*pp, int A::* A::* A::*ppp) {
|
|||
mquals2(pp);
|
||||
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