r219522 - Change how we distinguish bitfield widths, in-class

John McCall rjmccall at apple.com
Fri Oct 10 11:44:34 PDT 2014


Author: rjmccall
Date: Fri Oct 10 13:44:34 2014
New Revision: 219522

URL: http://llvm.org/viewvc/llvm-project?rev=219522&view=rev
Log:
Change how we distinguish bitfield widths, in-class
initializers, and captured VLA types so that we can
answer questions like "is this a bit-field" without
looking at the enclosing DeclContext.  NFC.

Modified:
    cfe/trunk/include/clang/AST/Decl.h
    cfe/trunk/lib/AST/Decl.cpp
    cfe/trunk/lib/Serialization/ASTReaderDecl.cpp
    cfe/trunk/lib/Serialization/ASTWriterDecl.cpp

Modified: cfe/trunk/include/clang/AST/Decl.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/AST/Decl.h?rev=219522&r1=219521&r2=219522&view=diff
==============================================================================
--- cfe/trunk/include/clang/AST/Decl.h (original)
+++ cfe/trunk/include/clang/AST/Decl.h Fri Oct 10 13:44:34 2014
@@ -2168,18 +2168,41 @@ class FieldDecl : public DeclaratorDecl,
   bool Mutable : 1;
   mutable unsigned CachedFieldIndex : 31;
 
-  /// \brief An InClassInitStyle value, and either a bit width expression (if
-  /// the InClassInitStyle value is ICIS_NoInit) in struct/class, or a captured
-  /// variable length array bound in a lambda expression, or a pointer to the
-  /// in-class initializer for this field (otherwise).
+  /// The kinds of value we can store in InitializerOrBitWidth.
   ///
-  /// We can safely combine these two because in-class initializers are not
-  /// permitted for bit-fields.
+  /// Note that this is compatible with InClassInitStyle except for
+  /// ISK_CapturedVLAType.
+  enum InitStorageKind {
+    /// If the pointer is null, there's nothing special.  Otherwise,
+    /// this is a bitfield and the pointer is the Expr* storing the
+    /// bit-width.
+    ISK_BitWidthOrNothing = (unsigned) ICIS_NoInit,
+
+    /// The pointer is an (optional due to delayed parsing) Expr*
+    /// holding the copy-initializer.
+    ISK_InClassCopyInit = (unsigned) ICIS_CopyInit,
+
+    /// The pointer is an (optional due to delayed parsing) Expr*
+    /// holding the list-initializer.
+    ISK_InClassListInit = (unsigned) ICIS_ListInit,
+
+    /// The pointer is a VariableArrayType* that's been captured;
+    /// the enclosing context is a lambda or captured statement.
+    ISK_CapturedVLAType,
+  };
+
+  /// \brief Storage for either the bit-width, the in-class
+  /// initializer, or the captured variable length array bound.
+  ///
+  /// We can safely combine these because in-class initializers are
+  /// not permitted for bit-fields, and both are exclusive with VLA
+  /// captures.
   ///
-  /// If the InClassInitStyle is not ICIS_NoInit and the initializer is null,
-  /// then this field has an in-class initializer which has not yet been parsed
+  /// If the storage kind is ISK_InClassCopyInit or
+  /// ISK_InClassListInit, but the initializer is null, then this
+  /// field has an in-class initializer which has not yet been parsed
   /// and attached.
-  llvm::PointerIntPair<void *, 2, unsigned> InitializerOrBitWidth;
+  llvm::PointerIntPair<void *, 2, InitStorageKind> InitStorage;
 protected:
   FieldDecl(Kind DK, DeclContext *DC, SourceLocation StartLoc,
             SourceLocation IdLoc, IdentifierInfo *Id,
@@ -2187,7 +2210,7 @@ protected:
             InClassInitStyle InitStyle)
     : DeclaratorDecl(DK, DC, IdLoc, Id, T, TInfo, StartLoc),
       Mutable(Mutable), CachedFieldIndex(0),
