-
Notifications
You must be signed in to change notification settings - Fork 79
Fill in some missing cases for bounds-safe interface assignments #813
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from 3 commits
2446a2b
f3e8d10
6bdd92a
67d7dec
fb395a8
801c350
44033b5
467f609
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -8479,6 +8479,18 @@ Sema::CheckAssignmentConstraints(QualType LHSType, ExprResult &RHS, | |
| LHSType = Context.getCanonicalType(LHSType).getUnqualifiedType(); | ||
| RHSType = Context.getCanonicalType(RHSType).getUnqualifiedType(); | ||
|
|
||
| // If the LHS is a checked nt array type and the RHS is an unchecked | ||
| // nt array type with a bounds-safe interface, use the bounds-safe | ||
| // interface of the RHS to check the types. | ||
| if ((LHSType->isNtCheckedArrayType() || | ||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Is the test isNtCheckedArrayType needed? I don't think C allows you to make assignments to values with array type. |
||
| LHSType->isCheckedPointerNtArrayType()) && | ||
| (RHSType->isUncheckedPointerType() || | ||
| RHSType->isUncheckedArrayType())) { | ||
| QualType RHSInteropType = GetCheckedCRValueInteropType(RHS); | ||
| if (!RHSInteropType.isNull()) | ||
| RHSType = RHSInteropType; | ||
| } | ||
|
|
||
| // Common case: no conversion required. | ||
| if (LHSType == RHSType) { | ||
| Kind = CK_NoOp; | ||
|
|
@@ -9116,6 +9128,22 @@ QualType Sema::GetCheckedCInteropType(ExprResult LHS) { | |
| IsParam = isa<ParmVarDecl>(Var); | ||
| } | ||
| } | ||
| // If `e` has bounds-safe interface T* (or ptr<T>, etc.), then `*e` has | ||
| // bounds-safe interface T. | ||
| else if (UnaryOperator *Unary = dyn_cast<UnaryOperator>(LHSExpr)) { | ||
| if (Unary->getOpcode() == UnaryOperatorKind::UO_Deref) { | ||
| QualType T = GetCheckedCRValueInteropType(Unary->getSubExpr()); | ||
| if (!T.isNull() && T->isPointerType()) | ||
| return T->getPointeeType(); | ||
| } | ||
| } | ||
| // If `e2` is an integer and `e1` has bounds-safe interface T* (or ptr<T>, | ||
| // etc.), then `e1[e2]` and `e2[e1]` have bounds-safe interface T. | ||
| else if (ArraySubscriptExpr *Array = dyn_cast<ArraySubscriptExpr>(LHSExpr)) { | ||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I think the same change applies here. |
||
| QualType T = GetCheckedCRValueInteropType(Array->getBase()); | ||
| if (!T.isNull() && T->isPointerType()) | ||
| return T->getPointeeType(); | ||
| } | ||
| } | ||
|
|
||
| if (D) | ||
|
|
@@ -9124,6 +9152,43 @@ QualType Sema::GetCheckedCInteropType(ExprResult LHS) { | |
| return QualType(); | ||
| } | ||
|
|
||
| /// Get the bounds-safe interface type for an rvalue expression, if the | ||
| /// rvalue expression has a bounds-safe interface. Return a null QualType | ||
| /// otherwise. The rvalue expression may appear as part of the left-hand | ||
| /// side of an assignment - for example, as the subexpression of a pointer | ||
| /// deference or an array subscript. For rvalue expressions appearing as | ||
| /// part of the left-hand side of an assignment, only lvalue-to-rvalue casts | ||
| /// and pointer arithmetic have bounds-safe interfaces. | ||
| QualType Sema::GetCheckedCRValueInteropType(ExprResult RHS) { | ||
|
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. In addition to returning the bounds-safe interface type for As an example, making this change would allow the following to compile: Currently, this example does not compile since |
||
| if (!RHS.isInvalid()) { | ||
| Expr *RHSExpr = RHS.get()->IgnoreParens(); | ||
| // If `e` has bounds-safe interface T, then `LValueToRValue(e)` has | ||
| // bounds-safe interface T. | ||
| if (CastExpr *Cast = dyn_cast<CastExpr>(RHSExpr)) { | ||
| if (Cast->getCastKind() == CastKind::CK_LValueToRValue) { | ||
| QualType T = GetCheckedCInteropType(Cast->getSubExpr()); | ||
| return T; | ||
| } | ||
| } | ||
| // If `p` has bounds-safe interface T, then `p +/- i` has bounds-safe | ||
| // interface T, where `p` is a pointer and `i` is an integer. | ||
| else if (BinaryOperator *Binary = dyn_cast<BinaryOperator>(RHSExpr)) { | ||
| if (BinaryOperator::isAdditiveOp(Binary->getOpcode())) { | ||
| Expr *Left = Binary->getLHS(); | ||
| Expr *Right = Binary->getRHS(); | ||
| if (Left->getType()->isPointerType() && | ||
| Right->getType()->isIntegerType()) | ||
| return GetCheckedCRValueInteropType(Left); | ||
| else if (Right->getType()->isPointerType() && | ||
| Left->getType()->isIntegerType()) | ||
| return GetCheckedCRValueInteropType(Right); | ||
| } | ||
| } | ||
| } | ||
|
|
||
| return QualType(); | ||
| } | ||
|
|
||
| QualType Sema::InvalidOperands(SourceLocation Loc, ExprResult &LHS, | ||
| ExprResult &RHS) { | ||
| OriginalOperand OrigLHS(LHS.get()), OrigRHS(RHS.get()); | ||
|
|
||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Does this need a clarifying comment? Or to be renamed?