[clang] 886adf8 - [clang][ExprConst] Let diagnostics point to std::allocator calls (#123744)
via cfe-commits
cfe-commits at lists.llvm.org
Thu Jan 23 23:40:52 PST 2025
Author: Timm Baeder
Date: 2025-01-24T08:40:49+01:00
New Revision: 886adf8fb3ba5ec358a9a4fbe87e4da6b3ae8973
URL: https://github.com/llvm/llvm-project/commit/886adf8fb3ba5ec358a9a4fbe87e4da6b3ae8973
DIFF: https://github.com/llvm/llvm-project/commit/886adf8fb3ba5ec358a9a4fbe87e4da6b3ae8973.diff
LOG: [clang][ExprConst] Let diagnostics point to std::allocator calls (#123744)
Instead of the underlying operator new calls. This fixes a longstanding
FIXME comment in cxx2a-constexpr-dynalloc.cpp.
Added:
Modified:
clang/lib/AST/ExprConstant.cpp
clang/test/AST/ByteCode/new-delete.cpp
clang/test/SemaCXX/cxx2a-constexpr-dynalloc.cpp
Removed:
################################################################################
diff --git a/clang/lib/AST/ExprConstant.cpp b/clang/lib/AST/ExprConstant.cpp
index 734311e5d8b9aa..3b5ab839c6cf79 100644
--- a/clang/lib/AST/ExprConstant.cpp
+++ b/clang/lib/AST/ExprConstant.cpp
@@ -1136,6 +1136,7 @@ namespace {
struct StdAllocatorCaller {
unsigned FrameIndex;
QualType ElemType;
+ const Expr *Call;
explicit operator bool() const { return FrameIndex != 0; };
};
@@ -1159,7 +1160,7 @@ namespace {
if (CTSD->isInStdNamespace() && ClassII &&
ClassII->isStr("allocator") && TAL.size() >= 1 &&
TAL[0].getKind() == TemplateArgument::Type)
- return {Call->Index, TAL[0].getAsType()};
+ return {Call->Index, TAL[0].getAsType(), Call->CallExpr};
}
return {};
@@ -7113,7 +7114,7 @@ static bool HandleOperatorNewCall(EvalInfo &Info, const CallExpr *E,
QualType AllocType = Info.Ctx.getConstantArrayType(
ElemType, Size, nullptr, ArraySizeModifier::Normal, 0);
- APValue *Val = Info.createHeapAlloc(E, AllocType, Result);
+ APValue *Val = Info.createHeapAlloc(Caller.Call, AllocType, Result);
*Val = APValue(APValue::UninitArray(), 0, Size.getZExtValue());
Result.addArray(Info, E, cast<ConstantArrayType>(AllocType));
return true;
diff --git a/clang/test/AST/ByteCode/new-delete.cpp b/clang/test/AST/ByteCode/new-delete.cpp
index 8466e9b88782f2..87aa220d6f6cfe 100644
--- a/clang/test/AST/ByteCode/new-delete.cpp
+++ b/clang/test/AST/ByteCode/new-delete.cpp
@@ -602,7 +602,7 @@ namespace std {
using size_t = decltype(sizeof(0));
template<typename T> struct allocator {
constexpr T *allocate(size_t N) {
- return (T*)__builtin_operator_new(sizeof(T) * N); // both-note 2{{allocation performed here}} \
+ return (T*)__builtin_operator_new(sizeof(T) * N); // expected-note 2{{allocation performed here}} \
// #alloc
}
constexpr void deallocate(void *p) {
@@ -641,7 +641,7 @@ namespace OperatorNewDelete {
p = new int[1]; // both-note {{heap allocation performed here}}
break;
case 2:
- p = std::allocator<int>().allocate(1);
+ p = std::allocator<int>().allocate(1); // ref-note 2{{heap allocation performed here}}
break;
}
switch (dealloc_kind) {
diff --git a/clang/test/SemaCXX/cxx2a-constexpr-dynalloc.cpp b/clang/test/SemaCXX/cxx2a-constexpr-dynalloc.cpp
index 6d9c0b607d8a67..ed8cbbbfe70678 100644
--- a/clang/test/SemaCXX/cxx2a-constexpr-dynalloc.cpp
+++ b/clang/test/SemaCXX/cxx2a-constexpr-dynalloc.cpp
@@ -12,10 +12,9 @@ static_assert(alloc_from_user_code()); // expected-error {{constant expression}}
namespace std {
using size_t = decltype(sizeof(0));
- // FIXME: It would be preferable to point these notes at the location of the call to allocator<...>::[de]allocate instead
template<typename T> struct allocator {
constexpr T *allocate(size_t N) {
- return (T*)NEW(sizeof(T) * N); // expected-note 3{{heap allocation}} expected-note {{not deallocated}}
+ return (T*)NEW(sizeof(T) * N);
}
constexpr void deallocate(void *p) {
DELETE(p); // #dealloc expected-note 2{{'std::allocator<...>::deallocate' used to delete pointer to object allocated with 'new'}}
@@ -59,7 +58,7 @@ constexpr bool mismatched(int alloc_kind, int dealloc_kind) {
p = new int[1]; // expected-note {{heap allocation}}
break;
case 2:
- p = std::allocator<int>().allocate(1);
+ p = std::allocator<int>().allocate(1); // expected-note 2{{heap allocation}}
break;
}
switch (dealloc_kind) {
@@ -81,8 +80,10 @@ static_assert(mismatched(2, 0)); // expected-error {{constant expression}} expec
static_assert(mismatched(2, 1)); // expected-error {{constant expression}} expected-note {{in call}}
static_assert(mismatched(2, 2));
-constexpr int *escape = std::allocator<int>().allocate(3); // expected-error {{constant expression}} expected-note {{pointer to subobject of heap-allocated}}
-constexpr int leak = (std::allocator<int>().allocate(3), 0); // expected-error {{constant expression}}
+constexpr int *escape = std::allocator<int>().allocate(3); // expected-error {{constant expression}} expected-note {{pointer to subobject of heap-allocated}} \
+ // expected-note {{heap allocation performed here}}
+constexpr int leak = (std::allocator<int>().allocate(3), 0); // expected-error {{constant expression}} \
+ // expected-note {{not deallocated}}
constexpr int no_lifetime_start = (*std::allocator<int>().allocate(1) = 1); // expected-error {{constant expression}} expected-note {{assignment to object outside its lifetime}}
constexpr int no_deallocate_nullptr = (std::allocator<int>().deallocate(nullptr), 1); // expected-error {{constant expression}} expected-note {{in call}}
// expected-note@#dealloc {{'std::allocator<...>::deallocate' used to delete a null pointer}}
More information about the cfe-commits
mailing list