From: Douglas Gregor Date: Mon, 13 Apr 2009 18:14:40 +0000 (+0000) Subject: Add PCH support for enumerations and enumerators. X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=0a2b45e5885b6b8477b167042c0f6cd1d99a1f13;p=clang Add PCH support for enumerations and enumerators. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@68974 91177308-0d34-0410-b5e6-96231b3b80d8 --- diff --git a/include/clang/AST/Decl.h b/include/clang/AST/Decl.h index f954934898..f162689092 100644 --- a/include/clang/AST/Decl.h +++ b/include/clang/AST/Decl.h @@ -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(const_cast(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; } diff --git a/include/clang/Frontend/PCHBitCodes.h b/include/clang/Frontend/PCHBitCodes.h index 79d70c8a61..fe3d8ed86c 100644 --- a/include/clang/Frontend/PCHBitCodes.h +++ b/include/clang/Frontend/PCHBitCodes.h @@ -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 diff --git a/include/clang/Frontend/PCHReader.h b/include/clang/Frontend/PCHReader.h index b59790ddaf..3490cb5070 100644 --- a/include/clang/Frontend/PCHReader.h +++ b/include/clang/Frontend/PCHReader.h @@ -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 diff --git a/include/clang/Frontend/PCHWriter.h b/include/clang/Frontend/PCHWriter.h index 92bab50db5..a899fb43e6 100644 --- a/include/clang/Frontend/PCHWriter.h +++ b/include/clang/Frontend/PCHWriter.h @@ -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); diff --git a/lib/Frontend/PCHReader.cpp b/lib/Frontend/PCHReader.cpp index 9a0061ea0e..99c33613c8 100644 --- a/lib/Frontend/PCHReader.cpp +++ b/lib/Frontend/PCHReader.cpp @@ -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 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(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(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); } diff --git a/lib/Frontend/PCHWriter.cpp b/lib/Frontend/PCHWriter.cpp index 6056fbc539..2ba8e9eeb6 100644 --- a/lib/Frontend/PCHWriter.cpp +++ b/lib/Frontend/PCHWriter.cpp @@ -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 index 0000000000..92869b6bc8 --- /dev/null +++ b/test/PCH/enum.c @@ -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 index 0000000000..cfa8d6f3d8 --- /dev/null +++ b/test/PCH/enum.h @@ -0,0 +1,16 @@ +/* Used in enum.c test */ + +enum Color { + Red, + Green, + Blue +}; + +enum Shape { + Square, + Triangle, + Rhombus, + Circle +}; + +enum Shape aRoundShape = Circle;