r345419 - PR26547: alignof should return ABI alignment, not preferred alignment

Richard Smith via cfe-commits cfe-commits at lists.llvm.org
Fri Oct 26 12:26:45 PDT 2018


Author: rsmith
Date: Fri Oct 26 12:26:45 2018
New Revision: 345419

URL: http://llvm.org/viewvc/llvm-project?rev=345419&view=rev
Log:
PR26547: alignof should return ABI alignment, not preferred alignment

Summary:
- Add `UETT_PreferredAlignOf` to account for the difference between `__alignof` and `alignof`
- `AlignOfType` now returns ABI alignment instead of preferred alignment iff clang-abi-compat > 7, and one uses _Alignof or alignof

Patch by Nicole Mazzuca!

Differential Revision: https://reviews.llvm.org/D53207

Added:
    cfe/trunk/test/Sema/align-x86-abi7.c
    cfe/trunk/test/SemaCXX/align-x86-abi7.cpp
    cfe/trunk/test/SemaCXX/align-x86.cpp
Modified:
    cfe/trunk/docs/ReleaseNotes.rst
    cfe/trunk/include/clang/AST/Stmt.h
    cfe/trunk/include/clang/ASTMatchers/ASTMatchers.h
    cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td
    cfe/trunk/include/clang/Basic/LangOptions.h
    cfe/trunk/include/clang/Basic/TypeTraits.h
    cfe/trunk/lib/AST/ASTDumper.cpp
    cfe/trunk/lib/AST/Expr.cpp
    cfe/trunk/lib/AST/ExprConstant.cpp
    cfe/trunk/lib/AST/ItaniumMangle.cpp
    cfe/trunk/lib/AST/StmtPrinter.cpp
    cfe/trunk/lib/Frontend/CompilerInvocation.cpp
    cfe/trunk/lib/Parse/ParseExpr.cpp
    cfe/trunk/lib/Sema/SemaChecking.cpp
    cfe/trunk/lib/Sema/SemaExpr.cpp
    cfe/trunk/test/Headers/thumbv7-apple-ios-types.cpp
    cfe/trunk/test/Sema/align-x86.c
    cfe/trunk/test/SemaCXX/alignof.cpp

Modified: cfe/trunk/docs/ReleaseNotes.rst
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/docs/ReleaseNotes.rst?rev=345419&r1=345418&r2=345419&view=diff
==============================================================================
--- cfe/trunk/docs/ReleaseNotes.rst (original)
+++ cfe/trunk/docs/ReleaseNotes.rst Fri Oct 26 12:26:45 2018
@@ -77,6 +77,11 @@ future versions of Clang.
 Modified Compiler Flags
 -----------------------
 
+- As of clang 8, `alignof` and `_Alignof` return the ABI alignment of a type,
+  as opposed to the preferred alignment. `__alignof` still returns the
+  preferred alignment. `-fclang-abi-compat=7` (and previous) will make
+  `alignof` and `_Alignof` return preferred alignment again.
+
 
 New Pragmas in Clang
 --------------------
@@ -132,6 +137,21 @@ OpenCL C Language Changes in Clang
 
 ...
 
+ABI Changes in Clang
+--------------------
+
+- `_Alignof` and `alignof` now return the ABI alignment of a type, as opposed
+  to the preferred alignment.
+  - This is more in keeping with the language of the standards, as well as
+    being compatible with gcc
+  - `__alignof` and `__alignof__` still return the preferred alignment of
+    a type
+  - This shouldn't break any ABI except for things that explicitly ask for
+    `alignas(alignof(T))`.
+  - If you have interfaces that break with this change, you may wish to switch
+    to `alignas(__alignof(T))`, instead of using the `-fclang-abi-compat`
+    switch.
+
 OpenMP Support in Clang
 ----------------------------------
 

Modified: cfe/trunk/include/clang/AST/Stmt.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/AST/Stmt.h?rev=345419&r1=345418&r2=345419&view=diff
==============================================================================
--- cfe/trunk/include/clang/AST/Stmt.h (original)
+++ cfe/trunk/include/clang/AST/Stmt.h Fri Oct 26 12:26:45 2018
@@ -179,7 +179,7 @@ protected:
 
     unsigned : NumExprBits;
 
-    unsigned Kind : 2;
+    unsigned Kind : 3;
     unsigned IsType : 1; // true if operand is a type, false if an expression.
   };
 

