llvmbot wrote:
<!--LLVM PR SUMMARY COMMENT--> @llvm/pr-subscribers-clang <details> <summary>Changes</summary> The data size is required for implementing the `memmove` optimization for `std::copy`, `std::move` etc. correctly as well as replacing `__compressed_pair` with `[[no_unique_address]]` in libc++. Since the compiler already knows the data size, we can avoid some complexity by exposing that information. --- Full diff: https://github.com/llvm/llvm-project/pull/67805.diff 8 Files Affected: - (modified) clang/include/clang/Basic/DiagnosticASTKinds.td (+3) - (modified) clang/include/clang/Basic/Features.def (+1) - (modified) clang/include/clang/Basic/TokenKinds.def (+1) - (modified) clang/lib/AST/ExprConstant.cpp (+16-4) - (modified) clang/lib/AST/ItaniumMangle.cpp (+10-9) - (modified) clang/lib/Parse/ParseExpr.cpp (+27-8) - (modified) clang/lib/Sema/SemaExpr.cpp (+3-2) - (added) clang/test/SemaCXX/datasizeof.cpp (+34) ``````````diff diff --git a/clang/include/clang/Basic/DiagnosticASTKinds.td b/clang/include/clang/Basic/DiagnosticASTKinds.td index d2656310e79c9b8..cd9d84d8e59992a 100644 --- a/clang/include/clang/Basic/DiagnosticASTKinds.td +++ b/clang/include/clang/Basic/DiagnosticASTKinds.td @@ -1016,4 +1016,7 @@ def warn_unpacked_field def warn_unaligned_access : Warning< "field %1 within %0 is less aligned than %2 and is usually due to %0 being " "packed, which can lead to unaligned accesses">, InGroup<UnalignedAccess>, DefaultIgnore; + +def err_cannot_mangle_expression : Error< + "cannot yet mangle %0 expression">; } diff --git a/clang/include/clang/Basic/Features.def b/clang/include/clang/Basic/Features.def index cbeb92fbe4fdd19..d8ca9395368cbbc 100644 --- a/clang/include/clang/Basic/Features.def +++ b/clang/include/clang/Basic/Features.def @@ -236,6 +236,7 @@ FEATURE(shadow_call_stack, FEATURE(tls, PP.getTargetInfo().isTLSSupported()) FEATURE(underlying_type, LangOpts.CPlusPlus) FEATURE(experimental_library, LangOpts.ExperimentalLibrary) +FEATURE(datasizeof, LangOpts.CPlusPlus) // C11 features supported by other languages as extensions. EXTENSION(c_alignas, true) diff --git a/clang/include/clang/Basic/TokenKinds.def b/clang/include/clang/Basic/TokenKinds.def index 72e8df8c793a7b6..0870613eb5a6cad 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 fea06b97259fe31..492e22db7826a00 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; } @@ -13548,6 +13556,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, @@ -13556,8 +13565,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 e7a5a6b6b8119c0..92c2dfead7f6c25 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" @@ -5038,19 +5039,19 @@ void CXXNameMangler::mangleExpression(const Expr *E, unsigned Arity, Out << 'a'; MangleAlignofSizeofArg(); break; + case UETT_DataSizeOf: { + Context.getDiags().Report(diag::err_cannot_mangle_expression) + << "__datasizeof"; + return; + } case UETT_VecStep: { - DiagnosticsEngine &Diags = Context.getDiags(); - unsigned DiagID = Diags.getCustomDiagID(DiagnosticsEngine::Error, - "cannot yet mangle vec_step expression"); - Diags.Report(DiagID); + Context.getDiags().Report(diag::err_cannot_mangle_expression) + << "vec_step"; return; } case UETT_OpenMPRequiredSimdAlign: { - DiagnosticsEngine &Diags = Context.getDiags(); - unsigned DiagID = Diags.getCustomDiagID( - DiagnosticsEngine::Error, - "cannot yet mangle __builtin_omp_required_simd_align expression"); - Diags.Report(DiagID); + Context.getDiags().Report(diag::err_cannot_mangle_expression) + << "__builtin_omp_required_simd_align"; return; } } diff --git a/clang/lib/Parse/ParseExpr.cpp b/clang/lib/Parse/ParseExpr.cpp index 74664c34abdbd89..8d8be8960ea2736 100644 --- a/clang/lib/Parse/ParseExpr.cpp +++ b/clang/lib/Parse/ParseExpr.cpp @@ -1451,6 +1451,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: @@ -2297,6 +2300,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 ')' @@ -2325,8 +2330,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!"); @@ -2440,14 +2445,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; @@ -2519,14 +2526,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 92496b03ecabe54..b8daee02951a520 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..5f7169bd86f0b99 --- /dev/null +++ b/clang/test/SemaCXX/datasizeof.cpp @@ -0,0 +1,34 @@ +// RUN: %clang_cc1 -fsyntax-only -triple x86_64-linux-gnu -verify %s + +// expected-no-diagnostics + +#if !__has_feature(datasizeof) +# error "Expected datasizeof feature" +#endif + +struct HasPadding { + int i; + char c; +}; + +struct HasUsablePadding { + int i; + char c; + + HasUsablePadding() {} +}; + +static_assert(__datasizeof(int) == 4); +static_assert(__datasizeof(HasPadding) == 8); +static_assert(__datasizeof(HasUsablePadding) == 5); + +static_assert([] { + int* p = nullptr; + HasPadding* p2 = nullptr; + HasUsablePadding* p3 = nullptr; + static_assert(__datasizeof(*p) == 4); + static_assert(__datasizeof(*p2) == 8); + static_assert(__datasizeof(*p3) == 5); + + return true; +}()); `````````` </details> https://github.com/llvm/llvm-project/pull/67805 _______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits