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
llvm-svn: 345419
diff --git a/clang/lib/AST/ASTDumper.cpp b/clang/lib/AST/ASTDumper.cpp
index 38a2fe9..03833ef 100644
--- a/clang/lib/AST/ASTDumper.cpp
+++ b/clang/lib/AST/ASTDumper.cpp
@@ -2281,6 +2281,9 @@
case UETT_OpenMPRequiredSimdAlign:
OS << " __builtin_omp_required_simd_align";
break;
+ case UETT_PreferredAlignOf:
+ OS << " __alignof";
+ break;
}
if (Node->isArgumentType())
dumpType(Node->getArgumentType());
diff --git a/clang/lib/AST/Expr.cpp b/clang/lib/AST/Expr.cpp
index e1e5c45..9df8aaa 100644
--- a/clang/lib/AST/Expr.cpp
+++ b/clang/lib/AST/Expr.cpp
@@ -1446,7 +1446,7 @@
// 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();
diff --git a/clang/lib/AST/ExprConstant.cpp b/clang/lib/AST/ExprConstant.cpp
index c64e335..d5bbbd2 100644
--- a/clang/lib/AST/ExprConstant.cpp
+++ b/clang/lib/AST/ExprConstant.cpp
@@ -5946,21 +5946,35 @@
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 @@
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 @@
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::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: {
diff --git a/clang/lib/AST/ItaniumMangle.cpp b/clang/lib/AST/ItaniumMangle.cpp
index 4b72633..d276ccc 100644
--- a/clang/lib/AST/ItaniumMangle.cpp
+++ b/clang/lib/AST/ItaniumMangle.cpp
@@ -3864,6 +3864,7 @@
case UETT_SizeOf:
Out << 's';
break;
+ case UETT_PreferredAlignOf:
case UETT_AlignOf:
Out << 'a';
break;
diff --git a/clang/lib/AST/StmtPrinter.cpp b/clang/lib/AST/StmtPrinter.cpp
index 192beec..012a9d6 100644
--- a/clang/lib/AST/StmtPrinter.cpp
+++ b/clang/lib/AST/StmtPrinter.cpp
@@ -1235,6 +1235,9 @@
else
OS << "__alignof";
break;
+ case UETT_PreferredAlignOf:
+ OS << "__alignof";
+ break;
case UETT_VecStep:
OS << "vec_step";
break;