mirror of
https://github.com/llvm/llvm-project.git
synced 2025-04-18 18:56:43 +00:00
[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: https://github.com/llvm/llvm-project/issues/127683.
This commit is contained in:
parent
8a53324aa5
commit
e9988c36ed
@ -340,6 +340,8 @@ Bug Fixes to C++ Support
|
||||
- Fixed an assertion failure affecting code that uses C++23 "deducing this". (#GH130272)
|
||||
- Clang now properly instantiates destructors for initialized members within non-delegating constructors. (#GH93251)
|
||||
- Correctly diagnoses if unresolved using declarations shadows template paramters (#GH129411)
|
||||
- Clang was previously coalescing volatile writes to members of volatile base class subobjects.
|
||||
The issue has been addressed by propagating qualifiers during derived-to-base conversions in the AST. (#GH127824)
|
||||
|
||||
Bug Fixes to AST Handling
|
||||
^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
@ -3113,8 +3113,15 @@ Sema::PerformObjectMemberConversion(Expr *From,
|
||||
/*IgnoreAccess=*/true))
|
||||
return ExprError();
|
||||
|
||||
return ImpCastExprToType(From, DestType, CK_UncheckedDerivedToBase,
|
||||
VK, &BasePath);
|
||||
// Propagate qualifiers to base subobjects as per:
|
||||
// C++ [basic.type.qualifier]p1.2:
|
||||
// A volatile object is [...] a subobject of a volatile object.
|
||||
Qualifiers FromTypeQuals = FromType.getQualifiers();
|
||||
FromTypeQuals.setAddressSpace(DestType.getAddressSpace());
|
||||
DestType = Context.getQualifiedType(DestType, FromTypeQuals);
|
||||
|
||||
return ImpCastExprToType(From, DestType, CK_UncheckedDerivedToBase, VK,
|
||||
&BasePath);
|
||||
}
|
||||
|
||||
bool Sema::UseArgumentDependentLookup(const CXXScopeSpec &SS,
|
||||
|
@ -46,4 +46,29 @@ namespace test3 {
|
||||
}
|
||||
}
|
||||
|
||||
// Ensure volatile is preserved during derived-to-base conversion.
|
||||
namespace PR127683 {
|
||||
|
||||
struct Base {
|
||||
int Val;
|
||||
};
|
||||
|
||||
struct Derived : Base { };
|
||||
|
||||
volatile Derived Obj;
|
||||
|
||||
// CHECK-LABEL: define void @_ZN8PR12768319test_volatile_storeEv()
|
||||
// CHECK: store volatile i32 0, ptr @_ZN8PR1276833ObjE, align 4
|
||||
void test_volatile_store() {
|
||||
Obj.Val = 0;
|
||||
}
|
||||
|
||||
// CHECK-LABEL: define void @_ZN8PR12768318test_volatile_loadEv()
|
||||
// CHECK: %0 = load volatile i32, ptr @_ZN8PR1276833ObjE, align 4
|
||||
void test_volatile_load() {
|
||||
[[maybe_unused]] int Val = Obj.Val;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
// CHECK: attributes [[NUW]] = { mustprogress noinline nounwind{{.*}} }
|
||||
|
46
clang/test/SemaCXX/derived-to-base-propagate-qualifiers.cpp
Normal file
46
clang/test/SemaCXX/derived-to-base-propagate-qualifiers.cpp
Normal file
@ -0,0 +1,46 @@
|
||||
// RUN: %clang_cc1 -std=c++20 -fsyntax-only -ast-dump -verify %s | FileCheck %s
|
||||
|
||||
// Ensure qualifiers are preserved during derived-to-base conversion.
|
||||
namespace PR127683 {
|
||||
|
||||
struct Base {
|
||||
int Val;
|
||||
};
|
||||
|
||||
struct Derived : Base { };
|
||||
|
||||
// Value-initialize base class subobjects with type qualifiers.
|
||||
volatile Derived VObj;
|
||||
const Derived CObj{}; // expected-note{{variable 'CObj' declared const here}}
|
||||
const volatile Derived CVObj{}; // expected-note{{variable 'CVObj' declared const here}}
|
||||
__attribute__((address_space(1))) Derived AddrSpaceObj{};
|
||||
|
||||
void test_store() {
|
||||
// CHECK: `-ImplicitCastExpr {{.*}} 'volatile PR127683::Base' lvalue <UncheckedDerivedToBase (Base)>
|
||||
VObj.Val = 0;
|
||||
|
||||
// CHECK: `-ImplicitCastExpr {{.*}} 'const PR127683::Base' lvalue <UncheckedDerivedToBase (Base)>
|
||||
CObj.Val = 1; // expected-error {{cannot assign to variable 'CObj' with const-qualified type 'const Derived'}}
|
||||
|
||||
// CHECK: `-ImplicitCastExpr {{.*}} 'const volatile PR127683::Base' lvalue <UncheckedDerivedToBase (Base)>
|
||||
CVObj.Val = 1; // expected-error {{cannot assign to variable 'CVObj' with const-qualified type 'const volatile Derived'}}
|
||||
|
||||
// CHECK: `-ImplicitCastExpr {{.*}} '__attribute__((address_space(1))) PR127683::Base' lvalue <UncheckedDerivedToBase (Base)>
|
||||
AddrSpaceObj.Val = 1;
|
||||
}
|
||||
|
||||
void test_load() {
|
||||
// CHECK: `-ImplicitCastExpr {{.*}} <col:30> 'volatile PR127683::Base' lvalue <UncheckedDerivedToBase (Base)>
|
||||
[[maybe_unused]] int Val = VObj.Val;
|
||||
|
||||
// CHECK: `-ImplicitCastExpr {{.*}} 'const PR127683::Base' lvalue <UncheckedDerivedToBase (Base)>
|
||||
Val = CObj.Val;
|
||||
|
||||
// CHECK: `-ImplicitCastExpr {{.*}} 'const volatile PR127683::Base' lvalue <UncheckedDerivedToBase (Base)>
|
||||
Val = CVObj.Val;
|
||||
|
||||
// CHECK: `-ImplicitCastExpr {{.*}} '__attribute__((address_space(1))) PR127683::Base' lvalue <UncheckedDerivedToBase (Base)>
|
||||
Val = AddrSpaceObj.Val;
|
||||
}
|
||||
|
||||
}
|
Loading…
x
Reference in New Issue
Block a user