[cfe-commits] r89668 - in /cfe/trunk: include/clang/AST/ASTContext.h lib/AST/ASTContext.cpp lib/AST/ExprConstant.cpp lib/Sema/SemaExpr.cpp test/CodeGenCXX/references.cpp test/SemaCXX/alignof-sizeof-reference.cpp

Sebastian Redl sebastian.redl at getdesigned.at
Mon Nov 23 09:18:46 PST 2009


Author: cornedbee
Date: Mon Nov 23 11:18:46 2009
New Revision: 89668

URL: http://llvm.org/viewvc/llvm-project?rev=89668&view=rev
Log:
Intercept sizeof and alignof references before they get into ASTContext methods. This fixes a crash when writing sizeof(Incomplete&), and lets ASTContext's methods do the right thing for CodeGen, which fixes PR5590.

Added:
    cfe/trunk/test/SemaCXX/alignof-sizeof-reference.cpp
Modified:
    cfe/trunk/include/clang/AST/ASTContext.h
    cfe/trunk/lib/AST/ASTContext.cpp
    cfe/trunk/lib/AST/ExprConstant.cpp
    cfe/trunk/lib/Sema/SemaExpr.cpp
    cfe/trunk/test/CodeGenCXX/references.cpp

Modified: cfe/trunk/include/clang/AST/ASTContext.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/AST/ASTContext.h?rev=89668&r1=89667&r2=89668&view=diff

==============================================================================
--- cfe/trunk/include/clang/AST/ASTContext.h (original)
+++ cfe/trunk/include/clang/AST/ASTContext.h Mon Nov 23 11:18:46 2009
@@ -810,10 +810,7 @@
   /// a data type.
   unsigned getPreferredTypeAlign(const Type *T);
 
-  /// getDeclAlignInBytes - Return the alignment of the specified decl
-  /// that should be returned by __alignof().  Note that bitfields do
-  /// not have a valid alignment, so this method will assert on them.
-  unsigned getDeclAlignInBytes(const Decl *D);
+  unsigned getDeclAlignInBytes(const Decl *D, bool RefAsPointee = false);
 
   /// getASTRecordLayout - Get or compute information about the layout of the
   /// specified record (struct/union/class), which indicates its size and field

Modified: cfe/trunk/lib/AST/ASTContext.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/AST/ASTContext.cpp?rev=89668&r1=89667&r2=89668&view=diff

==============================================================================
--- cfe/trunk/lib/AST/ASTContext.cpp (original)
+++ cfe/trunk/lib/AST/ASTContext.cpp Mon Nov 23 11:18:46 2009
@@ -520,7 +520,9 @@
 /// getDeclAlignInBytes - Return a conservative estimate of the alignment of the
 /// specified decl.  Note that bitfields do not have a valid alignment, so
 /// this method will assert on them.
