|
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> |
@@ -3421,8 +3422,42 @@ void Converter::ConvertPointerOffset(clang::Expr *base, clang::Expr *idx, |
3421 | 3422 | computed_expr_type_ = ComputedExprType::FreshPointer; |
3422 | 3423 | } |
3423 | 3424 |
|
| 3425 | +static bool IsFlexibleArrayMemberAccess(clang::ASTContext &ctx, |
| 3426 | + clang::Expr *array) { |
| 3427 | + return array->isFlexibleArrayMemberLike( |
| 3428 | + ctx, clang::LangOptions::StrictFlexArraysLevelKind::OneZeroOrIncomplete, |
| 3429 | + /*IgnoreTemplateOrMacroSubstitution=*/true); |
| 3430 | +} |
| 3431 | + |
| 3432 | +void Converter::EmitFlexibleArrayElementPtr(clang::Expr *array, |
| 3433 | + clang::Expr *idx, bool is_mut) { |
| 3434 | + { |
| 3435 | + PushExplicitAutoref no_autoref(*this, std::nullopt); |
| 3436 | + Convert(array); |
| 3437 | + } |
| 3438 | + StrCat(is_mut ? ".as_mut_ptr()" : ".as_ptr()", ".add"); |
| 3439 | + { |
| 3440 | + PushParen call(*this); |
| 3441 | + { |
| 3442 | + PushParen paren(*this); |
| 3443 | + Convert(idx); |
| 3444 | + } |
| 3445 | + StrCat(keyword::kAs, "usize"); |
| 3446 | + } |
| 3447 | +} |
| 3448 | + |
3424 | 3449 | void Converter::ConvertArraySubscript(clang::Expr *base, clang::Expr *idx, |
3425 | 3450 | clang::QualType type) { |
| 3451 | + if (auto inner = base->IgnoreImplicit()) { |
| 3452 | + if (inner->getType()->isArrayType() && |
| 3453 | + IsFlexibleArrayMemberAccess(ctx_, inner)) { |
| 3454 | + PushParen outer(*this); |
| 3455 | + StrCat(token::kStar); |
| 3456 | + EmitFlexibleArrayElementPtr(inner, idx, |
| 3457 | + !inner->getType().isConstQualified()); |
| 3458 | + return; |
| 3459 | + } |
| 3460 | + } |
3426 | 3461 | if (IsUniquePtr(base->getType())) { |
3427 | 3462 | PushExplicitAutoref no_autoref(*this, std::nullopt); |
3428 | 3463 | Convert(base->IgnoreImplicit()); |
@@ -3725,6 +3760,19 @@ void Converter::ConvertUnsignedArithBinaryOperator(clang::BinaryOperator *op, |
3725 | 3760 |
|
3726 | 3761 | void Converter::ConvertAddrOf(clang::Expr *expr, clang::QualType pointer_type) { |
3727 | 3762 | assert(pointer_type->isPointerType()); |
| 3763 | + if (auto ase = |
| 3764 | + clang::dyn_cast<clang::ArraySubscriptExpr>(expr->IgnoreParens())) { |
| 3765 | + auto base = ase->getBase(); |
| 3766 | + auto inner = base->IgnoreImplicit(); |
| 3767 | + if (base->IgnoreCasts()->getType()->isArrayType() && |
| 3768 | + IsFlexibleArrayMemberAccess(ctx_, inner)) { |
| 3769 | + EmitFlexibleArrayElementPtr( |
| 3770 | + inner, ase->getIdx(), |
| 3771 | + !pointer_type->getPointeeType().isConstQualified()); |
| 3772 | + computed_expr_type_ = ComputedExprType::FreshPointer; |
| 3773 | + return; |
| 3774 | + } |
| 3775 | + } |
3728 | 3776 | if (IsReferenceType(expr) || pointer_type->isFunctionPointerType()) { |
3729 | 3777 | PushExprKind push(*this, ExprKind::AddrOf); |
3730 | 3778 | Convert(expr); |
|
0 commit comments