-      InitializerOrBitWidth(BW, InitStyle) {
+      InitStorage(BW, (InitStorageKind) InitStyle) {
     assert((!BW || InitStyle == ICIS_NoInit) && "got initializer for bitfield");
   }
 
@@ -2208,7 +2231,10 @@ public:
   bool isMutable() const { return Mutable; }
 
   /// \brief Determines whether this field is a bitfield.
-  bool isBitField() const;
+  bool isBitField() const {
+    return InitStorage.getInt() == ISK_BitWidthOrNothing &&
+           InitStorage.getPointer() != nullptr;
+  }
 
   /// @brief Determines whether this is an unnamed bitfield.
   bool isUnnamedBitfield() const { return isBitField() && !getDeclName(); }
@@ -2221,25 +2247,33 @@ public:
 
   Expr *getBitWidth() const {
     return isBitField()
-               ? static_cast<Expr *>(InitializerOrBitWidth.getPointer())
+               ? static_cast<Expr *>(InitStorage.getPointer())
                : nullptr;
   }
   unsigned getBitWidthValue(const ASTContext &Ctx) const;
 
   /// setBitWidth - Set the bit-field width for this member.
   // Note: used by some clients (i.e., do not remove it).
-  void setBitWidth(Expr *Width);
+  void setBitWidth(Expr *Width) {
+    assert(InitStorage.getInt() == ISK_BitWidthOrNothing &&
+           InitStorage.getPointer() == nullptr &&
+           "bit width, initializer or captured type already set");
+    InitStorage.setPointerAndInt(Width, ISK_BitWidthOrNothing);
+  }
+
   /// removeBitWidth - Remove the bit-field width from this member.
   // Note: used by some clients (i.e., do not remove it).
   void removeBitWidth() {
     assert(isBitField() && "no bitfield width to remove");
-    InitializerOrBitWidth.setPointer(nullptr);
+    InitStorage.setPointerAndInt(nullptr, ISK_BitWidthOrNothing);
   }
 
   /// getInClassInitStyle - Get the kind of (C++11) in-class initializer which
   /// this field has.
   InClassInitStyle getInClassInitStyle() const {
-    return static_cast<InClassInitStyle>(InitializerOrBitWidth.getInt());
+    InitStorageKind storageKind = InitStorage.getInt();
+    return (storageKind == ISK_CapturedVLAType
+              ? ICIS_NoInit : (InClassInitStyle) storageKind);
   }
 
   /// hasInClassInitializer - Determine whether this member has a C++11 in-class
@@ -2247,33 +2281,43 @@ public:
   bool hasInClassInitializer() const {
     return getInClassInitStyle() != ICIS_NoInit;
   }
+
   /// getInClassInitializer - Get the C++11 in-class initializer for this
   /// member, or null if one has not been set. If a valid declaration has an
   /// in-class initializer, but this returns null, then we have not parsed and
   /// attached it yet.
   Expr *getInClassInitializer() const {
     return hasInClassInitializer()
-               ? static_cast<Expr *>(InitializerOrBitWidth.getPointer())
+               ? static_cast<Expr *>(InitStorage.getPointer())
                : nullptr;
   }
+
   /// setInClassInitializer - Set the C++11 in-class initializer for this
   /// member.
-  void setInClassInitializer(Expr *Init);
+  void setInClassInitializer(Expr *Init) {
+    assert(hasInClassInitializer() &&
+           InitStorage.getPointer() == nullptr &&
+           "bit width, initializer or captured type already set");
+    InitStorage.setPointer(Init);
+  }
+
   /// removeInClassInitializer - Remove the C++11 in-class initializer from this
   /// member.
   void removeInClassInitializer() {
     assert(hasInClassInitializer() && "no initializer to remove");
-    InitializerOrBitWidth.setPointer(nullptr);
-    InitializerOrBitWidth.setInt(ICIS_NoInit);
+    InitStorage.setPointerAndInt(nullptr, ISK_BitWidthOrNothing);
   }
 
   /// \brief Determine whether this member captures the variable length array
   /// type.
-  bool hasCapturedVLAType() const;
+  bool hasCapturedVLAType() const {
+    return InitStorage.getInt() == ISK_CapturedVLAType;
+  }
+
   /// \brief Get the captured variable length array type.
   const VariableArrayType *getCapturedVLAType() const {
     return hasCapturedVLAType() ? static_cast<const VariableArrayType *>(
-                                      InitializerOrBitWidth.getPointer())
+                                      InitStorage.getPointer())
                                 : nullptr;
   }
   /// \brief Set the captured variable length array type for this field.

