@@ -9032,15 +9032,107 @@ static bool IsInvalidCmseNSCallConversion(Sema &S, QualType FromType,
90329032 return false;
90339033}
90349034
9035+ /// This helper function returns element type if QT is a multidimentional array
9036+ static std::optional<QualType> getMultiDimentionalArrayType(Sema const *S,
9037+ QualType QT) {
9038+ const ArrayType *AT = S->Context.getAsArrayType(QT);
9039+ if (AT) {
9040+ const ConstantArrayType *CAT = llvm::dyn_cast<ConstantArrayType>(AT);
9041+ if (CAT) {
9042+ QualType ElementType = CAT->getElementType();
9043+ while (CAT) {
9044+ llvm::APInt Size = CAT->getSize();
9045+ // Zero sized array are no good.
9046+ if (Size == 0)
9047+ return std::optional<QualType>();
9048+ ElementType = CAT->getElementType();
9049+ CAT = llvm::dyn_cast<ConstantArrayType>(ElementType);
9050+ }
9051+ return std::optional<QualType>(
9052+ QualType(std::get<const Type *>(ElementType.split().asPair()), 0));
9053+ }
9054+ }
9055+ return std::optional<QualType>();
9056+ }
9057+
9058+ /// This helper function return AssignConvertType if pointers are not
9059+ /// compatible
9060+ static std::optional<AssignConvertType> checkPointerAssignmentCompatibility(
9061+ Sema &S, const Type *lhptee, const Type *rhptee, QualType ltrans,
9062+ QualType rtrans, QualType LHSType, QualType RHSType,
9063+ AssignConvertType ConvTy) {
9064+ if (!S.Context.typesAreCompatible(ltrans, rtrans)) {
9065+ // Check if the pointee types are compatible ignoring the sign.
9066+ // We explicitly check for char so that we catch "char" vs
9067+ // "unsigned char" on systems where "char" is unsigned.
9068+ if (lhptee->isCharType())
9069+ ltrans = S.Context.UnsignedCharTy;
9070+ else if (lhptee->hasSignedIntegerRepresentation())
9071+ ltrans = S.Context.getCorrespondingUnsignedType(ltrans);
9072+
9073+ if (rhptee->isCharType())
9074+ rtrans = S.Context.UnsignedCharTy;
9075+ else if (rhptee->hasSignedIntegerRepresentation())
9076+ rtrans = S.Context.getCorrespondingUnsignedType(rtrans);
9077+
9078+ if (ltrans == rtrans) {
9079+ // Types are compatible ignoring the sign. Qualifier incompatibility
9080+ // takes priority over sign incompatibility because the sign
9081+ // warning can be disabled.
9082+ if (!S.IsAssignConvertCompatible(ConvTy))
9083+ return ConvTy;
9084+
9085+ return AssignConvertType::IncompatiblePointerSign;
9086+ }
9087+
9088+ // If we are a multi-level pointer, it's possible that our issue is simply
9089+ // one of qualification - e.g. char ** -> const char ** is not allowed. If
9090+ // the eventual target type is the same and the pointers have the same
9091+ // level of indirection, this must be the issue.
9092+ if (isa<PointerType>(lhptee) && isa<PointerType>(rhptee)) {
9093+ Qualifiers lhq, rhq;
9094+ do {
9095+ std::tie(lhptee, lhq) =
9096+ cast<PointerType>(lhptee)->getPointeeType().split().asPair();
9097+ std::tie(rhptee, rhq) =
9098+ cast<PointerType>(rhptee)->getPointeeType().split().asPair();
9099+
9100+ // Inconsistent address spaces at this point is invalid, even if the
9101+ // address spaces would be compatible.
9102+ // FIXME: This doesn't catch address space mismatches for pointers of
9103+ // different nesting levels, like:
9104+ // __local int *** a;
9105+ // int ** b = a;
9106+ // It's not clear how to actually determine when such pointers are
9107+ // invalidly incompatible.
9108+ if (lhq.getAddressSpace() != rhq.getAddressSpace())
9109+ return AssignConvertType::
9110+ IncompatibleNestedPointerAddressSpaceMismatch;
9111+
9112+ } while (isa<PointerType>(lhptee) && isa<PointerType>(rhptee));
9113+
9114+ if (lhptee == rhptee)
9115+ return AssignConvertType::IncompatibleNestedPointerQualifiers;
9116+ }
9117+
9118+ // General pointer incompatibility takes priority over qualifiers.
9119+ if (RHSType->isFunctionPointerType() && LHSType->isFunctionPointerType())
9120+ return AssignConvertType::IncompatibleFunctionPointer;
9121+
9122+ // Return pointers as incompatible
9123+ return AssignConvertType::IncompatiblePointer;
9124+ }
9125+ return std::optional<AssignConvertType>();
9126+ }
9127+
90359128// checkPointerTypesForAssignment - This is a very tricky routine (despite
90369129// being closely modeled after the C99 spec:-). The odd characteristic of this
90379130// routine is it effectively iqnores the qualifiers on the top level pointee.
90389131// This circumvents the usual type rules specified in 6.2.7p1 & 6.7.5.[1-3].
90399132// FIXME: add a couple examples in this comment.
9040- static AssignConvertType checkPointerTypesForAssignment(Sema &S,
9041- QualType LHSType,
9042- QualType RHSType,
9043- SourceLocation Loc) {
9133+ static AssignConvertType
9134+ checkPointerTypesForAssignment(Sema &S, QualType LHSType, QualType RHSType,
9135+ QualType OrigRHSType, SourceLocation Loc) {
90449136 assert(LHSType.isCanonical() && "LHS not canonicalized!");
90459137 assert(RHSType.isCanonical() && "RHS not canonicalized!");
90469138
@@ -9128,65 +9220,26 @@ static AssignConvertType checkPointerTypesForAssignment(Sema &S,
91289220
91299221 // C99 6.5.16.1p1 (constraint 3): both operands are pointers to qualified or
91309222 // unqualified versions of compatible types, ...
9131- QualType ltrans = QualType(lhptee, 0), rtrans = QualType(rhptee, 0);
9132- if (!S.Context.typesAreCompatible(ltrans, rtrans)) {
9133- // Check if the pointee types are compatible ignoring the sign.
9134- // We explicitly check for char so that we catch "char" vs
9135- // "unsigned char" on systems where "char" is unsigned.
9136- if (lhptee->isCharType())
9137- ltrans = S.Context.UnsignedCharTy;
9138- else if (lhptee->hasSignedIntegerRepresentation())
9139- ltrans = S.Context.getCorrespondingUnsignedType(ltrans);
9140-
9141- if (rhptee->isCharType())
9142- rtrans = S.Context.UnsignedCharTy;
9143- else if (rhptee->hasSignedIntegerRepresentation())
9144- rtrans = S.Context.getCorrespondingUnsignedType(rtrans);
9145-
9146- if (ltrans == rtrans) {
9147- // Types are compatible ignoring the sign. Qualifier incompatibility
9148- // takes priority over sign incompatibility because the sign
9149- // warning can be disabled.
9150- if (!S.IsAssignConvertCompatible(ConvTy))
9151- return ConvTy;
9152-
9153- return AssignConvertType::IncompatiblePointerSign;
9154- }
9155-
9156- // If we are a multi-level pointer, it's possible that our issue is simply
9157- // one of qualification - e.g. char ** -> const char ** is not allowed. If
9158- // the eventual target type is the same and the pointers have the same
9159- // level of indirection, this must be the issue.
9160- if (isa<PointerType>(lhptee) && isa<PointerType>(rhptee)) {
9161- do {
9162- std::tie(lhptee, lhq) =
9163- cast<PointerType>(lhptee)->getPointeeType().split().asPair();
9164- std::tie(rhptee, rhq) =
9165- cast<PointerType>(rhptee)->getPointeeType().split().asPair();
9166-
9167- // Inconsistent address spaces at this point is invalid, even if the
9168- // address spaces would be compatible.
9169- // FIXME: This doesn't catch address space mismatches for pointers of
9170- // different nesting levels, like:
9171- // __local int *** a;
9172- // int ** b = a;
9173- // It's not clear how to actually determine when such pointers are
9174- // invalidly incompatible.
9175- if (lhq.getAddressSpace() != rhq.getAddressSpace())
9176- return AssignConvertType::
9177- IncompatibleNestedPointerAddressSpaceMismatch;
9178-
9179- } while (isa<PointerType>(lhptee) && isa<PointerType>(rhptee));
9180-
9181- if (lhptee == rhptee)
9182- return AssignConvertType::IncompatibleNestedPointerQualifiers;
9183- }
9184-
9185- // General pointer incompatibility takes priority over qualifiers.
9186- if (RHSType->isFunctionPointerType() && LHSType->isFunctionPointerType())
9187- return AssignConvertType::IncompatibleFunctionPointer;
9188- return AssignConvertType::IncompatiblePointer;
9223+ QualType ltrans = QualType(lhptee, 0);
9224+ QualType rtrans;
9225+ std::optional<AssignConvertType> CvtT;
9226+ std::optional<QualType> ArrET = getMultiDimentionalArrayType(&S, OrigRHSType);
9227+ if (ArrET) {
9228+ rtrans = ArrET.value();
9229+ CvtT = checkPointerAssignmentCompatibility(
9230+ S, lhptee, rhptee, ltrans, rtrans, LHSType, RHSType, ConvTy);
9231+ if (CvtT && CvtT.value() != AssignConvertType::IncompatiblePointer)
9232+ return CvtT.value();
9233+ }
9234+ if (!ArrET ||
9235+ (CvtT && CvtT.value() == AssignConvertType::IncompatiblePointer)) {
9236+ rtrans = QualType(rhptee, 0);
9237+ CvtT = checkPointerAssignmentCompatibility(
9238+ S, lhptee, rhptee, ltrans, rtrans, LHSType, RHSType, ConvTy);
9239+ if (CvtT)
9240+ return CvtT.value();
91899241 }
9242+
91909243 bool DiscardingCFIUncheckedCallee, AddingCFIUncheckedCallee;
91919244 if (!S.getLangOpts().CPlusPlus &&
91929245 S.IsFunctionConversion(ltrans, rtrans, &DiscardingCFIUncheckedCallee,
@@ -9313,6 +9366,22 @@ static bool isVector(QualType QT, QualType ElementType) {
93139366 return false;
93149367}
93159368
9369+ /// This helper function returns pre array-to-pointer decay type if possible
9370+ static QualType getPreDecayType(ExprResult &RHS) {
9371+ QualType OrigRHSType = RHS.get()->getType();
9372+ ImplicitCastExpr *ICE = dyn_cast<ImplicitCastExpr>(RHS.get());
9373+ if (ICE) {
9374+ Expr *E = ICE->getSubExpr();
9375+ if (E) {
9376+ DeclRefExpr *DRE = dyn_cast<DeclRefExpr>(E);
9377+ if (DRE) {
9378+ OrigRHSType = DRE->getType();
9379+ }
9380+ }
9381+ }
9382+ return OrigRHSType;
9383+ }
9384+
93169385/// CheckAssignmentConstraints (C99 6.5.16) - This routine currently
93179386/// has code to accommodate several GCC extensions when type checking
93189387/// pointers. Here are some objectionable examples that GCC considers warnings:
@@ -9510,7 +9579,9 @@ AssignConvertType Sema::CheckAssignmentConstraints(QualType LHSType,
95109579 Kind = CK_NoOp;
95119580 else
95129581 Kind = CK_BitCast;
9513- return checkPointerTypesForAssignment(*this, LHSType, RHSType,
9582+
9583+ QualType OrigType = getPreDecayType(RHS);
9584+ return checkPointerTypesForAssignment(*this, LHSType, RHSType, OrigType,
95149585 RHS.get()->getBeginLoc());
95159586 }
95169587
@@ -9629,7 +9700,6 @@ AssignConvertType Sema::CheckAssignmentConstraints(QualType LHSType,
96299700 Context.getObjCClassRedefinitionType())) {
96309701 return AssignConvertType::Compatible;
96319702 }
9632-
96339703 return AssignConvertType::IncompatiblePointer;
96349704 }
96359705
@@ -9902,7 +9972,7 @@ AssignConvertType Sema::CheckSingleAssignmentConstraints(QualType LHSType,
99029972 RHS.get()->getType().getCanonicalType().getUnqualifiedType();
99039973 QualType CanLHS = LHSType.getCanonicalType().getUnqualifiedType();
99049974 if (CanRHS->isVoidPointerType() && CanLHS->isPointerType()) {
9905- Ret = checkPointerTypesForAssignment(*this, CanLHS, CanRHS,
9975+ Ret = checkPointerTypesForAssignment(*this, CanLHS, CanRHS, CanRHS,
99069976 RHS.get()->getExprLoc());
99079977 // Anything that's not considered perfectly compatible would be
99089978 // incompatible in C++.
0 commit comments