Skip to content

Commit 193995d

Browse files
authored
[clang][bytecode] Handle more invalid member pointer casts (#152546)
1 parent b590292 commit 193995d

File tree

5 files changed

+64
-2
lines changed

5 files changed

+64
-2
lines changed

clang/lib/AST/ByteCode/Interp.cpp

Lines changed: 11 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1646,8 +1646,17 @@ bool CallVirt(InterpState &S, CodePtr OpPC, const Function *Func,
16461646

16471647
const auto *StaticDecl = cast<CXXRecordDecl>(Func->getParentDecl());
16481648
const auto *InitialFunction = cast<CXXMethodDecl>(Callee);
1649-
const CXXMethodDecl *Overrider = S.getContext().getOverridingFunction(
1650-
DynamicDecl, StaticDecl, InitialFunction);
1649+
const CXXMethodDecl *Overrider;
1650+
1651+
if (StaticDecl != DynamicDecl) {
1652+
if (!DynamicDecl->isDerivedFrom(StaticDecl))
1653+
return false;
1654+
Overrider = S.getContext().getOverridingFunction(DynamicDecl, StaticDecl,
1655+
InitialFunction);
1656+
1657+
} else {
1658+
Overrider = InitialFunction;
1659+
}
16511660

16521661
if (Overrider != InitialFunction) {
16531662
// DR1872: An instantiated virtual constexpr function can't be called in a

clang/lib/AST/ByteCode/Interp.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3201,6 +3201,9 @@ inline bool GetMemberPtr(InterpState &S, CodePtr OpPC, const ValueDecl *D) {
32013201
inline bool GetMemberPtrBase(InterpState &S, CodePtr OpPC) {
32023202
const auto &MP = S.Stk.pop<MemberPointer>();
32033203

3204+
if (!MP.isBaseCastPossible())
3205+
return false;
3206+
32043207
S.Stk.push<Pointer>(MP.getBase());
32053208
return true;
32063209
}

clang/lib/AST/ByteCode/MemberPointer.h

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -51,6 +51,12 @@ class MemberPointer final {
5151

5252
FunctionPointer toFunctionPointer(const Context &Ctx) const;
5353

54+
bool isBaseCastPossible() const {
55+
if (PtrOffset < 0)
56+
return true;
57+
return static_cast<uint64_t>(PtrOffset) <= Base.getByteOffset();
58+
}
59+
5460
Pointer getBase() const {
5561
if (PtrOffset < 0)
5662
return Base.atField(-PtrOffset);

clang/test/AST/ByteCode/cxx11.cpp

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -330,3 +330,33 @@ namespace ReadMutableInCopyCtor {
330330
// both-note {{read of mutable member 'u'}} \
331331
// both-note {{in call to 'G(g1)'}}
332332
}
333+
334+
namespace GH150709 {
335+
struct C { };
336+
struct D : C {
337+
constexpr int f() const { return 1; };
338+
};
339+
struct E : C { };
340+
struct F : D { };
341+
struct G : E { };
342+
343+
constexpr C c1, c2[2];
344+
constexpr D d1, d2[2];
345+
constexpr E e1, e2[2];
346+
constexpr F f;
347+
constexpr G g;
348+
349+
constexpr auto mp = static_cast<int (C::*)() const>(&D::f);
350+
351+
// sanity checks for fix of GH150709 (unchanged behavior)
352+
static_assert((c1.*mp)() == 1, ""); // both-error {{constant expression}}
353+
static_assert((d1.*mp)() == 1, "");
354+
static_assert((f.*mp)() == 1, "");
355+
static_assert((c2[0].*mp)() == 1, ""); // ref-error {{constant expression}}
356+
static_assert((d2[0].*mp)() == 1, "");
357+
358+
// incorrectly undiagnosed before fix of GH150709
359+
static_assert((e1.*mp)() == 1, ""); // ref-error {{constant expression}}
360+
static_assert((e2[0].*mp)() == 1, ""); // ref-error {{constant expression}}
361+
static_assert((g.*mp)() == 1, ""); // ref-error {{constant expression}}
362+
}

clang/test/AST/ByteCode/cxx2a.cpp

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -225,3 +225,17 @@ namespace Dtor {
225225
static_assert(pseudo(true, false)); // both-error {{constant expression}} both-note {{in call}}
226226
static_assert(pseudo(false, true));
227227
}
228+
229+
namespace GH150705 {
230+
struct A { };
231+
struct B : A { };
232+
struct C : A {
233+
constexpr virtual int foo() const { return 0; }
234+
};
235+
236+
constexpr auto p = &C::foo;
237+
constexpr auto q = static_cast<int (A::*)() const>(p);
238+
constexpr B b;
239+
constexpr const A& a = b;
240+
constexpr auto x = (a.*q)(); // both-error {{constant expression}}
241+
}

0 commit comments

Comments
 (0)