]> granicus.if.org Git - clang/commitdiff
Add PCH support for enumerations and enumerators.
authorDouglas Gregor <dgregor@apple.com>
Mon, 13 Apr 2009 18:14:40 +0000 (18:14 +0000)
committerDouglas Gregor <dgregor@apple.com>
Mon, 13 Apr 2009 18:14:40 +0000 (18:14 +0000)
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@68974 91177308-0d34-0410-b5e6-96231b3b80d8

include/clang/AST/Decl.h
include/clang/Frontend/PCHBitCodes.h
include/clang/Frontend/PCHReader.h
include/clang/Frontend/PCHWriter.h
lib/Frontend/PCHReader.cpp
lib/Frontend/PCHWriter.cpp
test/PCH/enum.c [new file with mode: 0644]
test/PCH/enum.h [new file with mode: 0644]

index f954934898e385fdfebbb9c6d458c271e8e63746..f1626890920d8393f1db9b13865cb9ae65f467f7 100644 (file)
@@ -992,6 +992,8 @@ public:
     return TagKind(TagDeclKind);
   }
 
+  void setTagKind(TagKind TK) { TagDeclKind = TK; }
+
   bool isStruct() const { return getTagKind() == TK_struct; }
   bool isClass()  const { return getTagKind() == TK_class; }
   bool isUnion()  const { return getTagKind() == TK_union; }
@@ -1013,7 +1015,6 @@ public:
     return static_cast<TagDecl *>(const_cast<DeclContext*>(DC));
   }
 
-protected:
   void setDefinition(bool V) { IsDefinition = V; }
 };
 
@@ -1059,7 +1060,10 @@ public:
   /// getIntegerType - Return the integer type this enum decl corresponds to.
   /// This returns a null qualtype for an enum forward definition.
   QualType getIntegerType() const { return IntegerType; }
-    
+
+  /// \brief Set the underlying integer type.
+  void setIntegerType(QualType T) { IntegerType = T; }
+
   static bool classof(const Decl *D) { return D->getKind() == Enum; }
   static bool classof(const EnumDecl *D) { return true; }
   
index 79d70c8a61909cf208bd5d19b77d210f18eaee73..fe3d8ed86c14381eac969c807d8c9ade2cb84d8b 100644 (file)
@@ -314,6 +314,10 @@ namespace clang {
       DECL_TRANSLATION_UNIT = 1,
       /// \brief A TypedefDecl record.
       DECL_TYPEDEF,
+      /// \brief An EnumDecl record.
+      DECL_ENUM,
+      /// \brief An EnumConstantDecl record.
+      DECL_ENUM_CONSTANT,
       /// \brief A VarDecl record.
       DECL_VAR,
       /// \brief A record that stores the set of declarations that are
index b59790ddaf4cd89616ff9395a6a7502eccc0d905..3490cb50708fb3a9197786e3e0b4931b4b5ea50f 100644 (file)
@@ -18,6 +18,8 @@
 #include "clang/AST/ExternalASTSource.h"
 #include "clang/AST/Type.h"
 #include "clang/Basic/Diagnostic.h"
+#include "llvm/ADT/APInt.h"
+#include "llvm/ADT/APSInt.h"
 #include "llvm/ADT/DenseMap.h"
 #include "llvm/ADT/OwningPtr.h"
 #include "llvm/ADT/SmallVector.h"
@@ -201,6 +203,12 @@ public:
     return DecodeIdentifierInfo(Record[Idx++]);
   }
   DeclarationName ReadDeclarationName(const RecordData &Record, unsigned &Idx);
+
+  /// \brief Read an integral value
+  llvm::APInt ReadAPInt(const RecordData &Record, unsigned &Idx);
+
+  /// \brief Read a signed integral value
+  llvm::APSInt ReadAPSInt(const RecordData &Record, unsigned &Idx);
 };
 
 } // end namespace clang
index 92bab50db59ece6a0034a6277a59bf04458f93c0..a899fb43e6e0512b63d0792ee6a53db5579abd5b 100644 (file)
@@ -112,6 +112,9 @@ public:
   /// \brief Emit an integral value.
   void AddAPInt(const llvm::APInt &Value, RecordData &Record);
 
+  /// \brief Emit a signed integral value.
+  void AddAPSInt(const llvm::APSInt &Value, RecordData &Record);
+
   /// \brief Emit a reference to an identifier
   void AddIdentifierRef(const IdentifierInfo *II, RecordData &Record);
 
