[c++20] P1327R1: Support for typeid applied to objects of polymorphic
class type in constant evaluation.

This reinstates r360977, reverted in r360987, now that its rerequisite
patch is reinstated and fixed.

llvm-svn: 361067
diff --git a/clang/lib/AST/ExprConstant.cpp b/clang/lib/AST/ExprConstant.cpp
index af33209..856efc8 100644
--- a/clang/lib/AST/ExprConstant.cpp
+++ b/clang/lib/AST/ExprConstant.cpp
@@ -1349,6 +1349,7 @@
   AK_Decrement,
   AK_MemberCall,
   AK_DynamicCast,
+  AK_TypeId,
 };
 
 static bool isModification(AccessKinds AK) {
@@ -1356,6 +1357,7 @@
   case AK_Read:
   case AK_MemberCall:
   case AK_DynamicCast:
+  case AK_TypeId:
     return false;
   case AK_Assign:
   case AK_Increment:
@@ -6034,19 +6036,33 @@
 }
 
 bool LValueExprEvaluator::VisitCXXTypeidExpr(const CXXTypeidExpr *E) {
+  TypeInfoLValue TypeInfo;
+
   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()));
+  } else {
+    if (!Info.Ctx.getLangOpts().CPlusPlus2a) {
+      Info.CCEDiag(E, diag::note_constexpr_typeid_polymorphic)
+        << E->getExprOperand()->getType()
+        << E->getExprOperand()->getSourceRange();
+    }
+
+    if (!Visit(E->getExprOperand()))
+      return false;
+
+    Optional<DynamicType> DynType =
+        ComputeDynamicType(Info, E, Result, AK_TypeId);
+    if (!DynType)
+      return false;
+
+    TypeInfo =
+        TypeInfoLValue(Info.Ctx.getRecordType(DynType->Type).getTypePtr());
   }
 
-  Info.FFDiag(E, diag::note_constexpr_typeid_polymorphic)
-    << E->getExprOperand()->getType()
-    << E->getExprOperand()->getSourceRange();
-  return false;
+  return Success(APValue::LValueBase::getTypeInfo(TypeInfo, E->getType()));
 }
 
 bool LValueExprEvaluator::VisitCXXUuidofExpr(const CXXUuidofExpr *E) {