Modified: cfe/trunk/include/clang/ASTMatchers/ASTMatchers.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/ASTMatchers/ASTMatchers.h?rev=345419&r1=345418&r2=345419&view=diff
==============================================================================
--- cfe/trunk/include/clang/ASTMatchers/ASTMatchers.h (original)
+++ cfe/trunk/include/clang/ASTMatchers/ASTMatchers.h Fri Oct 26 12:26:45 2018
@@ -2425,8 +2425,9 @@ AST_MATCHER_P(UnaryExprOrTypeTraitExpr,
 /// alignof.
 inline internal::Matcher<Stmt> alignOfExpr(
     const internal::Matcher<UnaryExprOrTypeTraitExpr> &InnerMatcher) {
-  return stmt(unaryExprOrTypeTraitExpr(allOf(
-      ofKind(UETT_AlignOf), InnerMatcher)));
+  return stmt(unaryExprOrTypeTraitExpr(
+      allOf(anyOf(ofKind(UETT_AlignOf), ofKind(UETT_PreferredAlignOf)),
+            InnerMatcher)));
 }
 
 /// Same as unaryExprOrTypeTraitExpr, but only matching

Modified: cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td?rev=345419&r1=345418&r2=345419&view=diff
==============================================================================
--- cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td (original)
+++ cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td Fri Oct 26 12:26:45 2018
@@ -5474,20 +5474,24 @@ def err_atomic_specifier_bad_type : Erro
   "%1 %select{||||||which is not trivially copyable}0">;
 
 // Expressions.
+def select_unary_expr_or_type_trait_kind : TextSubstitution<
+  "%select{sizeof|alignof|vec_step|__builtin_omp_required_simd_align|"
+  "__alignof}0">
 def ext_sizeof_alignof_function_type : Extension<
-  "invalid application of '%select{sizeof|alignof|vec_step}0' to a "
-  "function type">, InGroup<PointerArith>;
+  "invalid application of '%sub{select_unary_expr_or_type_trait_kind}0' "
+  "to a function type">, InGroup<PointerArith>;
 def ext_sizeof_alignof_void_type : Extension<
-  "invalid application of '%select{sizeof|alignof|vec_step}0' to a void "
-  "type">, InGroup<PointerArith>;
+  "invalid application of '%sub{select_unary_expr_or_type_trait_kind}0' "
+  "to a void type">, InGroup<PointerArith>;
 def err_opencl_sizeof_alignof_type : Error<
-  "invalid application of '%select{sizeof|alignof|vec_step|__builtin_omp_required_simd_align}0' to a void type">;
+  "invalid application of '%sub{select_unary_expr_or_type_trait_kind}0' "
+  "to a void type">;
 def err_sizeof_alignof_incomplete_type : Error<
-  "invalid application of '%select{sizeof|alignof|vec_step|__builtin_omp_required_simd_align}0' to an "
-  "incomplete type %1">;
+  "invalid application of '%sub{select_unary_expr_or_type_trait_kind}0' "
+  "to an incomplete type %1">;
 def err_sizeof_alignof_function_type : Error<
-  "invalid application of '%select{sizeof|alignof|vec_step|__builtin_omp_required_simd_align}0' to a "
-  "function type">;
+  "invalid application of '%sub{select_unary_expr_or_type_trait_kind}0' "
+  "to a function type">;
 def err_openmp_default_simd_align_expr : Error<
   "invalid application of '__builtin_omp_required_simd_align' to an expression, only type is allowed">;
 def err_sizeof_alignof_typeof_bitfield : Error<

Modified: cfe/trunk/include/clang/Basic/LangOptions.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Basic/LangOptions.h?rev=345419&r1=345418&r2=345419&view=diff
==============================================================================
--- cfe/trunk/include/clang/Basic/LangOptions.h (original)
+++ cfe/trunk/include/clang/Basic/LangOptions.h Fri Oct 26 12:26:45 2018
@@ -124,6 +124,12 @@ public:
     /// whether we reuse base class tail padding in some ABIs.
     Ver6,
 
+    /// Attempt to be ABI-compatible with code generated by Clang 7.0.x
+    /// (SVN r338536). This causes alignof (C++) and _Alignof (C11) to be
+    /// compatible with __alignof (i.e., return the preferred alignment)
+    /// rather than returning the required alignment.
+    Ver7,
+
     /// Conform to the underlying platform's C and C++ ABIs as closely
     /// as we can.
     Latest

Modified: cfe/trunk/include/clang/Basic/TypeTraits.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Basic/TypeTraits.h?rev=345419&r1=345418&r2=345419&view=diff
==============================================================================
--- cfe/trunk/include/clang/Basic/TypeTraits.h (original)
+++ cfe/trunk/include/clang/Basic/TypeTraits.h Fri Oct 26 12:26:45 2018
@@ -96,9 +96,15 @@ namespace clang {
   /// Names for the "expression or type" traits.
   enum UnaryExprOrTypeTrait {
     UETT_SizeOf,
+    /// Used for C's _Alignof and C++'s alignof.
+    /// _Alignof and alignof return the required ABI alignment.
     UETT_AlignOf,
     UETT_VecStep,
     UETT_OpenMPRequiredSimdAlign,
+    /// Used for GCC's __alignof.
+    /// __alignof returns the preferred alignment of a type, the alignment
+    /// clang will attempt to give an object of the type if allowed by ABI.
+    UETT_PreferredAlignOf,
   };
 }
 

Modified: cfe/trunk/lib/AST/ASTDumper.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/AST/ASTDumper.cpp?rev=345419&r1=345418&r2=345419&view=diff
==============================================================================
--- cfe/trunk/lib/AST/ASTDumper.cpp (original)
+++ cfe/trunk/lib/AST/ASTDumper.cpp Fri Oct 26 12:26:45 2018
@@ -2281,6 +2281,9 @@ void ASTDumper::VisitUnaryExprOrTypeTrai
   case UETT_OpenMPRequiredSimdAlign:
     OS << " __builtin_omp_required_simd_align";
     break;
+  case UETT_PreferredAlignOf:
+    OS << " __alignof";
+    break;
   }
   if (Node->isArgumentType())
     dumpType(Node->getArgumentType());

