From 7d538dc99627f811415d644b42a30414802a7729 Mon Sep 17 00:00:00 2001 From: Richard Smith Date: Tue, 10 Jun 2014 21:11:26 +0000 Subject: [PATCH] PR19992: alignof is permitted on an array of unknown bound. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@210585 91177308-0d34-0410-b5e6-96231b3b80d8 --- lib/Sema/SemaExpr.cpp | 35 ++++++++++++++++------------------- test/SemaCXX/alignof.cpp | 6 ++++++ 2 files changed, 22 insertions(+), 19 deletions(-) diff --git a/lib/Sema/SemaExpr.cpp b/lib/Sema/SemaExpr.cpp index fa444bc962..47bcc817e4 100644 --- a/lib/Sema/SemaExpr.cpp +++ b/lib/Sema/SemaExpr.cpp @@ -3398,13 +3398,21 @@ bool Sema::CheckUnaryExprOrTypeTraitOperand(QualType ExprType, if (ExprType->isDependentType()) return false; - // C++ [expr.sizeof]p2: "When applied to a reference or a reference type, - // the result is the size of the referenced type." - // C++ [expr.alignof]p3: "When alignof is applied to a reference type, the - // result shall be the alignment of the referenced type." + // C++ [expr.sizeof]p2: + // When applied to a reference or a reference type, the result + // is the size of the referenced type. + // C++11 [expr.alignof]p3: + // When alignof is applied to a reference type, the result + // shall be the alignment of the referenced type. if (const ReferenceType *Ref = ExprType->getAs()) ExprType = Ref->getPointeeType(); + // 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) + ExprType = Context.getBaseElementType(ExprType); + if (ExprKind == UETT_VecStep) return CheckVecStepTraitOperandType(*this, ExprType, OpLoc, ExprRange); @@ -3454,21 +3462,10 @@ static bool CheckAlignOfExpr(Sema &S, Expr *E) { // If it's a field, require the containing struct to have a // complete definition so that we can compute the layout. // - // This requires a very particular set of circumstances. For a - // field to be contained within an incomplete type, we must in the - // process of parsing that type. To have an expression refer to a - // field, it must be an id-expression or a member-expression, but - // the latter are always ill-formed when the base type is - // incomplete, including only being partially complete. An - // id-expression can never refer to a field in C because fields - // are not in the ordinary namespace. In C++, an id-expression - // can implicitly be a member access, but only if there's an - // implicit 'this' value, and all such contexts are subject to - // delayed parsing --- except for trailing return types in C++11. - // And if an id-expression referring to a field occurs in a - // context that lacks a 'this' value, it's ill-formed --- except, - // again, in C++11, where such references are allowed in an - // unevaluated context. So C++11 introduces some new complexity. + // This can happen in C++11 onwards, either by naming the member + // in a way that is not transformed into a member access expression + // (in an unevaluated operand, for instance), or by naming the member + // in a trailing-return-type. // // For the record, since __alignof__ on expressions is a GCC // extension, GCC seems to permit this but always gives the diff --git a/test/SemaCXX/alignof.cpp b/test/SemaCXX/alignof.cpp index f0b89eef65..3b56ae1085 100644 --- a/test/SemaCXX/alignof.cpp +++ b/test/SemaCXX/alignof.cpp @@ -62,3 +62,9 @@ const int test8 = __alignof__(S5::x); long long int test14[2]; static_assert(alignof(test14) == 8, "foo"); // expected-warning {{'alignof' applied to an expression is a GNU extension}} + +// PR19992 +alignas(32) extern int test15[]; +static_assert(alignof(int[]) == alignof(int), ""); // ok +// FIXME: We should accept this. +static_assert(alignof(test15) == 32, ""); // expected-warning {{GNU extension}} expected-error {{incomplete type}} -- 2.40.0