Skip to content

Commit 9e75544

Browse files
authored
[clang][bytecode] Create implicit variables for wider base types (#156658)
If we create an implicit local variable for a derived-to-base cast, we still should allocate enough space for the entire derived type. Fixes #156219
1 parent 1b47135 commit 9e75544

File tree

2 files changed

+38
-14
lines changed

2 files changed

+38
-14
lines changed

clang/lib/AST/ByteCode/Compiler.cpp

Lines changed: 27 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -4191,6 +4191,31 @@ template <class Emitter> bool Compiler<Emitter>::delegate(const Expr *E) {
41914191
return this->Visit(E);
41924192
}
41934193

4194+
static const Expr *stripCheckedDerivedToBaseCasts(const Expr *E) {
4195+
if (const auto *PE = dyn_cast<ParenExpr>(E))
4196+
return stripCheckedDerivedToBaseCasts(PE->getSubExpr());
4197+
4198+
if (const auto *CE = dyn_cast<CastExpr>(E);
4199+
CE &&
4200+
(CE->getCastKind() == CK_DerivedToBase || CE->getCastKind() == CK_NoOp))
4201+
return stripCheckedDerivedToBaseCasts(CE->getSubExpr());
4202+
4203+
return E;
4204+
}
4205+
4206+
static const Expr *stripDerivedToBaseCasts(const Expr *E) {
4207+
if (const auto *PE = dyn_cast<ParenExpr>(E))
4208+
return stripDerivedToBaseCasts(PE->getSubExpr());
4209+
4210+
if (const auto *CE = dyn_cast<CastExpr>(E);
4211+
CE && (CE->getCastKind() == CK_DerivedToBase ||
4212+
CE->getCastKind() == CK_UncheckedDerivedToBase ||
4213+
CE->getCastKind() == CK_NoOp))
4214+
return stripDerivedToBaseCasts(CE->getSubExpr());
4215+
4216+
return E;
4217+
}
4218+
41944219
template <class Emitter> bool Compiler<Emitter>::visit(const Expr *E) {
41954220
if (E->getType().isNull())
41964221
return false;
@@ -4200,7 +4225,7 @@ template <class Emitter> bool Compiler<Emitter>::visit(const Expr *E) {
42004225

42014226
// Create local variable to hold the return value.
42024227
if (!E->isGLValue() && !canClassify(E->getType())) {
4203-
UnsignedOrNone LocalIndex = allocateLocal(E);
4228+
UnsignedOrNone LocalIndex = allocateLocal(stripDerivedToBaseCasts(E));
42044229
if (!LocalIndex)
42054230
return false;
42064231

@@ -5078,18 +5103,6 @@ bool Compiler<Emitter>::VisitBuiltinCallExpr(const CallExpr *E,
50785103
return true;
50795104
}
50805105

5081-
static const Expr *stripDerivedToBaseCasts(const Expr *E) {
5082-
if (const auto *PE = dyn_cast<ParenExpr>(E))
5083-
return stripDerivedToBaseCasts(PE->getSubExpr());
5084-
5085-
if (const auto *CE = dyn_cast<CastExpr>(E);
5086-
CE &&
5087-
(CE->getCastKind() == CK_DerivedToBase || CE->getCastKind() == CK_NoOp))
5088-
return stripDerivedToBaseCasts(CE->getSubExpr());
5089-
5090-
return E;
5091-
}
5092-
50935106
template <class Emitter>
50945107
bool Compiler<Emitter>::VisitCallExpr(const CallExpr *E) {
50955108
const FunctionDecl *FuncDecl = E->getDirectCallee();
@@ -5194,7 +5207,7 @@ bool Compiler<Emitter>::VisitCallExpr(const CallExpr *E) {
51945207
const auto *InstancePtr = MC->getImplicitObjectArgument();
51955208
if (isa_and_nonnull<CXXDestructorDecl>(CompilingFunction) ||
51965209
isa_and_nonnull<CXXConstructorDecl>(CompilingFunction)) {
5197-
const auto *Stripped = stripDerivedToBaseCasts(InstancePtr);
5210+
const auto *Stripped = stripCheckedDerivedToBaseCasts(InstancePtr);
51985211
if (isa<CXXThisExpr>(Stripped)) {
51995212
FuncDecl =
52005213
cast<CXXMethodDecl>(FuncDecl)->getCorrespondingMethodInClass(

clang/test/AST/ByteCode/cxx03.cpp

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,3 +29,14 @@ void LambdaAccessingADummy() {
2929
int d;
3030
int a9[1] = {[d = 0] = 1}; // both-error {{is not an integral constant expression}}
3131
}
32+
33+
const int p = 10;
34+
struct B {
35+
int a;
36+
void *p;
37+
};
38+
struct B2 : B {
39+
void *q;
40+
};
41+
_Static_assert(&(B2().a) == &p, ""); // both-error {{taking the address of a temporary object of type 'int'}} \
42+
// both-error {{not an integral constant expression}}

0 commit comments

Comments
 (0)