forked from OSchip/llvm-project
Fix the CodeGen half of PR5911 by changing reference initialization to
correctly look through arrays to see cv-qualifiers. Also enhances the routine for doing this to preserve more type sugaring for diagnostics. llvm-svn: 93252
This commit is contained in:
parent
7c743f2c74
commit
04bdce6407
|
@ -898,17 +898,18 @@ public:
|
||||||
return getCanonicalType(T1) == getCanonicalType(T2);
|
return getCanonicalType(T1) == getCanonicalType(T2);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// \brief Returns this type as a completely-unqualified array type, capturing
|
/// \brief Returns this type as a completely-unqualified array type,
|
||||||
/// the qualifiers in Quals. This only operates on canonical types in order
|
/// capturing the qualifiers in Quals. This will remove the minimal amount of
|
||||||
/// to ensure the ArrayType doesn't itself have qualifiers.
|
/// sugaring from the types, similar to the behavior of
|
||||||
|
/// QualType::getUnqualifiedType().
|
||||||
///
|
///
|
||||||
/// \param T is the canonicalized QualType, which may be an ArrayType
|
/// \param T is the qualified type, which may be an ArrayType
|
||||||
///
|
///
|
||||||
/// \param Quals will receive the full set of qualifiers that were
|
/// \param Quals will receive the full set of qualifiers that were
|
||||||
/// applied to the element type of the array.
|
/// applied to the array.
|
||||||
///
|
///
|
||||||
/// \returns if this is an array type, the completely unqualified array type
|
/// \returns if this is an array type, the completely unqualified array type
|
||||||
/// that corresponds to it. Otherwise, returns this->getUnqualifiedType().
|
/// that corresponds to it. Otherwise, returns T.getUnqualifiedType().
|
||||||
QualType getUnqualifiedArrayType(QualType T, Qualifiers &Quals);
|
QualType getUnqualifiedArrayType(QualType T, Qualifiers &Quals);
|
||||||
|
|
||||||
/// \brief Determine whether the given types are equivalent after
|
/// \brief Determine whether the given types are equivalent after
|
||||||
|
|
|
@ -2374,13 +2374,11 @@ CanQualType ASTContext::getCanonicalType(QualType T) {
|
||||||
|
|
||||||
QualType ASTContext::getUnqualifiedArrayType(QualType T,
|
QualType ASTContext::getUnqualifiedArrayType(QualType T,
|
||||||
Qualifiers &Quals) {
|
Qualifiers &Quals) {
|
||||||
assert(T.isCanonical() && "Only operates on canonical types");
|
Quals = T.getQualifiers();
|
||||||
if (!isa<ArrayType>(T)) {
|
if (!isa<ArrayType>(T)) {
|
||||||
Quals = T.getLocalQualifiers();
|
return T.getUnqualifiedType();
|
||||||
return T.getLocalUnqualifiedType();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
assert(!T.hasQualifiers() && "canonical array type has qualifiers!");
|
|
||||||
const ArrayType *AT = cast<ArrayType>(T);
|
const ArrayType *AT = cast<ArrayType>(T);
|
||||||
QualType Elt = AT->getElementType();
|
QualType Elt = AT->getElementType();
|
||||||
QualType UnqualElt = getUnqualifiedArrayType(Elt, Quals);
|
QualType UnqualElt = getUnqualifiedArrayType(Elt, Quals);
|
||||||
|
|
|
@ -2227,9 +2227,11 @@ static void TryReferenceInitialization(Sema &S,
|
||||||
|
|
||||||
QualType DestType = Entity.getType();
|
QualType DestType = Entity.getType();
|
||||||
QualType cv1T1 = DestType->getAs<ReferenceType>()->getPointeeType();
|
QualType cv1T1 = DestType->getAs<ReferenceType>()->getPointeeType();
|
||||||
QualType T1 = cv1T1.getUnqualifiedType();
|
Qualifiers T1Quals;
|
||||||
|
QualType T1 = S.Context.getUnqualifiedArrayType(cv1T1, T1Quals);
|
||||||
QualType cv2T2 = Initializer->getType();
|
QualType cv2T2 = Initializer->getType();
|
||||||
QualType T2 = cv2T2.getUnqualifiedType();
|
Qualifiers T2Quals;
|
||||||
|
QualType T2 = S.Context.getUnqualifiedArrayType(cv2T2, T2Quals);
|
||||||
SourceLocation DeclLoc = Initializer->getLocStart();
|
SourceLocation DeclLoc = Initializer->getLocStart();
|
||||||
|
|
||||||
// If the initializer is the address of an overloaded function, try
|
// If the initializer is the address of an overloaded function, try
|
||||||
|
@ -2279,9 +2281,9 @@ static void TryReferenceInitialization(Sema &S,
|
||||||
// can occur. This property will be checked by PerformInitialization.
|
// can occur. This property will be checked by PerformInitialization.
|
||||||
if (DerivedToBase)
|
if (DerivedToBase)
|
||||||
Sequence.AddDerivedToBaseCastStep(
|
Sequence.AddDerivedToBaseCastStep(
|
||||||
S.Context.getQualifiedType(T1, cv2T2.getQualifiers()),
|
S.Context.getQualifiedType(T1, T2Quals),
|
||||||
/*isLValue=*/true);
|
/*isLValue=*/true);
|
||||||
if (cv1T1.getQualifiers() != cv2T2.getQualifiers())
|
if (T1Quals != T2Quals)
|
||||||
Sequence.AddQualificationConversionStep(cv1T1, /*IsLValue=*/true);
|
Sequence.AddQualificationConversionStep(cv1T1, /*IsLValue=*/true);
|
||||||
Sequence.AddReferenceBindingStep(cv1T1, /*bindingTemporary=*/false);
|
Sequence.AddReferenceBindingStep(cv1T1, /*bindingTemporary=*/false);
|
||||||
return;
|
return;
|
||||||
|
@ -2312,7 +2314,7 @@ static void TryReferenceInitialization(Sema &S,
|
||||||
// non-volatile const type (i.e., cv1 shall be const), or the reference
|
// non-volatile const type (i.e., cv1 shall be const), or the reference
|
||||||
// shall be an rvalue reference and the initializer expression shall
|
// shall be an rvalue reference and the initializer expression shall
|
||||||
// be an rvalue.
|
// be an rvalue.
|
||||||
if (!((isLValueRef && cv1T1.getCVRQualifiers() == Qualifiers::Const) ||
|
if (!((isLValueRef && T1Quals.hasConst()) ||
|
||||||
(isRValueRef && InitLvalue != Expr::LV_Valid))) {
|
(isRValueRef && InitLvalue != Expr::LV_Valid))) {
|
||||||
if (ConvOvlResult && !Sequence.getFailedCandidateSet().empty())
|
if (ConvOvlResult && !Sequence.getFailedCandidateSet().empty())
|
||||||
Sequence.SetOverloadFailure(
|
Sequence.SetOverloadFailure(
|
||||||
|
@ -2339,9 +2341,9 @@ static void TryReferenceInitialization(Sema &S,
|
||||||
RefRelationship >= Sema::Ref_Compatible_With_Added_Qualification) {
|
RefRelationship >= Sema::Ref_Compatible_With_Added_Qualification) {
|
||||||
if (DerivedToBase)
|
if (DerivedToBase)
|
||||||
Sequence.AddDerivedToBaseCastStep(
|
Sequence.AddDerivedToBaseCastStep(
|
||||||
S.Context.getQualifiedType(T1, cv2T2.getQualifiers()),
|
S.Context.getQualifiedType(T1, T2Quals),
|
||||||
/*isLValue=*/false);
|
/*isLValue=*/false);
|
||||||
if (cv1T1.getQualifiers() != cv2T2.getQualifiers())
|
if (T1Quals != T2Quals)
|
||||||
Sequence.AddQualificationConversionStep(cv1T1, /*IsLValue=*/false);
|
Sequence.AddQualificationConversionStep(cv1T1, /*IsLValue=*/false);
|
||||||
Sequence.AddReferenceBindingStep(cv1T1, /*bindingTemporary=*/true);
|
Sequence.AddReferenceBindingStep(cv1T1, /*bindingTemporary=*/true);
|
||||||
return;
|
return;
|
||||||
|
@ -2406,8 +2408,10 @@ static void TryReferenceInitialization(Sema &S,
|
||||||
// [...] If T1 is reference-related to T2, cv1 must be the
|
// [...] If T1 is reference-related to T2, cv1 must be the
|
||||||
// same cv-qualification as, or greater cv-qualification
|
// same cv-qualification as, or greater cv-qualification
|
||||||
// than, cv2; otherwise, the program is ill-formed.
|
// than, cv2; otherwise, the program is ill-formed.
|
||||||
|
unsigned T1CVRQuals = T1Quals.getCVRQualifiers();
|
||||||
|
unsigned T2CVRQuals = T2Quals.getCVRQualifiers();
|
||||||
if (RefRelationship == Sema::Ref_Related &&
|
if (RefRelationship == Sema::Ref_Related &&
|
||||||
!cv1T1.isAtLeastAsQualifiedAs(cv2T2)) {
|
(T1CVRQuals | T2CVRQuals) != T1CVRQuals) {
|
||||||
Sequence.SetFailed(InitializationSequence::FK_ReferenceInitDropsQualifiers);
|
Sequence.SetFailed(InitializationSequence::FK_ReferenceInitDropsQualifiers);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
|
@ -7,3 +7,10 @@ struct nsXPTParamInfo {
|
||||||
void a(XPTParamDescriptor *params) {
|
void a(XPTParamDescriptor *params) {
|
||||||
const nsXPTParamInfo& paramInfo = params[0];
|
const nsXPTParamInfo& paramInfo = params[0];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// CodeGen of reference initialized const arrays.
|
||||||
|
namespace PR5911 {
|
||||||
|
template <typename T, int N> int f(const T (&a)[N]) { return N; }
|
||||||
|
int iarr[] = { 1 };
|
||||||
|
int test() { return f(iarr); }
|
||||||
|
}
|
||||||
|
|
Loading…
Reference in New Issue