-unsigned ASTContext::getDeclAlignInBytes(const Decl *D) {
+/// If @p RefAsPointee, references are treated like their underlying type
+/// (for alignof), else they're treated like pointers (for CodeGen).
+unsigned ASTContext::getDeclAlignInBytes(const Decl *D, bool RefAsPointee) {
   unsigned Align = Target.getCharWidth();
 
   if (const AlignedAttr* AA = D->getAttr<AlignedAttr>())
@@ -529,9 +531,12 @@
   if (const ValueDecl *VD = dyn_cast<ValueDecl>(D)) {
     QualType T = VD->getType();
     if (const ReferenceType* RT = T->getAs<ReferenceType>()) {
-      unsigned AS = RT->getPointeeType().getAddressSpace();
-      Align = Target.getPointerAlign(AS);
-    } else if (!T->isIncompleteType() && !T->isFunctionType()) {
+      if (RefAsPointee)
+        T = RT->getPointeeType();
+      else
+        T = getPointerType(RT->getPointeeType());
+    }
+    if (!T->isIncompleteType() && !T->isFunctionType()) {
       // Incomplete or function types default to 1.
       while (isa<VariableArrayType>(T) || isa<IncompleteArrayType>(T))
         T = cast<ArrayType>(T)->getElementType();
@@ -690,19 +695,21 @@
     Align = Target.getPointerAlign(AS);
     break;
   }
+  case Type::LValueReference:
+  case Type::RValueReference: {
+    // alignof and sizeof should never enter this code path here, so we go
+    // the pointer route.
+    unsigned AS = cast<ReferenceType>(T)->getPointeeType().getAddressSpace();
+    Width = Target.getPointerWidth(AS);
+    Align = Target.getPointerAlign(AS);
+    break;
+  }
   case Type::Pointer: {
     unsigned AS = cast<PointerType>(T)->getPointeeType().getAddressSpace();
     Width = Target.getPointerWidth(AS);
     Align = Target.getPointerAlign(AS);
     break;
   }
-  case Type::LValueReference:
-  case Type::RValueReference:
-    // "When applied to a reference or a reference type, the result is the size
-    // of the referenced type." C++98 5.3.3p2: expr.sizeof.
-    // FIXME: This is wrong for struct layout: a reference in a struct has
-    // pointer size.
-    return getTypeInfo(cast<ReferenceType>(T)->getPointeeType());
   case Type::MemberPointer: {
     // FIXME: This is ABI dependent. We use the Itanium C++ ABI.
     // http://www.codesourcery.com/public/cxx-abi/abi.html#member-pointers

Modified: cfe/trunk/lib/AST/ExprConstant.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/AST/ExprConstant.cpp?rev=89668&r1=89667&r2=89668&view=diff

==============================================================================
--- cfe/trunk/lib/AST/ExprConstant.cpp (original)
+++ cfe/trunk/lib/AST/ExprConstant.cpp Mon Nov 23 11:18:46 2009
@@ -1244,6 +1244,13 @@
 }
 
 unsigned IntExprEvaluator::GetAlignOfType(QualType T) {
+  // 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."
+  if (const ReferenceType *Ref = T->getAs<ReferenceType>())
+    T = Ref->getPointeeType();
+
   // Get information about the alignment.
   unsigned CharSize = Info.Ctx.Target.getCharWidth();
 
@@ -1257,10 +1264,11 @@
   // 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.getDeclAlignInBytes(DRE->getDecl());
+    return Info.Ctx.getDeclAlignInBytes(DRE->getDecl(), /*RefAsPointee*/true);
 
   if (const MemberExpr *ME = dyn_cast<MemberExpr>(E))
-    return Info.Ctx.getDeclAlignInBytes(ME->getMemberDecl());
+    return Info.Ctx.getDeclAlignInBytes(ME->getMemberDecl(),
+                                        /*RefAsPointee*/true);
 
   return GetAlignOfType(E->getType());
 }
@@ -1280,6 +1288,12 @@
   }
 
   QualType SrcTy = E->getTypeOfArgument();
+  // 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."
+  if (const ReferenceType *Ref = SrcTy->getAs<ReferenceType>())
+    SrcTy = Ref->getPointeeType();
 
   // sizeof(void), __alignof__(void), sizeof(function) = 1 as a gcc
   // extension.

Modified: cfe/trunk/lib/Sema/SemaExpr.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaExpr.cpp?rev=89668&r1=89667&r2=89668&view=diff

==============================================================================
--- cfe/trunk/lib/Sema/SemaExpr.cpp (original)
+++ cfe/trunk/lib/Sema/SemaExpr.cpp Mon Nov 23 11:18:46 2009
@@ -1341,6 +1341,13 @@
   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."
+  if (const ReferenceType *Ref = exprType->getAs<ReferenceType>())
+    exprType = Ref->getPointeeType();
+
   // C99 6.5.3.4p1:
   if (exprType->isFunctionType()) {
     // alignof(function) is allowed as an extension.

Modified: cfe/trunk/test/CodeGenCXX/references.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CodeGenCXX/references.cpp?rev=89668&r1=89667&r2=89668&view=diff

==============================================================================
--- cfe/trunk/test/CodeGenCXX/references.cpp (original)
+++ cfe/trunk/test/CodeGenCXX/references.cpp Mon Nov 23 11:18:46 2009
@@ -136,3 +136,8 @@
   (a = 10) = 20;
 }
 }
+
+// PR5590
+struct s0;
+struct s1 { struct s0 &s0; };
+void f0(s1 a) { s1 b = a; }

Added: cfe/trunk/test/SemaCXX/alignof-sizeof-reference.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/SemaCXX/alignof-sizeof-reference.cpp?rev=89668&view=auto

==============================================================================
--- cfe/trunk/test/SemaCXX/alignof-sizeof-reference.cpp (added)
+++ cfe/trunk/test/SemaCXX/alignof-sizeof-reference.cpp Mon Nov 23 11:18:46 2009
@@ -0,0 +1,9 @@
+// RUN: clang-cc -std=c++0x -fsyntax-only -verify %s
+
+struct s0; // expected-note {{forward declaration}}
+char ar[sizeof(s0&)]; // expected-error {{invalid application of 'sizeof' to an incomplete type}}
+void test() {
+  char &r = ar[0];
+  static_assert(alignof(r) == 1, "bad alignment");
+  static_assert(sizeof(r) == 1, "bad size");
+}





More information about the cfe-commits mailing list