Skip to content

Commit bd2b305

Browse files
antoniofrighettoresistor
authored andcommitted
[clang][Sema] Propagate qualifiers during derived-to-base conversion
When accessing a field member through a derived-to-base conversion, ensure qualifiers are propagated to the base class subobject. Fixes: llvm/llvm-project#127683. Cherry-picked from e9988c3
1 parent b324394 commit bd2b305

File tree

3 files changed

+80
-2
lines changed

3 files changed

+80
-2
lines changed

clang/lib/Sema/SemaExpr.cpp

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3154,8 +3154,15 @@ Sema::PerformObjectMemberConversion(Expr *From,
31543154
/*IgnoreAccess=*/true))
31553155
return ExprError();
31563156

3157-
return ImpCastExprToType(From, DestType, CK_UncheckedDerivedToBase,
3158-
VK, &BasePath);
3157+
// Propagate qualifiers to base subobjects as per:
3158+
// C++ [basic.type.qualifier]p1.2:
3159+
// A volatile object is [...] a subobject of a volatile object.
3160+
Qualifiers FromTypeQuals = FromType.getQualifiers();
3161+
FromTypeQuals.setAddressSpace(DestType.getAddressSpace());
3162+
DestType = Context.getQualifiedType(DestType, FromTypeQuals);
3163+
3164+
return ImpCastExprToType(From, DestType, CK_UncheckedDerivedToBase, VK,
3165+
&BasePath);
31593166
}
31603167

31613168
bool Sema::UseArgumentDependentLookup(const CXXScopeSpec &SS,

clang/test/CodeGenCXX/derived-to-base.cpp

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -46,4 +46,29 @@ namespace test3 {
4646
}
4747
}
4848

49+
// Ensure volatile is preserved during derived-to-base conversion.
50+
namespace PR127683 {
51+
52+
struct Base {
53+
int Val;
54+
};
55+
56+
struct Derived : Base { };
57+
58+
volatile Derived Obj;
59+
60+
// CHECK-LABEL: define void @_ZN8PR12768319test_volatile_storeEv()
61+
// CHECK: store volatile i32 0, ptr @_ZN8PR1276833ObjE, align 4
62+
void test_volatile_store() {
63+
Obj.Val = 0;
64+
}
65+
66+
// CHECK-LABEL: define void @_ZN8PR12768318test_volatile_loadEv()
67+
// CHECK: %0 = load volatile i32, ptr @_ZN8PR1276833ObjE, align 4
68+
void test_volatile_load() {
69+
[[maybe_unused]] int Val = Obj.Val;
70+
}
71+
72+
}
73+
4974
// CHECK: attributes [[NUW]] = { mustprogress noinline nounwind{{.*}} }
Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,46 @@
1+
// RUN: %clang_cc1 -std=c++20 -fsyntax-only -ast-dump -verify %s | FileCheck %s
2+
3+
// Ensure qualifiers are preserved during derived-to-base conversion.
4+
namespace PR127683 {
5+
6+
struct Base {
7+
int Val;
8+
};
9+
10+
struct Derived : Base { };
11+
12+
// Value-initialize base class subobjects with type qualifiers.
13+
volatile Derived VObj;
14+
const Derived CObj{}; // expected-note{{variable 'CObj' declared const here}}
15+
const volatile Derived CVObj{}; // expected-note{{variable 'CVObj' declared const here}}
16+
__attribute__((address_space(1))) Derived AddrSpaceObj{};
17+
18+
void test_store() {
19+
// CHECK: `-ImplicitCastExpr {{.*}} 'volatile PR127683::Base' lvalue <UncheckedDerivedToBase (Base)>
20+
VObj.Val = 0;
21+
22+
// CHECK: `-ImplicitCastExpr {{.*}} 'const PR127683::Base' lvalue <UncheckedDerivedToBase (Base)>
23+
CObj.Val = 1; // expected-error {{cannot assign to variable 'CObj' with const-qualified type 'const Derived'}}
24+
25+
// CHECK: `-ImplicitCastExpr {{.*}} 'const volatile PR127683::Base' lvalue <UncheckedDerivedToBase (Base)>
26+
CVObj.Val = 1; // expected-error {{cannot assign to variable 'CVObj' with const-qualified type 'const volatile Derived'}}
27+
28+
// CHECK: `-ImplicitCastExpr {{.*}} '__attribute__((address_space(1))) PR127683::Base' lvalue <UncheckedDerivedToBase (Base)>
29+
AddrSpaceObj.Val = 1;
30+
}
31+
32+
void test_load() {
33+
// CHECK: `-ImplicitCastExpr {{.*}} <col:30> 'volatile PR127683::Base' lvalue <UncheckedDerivedToBase (Base)>
34+
[[maybe_unused]] int Val = VObj.Val;
35+
36+
// CHECK: `-ImplicitCastExpr {{.*}} 'const PR127683::Base' lvalue <UncheckedDerivedToBase (Base)>
37+
Val = CObj.Val;
38+
39+
// CHECK: `-ImplicitCastExpr {{.*}} 'const volatile PR127683::Base' lvalue <UncheckedDerivedToBase (Base)>
40+
Val = CVObj.Val;
41+
42+
// CHECK: `-ImplicitCastExpr {{.*}} '__attribute__((address_space(1))) PR127683::Base' lvalue <UncheckedDerivedToBase (Base)>
43+
Val = AddrSpaceObj.Val;
44+
}
45+
46+
}

0 commit comments

Comments
 (0)