index 9a0061ea0eed264a8aa42bb4a170e8c8b7ed0793..99c33613c842a682527cc9216445351b3a68a034 100644 (file)
@@ -48,7 +48,10 @@ namespace {
     void VisitNamedDecl(NamedDecl *ND);
     void VisitTypeDecl(TypeDecl *TD);
     void VisitTypedefDecl(TypedefDecl *TD);
+    void VisitTagDecl(TagDecl *TD);
+    void VisitEnumDecl(EnumDecl *ED);
     void VisitValueDecl(ValueDecl *VD);
+    void VisitEnumConstantDecl(EnumConstantDecl *ECD);
     void VisitVarDecl(VarDecl *VD);
 
     std::pair<uint64_t, uint64_t> VisitDeclContext(DeclContext *DC);
@@ -86,11 +89,30 @@ void PCHDeclReader::VisitTypedefDecl(TypedefDecl *TD) {
   TD->setUnderlyingType(Reader.GetType(Record[Idx++]));
 }
 
+void PCHDeclReader::VisitTagDecl(TagDecl *TD) {
+  VisitTypeDecl(TD);
+  TD->setTagKind((TagDecl::TagKind)Record[Idx++]);
+  TD->setDefinition(Record[Idx++]);
+  TD->setTypedefForAnonDecl(
+                    cast_or_null<TypedefDecl>(Reader.GetDecl(Record[Idx++])));
+}
+
+void PCHDeclReader::VisitEnumDecl(EnumDecl *ED) {
+  VisitTagDecl(ED);
+  ED->setIntegerType(Reader.GetType(Record[Idx++]));
+}
+
 void PCHDeclReader::VisitValueDecl(ValueDecl *VD) {
   VisitNamedDecl(VD);
   VD->setType(Reader.GetType(Record[Idx++]));
 }
 
+void PCHDeclReader::VisitEnumConstantDecl(EnumConstantDecl *ECD) {
+  VisitValueDecl(ECD);
+  // FIXME: initialization expression
+  ECD->setInitVal(Reader.ReadAPSInt(Record, Idx));
+}
+
 void PCHDeclReader::VisitVarDecl(VarDecl *VD) {
   VisitValueDecl(VD);
   VD->setStorageClass((VarDecl::StorageClass)Record[Idx++]);
@@ -795,6 +817,10 @@ QualType PCHReader::ReadTypeRecord(uint64_t Offset) {
     return Context.getMemberPointerType(PointeeType, ClassType.getTypePtr());
   }
 
+  case pch::TYPE_ENUM:
+    assert(Record.size() == 1 && "Incorrect encoding of enum type");
+    return Context.getTypeDeclType(cast<EnumDecl>(GetDecl(Record[0])));
+
     // FIXME: Several other kinds of types to deserialize here!
   default:
     assert(false && "Unable to deserialize this type");
@@ -842,6 +868,25 @@ Decl *PCHReader::ReadDeclRecord(uint64_t Offset, unsigned Index) {
     break;
   }
 
+  case pch::DECL_ENUM: {
+    EnumDecl *Enum = EnumDecl::Create(Context, 0, SourceLocation(), 0, 0);
+    LoadedDecl(Index, Enum);
+    Reader.VisitEnumDecl(Enum);
+    D = Enum;
+    break;
+  }
+
+  case pch::DECL_ENUM_CONSTANT: {
+    EnumConstantDecl *ECD = EnumConstantDecl::Create(Context, 0, 
+                                                     SourceLocation(), 0,
+                                                     QualType(), 0,
+                                                     llvm::APSInt());
+    LoadedDecl(Index, ECD);
+    Reader.VisitEnumConstantDecl(ECD);
+    D = ECD;
+    break;
+  }
+
   case pch::DECL_VAR: {
     VarDecl *Var = VarDecl::Create(Context, 0, SourceLocation(), 0, QualType(),
                                    VarDecl::None, SourceLocation());
@@ -1064,6 +1109,21 @@ PCHReader::ReadDeclarationName(const RecordData &Record, unsigned &Idx) {
   return DeclarationName();
 }
 
+/// \brief Read an integral value
+llvm::APInt PCHReader::ReadAPInt(const RecordData &Record, unsigned &Idx) {
+  unsigned BitWidth = Record[Idx++];
+  unsigned NumWords = llvm::APInt::getNumWords(BitWidth);
+  llvm::APInt Result(BitWidth, NumWords, &Record[Idx]);
+  Idx += NumWords;
+  return Result;
+}
+
+/// \brief Read a signed integral value
+llvm::APSInt PCHReader::ReadAPSInt(const RecordData &Record, unsigned &Idx) {
+  bool isUnsigned = Record[Idx++];
+  return llvm::APSInt(ReadAPInt(Record, Idx), isUnsigned);
+}
+
 DiagnosticBuilder PCHReader::Diag(unsigned DiagID) {
   return Diag(SourceLocation(), DiagID);
 }
index 6056fbc53925d4d9f9d82659e5ee56662a333db6..2ba8e9eeb617f4b885525cb83ea8ba94579a4197 100644 (file)
@@ -252,9 +252,11 @@ namespace {
     void VisitNamedDecl(NamedDecl *D);
     void VisitTypeDecl(TypeDecl *D);
     void VisitTypedefDecl(TypedefDecl *D);
+    void VisitTagDecl(TagDecl *D);
+    void VisitEnumDecl(EnumDecl *D);
     void VisitValueDecl(ValueDecl *D);
+    void VisitEnumConstantDecl(EnumConstantDecl *D);
     void VisitVarDecl(VarDecl *D);
-
     void VisitDeclContext(DeclContext *DC, uint64_t LexicalOffset, 
                           uint64_t VisibleOffset);
   };
@@ -291,11 +293,31 @@ void PCHDeclWriter::VisitTypedefDecl(TypedefDecl *D) {
   Code = pch::DECL_TYPEDEF;
 }
 
+void PCHDeclWriter::VisitTagDecl(TagDecl *D) {
+  VisitTypeDecl(D);
+  Record.push_back((unsigned)D->getTagKind()); // FIXME: stable encoding
+  Record.push_back(D->isDefinition());
+  Writer.AddDeclRef(D->getTypedefForAnonDecl(), Record);
+}
+
+void PCHDeclWriter::VisitEnumDecl(EnumDecl *D) {
+  VisitTagDecl(D);
+  Writer.AddTypeRef(D->getIntegerType(), Record);
+  Code = pch::DECL_ENUM;
+}
+
 void PCHDeclWriter::VisitValueDecl(ValueDecl *D) {
   VisitNamedDecl(D);
   Writer.AddTypeRef(D->getType(), Record);
 }
 
+void PCHDeclWriter::VisitEnumConstantDecl(EnumConstantDecl *D) {
+  VisitValueDecl(D);
+  // FIXME: Writer.AddExprRef(D->getInitExpr());
+  Writer.AddAPSInt(D->getInitVal(), Record);
+  Code = pch::DECL_ENUM_CONSTANT;
+}
+
 void PCHDeclWriter::VisitVarDecl(VarDecl *D) {
   VisitValueDecl(D);
   Record.push_back(D->getStorageClass());
@@ -935,6 +957,11 @@ void PCHWriter::AddAPInt(const llvm::APInt &Value, RecordData &Record) {
     Record.push_back(Words[I]);
 }
 
+void PCHWriter::AddAPSInt(const llvm::APSInt &Value, RecordData &Record) {
+  Record.push_back(Value.isUnsigned());
+  AddAPInt(Value, Record);
+}
+
 void PCHWriter::AddIdentifierRef(const IdentifierInfo *II, RecordData &Record) {
   if (II == 0) {
     Record.push_back(0);
diff --git a/test/PCH/enum.c b/test/PCH/enum.c
new file mode 100644 (file)
index 0000000..92869b6
--- /dev/null
@@ -0,0 +1,15 @@
+// Test this without pch.
+// RUN: clang-cc -triple=i686-apple-darwin9 -include %S/enum.h -fsyntax-only -verify %s
+
+// Test with pch.
+// RUN: clang-cc -emit-pch -triple=i686-apple-darwin9 -o %t %S/enum.h &&
+// RUN: clang-cc -triple=i686-apple-darwin9 -include-pch %t -fsyntax-only -verify %s 
+
+int i = Red;
+
+int return_enum_constant() {
+  int result = aRoundShape;
+  return result;
+}
+
+enum Shape s = Triangle;
diff --git a/test/PCH/enum.h b/test/PCH/enum.h
new file mode 100644 (file)
index 0000000..cfa8d6f
--- /dev/null
@@ -0,0 +1,16 @@
+/* Used in enum.c test */
+
+enum Color {
+  Red,
+  Green,
+  Blue
+};
+
+enum Shape {
+  Square,
+  Triangle,
+  Rhombus,
+  Circle
+};
+
+enum Shape aRoundShape = Circle;