r210608 - Related to PR19992: when the GNU alignof-expression extension is applied to an

Richard Smith richard-llvm at metafoo.co.uk
Tue Jun 10 16:34:28 PDT 2014


Author: rsmith
Date: Tue Jun 10 18:34:28 2014
New Revision: 210608

URL: http://llvm.org/viewvc/llvm-project?rev=210608&view=rev
Log:
Related to PR19992: when the GNU alignof-expression extension is applied to an
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.

Modified:
    cfe/trunk/lib/AST/ASTContext.cpp
    cfe/trunk/lib/AST/ExprConstant.cpp
    cfe/trunk/lib/Sema/SemaExpr.cpp
    cfe/trunk/test/SemaCXX/alignof.cpp

Modified: cfe/trunk/lib/AST/ASTContext.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/AST/ASTContext.cpp?rev=210608&r1=210607&r2=210608&view=diff
==============================================================================
--- cfe/trunk/lib/AST/ASTContext.cpp (original)
+++ cfe/trunk/lib/AST/ASTContext.cpp Tue Jun 10 18:34:28 2014
@@ -1309,13 +1309,14 @@ CharUnits ASTContext::getDeclAlign(const
 
   } else if (const ValueDecl *VD = dyn_cast<ValueDecl>(D)) {
     QualType T = VD->getType();
-    if (const ReferenceType* RT = 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
 
         // 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)) {

Modified: cfe/trunk/lib/AST/ExprConstant.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/AST/ExprConstant.cpp?rev=210608&r1=210607&r2=210608&view=diff
==============================================================================
--- cfe/trunk/lib/AST/ExprConstant.cpp (original)
+++ cfe/trunk/lib/AST/ExprConstant.cpp Tue Jun 10 18:34:28 2014
@@ -6910,8 +6910,9 @@ bool IntExprEvaluator::VisitBinaryOperat
 }
 
 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::GetAlignOfEx
   // 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))

Modified: cfe/trunk/lib/Sema/SemaExpr.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaExpr.cpp?rev=210608&r1=210607&r2=210608&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/SemaExpr.cpp (original)
+++ cfe/trunk/lib/Sema/SemaExpr.cpp Tue Jun 10 18:34:28 2014
@@ -3341,10 +3341,21 @@ bool Sema::CheckUnaryExprOrTypeTraitOper
                                       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();

Modified: cfe/trunk/test/SemaCXX/alignof.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/SemaCXX/alignof.cpp?rev=210608&r1=210607&r2=210608&view=diff
==============================================================================
--- cfe/trunk/test/SemaCXX/alignof.cpp (original)
+++ cfe/trunk/test/SemaCXX/alignof.cpp Tue Jun 10 18:34:28 2014
@@ -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}}
+}





More information about the cfe-commits mailing list