sepavloff created this revision.
sepavloff added reviewers: rsmith, rjmccall, varungandhi-apple, Tyker, EricWF, 
george.burgess.iv, nand.
Herald added a subscriber: martong.
Herald added a reviewer: shafik.
sepavloff requested review of this revision.
Herald added a project: clang.

APValue::LValuePathEntry was implemented as non-discriminated union. It
complicated operations on it and inspection in debugger. This change
turns it into discriminated union.

No functional changed intended.


Repository:
  rG LLVM Github Monorepo

https://reviews.llvm.org/D101425

Files:
  clang/include/clang/AST/APValue.h
  clang/include/clang/AST/AbstractBasicReader.h
  clang/include/clang/AST/AbstractBasicWriter.h
  clang/lib/AST/APValue.cpp
  clang/lib/AST/ASTImporter.cpp
  clang/lib/AST/ExprConstant.cpp
  clang/lib/AST/Interp/Pointer.cpp
  clang/lib/AST/ItaniumMangle.cpp
  clang/lib/AST/MicrosoftMangle.cpp

Index: clang/lib/AST/MicrosoftMangle.cpp
===================================================================
--- clang/lib/AST/MicrosoftMangle.cpp
+++ clang/lib/AST/MicrosoftMangle.cpp
@@ -1722,8 +1722,7 @@
         if (T->isArrayType())
           goto mangling_unknown;
 
-        const Decl *D = E.getAsBaseOrMember().getPointer();
-        auto *FD = dyn_cast<FieldDecl>(D);
+        const FieldDecl *FD = E.getAsFieldOrNull();
         // We don't know how to mangle derived-to-base conversions yet.
         if (!FD)
           goto mangling_unknown;
@@ -1739,10 +1738,8 @@
       Out << "E";
       mangle(VD);
 
-      for (APValue::LValuePathEntry E : V.getLValuePath()) {
-        const Decl *D = E.getAsBaseOrMember().getPointer();
-        mangleUnqualifiedName(cast<FieldDecl>(D));
-      }
+      for (APValue::LValuePathEntry E : V.getLValuePath())
+        mangleUnqualifiedName(E.getAsField());
       for (unsigned I = 0; I != NumAts; ++I)
         Out << '@';
     }
Index: clang/lib/AST/ItaniumMangle.cpp
===================================================================
--- clang/lib/AST/ItaniumMangle.cpp
+++ clang/lib/AST/ItaniumMangle.cpp
@@ -5376,12 +5376,10 @@
   for (APValue::LValuePathEntry E : LV.getLValuePath()) {
     if (const ArrayType *AT = Ctx.getAsArrayType(T))
       T = AT->getElementType();
-    else if (const FieldDecl *FD =
-                 dyn_cast<FieldDecl>(E.getAsBaseOrMember().getPointer()))
+    else if (const FieldDecl *FD = E.getAsFieldOrNull())
       T = FD->getType();
     else
-      T = Ctx.getRecordType(
-          cast<CXXRecordDecl>(E.getAsBaseOrMember().getPointer()));
+      T = Ctx.getRecordType(E.getAsBase());
   }
   return T;
 }
@@ -5682,8 +5680,7 @@
             OnePastTheEnd |= CAT->getSize() == E.getAsArrayIndex();
           TypeSoFar = AT->getElementType();
         } else {
-          const Decl *D = E.getAsBaseOrMember().getPointer();
-          if (auto *FD = dyn_cast<FieldDecl>(D)) {
+          if (const FieldDecl *FD = E.getAsFieldOrNull()) {
             // <union-selector> ::= _ <number>
             if (FD->getParent()->isUnion()) {
               Out << '_';
@@ -5692,7 +5689,7 @@
             }
             TypeSoFar = FD->getType();
           } else {
-            TypeSoFar = Ctx.getRecordType(cast<CXXRecordDecl>(D));
+            TypeSoFar = Ctx.getRecordType(E.getAsBase());
           }
         }
       }
Index: clang/lib/AST/Interp/Pointer.cpp
===================================================================
--- clang/lib/AST/Interp/Pointer.cpp
+++ clang/lib/AST/Interp/Pointer.cpp
@@ -116,8 +116,8 @@
 
           // Create a path entry for the field.
           Descriptor *Desc = Ptr.getFieldDesc();
