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.

git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@89668 91177308-0d34-0410-b5e6-96231b3b80d8
diff --git a/lib/AST/ASTContext.cpp b/lib/AST/ASTContext.cpp
index dc92afd..7422ca8 100644
--- a/lib/AST/ASTContext.cpp
+++ b/lib/AST/ASTContext.cpp
@@ -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