Skip to content

Commit 09bb215

Browse files
committed
[clang][bytecode] Use std::allocator calls for Descriptor source
... for the dynamic blocks created for operator new calls. This way we get the type of memory allocated right. As a side-effect, the diagnostics now point to the std::allocator calls, which is an improvement.
1 parent 990837f commit 09bb215

File tree

3 files changed

+39
-7
lines changed

3 files changed

+39
-7
lines changed

clang/lib/AST/ByteCode/Interp.cpp

Lines changed: 9 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -873,13 +873,17 @@ bool CheckNewDeleteForms(InterpState &S, CodePtr OpPC,
873873

874874
bool CheckDeleteSource(InterpState &S, CodePtr OpPC, const Expr *Source,
875875
const Pointer &Ptr) {
876-
// The two sources we currently allow are new expressions and
877-
// __builtin_operator_new calls.
876+
// Regular new type(...) call.
878877
if (isa_and_nonnull<CXXNewExpr>(Source))
879878
return true;
880-
if (const CallExpr *CE = dyn_cast_if_present<CallExpr>(Source);
879+
// operator new.
880+
if (const auto *CE = dyn_cast_if_present<CallExpr>(Source);
881881
CE && CE->getBuiltinCallee() == Builtin::BI__builtin_operator_new)
882882
return true;
883+
// std::allocator.allocate() call
884+
if (const auto *MCE = dyn_cast_if_present<CXXMemberCallExpr>(Source);
885+
MCE && MCE->getMethodDecl()->getIdentifier()->isStr("allocate"))
886+
return true;
883887

884888
// Whatever this is, we didn't heap allocate it.
885889
const SourceInfo &Loc = S.Current->getSource(OpPC);
@@ -1489,7 +1493,8 @@ bool CheckNewTypeMismatch(InterpState &S, CodePtr OpPC, const Expr *E,
14891493
const auto *NewExpr = cast<CXXNewExpr>(E);
14901494
QualType StorageType = Ptr.getType();
14911495

1492-
if (isa_and_nonnull<CXXNewExpr>(Ptr.getFieldDesc()->asExpr()) &&
1496+
if ((isa_and_nonnull<CXXNewExpr>(Ptr.getFieldDesc()->asExpr()) ||
1497+
isa_and_nonnull<CXXMemberCallExpr>(Ptr.getFieldDesc()->asExpr())) &&
14931498
StorageType->isPointerType()) {
14941499
// FIXME: Are there other cases where this is a problem?
14951500
StorageType = StorageType->getPointeeType();

clang/lib/AST/ByteCode/InterpBuiltin.cpp

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1584,6 +1584,7 @@ static bool interp__builtin_operator_new(InterpState &S, CodePtr OpPC,
15841584
// Walk up the call stack to find the appropriate caller and get the
15851585
// element type from it.
15861586
QualType ElemType;
1587+
const CallExpr *NewCall = nullptr;
15871588

15881589
for (const InterpFrame *F = Frame; F; F = F->Caller) {
15891590
const Function *Func = F->getFunction();
@@ -1606,6 +1607,7 @@ static bool interp__builtin_operator_new(InterpState &S, CodePtr OpPC,
16061607
if (CTSD->isInStdNamespace() && ClassII && ClassII->isStr("allocator") &&
16071608
TAL.size() >= 1 && TAL[0].getKind() == TemplateArgument::Type) {
16081609
ElemType = TAL[0].getAsType();
1610+
NewCall = cast<CallExpr>(F->Caller->getExpr(F->getRetPC()));
16091611
break;
16101612
}
16111613
}
@@ -1616,6 +1618,7 @@ static bool interp__builtin_operator_new(InterpState &S, CodePtr OpPC,
16161618
: diag::note_constexpr_new);
16171619
return false;
16181620
}
1621+
assert(NewCall);
16191622

16201623
if (ElemType->isIncompleteType() || ElemType->isFunctionType()) {
16211624
S.FFDiag(Call, diag::note_constexpr_new_not_complete_object_type)
@@ -1654,7 +1657,7 @@ static bool interp__builtin_operator_new(InterpState &S, CodePtr OpPC,
16541657
if (ElemT) {
16551658
if (NumElems.ule(1)) {
16561659
const Descriptor *Desc =
1657-
S.P.createDescriptor(Call, *ElemT, Descriptor::InlineDescMD,
1660+
S.P.createDescriptor(NewCall, *ElemT, Descriptor::InlineDescMD,
16581661
/*IsConst=*/false, /*IsTemporary=*/false,
16591662
/*IsMutable=*/false);
16601663
Block *B = Allocator.allocate(Desc, S.getContext().getEvalID(),
@@ -1667,7 +1670,7 @@ static bool interp__builtin_operator_new(InterpState &S, CodePtr OpPC,
16671670
assert(NumElems.ugt(1));
16681671

16691672
Block *B =
1670-
Allocator.allocate(Call, *ElemT, NumElems.getZExtValue(),
1673+
Allocator.allocate(NewCall, *ElemT, NumElems.getZExtValue(),
16711674
S.Ctx.getEvalID(), DynamicAllocator::Form::Operator);
16721675
assert(B);
16731676
S.Stk.push<Pointer>(B);

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

Lines changed: 25 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -602,7 +602,11 @@ namespace std {
602602
using size_t = decltype(sizeof(0));
603603
template<typename T> struct allocator {
604604
constexpr T *allocate(size_t N) {
605+
<<<<<<< HEAD
605606
return (T*)__builtin_operator_new(sizeof(T) * N); // expected-note 2{{allocation performed here}} \
607+
=======
608+
return (T*)__builtin_operator_new(sizeof(T) * N); // ref-note 2{{allocation performed here}} \
609+
>>>>>>> 6ca82f93ccaf ([clang][bytecode] Use std::allocator calls for Descriptor source)
606610
// #alloc
607611
}
608612
constexpr void deallocate(void *p) {
@@ -641,7 +645,7 @@ namespace OperatorNewDelete {
641645
p = new int[1]; // both-note {{heap allocation performed here}}
642646
break;
643647
case 2:
644-
p = std::allocator<int>().allocate(1); // ref-note 2{{heap allocation performed here}}
648+
p = std::allocator<int>().allocate(1); // both-note 2{{heap allocation performed here}}
645649
break;
646650
}
647651
switch (dealloc_kind) {
@@ -838,6 +842,26 @@ namespace ToplevelScopeInTemplateArg {
838842
}
839843
}
840844

845+
template <typename T>
846+
struct SS {
847+
constexpr SS(unsigned long long N)
848+
: data(nullptr){
849+
data = alloc.allocate(N); // #call
850+
for(std::size_t i = 0; i < N; i ++)
851+
std::construct_at<T>(data + i, i); // #construct_call
852+
}
853+
constexpr T operator[](std::size_t i) const {
854+
return data[i];
855+
}
856+
857+
constexpr ~SS() {
858+
alloc.deallocate(data);
859+
}
860+
std::allocator<T> alloc;
861+
T* data;
862+
};
863+
constexpr unsigned short ssmall = SS<unsigned short>(100)[42];
864+
841865
#else
842866
/// Make sure we reject this prior to C++20
843867
constexpr int a() { // both-error {{never produces a constant expression}}

0 commit comments

Comments
 (0)