Skip to content

Commit 547d1fb

Browse files
committed
[Clang] Add __datasizeof
1 parent 658b655 commit 547d1fb

File tree

8 files changed

+95
-23
lines changed

8 files changed

+95
-23
lines changed

clang/include/clang/Basic/DiagnosticASTKinds.td

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1016,4 +1016,7 @@ def warn_unpacked_field
10161016
def warn_unaligned_access : Warning<
10171017
"field %1 within %0 is less aligned than %2 and is usually due to %0 being "
10181018
"packed, which can lead to unaligned accesses">, InGroup<UnalignedAccess>, DefaultIgnore;
1019+
1020+
def err_cannot_mangle_expression : Error<
1021+
"cannot yet mangle %0 expression">;
10191022
}

clang/include/clang/Basic/Features.def

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -236,6 +236,7 @@ FEATURE(shadow_call_stack,
236236
FEATURE(tls, PP.getTargetInfo().isTLSSupported())
237237
FEATURE(underlying_type, LangOpts.CPlusPlus)
238238
FEATURE(experimental_library, LangOpts.ExperimentalLibrary)
239+
FEATURE(datasizeof, LangOpts.CPlusPlus)
239240

240241
// C11 features supported by other languages as extensions.
241242
EXTENSION(c_alignas, true)

clang/include/clang/Basic/TokenKinds.def

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -310,6 +310,7 @@ KEYWORD(return , KEYALL)
310310
KEYWORD(short , KEYALL)
311311
KEYWORD(signed , KEYALL)
312312
UNARY_EXPR_OR_TYPE_TRAIT(sizeof, SizeOf, KEYALL)
313+
UNARY_EXPR_OR_TYPE_TRAIT(__datasizeof, DataSizeOf, KEYCXX)
313314
KEYWORD(static , KEYALL)
314315
KEYWORD(struct , KEYALL)
315316
KEYWORD(switch , KEYALL)

clang/lib/AST/ExprConstant.cpp

Lines changed: 16 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -3226,9 +3226,14 @@ static bool HandleLValueIndirectMember(EvalInfo &Info, const Expr *E,
32263226
return true;
32273227
}
32283228

3229+
enum class SizeOfType {
3230+
SizeOf,
3231+
DataSizeOf,
3232+
};
3233+
32293234
/// Get the size of the given type in char units.
3230-
static bool HandleSizeof(EvalInfo &Info, SourceLocation Loc,
3231-
QualType Type, CharUnits &Size) {
3235+
static bool HandleSizeof(EvalInfo &Info, SourceLocation Loc, QualType Type,
3236+
CharUnits &Size, SizeOfType SOT = SizeOfType::SizeOf) {
32323237
// sizeof(void), __alignof__(void), sizeof(function) = 1 as a gcc
32333238
// extension.
32343239
if (Type->isVoidType() || Type->isFunctionType()) {
@@ -3248,7 +3253,10 @@ static bool HandleSizeof(EvalInfo &Info, SourceLocation Loc,
32483253
return false;
32493254
}
32503255

3251-
Size = Info.Ctx.getTypeSizeInChars(Type);
3256+
if (SOT == SizeOfType::SizeOf)
3257+
Size = Info.Ctx.getTypeSizeInChars(Type);
3258+
else
3259+
Size = Info.Ctx.getTypeInfoDataSizeInChars(Type).Width;
32523260
return true;
32533261
}
32543262

@@ -13548,6 +13556,7 @@ bool IntExprEvaluator::VisitUnaryExprOrTypeTraitExpr(
1354813556
return Success(1, E);
1354913557
}
1355013558

13559+
case UETT_DataSizeOf:
1355113560
case UETT_SizeOf: {
1355213561
QualType SrcTy = E->getTypeOfArgument();
1355313562
// C++ [expr.sizeof]p2: "When applied to a reference or a reference type,
@@ -13556,8 +13565,11 @@ bool IntExprEvaluator::VisitUnaryExprOrTypeTraitExpr(
1355613565
SrcTy = Ref->getPointeeType();
1355713566

1355813567
CharUnits Sizeof;
13559-
if (!HandleSizeof(Info, E->getExprLoc(), SrcTy, Sizeof))
13568+
if (!HandleSizeof(Info, E->getExprLoc(), SrcTy, Sizeof,
13569+
E->getKind() == UETT_DataSizeOf ? SizeOfType::DataSizeOf
13570+
: SizeOfType::SizeOf)) {
1356013571
return false;
13572+
}
1356113573
return Success(Sizeof, E);
1356213574
}
1356313575
case UETT_OpenMPRequiredSimdAlign:

clang/lib/AST/ItaniumMangle.cpp

Lines changed: 10 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,7 @@
2828
#include "clang/AST/Mangle.h"
2929
#include "clang/AST/TypeLoc.h"
3030
#include "clang/Basic/ABI.h"
31+
#include "clang/Basic/DiagnosticAST.h"
3132
#include "clang/Basic/Module.h"
3233
#include "clang/Basic/SourceManager.h"
3334
#include "clang/Basic/TargetInfo.h"
@@ -5038,19 +5039,19 @@ void CXXNameMangler::mangleExpression(const Expr *E, unsigned Arity,
50385039
Out << 'a';
50395040
MangleAlignofSizeofArg();
50405041
break;
5042+
case UETT_DataSizeOf: {
5043+
Context.getDiags().Report(diag::err_cannot_mangle_expression)
5044+
<< "__datasizeof";
5045+
return;
5046+
}
50415047
case UETT_VecStep: {
5042-
DiagnosticsEngine &Diags = Context.getDiags();
5043-
unsigned DiagID = Diags.getCustomDiagID(DiagnosticsEngine::Error,
5044-
"cannot yet mangle vec_step expression");
5045-
Diags.Report(DiagID);
5048+
Context.getDiags().Report(diag::err_cannot_mangle_expression)
5049+
<< "vec_step";
50465050
return;
50475051
}
50485052
case UETT_OpenMPRequiredSimdAlign: {
5049-
DiagnosticsEngine &Diags = Context.getDiags();
5050-
unsigned DiagID = Diags.getCustomDiagID(
5051-
DiagnosticsEngine::Error,
5052-
"cannot yet mangle __builtin_omp_required_simd_align expression");
5053-
Diags.Report(DiagID);
5053+
Context.getDiags().Report(diag::err_cannot_mangle_expression)
5054+
<< "__builtin_omp_required_simd_align";
50545055
return;
50555056
}
50565057
}

clang/lib/Parse/ParseExpr.cpp

Lines changed: 27 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1451,6 +1451,9 @@ ExprResult Parser::ParseCastExpression(CastParseKind ParseKind,
14511451
// unary-expression: '__alignof' '(' type-name ')'
14521452
case tok::kw_sizeof: // unary-expression: 'sizeof' unary-expression
14531453
// unary-expression: 'sizeof' '(' type-name ')'
1454+
// unary-expression: '__datasizeof' unary-expression
1455+
// unary-expression: '__datasizeof' '(' type-name ')'
1456+
case tok::kw___datasizeof:
14541457
case tok::kw_vec_step: // unary-expression: OpenCL 'vec_step' expression
14551458
// unary-expression: '__builtin_omp_required_simd_align' '(' type-name ')'
14561459
case tok::kw___builtin_omp_required_simd_align:
@@ -2297,6 +2300,8 @@ Parser::ParsePostfixExpressionSuffix(ExprResult LHS) {
22972300
/// unary-expression: [C99 6.5.3]
22982301
/// 'sizeof' unary-expression
22992302
/// 'sizeof' '(' type-name ')'
2303+
/// [Clang] '__datasizeof' unary-expression
2304+
/// [Clang] '__datasizeof' '(' type-name ')'
23002305
/// [GNU] '__alignof' unary-expression
23012306
/// [GNU] '__alignof' '(' type-name ')'
23022307
/// [C11] '_Alignof' '(' type-name ')'
@@ -2325,8 +2330,8 @@ Parser::ParseExprAfterUnaryExprOrTypeTrait(const Token &OpTok,
23252330
SourceRange &CastRange) {
23262331

23272332
assert(OpTok.isOneOf(tok::kw_typeof, tok::kw_typeof_unqual, tok::kw_sizeof,
2328-
tok::kw___alignof, tok::kw_alignof, tok::kw__Alignof,
2329-
tok::kw_vec_step,
2333+
tok::kw___datasizeof, tok::kw___alignof, tok::kw_alignof,
2334+
tok::kw__Alignof, tok::kw_vec_step,
23302335
tok::kw___builtin_omp_required_simd_align) &&
23312336
"Not a typeof/sizeof/alignof/vec_step expression!");
23322337

@@ -2440,14 +2445,16 @@ ExprResult Parser::ParseSYCLUniqueStableNameExpression() {
24402445
/// 'sizeof' unary-expression
24412446
/// 'sizeof' '(' type-name ')'
24422447
/// [C++11] 'sizeof' '...' '(' identifier ')'
2448+
/// [Clang] '__datasizeof' unary-expression
2449+
/// [Clang] '__datasizeof' '(' type-name ')'
24432450
/// [GNU] '__alignof' unary-expression
24442451
/// [GNU] '__alignof' '(' type-name ')'
24452452
/// [C11] '_Alignof' '(' type-name ')'
24462453
/// [C++11] 'alignof' '(' type-id ')'
24472454
/// \endverbatim
24482455
ExprResult Parser::ParseUnaryExprOrTypeTraitExpression() {
2449-
assert(Tok.isOneOf(tok::kw_sizeof, tok::kw___alignof, tok::kw_alignof,
2450-
tok::kw__Alignof, tok::kw_vec_step,
2456+
assert(Tok.isOneOf(tok::kw_sizeof, tok::kw___datasizeof, tok::kw___alignof,
2457+
tok::kw_alignof, tok::kw__Alignof, tok::kw_vec_step,
24512458
tok::kw___builtin_omp_required_simd_align) &&
24522459
"Not a sizeof/alignof/vec_step expression!");
24532460
Token OpTok = Tok;
@@ -2519,14 +2526,26 @@ ExprResult Parser::ParseUnaryExprOrTypeTraitExpression() {
25192526
CastRange);
25202527

25212528
UnaryExprOrTypeTrait ExprKind = UETT_SizeOf;
2522-
if (OpTok.isOneOf(tok::kw_alignof, tok::kw__Alignof))
2529+
switch (OpTok.getKind()) {
2530+
case tok::kw_alignof:
2531+
case tok::kw__Alignof:
25232532
ExprKind = UETT_AlignOf;
2524-
else if (OpTok.is(tok::kw___alignof))
2533+
break;
2534+
case tok::kw___alignof:
25252535
ExprKind = UETT_PreferredAlignOf;
2526-
else if (OpTok.is(tok::kw_vec_step))
2536+
break;
2537+
case tok::kw_vec_step:
25272538
ExprKind = UETT_VecStep;
2528-
else if (OpTok.is(tok::kw___builtin_omp_required_simd_align))
2539+
break;
2540+
case tok::kw___builtin_omp_required_simd_align:
25292541
ExprKind = UETT_OpenMPRequiredSimdAlign;
2542+
break;
2543+
case tok::kw___datasizeof:
2544+
ExprKind = UETT_DataSizeOf;
2545+
break;
2546+
default:
2547+
break;
2548+
}
25302549

25312550
if (isCastExpr)
25322551
return Actions.ActOnUnaryExprOrTypeTraitExpr(OpTok.getLocation(),

clang/lib/Sema/SemaExpr.cpp

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4428,8 +4428,9 @@ bool Sema::CheckUnaryExprOrTypeTraitOperand(Expr *E,
44284428
assert(!ExprTy->isReferenceType());
44294429

44304430
bool IsUnevaluatedOperand =
4431-
(ExprKind == UETT_SizeOf || ExprKind == UETT_AlignOf ||
4432-
ExprKind == UETT_PreferredAlignOf || ExprKind == UETT_VecStep);
4431+
(ExprKind == UETT_SizeOf || ExprKind == UETT_DataSizeOf ||
4432+
ExprKind == UETT_AlignOf || ExprKind == UETT_PreferredAlignOf ||
4433+
ExprKind == UETT_VecStep);
44334434
if (IsUnevaluatedOperand) {
44344435
ExprResult Result = CheckUnevaluatedOperand(E);
44354436
if (Result.isInvalid())

clang/test/SemaCXX/datasizeof.cpp

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
// RUN: %clang_cc1 -fsyntax-only -triple x86_64-linux-gnu -verify %s
2+
3+
// expected-no-diagnostics
4+
5+
#if !__has_feature(datasizeof)
6+
# error "Expected datasizeof feature"
7+
#endif
8+
9+
struct HasPadding {
10+
int i;
11+
char c;
12+
};
13+
14+
struct HasUsablePadding {
15+
int i;
16+
char c;
17+
18+
HasUsablePadding() {}
19+
};
20+
21+
static_assert(__datasizeof(int) == 4);
22+
static_assert(__datasizeof(HasPadding) == 8);
23+
static_assert(__datasizeof(HasUsablePadding) == 5);
24+
25+
static_assert([] {
26+
int* p = nullptr;
27+
HasPadding* p2 = nullptr;
28+
HasUsablePadding* p3 = nullptr;
29+
static_assert(__datasizeof(*p) == 4);
30+
static_assert(__datasizeof(*p2) == 8);
31+
static_assert(__datasizeof(*p3) == 5);
32+
33+
return true;
34+
}());

0 commit comments

Comments
 (0)