-          if (auto *BaseOrMember = Desc->asDecl()) {
-            Path.push_back(APValue::LValuePathEntry({BaseOrMember, IsVirtual}));
+          if (auto *D = Desc->asDecl()) {
+            Path.push_back(APValue::LValuePathEntry::Declaration(D, IsVirtual));
             Ptr = Ptr.getBase();
             continue;
           }
Index: clang/lib/AST/ExprConstant.cpp
===================================================================
--- clang/lib/AST/ExprConstant.cpp
+++ clang/lib/AST/ExprConstant.cpp
@@ -82,22 +82,6 @@
     return B.getType();
   }
 
-  /// Get an LValue path entry, which is known to not be an array index, as a
-  /// field declaration.
-  static const FieldDecl *getAsField(APValue::LValuePathEntry E) {
-    return dyn_cast_or_null<FieldDecl>(E.getAsBaseOrMember().getPointer());
-  }
-  /// Get an LValue path entry, which is known to not be an array index, as a
-  /// base class declaration.
-  static const CXXRecordDecl *getAsBaseClass(APValue::LValuePathEntry E) {
-    return dyn_cast_or_null<CXXRecordDecl>(E.getAsBaseOrMember().getPointer());
-  }
-  /// Determine whether this LValue path entry for a base class names a virtual
-  /// base class.
-  static bool isVirtualBaseClass(APValue::LValuePathEntry E) {
-    return E.getAsBaseOrMember().getInt();
-  }
-
   /// Given an expression, determine the type used to store the result of
   /// evaluating that expression.
   static QualType getStorageType(const ASTContext &Ctx, const Expr *E) {
@@ -218,7 +202,7 @@
         ArraySize = 2;
         MostDerivedLength = I + 1;
         IsArray = true;
-      } else if (const FieldDecl *FD = getAsField(Path[I])) {
+      } else if (const FieldDecl *FD = Path[I].getAsFieldOrNull()) {
         Type = FD->getType();
         ArraySize = 0;
         MostDerivedLength = I + 1;
@@ -384,7 +368,7 @@
       assert(!Invalid && "invalid designator has no subobject type");
       return MostDerivedPathLength == Entries.size()
                  ? MostDerivedType
-                 : Ctx.getRecordType(getAsBaseClass(Entries.back()));
+                 : Ctx.getRecordType(Entries.back().getAsBase());
     }
 
     /// Update this designator to refer to the first element within this array.