Modified: cfe/trunk/lib/AST/Decl.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/AST/Decl.cpp?rev=219522&r1=219521&r2=219522&view=diff
==============================================================================
--- cfe/trunk/lib/AST/Decl.cpp (original)
+++ cfe/trunk/lib/AST/Decl.cpp Fri Oct 10 13:44:34 2014
@@ -3282,18 +3282,9 @@ bool FieldDecl::isAnonymousStructOrUnion
   return false;
 }
 
-bool FieldDecl::isBitField() const {
-  if (getInClassInitStyle() == ICIS_NoInit &&
-      InitializerOrBitWidth.getPointer()) {
-    assert(getDeclContext() && "No parent context for FieldDecl");
-    return !getDeclContext()->isRecord() || !getParent()->isLambda();
-  }
-  return false;
-}
-
 unsigned FieldDecl::getBitWidthValue(const ASTContext &Ctx) const {
   assert(isBitField() && "not a bitfield");
-  Expr *BitWidth = static_cast<Expr *>(InitializerOrBitWidth.getPointer());
+  Expr *BitWidth = static_cast<Expr *>(InitStorage.getPointer());
   return BitWidth->EvaluateKnownConstInt(Ctx).getZExtValue();
 }
 
@@ -3317,34 +3308,28 @@ unsigned FieldDecl::getFieldIndex() cons
 }
 
 SourceRange FieldDecl::getSourceRange() const {
-  if (const Expr *E =
-          static_cast<const Expr *>(InitializerOrBitWidth.getPointer()))
-    return SourceRange(getInnerLocStart(), E->getLocEnd());
-  return DeclaratorDecl::getSourceRange();
-}
+  switch (InitStorage.getInt()) {
+  // All three of these cases store an optional Expr*.
+  case ISK_BitWidthOrNothing:
+  case ISK_InClassCopyInit:
+  case ISK_InClassListInit:
+    if (const Expr *E = static_cast<const Expr *>(InitStorage.getPointer()))
+      return SourceRange(getInnerLocStart(), E->getLocEnd());
+    // FALLTHROUGH
 
-void FieldDecl::setBitWidth(Expr *Width) {
-  assert(!InitializerOrBitWidth.getPointer() && !hasInClassInitializer() &&
-         "bit width, initializer or captured type already set");
-  InitializerOrBitWidth.setPointer(Width);
-}
-
-void FieldDecl::setInClassInitializer(Expr *Init) {
-  assert(!InitializerOrBitWidth.getPointer() && hasInClassInitializer() &&
-         "bit width, initializer or captured expr already set");
-  InitializerOrBitWidth.setPointer(Init);
-}
-
-bool FieldDecl::hasCapturedVLAType() const {
-  return getDeclContext()->isRecord() && getParent()->isLambda() &&
-         InitializerOrBitWidth.getPointer();
+  case ISK_CapturedVLAType:
+    return DeclaratorDecl::getSourceRange();
+  }
+  llvm_unreachable("bad init storage kind");
 }
 
 void FieldDecl::setCapturedVLAType(const VariableArrayType *VLAType) {
   assert(getParent()->isLambda() && "capturing type in non-lambda.");
-  assert(!InitializerOrBitWidth.getPointer() && !hasInClassInitializer() &&
+  assert(InitStorage.getInt() == ISK_BitWidthOrNothing &&
+         InitStorage.getPointer() == nullptr &&
          "bit width, initializer or captured type already set");
-  InitializerOrBitWidth.setPointer(const_cast<VariableArrayType *>(VLAType));
+  InitStorage.setPointerAndInt(const_cast<VariableArrayType *>(VLAType),
+                               ISK_CapturedVLAType);
 }
 
 //===----------------------------------------------------------------------===//

Modified: cfe/trunk/lib/Serialization/ASTReaderDecl.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Serialization/ASTReaderDecl.cpp?rev=219522&r1=219521&r2=219522&view=diff
==============================================================================
--- cfe/trunk/lib/Serialization/ASTReaderDecl.cpp (original)
+++ cfe/trunk/lib/Serialization/ASTReaderDecl.cpp Fri Oct 10 13:44:34 2014
@@ -1000,13 +1000,14 @@ void ASTDeclReader::VisitFieldDecl(Field
   VisitDeclaratorDecl(FD);
   FD->Mutable = Record[Idx++];
   if (int BitWidthOrInitializer = Record[Idx++]) {
-    FD->InitializerOrBitWidth.setInt(BitWidthOrInitializer - 1);
-    if (FD->getDeclContext()->isRecord() && FD->getParent()->isLambda()) {
+    FD->InitStorage.setInt(
+          static_cast<FieldDecl::InitStorageKind>(BitWidthOrInitializer - 1));
+    if (FD->InitStorage.getInt() == FieldDecl::ISK_CapturedVLAType) {
       // Read captured variable length array.
-      FD->InitializerOrBitWidth.setPointer(
+      FD->InitStorage.setPointer(
           Reader.readType(F, Record, Idx).getAsOpaquePtr());
     } else {
-      FD->InitializerOrBitWidth.setPointer(Reader.ReadExpr(F));
+      FD->InitStorage.setPointer(Reader.ReadExpr(F));
     }
   }
   if (!FD->getDeclName()) {

Modified: cfe/trunk/lib/Serialization/ASTWriterDecl.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Serialization/ASTWriterDecl.cpp?rev=219522&r1=219521&r2=219522&view=diff
==============================================================================
--- cfe/trunk/lib/Serialization/ASTWriterDecl.cpp (original)
+++ cfe/trunk/lib/Serialization/ASTWriterDecl.cpp Fri Oct 10 13:44:34 2014
@@ -677,18 +677,17 @@ void ASTDeclWriter::VisitObjCPropertyImp
 void ASTDeclWriter::VisitFieldDecl(FieldDecl *D) {
   VisitDeclaratorDecl(D);
   Record.push_back(D->isMutable());
-  if ((D->InitializerOrBitWidth.getInt() != ICIS_NoInit ||
-       D->InitializerOrBitWidth.getPointer()) &&
-      !D->hasCapturedVLAType()) {
-    Record.push_back(D->InitializerOrBitWidth.getInt() + 1);
-    Writer.AddStmt(static_cast<Expr *>(D->InitializerOrBitWidth.getPointer()));
-  } else if (D->hasCapturedVLAType()) {
-    Record.push_back(D->InitializerOrBitWidth.getInt() + 1);
+  if (D->InitStorage.getInt() == FieldDecl::ISK_BitWidthOrNothing &&
+      D->InitStorage.getPointer() == nullptr) {
+    Record.push_back(0);
+  } else if (D->InitStorage.getInt() == FieldDecl::ISK_CapturedVLAType) {
+    Record.push_back(D->InitStorage.getInt() + 1);
     Writer.AddTypeRef(
-        QualType(static_cast<Type *>(D->InitializerOrBitWidth.getPointer()), 0),
+        QualType(static_cast<Type *>(D->InitStorage.getPointer()), 0),
         Record);
   } else {
-    Record.push_back(0);
+    Record.push_back(D->InitStorage.getInt() + 1);
+    Writer.AddStmt(static_cast<Expr *>(D->InitStorage.getPointer()));
   }
   if (!D->getDeclName())
     Writer.AddDeclRef(Context.getInstantiatedFromUnnamedFieldDecl(D), Record);





More information about the cfe-commits mailing list