Skip to content

Commit 70e2acf

Browse files
authored
[clang][bytecode] Check if operator delete calls are in the right frame (llvm#136141)
This is only permitted in a std::allocator::deallocate frame.
1 parent ecbd2d5 commit 70e2acf

File tree

2 files changed

+47
-0
lines changed

2 files changed

+47
-0
lines changed

clang/lib/AST/ByteCode/InterpBuiltin.cpp

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1651,6 +1651,41 @@ static bool interp__builtin_operator_delete(InterpState &S, CodePtr OpPC,
16511651
const Expr *Source = nullptr;
16521652
const Block *BlockToDelete = nullptr;
16531653

1654+
if (S.checkingPotentialConstantExpression())
1655+
return false;
1656+
1657+
// This is permitted only within a call to std::allocator<T>::deallocate.
1658+
bool DeallocateFrameFound = false;
1659+
for (const InterpFrame *F = Frame; F; F = F->Caller) {
1660+
const Function *Func = F->getFunction();
1661+
if (!Func)
1662+
continue;
1663+
const auto *MD = dyn_cast_if_present<CXXMethodDecl>(Func->getDecl());
1664+
if (!MD)
1665+
continue;
1666+
const IdentifierInfo *FnII = MD->getIdentifier();
1667+
if (!FnII || !FnII->isStr("deallocate"))
1668+
continue;
1669+
1670+
const auto *CTSD =
1671+
dyn_cast<ClassTemplateSpecializationDecl>(MD->getParent());
1672+
if (!CTSD)
1673+
continue;
1674+
1675+
const IdentifierInfo *ClassII = CTSD->getIdentifier();
1676+
const TemplateArgumentList &TAL = CTSD->getTemplateArgs();
1677+
if (CTSD->isInStdNamespace() && ClassII && ClassII->isStr("allocator") &&
1678+
TAL.size() >= 1 && TAL[0].getKind() == TemplateArgument::Type) {
1679+
DeallocateFrameFound = true;
1680+
break;
1681+
}
1682+
}
1683+
1684+
if (!DeallocateFrameFound) {
1685+
S.FFDiag(Call);
1686+
return true;
1687+
}
1688+
16541689
{
16551690
const Pointer &Ptr = S.Stk.peek<Pointer>();
16561691

clang/test/AST/ByteCode/new-delete.cpp

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -992,6 +992,18 @@ namespace ZeroSizeSub {
992992
// both-note {{in call to}}
993993
}
994994

995+
namespace WrongFrame {
996+
constexpr int foo() {
997+
int *p = nullptr;
998+
__builtin_operator_delete(p); // both-note {{subexpression not valid in a constant expression}}
999+
1000+
return 1;
1001+
}
1002+
static_assert(foo()); // both-error {{not an integral constant expression}} \
1003+
// both-note {{in call to}}
1004+
1005+
}
1006+
9951007
#else
9961008
/// Make sure we reject this prior to C++20
9971009
constexpr int a() { // both-error {{never produces a constant expression}}

0 commit comments

Comments
 (0)