]> granicus.if.org Git - clang/commitdiff
PR19992: alignof is permitted on an array of unknown bound.
authorRichard Smith <richard-llvm@metafoo.co.uk>
Tue, 10 Jun 2014 21:11:26 +0000 (21:11 +0000)
committerRichard Smith <richard-llvm@metafoo.co.uk>
Tue, 10 Jun 2014 21:11:26 +0000 (21:11 +0000)
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@210585 91177308-0d34-0410-b5e6-96231b3b80d8

lib/Sema/SemaExpr.cpp
test/SemaCXX/alignof.cpp

index fa444bc96293bc36af0e5c6d2c51544f1d694c24..47bcc817e4b01db73c0bd15c2ba8dd0079499dc6 100644 (file)
@@ -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<ReferenceType>())
     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
index f0b89eef656dcd002ae31916ff53347c81130e62..3b56ae1085ad3f2ec8ea6ae39e164603a1a944a5 100644 (file)
@@ -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}}