[clang] [Clang] Add __datasizeof (PR #67805)
via cfe-commits
cfe-commits at lists.llvm.org
Sat Oct 14 06:37:38 PDT 2023
https://github.com/philnik777 updated https://github.com/llvm/llvm-project/pull/67805
>From e6770ca7735285e1e669032a5a99b07709957803 Mon Sep 17 00:00:00 2001
From: Nikolas Klauser <nikolasklauser at berlin.de>
Date: Fri, 29 Sep 2023 15:45:56 +0200
Subject: [PATCH] [Clang] Add __datasizeof
---
clang/docs/LanguageExtensions.rst | 12 ++++++
clang/docs/ReleaseNotes.rst | 3 ++
clang/include/clang/Basic/Features.def | 1 +
clang/include/clang/Basic/TokenKinds.def | 1 +
clang/lib/AST/ExprConstant.cpp | 20 +++++++--
clang/lib/AST/ItaniumMangle.cpp | 9 ++++
clang/lib/Parse/ParseExpr.cpp | 35 ++++++++++++----
clang/lib/Sema/SemaExpr.cpp | 5 ++-
clang/test/SemaCXX/datasizeof.cpp | 53 ++++++++++++++++++++++++
9 files changed, 125 insertions(+), 14 deletions(-)
create mode 100644 clang/test/SemaCXX/datasizeof.cpp
diff --git a/clang/docs/LanguageExtensions.rst b/clang/docs/LanguageExtensions.rst
index b9466b5a0bc2087..98cb3de39284ef1 100644
--- a/clang/docs/LanguageExtensions.rst
+++ b/clang/docs/LanguageExtensions.rst
@@ -424,6 +424,18 @@ Builtin Macros
"UTF-16" or "UTF-32" (but may change in the future if the
``-fwide-exec-charset="Encoding-Name"`` option is implemented.)
+Implementation-defined keywords
+===============================
+
+__datasizeof
+------------
+
+``__datasizeof`` behaves like ``sizeof``, except that it returns the size of the
+type ignoring tail padding.
+
+..
+ FIXME: This should list all the keyword extensions
+
.. _langext-vectors:
Vectors and Extended Vectors
diff --git a/clang/docs/ReleaseNotes.rst b/clang/docs/ReleaseNotes.rst
index ea737fdb5fdad15..5421eb6c151f223 100644
--- a/clang/docs/ReleaseNotes.rst
+++ b/clang/docs/ReleaseNotes.rst
@@ -155,6 +155,9 @@ C23 Feature Support
Non-comprehensive list of changes in this release
-------------------------------------------------
+- The ``__datasizeof`` keyword has been added. It is similar to ``sizeof``
+ except that it returns the size of a type ignoring tail padding.
+
New Compiler Flags
------------------
diff --git a/clang/include/clang/Basic/Features.def b/clang/include/clang/Basic/Features.def
index cf626d0120cc7c7..4a4503ac2ec375d 100644
--- a/clang/include/clang/Basic/Features.def
+++ b/clang/include/clang/Basic/Features.def
@@ -277,6 +277,7 @@ EXTENSION(gnu_asm_goto_with_outputs_full, LangOpts.GNUAsm)
EXTENSION(matrix_types, LangOpts.MatrixTypes)
EXTENSION(matrix_types_scalar_division, true)
EXTENSION(cxx_attributes_on_using_declarations, LangOpts.CPlusPlus11)
+EXTENSION(datasizeof, LangOpts.CPlusPlus)
FEATURE(builtin_headers_in_system_modules, LangOpts.BuiltinHeadersInSystemModules)
FEATURE(cxx_abi_relative_vtable, LangOpts.CPlusPlus && LangOpts.RelativeCXXABIVTables)
diff --git a/clang/include/clang/Basic/TokenKinds.def b/clang/include/clang/Basic/TokenKinds.def
index 94db56a9fd5d78c..7b6ac3bf81b1e46 100644
--- a/clang/include/clang/Basic/TokenKinds.def
+++ b/clang/include/clang/Basic/TokenKinds.def
@@ -310,6 +310,7 @@ KEYWORD(return , KEYALL)
KEYWORD(short , KEYALL)
KEYWORD(signed , KEYALL)
UNARY_EXPR_OR_TYPE_TRAIT(sizeof, SizeOf, KEYALL)
+UNARY_EXPR_OR_TYPE_TRAIT(__datasizeof, DataSizeOf, KEYCXX)
KEYWORD(static , KEYALL)
KEYWORD(struct , KEYALL)
KEYWORD(switch , KEYALL)
diff --git a/clang/lib/AST/ExprConstant.cpp b/clang/lib/AST/ExprConstant.cpp
index 5a33e918db8e8c0..c955234ef1bdebd 100644
--- a/clang/lib/AST/ExprConstant.cpp
+++ b/clang/lib/AST/ExprConstant.cpp
@@ -3226,9 +3226,14 @@ static bool HandleLValueIndirectMember(EvalInfo &Info, const Expr *E,
return true;
}
+enum class SizeOfType {
+ SizeOf,
+ DataSizeOf,
+};
+
/// Get the size of the given type in char units.
-static bool HandleSizeof(EvalInfo &Info, SourceLocation Loc,
- QualType Type, CharUnits &Size) {
+static bool HandleSizeof(EvalInfo &Info, SourceLocation Loc, QualType Type,
+ CharUnits &Size, SizeOfType SOT = SizeOfType::SizeOf) {
// sizeof(void), __alignof__(void), sizeof(function) = 1 as a gcc
// extension.
if (Type->isVoidType() || Type->isFunctionType()) {
@@ -3248,7 +3253,10 @@ static bool HandleSizeof(EvalInfo &Info, SourceLocation Loc,
return false;
}
- Size = Info.Ctx.getTypeSizeInChars(Type);
+ if (SOT == SizeOfType::SizeOf)
+ Size = Info.Ctx.getTypeSizeInChars(Type);
+ else
+ Size = Info.Ctx.getTypeInfoDataSizeInChars(Type).Width;
return true;
}
@@ -13576,6 +13584,7 @@ bool IntExprEvaluator::VisitUnaryExprOrTypeTraitExpr(
return Success(1, E);
}
+ case UETT_DataSizeOf:
case UETT_SizeOf: {
QualType SrcTy = E->getTypeOfArgument();
// C++ [expr.sizeof]p2: "When applied to a reference or a reference type,
@@ -13584,8 +13593,11 @@ bool IntExprEvaluator::VisitUnaryExprOrTypeTraitExpr(
SrcTy = Ref->getPointeeType();
CharUnits Sizeof;
- if (!HandleSizeof(Info, E->getExprLoc(), SrcTy, Sizeof))
+ if (!HandleSizeof(Info, E->getExprLoc(), SrcTy, Sizeof,
+ E->getKind() == UETT_DataSizeOf ? SizeOfType::DataSizeOf
+ : SizeOfType::SizeOf)) {
return false;
+ }
return Success(Sizeof, E);
}
case UETT_OpenMPRequiredSimdAlign:
diff --git a/clang/lib/AST/ItaniumMangle.cpp b/clang/lib/AST/ItaniumMangle.cpp
index 23ec35cae4b7b40..1136bf6280c1d1d 100644
--- a/clang/lib/AST/ItaniumMangle.cpp
+++ b/clang/lib/AST/ItaniumMangle.cpp
@@ -28,6 +28,7 @@
#include "clang/AST/Mangle.h"
#include "clang/AST/TypeLoc.h"
#include "clang/Basic/ABI.h"
+#include "clang/Basic/DiagnosticAST.h"
#include "clang/Basic/Module.h"
#include "clang/Basic/SourceManager.h"
#include "clang/Basic/TargetInfo.h"
@@ -5111,6 +5112,14 @@ void CXXNameMangler::mangleExpression(const Expr *E, unsigned Arity,
Out << 'a';
MangleAlignofSizeofArg();
break;
+ case UETT_DataSizeOf: {
+ DiagnosticsEngine &Diags = Context.getDiags();
+ unsigned DiagID =
+ Diags.getCustomDiagID(DiagnosticsEngine::Error,
+ "cannot yet mangle __datasizeof expression");
+ Diags.Report(DiagID);
+ return;
+ }
case UETT_VecStep: {
DiagnosticsEngine &Diags = Context.getDiags();
unsigned DiagID = Diags.getCustomDiagID(DiagnosticsEngine::Error,
diff --git a/clang/lib/Parse/ParseExpr.cpp b/clang/lib/Parse/ParseExpr.cpp
index 9dbfc1c8c5e9ffe..2c08a765538b094 100644
--- a/clang/lib/Parse/ParseExpr.cpp
+++ b/clang/lib/Parse/ParseExpr.cpp
@@ -1460,6 +1460,9 @@ ExprResult Parser::ParseCastExpression(CastParseKind ParseKind,
// unary-expression: '__alignof' '(' type-name ')'
case tok::kw_sizeof: // unary-expression: 'sizeof' unary-expression
// unary-expression: 'sizeof' '(' type-name ')'
+ // unary-expression: '__datasizeof' unary-expression
+ // unary-expression: '__datasizeof' '(' type-name ')'
+ case tok::kw___datasizeof:
case tok::kw_vec_step: // unary-expression: OpenCL 'vec_step' expression
// unary-expression: '__builtin_omp_required_simd_align' '(' type-name ')'
case tok::kw___builtin_omp_required_simd_align:
@@ -2309,6 +2312,8 @@ Parser::ParsePostfixExpressionSuffix(ExprResult LHS) {
/// unary-expression: [C99 6.5.3]
/// 'sizeof' unary-expression
/// 'sizeof' '(' type-name ')'
+/// [Clang] '__datasizeof' unary-expression
+/// [Clang] '__datasizeof' '(' type-name ')'
/// [GNU] '__alignof' unary-expression
/// [GNU] '__alignof' '(' type-name ')'
/// [C11] '_Alignof' '(' type-name ')'
@@ -2337,8 +2342,8 @@ Parser::ParseExprAfterUnaryExprOrTypeTrait(const Token &OpTok,
SourceRange &CastRange) {
assert(OpTok.isOneOf(tok::kw_typeof, tok::kw_typeof_unqual, tok::kw_sizeof,
- tok::kw___alignof, tok::kw_alignof, tok::kw__Alignof,
- tok::kw_vec_step,
+ tok::kw___datasizeof, tok::kw___alignof, tok::kw_alignof,
+ tok::kw__Alignof, tok::kw_vec_step,
tok::kw___builtin_omp_required_simd_align) &&
"Not a typeof/sizeof/alignof/vec_step expression!");
@@ -2452,14 +2457,16 @@ ExprResult Parser::ParseSYCLUniqueStableNameExpression() {
/// 'sizeof' unary-expression
/// 'sizeof' '(' type-name ')'
/// [C++11] 'sizeof' '...' '(' identifier ')'
+/// [Clang] '__datasizeof' unary-expression
+/// [Clang] '__datasizeof' '(' type-name ')'
/// [GNU] '__alignof' unary-expression
/// [GNU] '__alignof' '(' type-name ')'
/// [C11] '_Alignof' '(' type-name ')'
/// [C++11] 'alignof' '(' type-id ')'
/// \endverbatim
ExprResult Parser::ParseUnaryExprOrTypeTraitExpression() {
- assert(Tok.isOneOf(tok::kw_sizeof, tok::kw___alignof, tok::kw_alignof,
- tok::kw__Alignof, tok::kw_vec_step,
+ assert(Tok.isOneOf(tok::kw_sizeof, tok::kw___datasizeof, tok::kw___alignof,
+ tok::kw_alignof, tok::kw__Alignof, tok::kw_vec_step,
tok::kw___builtin_omp_required_simd_align) &&
"Not a sizeof/alignof/vec_step expression!");
Token OpTok = Tok;
@@ -2531,14 +2538,26 @@ ExprResult Parser::ParseUnaryExprOrTypeTraitExpression() {
CastRange);
UnaryExprOrTypeTrait ExprKind = UETT_SizeOf;
- if (OpTok.isOneOf(tok::kw_alignof, tok::kw__Alignof))
+ switch (OpTok.getKind()) {
+ case tok::kw_alignof:
+ case tok::kw__Alignof:
ExprKind = UETT_AlignOf;
- else if (OpTok.is(tok::kw___alignof))
+ break;
+ case tok::kw___alignof:
ExprKind = UETT_PreferredAlignOf;
- else if (OpTok.is(tok::kw_vec_step))
+ break;
+ case tok::kw_vec_step:
ExprKind = UETT_VecStep;
- else if (OpTok.is(tok::kw___builtin_omp_required_simd_align))
+ break;
+ case tok::kw___builtin_omp_required_simd_align:
ExprKind = UETT_OpenMPRequiredSimdAlign;
+ break;
+ case tok::kw___datasizeof:
+ ExprKind = UETT_DataSizeOf;
+ break;
+ default:
+ break;
+ }
if (isCastExpr)
return Actions.ActOnUnaryExprOrTypeTraitExpr(OpTok.getLocation(),
diff --git a/clang/lib/Sema/SemaExpr.cpp b/clang/lib/Sema/SemaExpr.cpp
index 9c5f96eebd04165..0d3e8d63072eb58 100644
--- a/clang/lib/Sema/SemaExpr.cpp
+++ b/clang/lib/Sema/SemaExpr.cpp
@@ -4428,8 +4428,9 @@ bool Sema::CheckUnaryExprOrTypeTraitOperand(Expr *E,
assert(!ExprTy->isReferenceType());
bool IsUnevaluatedOperand =
- (ExprKind == UETT_SizeOf || ExprKind == UETT_AlignOf ||
- ExprKind == UETT_PreferredAlignOf || ExprKind == UETT_VecStep);
+ (ExprKind == UETT_SizeOf || ExprKind == UETT_DataSizeOf ||
+ ExprKind == UETT_AlignOf || ExprKind == UETT_PreferredAlignOf ||
+ ExprKind == UETT_VecStep);
if (IsUnevaluatedOperand) {
ExprResult Result = CheckUnevaluatedOperand(E);
if (Result.isInvalid())
diff --git a/clang/test/SemaCXX/datasizeof.cpp b/clang/test/SemaCXX/datasizeof.cpp
new file mode 100644
index 000000000000000..f96660d2028d078
--- /dev/null
+++ b/clang/test/SemaCXX/datasizeof.cpp
@@ -0,0 +1,53 @@
+// RUN: %clang_cc1 -fsyntax-only -triple x86_64-linux-gnu -verify %s
+
+#if !__has_extension(datasizeof)
+# error "Expected datasizeof extension"
+#endif
+
+struct HasPadding {
+ int i;
+ char c;
+};
+
+struct HasUsablePadding {
+ int i;
+ char c;
+
+ HasUsablePadding() {}
+};
+
+struct Incomplete; // expected-note {{forward declaration of 'Incomplete'}}
+
+static_assert(__datasizeof(int) == 4);
+static_assert(__datasizeof(HasPadding) == 8);
+static_assert(__datasizeof(HasUsablePadding) == 5);
+static_assert(__datasizeof(void)); // expected-error {{invalid application of '__datasizeof' to an incomplete type 'void'}}
+static_assert(__datasizeof(Incomplete)); // expected-error {{invalid application of '__datasizeof' to an incomplete type 'Incomplete'}}
+
+static_assert([] {
+ int* p = nullptr;
+ HasPadding* p2 = nullptr;
+ HasUsablePadding* p3 = nullptr;
+ static_assert(__datasizeof(*p) == 4);
+ static_assert(__datasizeof *p == 4);
+ static_assert(__datasizeof(*p2) == 8);
+ static_assert(__datasizeof(*p3) == 5);
+
+ return true;
+}());
+
+template <typename Ty>
+constexpr int data_size_of() {
+ return __datasizeof(Ty);
+}
+static_assert(data_size_of<int>() == __datasizeof(int));
+static_assert(data_size_of<HasPadding>() == __datasizeof(HasPadding));
+static_assert(data_size_of<HasUsablePadding>() == __datasizeof(HasUsablePadding));
+
+struct S {
+ int i = __datasizeof(S);
+ float f;
+ char c;
+};
+
+static_assert(S{}.i == 9);
More information about the cfe-commits
mailing list