Modified: cfe/trunk/lib/AST/Expr.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/AST/Expr.cpp?rev=345419&r1=345418&r2=345419&view=diff
==============================================================================
--- cfe/trunk/lib/AST/Expr.cpp (original)
+++ cfe/trunk/lib/AST/Expr.cpp Fri Oct 26 12:26:45 2018
@@ -1446,7 +1446,7 @@ UnaryExprOrTypeTraitExpr::UnaryExprOrTyp
 
   // Check to see if we are in the situation where alignof(decl) should be
   // dependent because decl's alignment is dependent.
-  if (ExprKind == UETT_AlignOf) {
+  if (ExprKind == UETT_AlignOf || ExprKind == UETT_PreferredAlignOf) {
     if (!isValueDependent() || !isInstantiationDependent()) {
       E = E->IgnoreParens();
 

Modified: cfe/trunk/lib/AST/ExprConstant.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/AST/ExprConstant.cpp?rev=345419&r1=345418&r2=345419&view=diff
==============================================================================
--- cfe/trunk/lib/AST/ExprConstant.cpp (original)
+++ cfe/trunk/lib/AST/ExprConstant.cpp Fri Oct 26 12:26:45 2018
@@ -5946,21 +5946,35 @@ bool PointerExprEvaluator::VisitCastExpr
   return ExprEvaluatorBaseTy::VisitCastExpr(E);
 }
 
-static CharUnits GetAlignOfType(EvalInfo &Info, QualType T) {
+static CharUnits GetAlignOfType(EvalInfo &Info, QualType T,
+                                UnaryExprOrTypeTrait ExprKind) {
   // C++ [expr.alignof]p3:
   //     When alignof is applied to a reference type, the result is the
   //     alignment of the referenced type.
   if (const ReferenceType *Ref = T->getAs<ReferenceType>())
     T = Ref->getPointeeType();
 
-  // __alignof is defined to return the preferred alignment.
   if (T.getQualifiers().hasUnaligned())
     return CharUnits::One();
-  return Info.Ctx.toCharUnitsFromBits(
-    Info.Ctx.getPreferredTypeAlign(T.getTypePtr()));
+
+  const bool AlignOfReturnsPreferred =
+      Info.Ctx.getLangOpts().getClangABICompat() <= LangOptions::ClangABI::Ver7;
+
+  // __alignof is defined to return the preferred alignment.
+  // Before 8, clang returned the preferred alignment for alignof and _Alignof
+  // as well.
+  if (ExprKind == UETT_PreferredAlignOf || AlignOfReturnsPreferred)
+    return Info.Ctx.toCharUnitsFromBits(
+      Info.Ctx.getPreferredTypeAlign(T.getTypePtr()));
+  // alignof and _Alignof are defined to return the ABI alignment.
+  else if (ExprKind == UETT_AlignOf)
+    return Info.Ctx.getTypeAlignInChars(T.getTypePtr());
+  else
+    llvm_unreachable("GetAlignOfType on a non-alignment ExprKind");
 }
 
-static CharUnits GetAlignOfExpr(EvalInfo &Info, const Expr *E) {
+static CharUnits GetAlignOfExpr(EvalInfo &Info, const Expr *E,
+                                UnaryExprOrTypeTrait ExprKind) {
   E = E->IgnoreParens();
 
   // The kinds of expressions that we have special-case logic here for
@@ -5977,7 +5991,7 @@ static CharUnits GetAlignOfExpr(EvalInfo
     return Info.Ctx.getDeclAlign(ME->getMemberDecl(),
                                  /*RefAsPointee*/true);
 
-  return GetAlignOfType(Info, E->getType());
+  return GetAlignOfType(Info, E->getType(), ExprKind);
 }
 
 // To be clear: this happily visits unsupported builtins. Better name welcomed.
@@ -6038,8 +6052,8 @@ bool PointerExprEvaluator::VisitBuiltinC
           OffsetResult.Base.dyn_cast<const ValueDecl*>()) {
         BaseAlignment = Info.Ctx.getDeclAlign(VD);
       } else {
-        BaseAlignment =
-          GetAlignOfExpr(Info, OffsetResult.Base.get<const Expr*>());
+        BaseAlignment = GetAlignOfExpr(
+            Info, OffsetResult.Base.get<const Expr *>(), UETT_AlignOf);
       }
 
       if (BaseAlignment < Align) {
@@ -9358,11 +9372,14 @@ bool IntExprEvaluator::VisitBinaryOperat
 bool IntExprEvaluator::VisitUnaryExprOrTypeTraitExpr(
                                     const UnaryExprOrTypeTraitExpr *E) {
   switch(E->getKind()) {
+  case UETT_PreferredAlignOf:
   case UETT_AlignOf: {
     if (E->isArgumentType())
-      return Success(GetAlignOfType(Info, E->getArgumentType()), E);
+      return Success(GetAlignOfType(Info, E->getArgumentType(), E->getKind()),
+                     E);
     else
-      return Success(GetAlignOfExpr(Info, E->getArgumentExpr()), E);
+      return Success(GetAlignOfExpr(Info, E->getArgumentExpr(), E->getKind()),
+                     E);
   }
 
   case UETT_VecStep: {

Modified: cfe/trunk/lib/AST/ItaniumMangle.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/AST/ItaniumMangle.cpp?rev=345419&r1=345418&r2=345419&view=diff
==============================================================================
--- cfe/trunk/lib/AST/ItaniumMangle.cpp (original)
+++ cfe/trunk/lib/AST/ItaniumMangle.cpp Fri Oct 26 12:26:45 2018
@@ -3864,6 +3864,7 @@ recurse:
     case UETT_SizeOf:
       Out << 's';
       break;
+    case UETT_PreferredAlignOf:
     case UETT_AlignOf:
       Out << 'a';
       break;

Modified: cfe/trunk/lib/AST/StmtPrinter.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/AST/StmtPrinter.cpp?rev=345419&r1=345418&r2=345419&view=diff
==============================================================================
--- cfe/trunk/lib/AST/StmtPrinter.cpp (original)
+++ cfe/trunk/lib/AST/StmtPrinter.cpp Fri Oct 26 12:26:45 2018
@@ -1235,6 +1235,9 @@ void StmtPrinter::VisitUnaryExprOrTypeTr
     else
       OS << "__alignof";
     break;
+  case UETT_PreferredAlignOf:
+    OS << "__alignof";
+    break;
   case UETT_VecStep:
     OS << "vec_step";
     break;

Modified: cfe/trunk/lib/Frontend/CompilerInvocation.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Frontend/CompilerInvocation.cpp?rev=345419&r1=345418&r2=345419&view=diff
==============================================================================
--- cfe/trunk/lib/Frontend/CompilerInvocation.cpp (original)
+++ cfe/trunk/lib/Frontend/CompilerInvocation.cpp Fri Oct 26 12:26:45 2018
@@ -2842,6 +2842,8 @@ static void ParseLangArgs(LangOptions &O
         Opts.setClangABICompat(LangOptions::ClangABI::Ver4);
       else if (Major <= 6)
         Opts.setClangABICompat(LangOptions::ClangABI::Ver6);
+      else if (Major <= 7)
+        Opts.setClangABICompat(LangOptions::ClangABI::Ver7);
     } else if (Ver != "latest") {
       Diags.Report(diag::err_drv_invalid_value)
           << A->getAsString(Args) << A->getValue();

Modified: cfe/trunk/lib/Parse/ParseExpr.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Parse/ParseExpr.cpp?rev=345419&r1=345418&r2=345419&view=diff
==============================================================================
--- cfe/trunk/lib/Parse/ParseExpr.cpp (original)
+++ cfe/trunk/lib/Parse/ParseExpr.cpp Fri Oct 26 12:26:45 2018
@@ -2023,8 +2023,10 @@ ExprResult Parser::ParseUnaryExprOrTypeT
                                                           CastRange);
 
   UnaryExprOrTypeTrait ExprKind = UETT_SizeOf;
-  if (OpTok.isOneOf(tok::kw_alignof, tok::kw___alignof, tok::kw__Alignof))
+  if (OpTok.isOneOf(tok::kw_alignof, tok::kw__Alignof))
     ExprKind = UETT_AlignOf;
+  else if (OpTok.is(tok::kw___alignof))
+    ExprKind = UETT_PreferredAlignOf;
   else if (OpTok.is(tok::kw_vec_step))
     ExprKind = UETT_VecStep;
   else if (OpTok.is(tok::kw___builtin_omp_required_simd_align))

Modified: cfe/trunk/lib/Sema/SemaChecking.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaChecking.cpp?rev=345419&r1=345418&r2=345419&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/SemaChecking.cpp (original)
+++ cfe/trunk/lib/Sema/SemaChecking.cpp Fri Oct 26 12:26:45 2018
@@ -5747,7 +5747,8 @@ bool Sema::SemaBuiltinAllocaWithAlign(Ca
   if (!Arg->isTypeDependent() && !Arg->isValueDependent()) {
     if (const auto *UE =
             dyn_cast<UnaryExprOrTypeTraitExpr>(Arg->IgnoreParenImpCasts()))
-      if (UE->getKind() == UETT_AlignOf)
+      if (UE->getKind() == UETT_AlignOf ||
+          UE->getKind() == UETT_PreferredAlignOf)
         Diag(TheCall->getBeginLoc(), diag::warn_alloca_align_alignof)
             << Arg->getSourceRange();
 
@@ -10365,7 +10366,7 @@ static void AnalyzeAssignment(Sema &S, B
   }
 
   AnalyzeImplicitConversions(S, E->getRHS(), E->getOperatorLoc());
-  
+
   // Diagnose implicitly sequentially-consistent atomic assignment.
   if (E->getLHS()->getType()->isAtomicType())
     S.Diag(E->getRHS()->getBeginLoc(), diag::warn_atomic_implicit_seq_cst);

Modified: cfe/trunk/lib/Sema/SemaExpr.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaExpr.cpp?rev=345419&r1=345418&r2=345419&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/SemaExpr.cpp (original)
+++ cfe/trunk/lib/Sema/SemaExpr.cpp Fri Oct 26 12:26:45 2018
@@ -3596,7 +3596,8 @@ static bool CheckExtensionTraitOperandTy
 
   // C99 6.5.3.4p1:
   if (T->isFunctionType() &&
-      (TraitKind == UETT_SizeOf || TraitKind == UETT_AlignOf)) {
+      (TraitKind == UETT_SizeOf || TraitKind == UETT_AlignOf ||
+       TraitKind == UETT_PreferredAlignOf)) {
     // sizeof(function)/alignof(function) is allowed as an extension.
     S.Diag(Loc, diag::ext_sizeof_alignof_function_type)
       << TraitKind << ArgRange;
@@ -3674,7 +3675,7 @@ bool Sema::CheckUnaryExprOrTypeTraitOper
   // the expression to be complete. 'sizeof' requires the expression's type to
   // be complete (and will attempt to complete it if it's an array of unknown
   // bound).
-  if (ExprKind == UETT_AlignOf) {
+  if (ExprKind == UETT_AlignOf || ExprKind == UETT_PreferredAlignOf) {
     if (RequireCompleteType(E->getExprLoc(),
                             Context.getBaseElementType(E->getType()),
                             diag::err_sizeof_alignof_incomplete_type, ExprKind,
@@ -3698,7 +3699,8 @@ bool Sema::CheckUnaryExprOrTypeTraitOper
 
   // The operand for sizeof and alignof is in an unevaluated expression context,
   // so side effects could result in unintended consequences.
-  if ((ExprKind == UETT_SizeOf || ExprKind == UETT_AlignOf) &&
+  if ((ExprKind == UETT_SizeOf || ExprKind == UETT_AlignOf ||
+       ExprKind == UETT_PreferredAlignOf) &&
       !inTemplateInstantiation() && E->HasSideEffects(Context, false))
     Diag(E->getExprLoc(), diag::warn_side_effects_unevaluated_context);
 
@@ -3767,7 +3769,8 @@ bool Sema::CheckUnaryExprOrTypeTraitOper
   // C11 6.5.3.4/3, C++11 [expr.alignof]p3:
   //   When alignof or _Alignof is applied to an array type, the result
   //   is the alignment of the element type.
-  if (ExprKind == UETT_AlignOf || ExprKind == UETT_OpenMPRequiredSimdAlign)
+  if (ExprKind == UETT_AlignOf || ExprKind == UETT_PreferredAlignOf ||
+      ExprKind == UETT_OpenMPRequiredSimdAlign)
     ExprType = Context.getBaseElementType(ExprType);
 
   if (ExprKind == UETT_VecStep)
@@ -3796,7 +3799,7 @@ bool Sema::CheckUnaryExprOrTypeTraitOper
   return false;
 }
 
-static bool CheckAlignOfExpr(Sema &S, Expr *E) {
+static bool CheckAlignOfExpr(Sema &S, Expr *E, UnaryExprOrTypeTrait ExprKind) {
   E = E->IgnoreParens();
 
   // Cannot know anything else if the expression is dependent.
@@ -3850,7 +3853,7 @@ static bool CheckAlignOfExpr(Sema &S, Ex
       return false;
   }
 
-  return S.CheckUnaryExprOrTypeTraitOperand(E, UETT_AlignOf);
+  return S.CheckUnaryExprOrTypeTraitOperand(E, ExprKind);
 }
 
 bool Sema::CheckVecStepExpr(Expr *E) {
@@ -4046,8 +4049,8 @@ Sema::CreateUnaryExprOrTypeTraitExpr(Exp
   bool isInvalid = false;
   if (E->isTypeDependent()) {
     // Delay type-checking for type-dependent expressions.
-  } else if (ExprKind == UETT_AlignOf) {
-    isInvalid = CheckAlignOfExpr(*this, E);
+  } else if (ExprKind == UETT_AlignOf || ExprKind == UETT_PreferredAlignOf) {
+    isInvalid = CheckAlignOfExpr(*this, E, ExprKind);
   } else if (ExprKind == UETT_VecStep) {
     isInvalid = CheckVecStepExpr(E);
   } else if (ExprKind == UETT_OpenMPRequiredSimdAlign) {

Modified: cfe/trunk/test/Headers/thumbv7-apple-ios-types.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Headers/thumbv7-apple-ios-types.cpp?rev=345419&r1=345418&r2=345419&view=diff
==============================================================================
--- cfe/trunk/test/Headers/thumbv7-apple-ios-types.cpp (original)
+++ cfe/trunk/test/Headers/thumbv7-apple-ios-types.cpp Fri Oct 26 12:26:45 2018
@@ -45,11 +45,11 @@ static_assert(check_type<unsigned int, 4
 static_assert(check_type<long, 4, 4>::value, "long is wrong");
 static_assert(check_type<unsigned long, 4, 4>::value, "unsigned long is wrong");
 
-static_assert(check_type<long long, 8, 8>::value, "long long is wrong");
-static_assert(check_type<unsigned long long, 8, 8>::value, "unsigned long long is wrong");
+static_assert(check_type<long long, 4, 8>::value, "long long is wrong");
+static_assert(check_type<unsigned long long, 4, 8>::value, "unsigned long long is wrong");
 
 static_assert(check_type<float, 4, 4>::value, "float is wrong");
-static_assert(check_type<double, 8, 8>::value, "double is wrong");
+static_assert(check_type<double, 4, 8>::value, "double is wrong");
 static_assert(check_type<long double, 4, 8>::value, "long double is wrong");
 
 static_assert(check_type<void *, 4, 4>::value, "'void *' is wrong");

Added: cfe/trunk/test/Sema/align-x86-abi7.c
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Sema/align-x86-abi7.c?rev=345419&view=auto
==============================================================================
--- cfe/trunk/test/Sema/align-x86-abi7.c (added)
+++ cfe/trunk/test/Sema/align-x86-abi7.c Fri Oct 26 12:26:45 2018
@@ -0,0 +1,21 @@
+// RUN: %clang_cc1 -std=c11 -triple i386-apple-darwin9 -fsyntax-only -verify -fclang-abi-compat=7 %s
+// expected-no-diagnostics
+
+#define STATIC_ASSERT(cond) _Static_assert(cond, #cond)
+
+// PR3433
+#define CHECK_ALIGNMENT(type, name, pref) \
+  type name; \
+  STATIC_ASSERT(__alignof__(name) == pref); \
+  STATIC_ASSERT(__alignof__(type) == pref); \
+  STATIC_ASSERT(_Alignof(type) == pref)
+
+CHECK_ALIGNMENT(double, g_double, 8);
+CHECK_ALIGNMENT(long long, g_longlong, 8);
+CHECK_ALIGNMENT(unsigned long long, g_ulonglong, 8);
+
+typedef double arr3double[3];
+CHECK_ALIGNMENT(arr3double, g_arr3double, 8);
+
+enum big_enum { x = 18446744073709551615ULL };
+CHECK_ALIGNMENT(enum big_enum, g_bigenum, 8);
\ No newline at end of file

Modified: cfe/trunk/test/Sema/align-x86.c
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Sema/align-x86.c?rev=345419&r1=345418&r2=345419&view=diff
==============================================================================
--- cfe/trunk/test/Sema/align-x86.c (original)
+++ cfe/trunk/test/Sema/align-x86.c Fri Oct 26 12:26:45 2018
@@ -1,34 +1,33 @@
-// RUN: %clang_cc1 -triple i386-apple-darwin9 -fsyntax-only -verify %s
+// RUN: %clang_cc1 -std=c11 -triple i386-apple-darwin9 -fsyntax-only -verify %s
 // expected-no-diagnostics
 
+#define STATIC_ASSERT(cond) _Static_assert(cond, #cond)
+
 // PR3433
-double g1;
-short chk1[__alignof__(g1) == 8 ? 1 : -1]; 
-short chk2[__alignof__(double) == 8 ? 1 : -1];
-
-long long g2;
-short chk1[__alignof__(g2) == 8 ? 1 : -1]; 
-short chk2[__alignof__(long long) == 8 ? 1 : -1];
-
-unsigned long long g5;
-short chk1[__alignof__(g5) == 8 ? 1 : -1]; 
-short chk2[__alignof__(unsigned long long) == 8 ? 1 : -1];
-
-_Complex double g3;
-short chk1[__alignof__(g3) == 8 ? 1 : -1]; 
-short chk2[__alignof__(_Complex double) == 8 ? 1 : -1];
+#define CHECK_ALIGNMENT(type, name, abi, pref) \
+  type name; \
+  STATIC_ASSERT(__alignof__(name) == pref); \
+  STATIC_ASSERT(__alignof__(type) == pref); \
+  STATIC_ASSERT(_Alignof(type) == abi)
+
+CHECK_ALIGNMENT(double, g_double, 4, 8);
+CHECK_ALIGNMENT(long long, g_longlong, 4, 8);
+CHECK_ALIGNMENT(unsigned long long, g_ulonglong, 4, 8);
+CHECK_ALIGNMENT(_Complex double, g_complexdouble, 4, 8);
 
 // PR6362
-struct __attribute__((packed)) {unsigned int a;} g4;
-short chk1[__alignof__(g4) == 1 ? 1 : -1];
-short chk2[__alignof__(g4.a) == 1 ? 1 : -1];
-
-double g6[3];
-short chk1[__alignof__(g6) == 8 ? 1 : -1];
-short chk2[__alignof__(double[3]) == 8 ? 1 : -1];
+struct __attribute__((packed))
+packed_struct {
+  unsigned int a;
+};
+CHECK_ALIGNMENT(struct packed_struct, g_packedstruct, 1, 1);
+STATIC_ASSERT(__alignof__(g_packedstruct.a) == 1);
+
+typedef double arr3double[3];
+CHECK_ALIGNMENT(arr3double, g_arr3double, 4, 8);
 
-enum { x = 18446744073709551615ULL } g7;
-short chk1[__alignof__(g7) == 8 ? 1 : -1];
+enum big_enum { x = 18446744073709551615ULL };
+CHECK_ALIGNMENT(enum big_enum, g_bigenum, 4, 8);
 
 // PR5637
 
@@ -36,20 +35,20 @@ short chk1[__alignof__(g7) == 8 ? 1 : -1
 
 typedef ALIGNED(2) struct {
   char a[3];
-} T;
+} aligned_before_struct;
 
-short chk1[sizeof(T)       == 3 ? 1 : -1];
-short chk2[sizeof(T[1])    == 4 ? 1 : -1];
-short chk3[sizeof(T[2])    == 6 ? 1 : -1];
-short chk4[sizeof(T[2][1]) == 8 ? 1 : -1];
-short chk5[sizeof(T[1][2]) == 6 ? 1 : -1];
+STATIC_ASSERT(sizeof(aligned_before_struct)       == 3);
+STATIC_ASSERT(sizeof(aligned_before_struct[1])    == 4);
+STATIC_ASSERT(sizeof(aligned_before_struct[2])    == 6);
+STATIC_ASSERT(sizeof(aligned_before_struct[2][1]) == 8);
+STATIC_ASSERT(sizeof(aligned_before_struct[1][2]) == 6);
 
 typedef struct ALIGNED(2) {
   char a[3];
-} T2;
+} aligned_after_struct;
 
-short chk1[sizeof(T2)       == 4 ? 1 : -1];
-short chk2[sizeof(T2[1])    == 4 ? 1 : -1];
-short chk3[sizeof(T2[2])    == 8 ? 1 : -1];
-short chk4[sizeof(T2[2][1]) == 8 ? 1 : -1];
-short chk5[sizeof(T2[1][2]) == 8 ? 1 : -1];
+STATIC_ASSERT(sizeof(aligned_after_struct)       == 4);
+STATIC_ASSERT(sizeof(aligned_after_struct[1])    == 4);
+STATIC_ASSERT(sizeof(aligned_after_struct[2])    == 8);
+STATIC_ASSERT(sizeof(aligned_after_struct[2][1]) == 8);
+STATIC_ASSERT(sizeof(aligned_after_struct[1][2]) == 8);

Added: cfe/trunk/test/SemaCXX/align-x86-abi7.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/SemaCXX/align-x86-abi7.cpp?rev=345419&view=auto
==============================================================================
--- cfe/trunk/test/SemaCXX/align-x86-abi7.cpp (added)
+++ cfe/trunk/test/SemaCXX/align-x86-abi7.cpp Fri Oct 26 12:26:45 2018
@@ -0,0 +1,25 @@
+// RUN: %clang_cc1 -std=c++11 -triple i386-apple-darwin9 -fsyntax-only -verify -fclang-abi-compat=7 %s
+// expected-no-diagnostics
+
+using size_t = decltype(sizeof(0));
+
+template <typename T, size_t Preferred>
+struct check_alignment {
+  using type = T;
+  static type value;
+
+  static_assert(__alignof__(value) == Preferred, "__alignof__(value) != Preferred");
+  static_assert(__alignof__(type) == Preferred, "__alignof__(type) != Preferred");
+  static_assert(alignof(type) == Preferred, "alignof(type) != Preferred");
+};
+
+// PR3433
+template struct check_alignment<double, 8>;
+template struct check_alignment<long long, 8>;
+template struct check_alignment<unsigned long long, 8>;
+
+// PR6362
+template struct check_alignment<double[3], 8>;
+
+enum big_enum { x = 18446744073709551615ULL };
+template struct check_alignment<big_enum, 8>;

Added: cfe/trunk/test/SemaCXX/align-x86.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/SemaCXX/align-x86.cpp?rev=345419&view=auto
==============================================================================
--- cfe/trunk/test/SemaCXX/align-x86.cpp (added)
+++ cfe/trunk/test/SemaCXX/align-x86.cpp Fri Oct 26 12:26:45 2018
@@ -0,0 +1,62 @@
+// RUN: %clang_cc1 -std=c++11 -triple i386-apple-darwin9 -fsyntax-only -verify %s
+// expected-no-diagnostics
+
+using size_t = decltype(sizeof(0));
+
+struct complex_double {
+  double real;
+  double imag;
+};
+
+template <typename T, size_t ABI, size_t Preferred>
+struct check_alignment {
+  using type = T;
+  static type value;
+
+  static_assert(__alignof__(value) == Preferred, "__alignof__(value) != Preferred");
+  static_assert(__alignof__(type) == Preferred, "__alignof__(type) != Preferred");
+  static_assert(alignof(type) == ABI, "alignof(type) != ABI");
+};
+
+// PR3433
+template struct check_alignment<double, 4, 8>;
+template struct check_alignment<long long, 4, 8>;
+template struct check_alignment<unsigned long long, 4, 8>;
+template struct check_alignment<complex_double, 4, 4>;
+
+// PR6362
+struct __attribute__((packed))
+packed_struct {
+  unsigned int a;
+} g_packedstruct;
+template struct check_alignment<packed_struct, 1, 1>;
+static_assert(__alignof__(g_packedstruct.a) == 1, "__alignof__(packed_struct.member) != 1");
+
+template struct check_alignment<double[3], 4, 8>;
+
+enum big_enum { x = 18446744073709551615ULL };
+template struct check_alignment<big_enum, 4, 8>;
+
+// PR5637
+
+#define ALIGNED(x) __attribute__((aligned(x)))
+
+typedef ALIGNED(2) struct {
+  char a[3];
+} aligned_before_struct;
+
+static_assert(sizeof(aligned_before_struct)       == 3, "");
+static_assert(sizeof(aligned_before_struct[1])    == 4, "");
+static_assert(sizeof(aligned_before_struct[2])    == 6, "");
+static_assert(sizeof(aligned_before_struct[2][1]) == 8, "");
+static_assert(sizeof(aligned_before_struct[1][2]) == 6, "");
+
+typedef struct ALIGNED(2) {
+  char a[3];
+} aligned_after_struct;
+
+static_assert(sizeof(aligned_after_struct)       == 4, "");
+static_assert(sizeof(aligned_after_struct[1])    == 4, "");
+static_assert(sizeof(aligned_after_struct[2])    == 8, "");
+static_assert(sizeof(aligned_after_struct[2][1]) == 8, "");
+static_assert(sizeof(aligned_after_struct[1][2]) == 8, "");

Modified: cfe/trunk/test/SemaCXX/alignof.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/SemaCXX/alignof.cpp?rev=345419&r1=345418&r2=345419&view=diff
==============================================================================
--- cfe/trunk/test/SemaCXX/alignof.cpp (original)
+++ cfe/trunk/test/SemaCXX/alignof.cpp Fri Oct 26 12:26:45 2018
@@ -4,14 +4,14 @@
 
 struct S0 {
   int x;
-  static const int test0 = __alignof__(x); // expected-error {{invalid application of 'alignof' to a field of a class still being defined}}
-  static const int test1 = __alignof__(S0::x); // expected-error {{invalid application of 'alignof' to a field of a class still being defined}}
-  auto test2() -> char(&)[__alignof__(x)]; // expected-error {{invalid application of 'alignof' to a field of a class still being defined}}
+  static const int test0 = __alignof__(x); // expected-error {{invalid application of '__alignof' to a field of a class still being defined}}
+  static const int test1 = __alignof__(S0::x); // expected-error {{invalid application of '__alignof' to a field of a class still being defined}}
+  auto test2() -> char(&)[__alignof__(x)]; // expected-error {{invalid application of '__alignof' to a field of a class still being defined}}
 };
 
 struct S1; // expected-note 6 {{forward declaration}}
 extern S1 s1;
-const int test3 = __alignof__(s1); // expected-error {{invalid application of 'alignof' to an incomplete type 'S1'}}
+const int test3 = __alignof__(s1); // expected-error {{invalid application of '__alignof' to an incomplete type 'S1'}}
 
 struct S2 {
   S2();
@@ -19,11 +19,11 @@ struct S2 {
   int x;
 
   int test4 = __alignof__(x); // ok
-  int test5 = __alignof__(s); // expected-error {{invalid application of 'alignof' to an incomplete type 'S1'}}
+  int test5 = __alignof__(s); // expected-error {{invalid application of '__alignof' to an incomplete type 'S1'}}
 };
 
 const int test6 = __alignof__(S2::x);
-const int test7 = __alignof__(S2::s); // expected-error {{invalid application of 'alignof' to an incomplete type 'S1'}}
+const int test7 = __alignof__(S2::s); // expected-error {{invalid application of '__alignof' to an incomplete type 'S1'}}
 
 // Arguably, these should fail like the S1 cases do: the alignment of
 // 's2.x' should depend on the alignment of both x-within-S2 and
@@ -34,10 +34,10 @@ struct S3 {
   S2 s2;
 
   static const int test8 = __alignof__(s2.x);
-  static const int test9 = __alignof__(s2.s); // expected-error {{invalid application of 'alignof' to an incomplete type 'S1'}}
+  static const int test9 = __alignof__(s2.s); // expected-error {{invalid application of '__alignof' to an incomplete type 'S1'}}
   auto test10() -> char(&)[__alignof__(s2.x)];
   static const int test11 = __alignof__(S3::s2.x);
-  static const int test12 = __alignof__(S3::s2.s); // expected-error {{invalid application of 'alignof' to an incomplete type 'S1'}}
+  static const int test12 = __alignof__(S3::s2.s); // expected-error {{invalid application of '__alignof' to an incomplete type 'S1'}}
   auto test13() -> char(&)[__alignof__(s2.x)];
 };
 
@@ -59,9 +59,9 @@ struct S5 {
 };
 const int test8 = __alignof__(S5::x);
 
-long long int test14[2];
+int test14[2];
 
-static_assert(alignof(test14) == 8, "foo"); // expected-warning {{'alignof' applied to an expression is a GNU extension}}
+static_assert(alignof(test14) == 4, "foo"); // expected-warning {{'alignof' applied to an expression is a GNU extension}}
 
 // PR19992
 static_assert(alignof(int[]) == alignof(int), ""); // ok




More information about the cfe-commits mailing list