|
5 | 5 |
|
6 | 6 | #include <clang/AST/APValue.h> |
7 | 7 | #include <clang/AST/ParentMapContext.h> |
| 8 | +#include <clang/Basic/LangOptions.h> |
8 | 9 | #include <clang/Basic/SourceManager.h> |
9 | 10 | #include <llvm/ADT/DenseMap.h> |
10 | 11 | #include <llvm/Support/ConvertUTF.h> |
@@ -3532,8 +3533,42 @@ void Converter::ConvertPointerOffset(clang::Expr *base, clang::Expr *idx, |
3532 | 3533 | computed_expr_type_ = ComputedExprType::FreshPointer; |
3533 | 3534 | } |
3534 | 3535 |
|
| 3536 | +static bool IsFlexibleArrayMemberAccess(clang::ASTContext &ctx, |
| 3537 | + clang::Expr *array) { |
| 3538 | + return array->isFlexibleArrayMemberLike( |
| 3539 | + ctx, clang::LangOptions::StrictFlexArraysLevelKind::OneZeroOrIncomplete, |
| 3540 | + /*IgnoreTemplateOrMacroSubstitution=*/true); |
| 3541 | +} |
| 3542 | + |
| 3543 | +void Converter::EmitFlexibleArrayElementPtr(clang::Expr *array, |
| 3544 | + clang::Expr *idx, bool is_mut) { |
| 3545 | + { |
| 3546 | + PushExplicitAutoref no_autoref(*this, std::nullopt); |
| 3547 | + Convert(array); |
| 3548 | + } |
| 3549 | + StrCat(is_mut ? ".as_mut_ptr()" : ".as_ptr()", ".add"); |
| 3550 | + { |
| 3551 | + PushParen call(*this); |
| 3552 | + { |
| 3553 | + PushParen paren(*this); |
| 3554 | + Convert(idx); |
| 3555 | + } |
| 3556 | + StrCat(keyword::kAs, "usize"); |
| 3557 | + } |
| 3558 | +} |
| 3559 | + |
3535 | 3560 | void Converter::ConvertArraySubscript(clang::Expr *base, clang::Expr *idx, |
3536 | 3561 | clang::QualType type) { |
| 3562 | + if (auto inner = base->IgnoreImplicit()) { |
| 3563 | + if (inner->getType()->isArrayType() && |
| 3564 | + IsFlexibleArrayMemberAccess(ctx_, inner)) { |
| 3565 | + PushParen outer(*this); |
| 3566 | + StrCat(token::kStar); |
| 3567 | + EmitFlexibleArrayElementPtr(inner, idx, |
| 3568 | + !inner->getType().isConstQualified()); |
| 3569 | + return; |
| 3570 | + } |
| 3571 | + } |
3537 | 3572 | if (IsUniquePtr(base->getType())) { |
3538 | 3573 | PushExplicitAutoref no_autoref(*this, std::nullopt); |
3539 | 3574 | Convert(base->IgnoreImplicit()); |
@@ -3836,6 +3871,19 @@ void Converter::ConvertUnsignedArithBinaryOperator(clang::BinaryOperator *op, |
3836 | 3871 |
|
3837 | 3872 | void Converter::ConvertAddrOf(clang::Expr *expr, clang::QualType pointer_type) { |
3838 | 3873 | assert(pointer_type->isPointerType()); |
| 3874 | + if (auto ase = |
| 3875 | + clang::dyn_cast<clang::ArraySubscriptExpr>(expr->IgnoreParens())) { |
| 3876 | + auto base = ase->getBase(); |
| 3877 | + auto inner = base->IgnoreImplicit(); |
| 3878 | + if (base->IgnoreCasts()->getType()->isArrayType() && |
| 3879 | + IsFlexibleArrayMemberAccess(ctx_, inner)) { |
| 3880 | + EmitFlexibleArrayElementPtr( |
| 3881 | + inner, ase->getIdx(), |
| 3882 | + !pointer_type->getPointeeType().isConstQualified()); |
| 3883 | + computed_expr_type_ = ComputedExprType::FreshPointer; |
| 3884 | + return; |
| 3885 | + } |
| 3886 | + } |
3839 | 3887 | if (IsReferenceType(expr) || pointer_type->isFunctionPointerType()) { |
3840 | 3888 | PushExprKind push(*this, ExprKind::AddrOf); |
3841 | 3889 | Convert(expr); |
|
0 commit comments