Refactor constant evaluation of typeid(T) to track a symbolic type_info
object rather than tracking the originating expression.

This is groundwork for supporting polymorphic typeid expressions. (Note
that this somewhat regresses our support for DR1968, but it turns out
that that never actually worked anyway, at least in non-trivial cases.)

This reinstates r360974, reverted in r360988, with a fix for a
static_assert failure on 32-bit builds: force Type base class to have
8-byte alignment like the rest of Clang's AST nodes.

llvm-svn: 360995
diff --git a/clang/lib/AST/APValue.cpp b/clang/lib/AST/APValue.cpp
index e7902e68..249c382 100644
--- a/clang/lib/AST/APValue.cpp
+++ b/clang/lib/AST/APValue.cpp
@@ -20,6 +20,61 @@
 #include "llvm/Support/raw_ostream.h"
 using namespace clang;
 
+/// The identity of a type_info object depends on the canonical unqualified
+/// type only.
+TypeInfoLValue::TypeInfoLValue(const Type *T)
+    : T(T->getCanonicalTypeUnqualified().getTypePtr()) {}
+
+void TypeInfoLValue::print(llvm::raw_ostream &Out,
+                           const PrintingPolicy &Policy) const {
+  Out << "typeid(";
+  QualType(getType(), 0).print(Out, Policy);
+  Out << ")";
+}
+
+static_assert(
+    1 << llvm::PointerLikeTypeTraits<TypeInfoLValue>::NumLowBitsAvailable <=
+        alignof(const Type *),
+    "Type is insufficiently aligned");
+
+APValue::LValueBase::LValueBase(const ValueDecl *P, unsigned I, unsigned V)
+    : Ptr(P), Local{I, V} {}
+APValue::LValueBase::LValueBase(const Expr *P, unsigned I, unsigned V)
+    : Ptr(P), Local{I, V} {}
+
+APValue::LValueBase APValue::LValueBase::getTypeInfo(TypeInfoLValue LV,
+                                                     QualType TypeInfo) {
+  LValueBase Base;
+  Base.Ptr = LV;
+  Base.TypeInfoType = TypeInfo.getAsOpaquePtr();
+  return Base;
+}
+
+unsigned APValue::LValueBase::getCallIndex() const {
+  return is<TypeInfoLValue>() ? 0 : Local.CallIndex;
+}
+
+unsigned APValue::LValueBase::getVersion() const {
+  return is<TypeInfoLValue>() ? 0 : Local.Version;
+}
+
+QualType APValue::LValueBase::getTypeInfoType() const {
+  assert(is<TypeInfoLValue>() && "not a type_info lvalue");
+  return QualType::getFromOpaquePtr(TypeInfoType);
+}
+
+namespace clang {
+bool operator==(const APValue::LValueBase &LHS,
+                const APValue::LValueBase &RHS) {
+  if (LHS.Ptr != RHS.Ptr)
+    return false;
+  if (LHS.is<TypeInfoLValue>())
+    return true;
+  return LHS.Local.CallIndex == RHS.Local.CallIndex &&
+         LHS.Local.Version == RHS.Local.Version;
+}
+}
+
 namespace {
   struct LVBase {
     APValue::LValueBase Base;
@@ -45,21 +100,19 @@
 clang::APValue::LValueBase
 llvm::DenseMapInfo<clang::APValue::LValueBase>::getEmptyKey() {
   return clang::APValue::LValueBase(
-      DenseMapInfo<clang::APValue::LValueBase::PtrTy>::getEmptyKey(),
-      DenseMapInfo<unsigned>::getEmptyKey(),
-      DenseMapInfo<unsigned>::getEmptyKey());
+      DenseMapInfo<const ValueDecl*>::getEmptyKey());
 }
 
 clang::APValue::LValueBase
 llvm::DenseMapInfo<clang::APValue::LValueBase>::getTombstoneKey() {
   return clang::APValue::LValueBase(
-      DenseMapInfo<clang::APValue::LValueBase::PtrTy>::getTombstoneKey(),
-      DenseMapInfo<unsigned>::getTombstoneKey(),
-      DenseMapInfo<unsigned>::getTombstoneKey());
+      DenseMapInfo<const ValueDecl*>::getTombstoneKey());
 }
 
 namespace clang {
 llvm::hash_code hash_value(const APValue::LValueBase &Base) {
+  if (Base.is<TypeInfoLValue>())
+    return llvm::hash_value(Base.getOpaqueValue());
   return llvm::hash_combine(Base.getOpaqueValue(), Base.getCallIndex(),
                             Base.getVersion());
 }
@@ -470,7 +523,9 @@
 
       if (const ValueDecl *VD = Base.dyn_cast<const ValueDecl*>())
         Out << *VD;
-      else {
+      else if (TypeInfoLValue TI = Base.dyn_cast<TypeInfoLValue>()) {
+        TI.print(Out, Ctx.getPrintingPolicy());
+      } else {
         assert(Base.get<const Expr *>() != nullptr &&
                "Expecting non-null Expr");
         Base.get<const Expr*>()->printPretty(Out, nullptr,
@@ -495,6 +550,9 @@
     if (const ValueDecl *VD = Base.dyn_cast<const ValueDecl*>()) {
       Out << *VD;
       ElemTy = VD->getType();
+    } else if (TypeInfoLValue TI = Base.dyn_cast<TypeInfoLValue>()) {
+      TI.print(Out, Ctx.getPrintingPolicy());
+      ElemTy = Base.getTypeInfoType();
     } else {
       const Expr *E = Base.get<const Expr*>();
       assert(E != nullptr && "Expecting non-null Expr");
diff --git a/clang/lib/AST/ExprConstant.cpp b/clang/lib/AST/ExprConstant.cpp
index 29b6d12..e41264e 100644
--- a/clang/lib/AST/ExprConstant.cpp
+++ b/clang/lib/AST/ExprConstant.cpp
@@ -87,6 +87,9 @@
       return D->getType();
     }
 
+    if (TypeInfoLValue TI = B.dyn_cast<TypeInfoLValue>())
+      return B.getTypeInfoType();
+
     const Expr *Base = B.get<const Expr*>();
 
     // For a materialized temporary, the type of the temporary we materialized
@@ -1783,6 +1786,9 @@
     return isa<FunctionDecl>(D);
   }
 
+  if (B.is<TypeInfoLValue>())
+    return true;
+
   const Expr *E = B.get<const Expr*>();
   switch (E->getStmtClass()) {
   default:
@@ -1800,7 +1806,6 @@
   case Expr::PredefinedExprClass:
   case Expr::ObjCStringLiteralClass:
   case Expr::ObjCEncodeExprClass:
-  case Expr::CXXTypeidExprClass:
   case Expr::CXXUuidofExprClass:
     return true;
   case Expr::ObjCBoxedExprClass:
@@ -1878,9 +1883,9 @@
   const ValueDecl *VD = Base.dyn_cast<const ValueDecl*>();
   if (VD)
     Info.Note(VD->getLocation(), diag::note_declared_at);
-  else
-    Info.Note(Base.get<const Expr*>()->getExprLoc(),
-              diag::note_constexpr_temporary_here);
+  else if (const Expr *E = Base.dyn_cast<const Expr*>())
+    Info.Note(E->getExprLoc(), diag::note_constexpr_temporary_here);
+  // We have no information to show for a typeid(T) object.
 }
 
 /// Check that this reference or pointer core constant expression is a valid
@@ -3404,7 +3409,7 @@
 
     if (!Frame) {
       if (const MaterializeTemporaryExpr *MTE =
-              dyn_cast<MaterializeTemporaryExpr>(Base)) {
+              dyn_cast_or_null<MaterializeTemporaryExpr>(Base)) {
         assert(MTE->getStorageDuration() == SD_Static &&
                "should have a frame for a non-global materialized temporary");
 
@@ -3439,7 +3444,13 @@
       } else {
         if (!IsAccess)
           return CompleteObject(LVal.getLValueBase(), nullptr, BaseType);
-        Info.FFDiag(E);
+        APValue Val;
+        LVal.moveInto(Val);
+        Info.FFDiag(E, diag::note_constexpr_access_unreadable_object)
+            << AK
+            << Val.getAsString(Info.Ctx,
+                               Info.Ctx.getLValueReferenceType(LValType));
+        NoteLValueLocation(Info, LVal.Base);
         return CompleteObject();
       }
     } else {
@@ -5777,13 +5788,13 @@
 // - Literals
 //  * CompoundLiteralExpr in C (and in global scope in C++)
 //  * StringLiteral
-//  * CXXTypeidExpr
 //  * PredefinedExpr
 //  * ObjCStringLiteralExpr
 //  * ObjCEncodeExpr
 //  * AddrLabelExpr
 //  * BlockExpr
 //  * CallExpr for a MakeStringConstant builtin
+// - typeid(T) expressions, as TypeInfoLValues
 // - Locals and temporaries
 //  * MaterializeTemporaryExpr
 //  * Any Expr, with a CallIndex indicating the function in which the temporary
@@ -6018,8 +6029,14 @@
 }
 
 bool LValueExprEvaluator::VisitCXXTypeidExpr(const CXXTypeidExpr *E) {
-  if (!E->isPotentiallyEvaluated())
-    return Success(E);
+  if (!E->isPotentiallyEvaluated()) {
+    TypeInfoLValue TypeInfo;
+    if (E->isTypeOperand())
+      TypeInfo = TypeInfoLValue(E->getTypeOperand(Info.Ctx).getTypePtr());
+    else
+      TypeInfo = TypeInfoLValue(E->getExprOperand()->getType().getTypePtr());
+    return Success(APValue::LValueBase::getTypeInfo(TypeInfo, E->getType()));
+  }
 
   Info.FFDiag(E, diag::note_constexpr_typeid_polymorphic)
     << E->getExprOperand()->getType()
@@ -6615,9 +6632,11 @@
       if (const ValueDecl *VD =
           OffsetResult.Base.dyn_cast<const ValueDecl*>()) {
         BaseAlignment = Info.Ctx.getDeclAlign(VD);
+      } else if (const Expr *E = OffsetResult.Base.dyn_cast<const Expr *>()) {
+        BaseAlignment = GetAlignOfExpr(Info, E, UETT_AlignOf);
       } else {
-        BaseAlignment = GetAlignOfExpr(
-            Info, OffsetResult.Base.get<const Expr *>(), UETT_AlignOf);
+        BaseAlignment = GetAlignOfType(
+            Info, OffsetResult.Base.getTypeInfoType(), UETT_AlignOf);
       }
 
       if (BaseAlignment < Align) {
@@ -8335,6 +8354,10 @@
     if (!isa<StringLiteral>(E))
       return false;
     return LV.getLValueOffset().isZero();
+  } else if (Base.is<TypeInfoLValue>()) {
+    // Surprisingly, GCC considers __builtin_constant_p(&typeid(int)) to
+    // evaluate to true.
+    return true;
   } else {
     // Any other base is not constant enough for GCC.
     return false;
@@ -8399,6 +8422,8 @@
   } else if (const Expr *E = B.get<const Expr*>()) {
     if (isa<CompoundLiteralExpr>(E))
       return E->getType();
+  } else if (B.is<TypeInfoLValue>()) {
+    return B.getTypeInfoType();
   }
 
   return QualType();