Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[Clang] Add __datasizeof #67805

Merged
merged 1 commit into from Nov 13, 2023
Merged

[Clang] Add __datasizeof #67805

merged 1 commit into from Nov 13, 2023

Conversation

philnik777
Copy link
Contributor

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.

@llvmbot llvmbot added clang Clang issues not falling into any other category clang:frontend Language frontend issues, e.g. anything involving "Sema" labels Sep 29, 2023
@llvmbot
Copy link
Collaborator

llvmbot commented Sep 29, 2023

@llvm/pr-subscribers-clang-codegen

@llvm/pr-subscribers-clang

Changes

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 --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;
+}());

Copy link
Collaborator

@shafik shafik left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks good but Aaron should look at it as well.

DiagnosticsEngine::Error,
"cannot yet mangle __builtin_omp_required_simd_align expression");
Diags.Report(DiagID);
Context.getDiags().Report(diag::err_cannot_mangle_expression)
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It looks like we have one other case we can replace as well:

unsigned DiagID = Diags.getCustomDiagID(DiagnosticsEngine::Error,

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think we should keep the more verbose form as it's more of a clear signal to the reader "this is weird and needs to be fixed". (These diagnostics are also strange in that they're not associated with a source location, which looks like a bug but isn't really one because we expect these diagnostics to go away at some point.)

clang/test/SemaCXX/datasizeof.cpp Show resolved Hide resolved
Quuxplusone added a commit to Quuxplusone/llvm-project that referenced this pull request Oct 5, 2023
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.

Patch by Nikolas Klauser!

Differential Review: llvm#67805
Copy link
Collaborator

@AaronBallman AaronBallman left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think this is a reasonable minor extension, but it should come with documentation in clang/docs/LanguageExtensions.rst and release note in clang/docs/ReleaseNotes.rst before we're done.

Comment on lines 1019 to 1021

def err_cannot_mangle_expression : Error<
"cannot yet mangle %0 expression">;
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

All of the other "cannot yet mangle" diagnostics are done with a custom diagnostic, as in

unsigned DiagID = Diags.getCustomDiagID(DiagnosticsEngine::Error,
-- I think we can drop this diagnostic and do the same (that helps make it more obvious in the code that the diagnostic is really a fixme issue rather than a diagnostic we intend to keep long-term). WDYT?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think a // FIXME would make that a lot more obvious than using the custom diagnostics engine. To me it wasn't obvious that these should be FIXMES, which is the reason I replaced them with a normal diagnostic.

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ah, so the "obvious" may be more obvious to people used to working with Clang's diagnostics and not so obvious to folks not as well-versed. Good feedback!

I'm okay with the changes but I have a preference for doing this in two steps. Step 1: your patch w/custom diagnostics engine, Step 2: replace all custom diagnostics with the regular diagnostic in one go. (This makes code archeology easier because the changes are kind of orthogonal to one another.) Would you be okay with splitting it up despite the extra work?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Sounds good!

@@ -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)
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

FEATURE is for standards features, this should be exposed under EXTENSION instead.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The problem with EXTENSION is that it's influenced by -pedantic-errors, which makes it pretty much useless for standard libraries.

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yeahhhhh, but we still need to diagnose it as an extension because that's what it is. (We should not add extensions that we do not diagnose under -pedantic -- we have been inconsistent in the past but we've gotten better in the past several years.)

Pedantic warnings aren't triggered in system headers, so I think I'm failing to see the concern: https://godbolt.org/z/nn7TdKrcv

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The problem is that -pedantic-errors makes __has_extension useless: https://godbolt.org/z/7TfMjf5h6

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Oh my. That behavior makes sense, but is really not helpful in this case.

You could use compiler version macro checks instead of __has_extension. That's pretty gross and likely easy to forget, but would it be a viable workaround?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yeah, that's what we'd have to fall back to - or just live with using the fallback when changing warning flags (!?).

Not really relevant for this patch, but I'm not sure the behaviour actually makes that much sense. There are a few things that make it somewhat weird IMO.

  1. -pedantic-errors disables __has_extension, but -Werror=pedantic doesn't. These are clearly distinct flags, but for a user they look like aliases, since they interact with warnings identically (AFAIK).
  2. If you use __has_extension you almost always want to know whether the compiler accepts some code, and if not you generate an error that you don't support the compiler or use some fallback implementation. (At least that's my interpretation)
  3. Changing diagnostic flags shouldn't influence anything other than the behaviour of the diagnostics engine. The code shouldn't compile differently, you should just get different diagnostics.

DiagnosticsEngine::Error,
"cannot yet mangle __builtin_omp_required_simd_align expression");
Diags.Report(DiagID);
Context.getDiags().Report(diag::err_cannot_mangle_expression)
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think we should keep the more verbose form as it's more of a clear signal to the reader "this is weird and needs to be fixed". (These diagnostics are also strange in that they're not associated with a source location, which looks like a bug but isn't really one because we expect these diagnostics to go away at some point.)

clang/test/SemaCXX/datasizeof.cpp Show resolved Hide resolved
@github-actions
Copy link

github-actions bot commented Oct 14, 2023

✅ With the latest revision this PR passed the C/C++ code formatter.

Copy link
Collaborator

@AaronBallman AaronBallman left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM assuming the requested codegen tests don't bring up any surprises for you.

clang/test/SemaCXX/datasizeof.cpp Show resolved Hide resolved
@philnik777
Copy link
Contributor Author

@AaronBallman This did indeed catch a bug. Also, I think there was something about how codegen tests should be written, but I don't remember exactly anymore. Could you take a look at the test?

Comment on lines 1 to 14
// RUN: %clang_cc1 -triple x86_64 -emit-llvm %s -o - | FileCheck %s

// CHECK: define dso_local noundef i32 @_Z4testi(i32 noundef %i) #0 {
// CHECK-NEXT: entry:
// CHECK-NEXT: %i.addr = alloca i32, align 4
// CHECK-NEXT: store i32 %i, ptr %i.addr, align 4
// CHECK-NEXT: %0 = load i32, ptr %i.addr, align 4
// CHECK-NEXT: %inc = add nsw i32 %0, 1
// CHECK-NEXT: store i32 %inc, ptr %i.addr, align 4
// CHECK-NEXT: %1 = zext i32 %0 to i64
// CHECK-NEXT: %2 = mul nuw i64 4, %1
// CHECK-NEXT: %3 = load i32, ptr %i.addr, align 4
// CHECK-NEXT: ret i32 %3
// CHECK-NEXT: }
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think you may need to add a more specific triple because of mangling differences between MSVC and Itanium. You should also replace the %<stuff> form to use a regex.

Actually, it might be worth generating the test comments via llvm/utils/update_cc_test_checks.py

Copy link
Collaborator

@AaronBallman AaronBallman left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM with the new codegen test, thank you!

@philnik777 philnik777 merged commit 4cc791b into llvm:main Nov 13, 2023
4 checks passed
zahiraam pushed a commit to zahiraam/llvm-project that referenced this pull request Nov 20, 2023
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.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
clang:codegen clang:frontend Language frontend issues, e.g. anything involving "Sema" clang Clang issues not falling into any other category
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

4 participants