]> granicus.if.org Git - clang/commitdiff
Related to PR19992: when the GNU alignof-expression extension is applied to an
authorRichard Smith <richard-llvm@metafoo.co.uk>
Tue, 10 Jun 2014 23:34:28 +0000 (23:34 +0000)
committerRichard Smith <richard-llvm@metafoo.co.uk>
Tue, 10 Jun 2014 23:34:28 +0000 (23:34 +0000)
expression of array-of-unknown-bound type, don't try to complete the array
bound, and return the alignment of the element type rather than 1.

git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@210608 91177308-0d34-0410-b5e6-96231b3b80d8

lib/AST/ASTContext.cpp
lib/AST/ExprConstant.cpp
lib/Sema/SemaExpr.cpp
test/SemaCXX/alignof.cpp

index 4dff88bbebe3a64df15a80b213134dc6e6ad16d4..f78f2a90a5b88ffa796c732aea0674b96b58d5ef 100644 (file)
@@ -1309,13 +1309,14 @@ CharUnits ASTContext::getDeclAlign(const Decl *D, bool ForAlignof) const {
 
   } else if (const ValueDecl *VD = dyn_cast<ValueDecl>(D)) {
     QualType T = VD->getType();
-    if (const ReferenceTypeRT = T->getAs<ReferenceType>()) {
+    if (const ReferenceType *RT = T->getAs<ReferenceType>()) {
       if (ForAlignof)
         T = RT->getPointeeType();
       else
         T = getPointerType(RT->getPointeeType());
     }
-    if (!T->isIncompleteType() && !T->isFunctionType()) {
+    QualType BaseT = getBaseElementType(T);
+    if (!BaseT->isIncompleteType() && !T->isFunctionType()) {
       // Adjust alignments of declarations with array type by the
       // large-array alignment on the target.
       if (const ArrayType *arrayType = getAsArrayType(T)) {
@@ -1330,8 +1331,12 @@ CharUnits ASTContext::getDeclAlign(const Decl *D, bool ForAlignof) const {
 
         // Keep track of extra alignment requirements on the array itself, then
         // work with the element type.
+        //
+        // FIXME: Computing the preferred type alignment for the array element
+        // type should not be necessary, but getPreferredTypeAlign returns the
+        // wrong thing in some cases (such as 'long long[]' on x86_64).
         Align = std::max(Align, getPreferredTypeAlign(T.getTypePtr()));
-        T = getBaseElementType(arrayType);
+        T = BaseT;
       }
       Align = std::max(Align, getPreferredTypeAlign(T.getTypePtr()));
       if (const VarDecl *VD = dyn_cast<VarDecl>(D)) {
index c1468cba15c17bdcc7b28af174736909b2c132ea..99b289a1c572076cd6866f9283709362cf18fdd7 100644 (file)
@@ -6910,8 +6910,9 @@ bool IntExprEvaluator::VisitBinaryOperator(const BinaryOperator *E) {
 }
 
 CharUnits IntExprEvaluator::GetAlignOfType(QualType T) {
-  // C++ [expr.alignof]p3: "When alignof is applied to a reference type, the
-  //   result shall be the alignment of the referenced type."
+  // 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();
 
@@ -6930,7 +6931,7 @@ CharUnits IntExprEvaluator::GetAlignOfExpr(const Expr *E) {
   // alignof decl is always accepted, even if it doesn't make sense: we default
   // to 1 in those cases.
   if (const DeclRefExpr *DRE = dyn_cast<DeclRefExpr>(E))
-    return Info.Ctx.getDeclAlign(DRE->getDecl(), 
+    return Info.Ctx.getDeclAlign(DRE->getDecl(),
                                  /*RefAsPointee*/true);
 
   if (const MemberExpr *ME = dyn_cast<MemberExpr>(E))
index d2ba82bc1677f21bb920219a23e9d9831ff99933..041a9eb9d4444bae6b7ad4bb407f9508bcd12aff 100644 (file)
@@ -3341,10 +3341,21 @@ bool Sema::CheckUnaryExprOrTypeTraitOperand(Expr *E,
                                       E->getSourceRange(), ExprKind))
     return false;
 
-  if (RequireCompleteExprType(E,
-                              diag::err_sizeof_alignof_incomplete_type,
-                              ExprKind, E->getSourceRange()))
-    return true;
+  // 'alignof' applied to an expression only requires the base element type of
+  // 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 (RequireCompleteType(E->getExprLoc(),
+                            Context.getBaseElementType(E->getType()),
+                            diag::err_sizeof_alignof_incomplete_type, ExprKind,
+                            E->getSourceRange()))
+      return true;
+  } else {
+    if (RequireCompleteExprType(E, diag::err_sizeof_alignof_incomplete_type,
+                                ExprKind, E->getSourceRange()))
+      return true;
+  }
 
   // Completing the expression's type may have changed it.
   ExprTy = E->getType();
index 3b56ae1085ad3f2ec8ea6ae39e164603a1a944a5..011f459abdf2df38f958ed77c230bdc900672191 100644 (file)
@@ -64,7 +64,16 @@ 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}}
+
+namespace alignof_array_expr {
+  alignas(32) extern int n[];
+  static_assert(alignof(n) == 32, ""); // expected-warning {{GNU extension}}
+
+  template<int> struct S {
+    static int a[];
+  };
+  template<int N> int S<N>::a[N];
+  // ok, does not complete type of S<-1>::a
+  static_assert(alignof(S<-1>::a) == alignof(int), ""); // expected-warning {{GNU extension}}
+}