@@ -413,7 +397,7 @@
     /// Update this designator to refer to the given base or member of this
     /// object.
     void addDeclUnchecked(const Decl *D, bool Virtual = false) {
-      Entries.push_back(APValue::BaseOrMemberType(D, Virtual));
+      Entries.push_back(APValue::LValuePathEntry::Declaration(D, Virtual));
 
       // If this isn't a base class, it's a new most-derived object.
       if (const FieldDecl *FD = dyn_cast<FieldDecl>(D)) {
@@ -3038,8 +3022,8 @@
   for (unsigned I = TruncatedElements, N = D.Entries.size(); I != N; ++I) {
     if (RD->isInvalidDecl()) return false;
     const ASTRecordLayout &Layout = Info.Ctx.getASTRecordLayout(RD);
-    const CXXRecordDecl *Base = getAsBaseClass(D.Entries[I]);
-    if (isVirtualBaseClass(D.Entries[I]))
+    const CXXRecordDecl *Base = D.Entries[I].getAsBase();
+    if (D.Entries[I].isVirtualBase())
       Result.Offset -= Layout.getVBaseClassOffset(Base);
     else
       Result.Offset -= Layout.getBaseClassOffset(Base);
@@ -3741,7 +3725,7 @@
         return handler.found(Index ? O->getComplexFloatImag()
                                    : O->getComplexFloatReal(), ObjType);
       }
-    } else if (const FieldDecl *Field = getAsField(Sub.Entries[I])) {
+    } else if (const FieldDecl *Field = Sub.Entries[I].getAsFieldOrNull()) {
       if (Field->isMutable() &&
           !Obj.mayAccessMutableMembers(Info, handler.AccessKind)) {
         Info.FFDiag(E, diag::note_constexpr_access_mutable, 1)
@@ -3780,7 +3764,7 @@
     } else {
       // Next subobject is a base class.
       const CXXRecordDecl *Derived = ObjType->getAsCXXRecordDecl();
-      const CXXRecordDecl *Base = getAsBaseClass(Sub.Entries[I]);
+      const CXXRecordDecl *Base = Sub.Entries[I].getAsBase();
       O = &O->getStructBase(getBaseIndex(Derived, Base));
 
       ObjType = getSubobjectType(ObjType, Info.Ctx.getRecordType(Base));
@@ -3906,7 +3890,7 @@
         WasArrayIndex = false;
         return I;
       }
-      if (const FieldDecl *FD = getAsField(A.Entries[I]))
+      if (const FieldDecl *FD = A.Entries[I].getAsFieldOrNull())
         // Next subobject is a field.
         ObjType = FD->getType();
       else
@@ -4621,8 +4605,8 @@
     unsigned PathLengthToMember =
         LV.Designator.Entries.size() - MemPtr.Path.size();
     for (unsigned I = 0, N = MemPtr.Path.size(); I != N; ++I) {
-      const CXXRecordDecl *LVDecl = getAsBaseClass(
-          LV.Designator.Entries[PathLengthToMember + I]);
+      const CXXRecordDecl *LVDecl =
+          LV.Designator.Entries[PathLengthToMember + I].getAsBase();
       const CXXRecordDecl *MPDecl = MemPtr.Path[I];
       if (LVDecl->getCanonicalDecl() != MPDecl->getCanonicalDecl()) {
         Info.FFDiag(RHS);
@@ -4719,7 +4703,7 @@
   if (NewEntriesSize == D.MostDerivedPathLength)
     FinalType = D.MostDerivedType->getAsCXXRecordDecl();
   else
-    FinalType = getAsBaseClass(D.Entries[NewEntriesSize - 1]);
+    FinalType = D.Entries[NewEntriesSize - 1].getAsBase();
   if (FinalType->getCanonicalDecl() != TargetType->getCanonicalDecl()) {
     Info.CCEDiag(E, diag::note_constexpr_invalid_downcast)
       << D.MostDerivedType << TargetQT;
@@ -5574,7 +5558,7 @@
       Designator.Entries.size() && "invalid path length");
   return (PathLength == Designator.MostDerivedPathLength)
              ? Designator.MostDerivedType->getAsCXXRecordDecl()
-             : getAsBaseClass(Designator.Entries[PathLength - 1]);
+             : Designator.Entries[PathLength - 1].getAsBase();
 }
 
 /// Determine the dynamic type of an object.
@@ -5918,9 +5902,8 @@
 
       E = ME->getBase();
       --PathLength;
-      assert(declaresSameEntity(FD,
-                                LHS.Designator.Entries[PathLength]
-                                    .getAsBaseOrMember().getPointer()));
+      assert(declaresSameEntity(
+          FD, LHS.Designator.Entries[PathLength].getAsBaseOrMember()));
 
       //   -- If E is of the form A[B] and is interpreted as a built-in array
       //      subscripting operator, S(E) is [S(the array operand, if any)].
@@ -5945,9 +5928,9 @@
       for (const CXXBaseSpecifier *Elt : llvm::reverse(ICE->path())) {
         --PathLength;
         (void)Elt;
-        assert(declaresSameEntity(Elt->getType()->getAsCXXRecordDecl(),
-                                  LHS.Designator.Entries[PathLength]
-                                      .getAsBaseOrMember().getPointer()));
+        assert(
+            declaresSameEntity(Elt->getType()->getAsCXXRecordDecl(),
+                               LHS.Designator.Entries[PathLength].getAsBase()));
       }
 
     //   -- Otherwise, S(E) is empty.
@@ -11255,13 +11238,13 @@
       if (Index != 1)
         return false;
       BaseType = CT->getElementType();
-    } else if (auto *FD = getAsField(Entry)) {
+    } else if (auto *FD = Entry.getAsFieldOrNull()) {
       bool Invalid;
       if (!IsLastOrInvalidFieldDecl(FD, Invalid))
         return Invalid;
       BaseType = FD->getType();
     } else {
-      assert(getAsBaseClass(Entry) && "Expecting cast to a base class");
+      assert(Entry.getAsBase() && "Expecting cast to a base class");
       return false;
     }
   }
@@ -12697,18 +12680,20 @@
       // constant expression.
       if (!WasArrayIndex && Mismatch < LHSDesignator.Entries.size() &&
           Mismatch < RHSDesignator.Entries.size()) {
-        const FieldDecl *LF = getAsField(LHSDesignator.Entries[Mismatch]);
-        const FieldDecl *RF = getAsField(RHSDesignator.Entries[Mismatch]);
+        const FieldDecl *LF =
+            LHSDesignator.Entries[Mismatch].getAsFieldOrNull();
+        const FieldDecl *RF =
+            RHSDesignator.Entries[Mismatch].getAsFieldOrNull();
         if (!LF && !RF)
           Info.CCEDiag(E, diag::note_constexpr_pointer_comparison_base_classes);
         else if (!LF)
           Info.CCEDiag(E, diag::note_constexpr_pointer_comparison_base_field)
-              << getAsBaseClass(LHSDesignator.Entries[Mismatch])
-              << RF->getParent() << RF;
+              << LHSDesignator.Entries[Mismatch].getAsBase() << RF->getParent()
+              << RF;
         else if (!RF)
           Info.CCEDiag(E, diag::note_constexpr_pointer_comparison_base_field)
-              << getAsBaseClass(RHSDesignator.Entries[Mismatch])
-              << LF->getParent() << LF;
+              << RHSDesignator.Entries[Mismatch].getAsBase() << LF->getParent()
+              << LF;
         else if (!LF->getParent()->isUnion() &&
                  LF->getAccess() != RF->getAccess())
           Info.CCEDiag(E,
Index: clang/lib/AST/ASTImporter.cpp
===================================================================
--- clang/lib/AST/ASTImporter.cpp
+++ clang/lib/AST/ASTImporter.cpp
@@ -9269,17 +9269,20 @@
           FromValue.getLValuePath();
       for (unsigned LoopIdx = 0; LoopIdx < PathLength; LoopIdx++) {
         if (FromElemTy->isRecordType()) {
-          const Decl *FromDecl =
-              FromPath[LoopIdx].getAsBaseOrMember().getPointer();
+          const Decl *FromDecl = FromPath[LoopIdx].getAsBaseOrMember();
           const Decl *ImpDecl = importChecked(Err, FromDecl);
           if (Err)
             return std::move(Err);
-          if (auto *RD = dyn_cast<CXXRecordDecl>(FromDecl))
+          if (auto *RD = dyn_cast<CXXRecordDecl>(FromDecl)) {
             FromElemTy = Importer.FromContext.getRecordType(RD);
-          else
+            ToPath[LoopIdx] =
+                APValue::LValuePathEntry(cast<CXXRecordDecl>(ImpDecl),
+                                         FromPath[LoopIdx].isVirtualBase());
+          } else {
             FromElemTy = cast<ValueDecl>(FromDecl)->getType();
-          ToPath[LoopIdx] = APValue::LValuePathEntry(APValue::BaseOrMemberType(
-              ImpDecl, FromPath[LoopIdx].getAsBaseOrMember().getInt()));
+            ToPath[LoopIdx] =
+                APValue::LValuePathEntry(cast<FieldDecl>(ImpDecl));
+          }
         } else {
           FromElemTy =
               Importer.FromContext.getAsArrayType(FromElemTy)->getElementType();
Index: clang/lib/AST/APValue.cpp
===================================================================
--- clang/lib/AST/APValue.cpp
+++ clang/lib/AST/APValue.cpp
@@ -144,14 +144,28 @@
 }
 }
 
-APValue::LValuePathEntry::LValuePathEntry(BaseOrMemberType BaseOrMember) {
-  if (const Decl *D = BaseOrMember.getPointer())
-    BaseOrMember.setPointer(D->getCanonicalDecl());
-  Value = reinterpret_cast<uintptr_t>(BaseOrMember.getOpaqueValue());
+APValue::LValuePathEntry::LValuePathEntry(const CXXRecordDecl *Base,
+                                          bool Virtual) {
+  Value.setPointerAndInt(Base, Virtual ? Kind::VirtualBase : Kind::Base);
+}
+
+APValue::LValuePathEntry::LValuePathEntry(const FieldDecl *Field) {
+  Value.setPointerAndInt(Field, Kind::Field);
+}
+
+APValue::LValuePathEntry::LValuePathEntry(size_t Index) {
+  Value.setPointerAndInt(reinterpret_cast<void *>(Index << 2), Kind::Index);
+}
+
+APValue::LValuePathEntry APValue::LValuePathEntry::Declaration(const Decl *D,
+                                                               bool Virtual) {
+  if (auto RD = dyn_cast<CXXRecordDecl>(D))
+    return LValuePathEntry(RD, Virtual);
+  return LValuePathEntry(cast<FieldDecl>(D));
 }
 
 void APValue::LValuePathEntry::Profile(llvm::FoldingSetNodeID &ID) const {
-  ID.AddInteger(Value);
+  ID.AddPointer(Value.getOpaqueValue());
 }
 
 APValue::LValuePathSerializationHelper::LValuePathSerializationHelper(
@@ -761,13 +775,12 @@
       if (ElemTy->isRecordType()) {
         // The lvalue refers to a class type, so the next path entry is a base
         // or member.
-        const Decl *BaseOrMember = Path[I].getAsBaseOrMember().getPointer();
-        if (const CXXRecordDecl *RD = dyn_cast<CXXRecordDecl>(BaseOrMember)) {
+        if (const CXXRecordDecl *RD = Path[I].getAsBaseOrNull()) {
           CastToBase = RD;
           // Leave ElemTy referring to the most-derived class. The actual type
           // doesn't matter except for array types.
         } else {
-          const ValueDecl *VD = cast<ValueDecl>(BaseOrMember);
+          const FieldDecl *VD = Path[I].getAsField();
           Out << ".";
           if (CastToBase)
             Out << *CastToBase << "::";
Index: clang/include/clang/AST/AbstractBasicWriter.h
===================================================================
--- clang/include/clang/AST/AbstractBasicWriter.h
+++ clang/include/clang/AST/AbstractBasicWriter.h
@@ -181,15 +181,15 @@
     auto &ctx = ((BasicWriterBase<Impl> *)this)->getASTContext();
     for (auto elem : path) {
       if (elemTy->getAs<RecordType>()) {
-        asImpl().writeUInt32(elem.getAsBaseOrMember().getInt());
-        const Decl *baseOrMember = elem.getAsBaseOrMember().getPointer();
-        if (const auto *recordDecl = dyn_cast<CXXRecordDecl>(baseOrMember)) {
-          asImpl().writeDeclRef(recordDecl);
-          elemTy = ctx.getRecordType(recordDecl);
-        } else {
-          const auto *valueDecl = cast<ValueDecl>(baseOrMember);
-          asImpl().writeDeclRef(valueDecl);
-          elemTy = valueDecl->getType();
+        asImpl().writeUInt32(elem.isVirtualBase());
+        if (elem.isAnyBase()) {
+          const CXXRecordDecl *D = elem.getAsBase();
+          asImpl().writeDeclRef(D);
+          elemTy = ctx.getRecordType(D);
+        } else if (elem.isField()) {
+          const FieldDecl *D = elem.getAsField();
+          asImpl().writeDeclRef(D);
+          elemTy = D->getType();
         }
       } else {
         asImpl().writeUInt32(elem.getAsArrayIndex());
Index: clang/include/clang/AST/AbstractBasicReader.h
===================================================================
--- clang/include/clang/AST/AbstractBasicReader.h
+++ clang/include/clang/AST/AbstractBasicReader.h
@@ -194,14 +194,16 @@
     unsigned pathLength = asImpl().readUInt32();
     for (unsigned i = 0; i < pathLength; ++i) {
       if (elemTy->template getAs<RecordType>()) {
-        unsigned int_ = asImpl().readUInt32();
-        Decl *decl = asImpl().template readDeclAs<Decl>();
-        if (auto *recordDecl = dyn_cast<CXXRecordDecl>(decl))
-          elemTy = getASTContext().getRecordType(recordDecl);
-        else
-          elemTy = cast<ValueDecl>(decl)->getType();
-        path.push_back(
-            APValue::LValuePathEntry(APValue::BaseOrMemberType(decl, int_)));
+        unsigned IsVirtualBase = asImpl().readUInt32();
+        Decl *D = asImpl().template readDeclAs<Decl>();
+        if (auto *RD = dyn_cast<CXXRecordDecl>(D)) {
+          elemTy = getASTContext().getRecordType(RD);
+          path.push_back(APValue::LValuePathEntry(RD, IsVirtualBase));
+        } else {
+          auto FD = cast<FieldDecl>(D);
+          elemTy = FD->getType();
+          path.push_back(APValue::LValuePathEntry(FD));
+        }
       } else {
         elemTy = getASTContext().getAsArrayType(elemTy)->getElementType();
         path.push_back(
Index: clang/include/clang/AST/APValue.h
===================================================================
--- clang/include/clang/AST/APValue.h
+++ clang/include/clang/AST/APValue.h
@@ -204,26 +204,55 @@
   /// mean a virtual or non-virtual base class subobject.
   typedef llvm::PointerIntPair<const Decl *, 1, bool> BaseOrMemberType;
 
-  /// A non-discriminated union of a base, field, or array index.
+  /// A discriminated union of a base, field, or array index.
   class LValuePathEntry {
-    static_assert(sizeof(uintptr_t) <= sizeof(uint64_t),
-                  "pointer doesn't fit in 64 bits?");
-    uint64_t Value;
+    enum class Kind {
+      Base,
+      VirtualBase,
+      Field,
+      Index
+    };
+    llvm::PointerIntPair<const void *, 2, Kind> Value;
 
   public:
     LValuePathEntry() : Value() {}
-    LValuePathEntry(BaseOrMemberType BaseOrMember);
+    LValuePathEntry(const CXXRecordDecl *Base, bool Virtual);
+    LValuePathEntry(const FieldDecl *Field);
+    LValuePathEntry(size_t Index);
     static LValuePathEntry ArrayIndex(uint64_t Index) {
-      LValuePathEntry Result;
-      Result.Value = Index;
-      return Result;
+      return LValuePathEntry(static_cast<size_t>(Index));
+    }
+    static LValuePathEntry Declaration(const Decl *D, bool Virtual);
+
+    bool isBase() const { return Value.getInt() == Kind::Base; }
+    bool isVirtualBase() const { return Value.getInt() == Kind::VirtualBase; }
+    bool isAnyBase() const { return isBase() || isVirtualBase(); }
+    bool isField() const { return Value.getInt() == Kind::Field; }
+    bool isArrayIndex() const { return Value.getInt() == Kind::Index; }
+
+    const CXXRecordDecl *getAsBase() const {
+      assert(isAnyBase() && "Not a base class");
+      return static_cast<const CXXRecordDecl *>(Value.getPointer());
+    }
+    const FieldDecl *getAsField() const {
+      assert(isField() && "Not a field");
+      return static_cast<const FieldDecl *>(Value.getPointer());
+    }
+    uint64_t getAsArrayIndex() const {
+      assert((Value.getInt() == Kind::Index) && "Not an index");
+      return reinterpret_cast<uintptr_t>(Value.getOpaqueValue()) >> 2;
+    }
+    const Decl *getAsBaseOrMember() const {
+      assert((isAnyBase() || isField()) && "Not a declaration");
+      return static_cast<const Decl *>(Value.getPointer());
     }
 
-    BaseOrMemberType getAsBaseOrMember() const {
-      return BaseOrMemberType::getFromOpaqueValue(
-          reinterpret_cast<void *>(Value));
+    const CXXRecordDecl *getAsBaseOrNull() const {
+      return isAnyBase() ? getAsBase() : nullptr;
+    }
+    const FieldDecl *getAsFieldOrNull() const {
+      return isField() ? getAsField() : nullptr;
     }
-    uint64_t getAsArrayIndex() const { return Value; }
 
     void Profile(llvm::FoldingSetNodeID &ID) const;
 
@@ -234,7 +263,7 @@
       return A.Value != B.Value;
     }
     friend llvm::hash_code hash_value(LValuePathEntry A) {
-      return llvm::hash_value(A.Value);
+      return llvm::hash_value(A.Value.getOpaqueValue());
     }
   };
   class LValuePathSerializationHelper {
_______________________________________________
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to