-
Notifications
You must be signed in to change notification settings - Fork 15.2k
[Clang] Fix 'counted_by' for nested struct pointers #110497
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
15b6932
0bdcbc6
841286c
60c3bd8
06d39e3
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 |
|---|---|---|
|
|
@@ -10,6 +10,7 @@ | |
| // | ||
| //===----------------------------------------------------------------------===// | ||
|
|
||
| #include <iostream> | ||
| #include "ABIInfoImpl.h" | ||
| #include "CGCUDARuntime.h" | ||
| #include "CGCXXABI.h" | ||
|
|
@@ -1095,6 +1096,8 @@ class StructAccessBase | |
| return Visit(E->getBase()); | ||
| } | ||
| const Expr *VisitCastExpr(const CastExpr *E) { | ||
| if (E->getCastKind() == CK_LValueToRValue) | ||
| return E; | ||
|
Collaborator
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. Should this be
Collaborator
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. It might be a good sanity check, though I think I've only seen an
Collaborator
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. See #111448 |
||
| return Visit(E->getSubExpr()); | ||
| } | ||
| const Expr *VisitParenExpr(const ParenExpr *E) { | ||
|
|
@@ -1161,21 +1164,15 @@ llvm::Value *CodeGenFunction::EmitLoadOfCountedByField( | |
| return nullptr; | ||
|
|
||
| llvm::Value *Res = nullptr; | ||
| if (const auto *DRE = dyn_cast<DeclRefExpr>(StructBase)) { | ||
| Res = EmitDeclRefLValue(DRE).getPointer(*this); | ||
| Res = Builder.CreateAlignedLoad(ConvertType(DRE->getType()), Res, | ||
| getPointerAlign(), "dre.load"); | ||
| } else if (const MemberExpr *ME = dyn_cast<MemberExpr>(StructBase)) { | ||
| LValue LV = EmitMemberExpr(ME); | ||
| if (StructBase->isLValue()) { | ||
| LValue LV = EmitLValue(StructBase); | ||
| Address Addr = LV.getAddress(); | ||
| Res = Addr.emitRawPointer(*this); | ||
| } else if (StructBase->getType()->isPointerType()) { | ||
| } else { | ||
| LValueBaseInfo BaseInfo; | ||
| TBAAAccessInfo TBAAInfo; | ||
| Address Addr = EmitPointerWithAlignment(StructBase, &BaseInfo, &TBAAInfo); | ||
| Res = Addr.emitRawPointer(*this); | ||
| } else { | ||
| return nullptr; | ||
| } | ||
|
|
||
| RecIndicesTy Indices; | ||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,62 @@ | ||
| // NOTE: Assertions have been autogenerated by utils/update_cc_test_checks.py UTC_ARGS: --version 4 | ||
| // RUN: %clang_cc1 -triple x86_64-unknown-linux-gnu -O2 -Wno-missing-declarations -emit-llvm -o - %s | FileCheck %s | ||
|
|
||
| // See #110385 | ||
| // Based on reproducer from Kees Cook: | ||
| // https://lore.kernel.org/all/202409170436.C3C6E7F7A@keescook/ | ||
|
|
||
| struct variable { | ||
| int a; | ||
| int b; | ||
| int length; | ||
| short array[] __attribute__((counted_by(length))); | ||
| }; | ||
|
|
||
| struct bucket { | ||
| int a; | ||
| struct variable *growable; | ||
| int b; | ||
| }; | ||
|
|
||
| struct bucket2 { | ||
| int a; | ||
| struct variable growable; | ||
| }; | ||
|
|
||
| void init(void * __attribute__((pass_dynamic_object_size(0)))); | ||
|
|
||
| // CHECK-LABEL: define dso_local void @test1( | ||
| // CHECK-SAME: ptr nocapture noundef readonly [[FOO:%.*]]) local_unnamed_addr #[[ATTR0:[0-9]+]] { | ||
| // CHECK-NEXT: entry: | ||
| // CHECK-NEXT: [[GROWABLE:%.*]] = getelementptr inbounds nuw i8, ptr [[FOO]], i64 8 | ||
| // CHECK-NEXT: [[TMP0:%.*]] = load ptr, ptr [[GROWABLE]], align 8, !tbaa [[TBAA2:![0-9]+]] | ||
| // CHECK-NEXT: [[ARRAY:%.*]] = getelementptr inbounds nuw i8, ptr [[TMP0]], i64 12 | ||
| // CHECK-NEXT: [[DOT_COUNTED_BY_GEP:%.*]] = getelementptr inbounds i8, ptr [[TMP0]], i64 8 | ||
| // CHECK-NEXT: [[DOT_COUNTED_BY_LOAD:%.*]] = load i32, ptr [[DOT_COUNTED_BY_GEP]], align 4 | ||
| // CHECK-NEXT: [[TMP1:%.*]] = sext i32 [[DOT_COUNTED_BY_LOAD]] to i64 | ||
| // CHECK-NEXT: [[TMP2:%.*]] = shl nsw i64 [[TMP1]], 1 | ||
| // CHECK-NEXT: [[TMP3:%.*]] = icmp sgt i32 [[DOT_COUNTED_BY_LOAD]], -1 | ||
| // CHECK-NEXT: [[TMP4:%.*]] = select i1 [[TMP3]], i64 [[TMP2]], i64 0 | ||
| // CHECK-NEXT: tail call void @init(ptr noundef nonnull [[ARRAY]], i64 noundef [[TMP4]]) #[[ATTR2:[0-9]+]] | ||
| // CHECK-NEXT: ret void | ||
| // | ||
| void test1(struct bucket *foo) { | ||
| init(foo->growable->array); | ||
| } | ||
|
|
||
| // CHECK-LABEL: define dso_local void @test2( | ||
| // CHECK-SAME: ptr noundef [[FOO:%.*]]) local_unnamed_addr #[[ATTR0]] { | ||
| // CHECK-NEXT: entry: | ||
| // CHECK-NEXT: [[ARRAY:%.*]] = getelementptr inbounds nuw i8, ptr [[FOO]], i64 16 | ||
| // CHECK-NEXT: [[DOT_COUNTED_BY_GEP:%.*]] = getelementptr inbounds i8, ptr [[FOO]], i64 12 | ||
| // CHECK-NEXT: [[DOT_COUNTED_BY_LOAD:%.*]] = load i32, ptr [[DOT_COUNTED_BY_GEP]], align 4 | ||
| // CHECK-NEXT: [[TMP0:%.*]] = sext i32 [[DOT_COUNTED_BY_LOAD]] to i64 | ||
| // CHECK-NEXT: [[TMP1:%.*]] = shl nsw i64 [[TMP0]], 1 | ||
| // CHECK-NEXT: [[TMP2:%.*]] = icmp sgt i32 [[DOT_COUNTED_BY_LOAD]], -1 | ||
| // CHECK-NEXT: [[TMP3:%.*]] = select i1 [[TMP2]], i64 [[TMP1]], i64 0 | ||
| // CHECK-NEXT: tail call void @init(ptr noundef nonnull [[ARRAY]], i64 noundef [[TMP3]]) #[[ATTR2]] | ||
| // CHECK-NEXT: ret void | ||
| // | ||
| void test2(struct bucket2 *foo) { | ||
| init(foo->growable.array); | ||
| } |
Uh oh!
There was an error while loading. Please reload this page.