Add PCH support for enumerations and enumerators.

llvm-svn: 68974
This commit is contained in:
Douglas Gregor 2009-04-13 18:14:40 +00:00
parent 0431504fb2
commit 1daeb69f95
8 changed files with 140 additions and 3 deletions

View 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; }

View 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

View 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

View 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);

View 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);
}

View 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);

15
clang/test/PCH/enum.c Normal file
View File

@ -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;

16
clang/test/PCH/enum.h Normal file
View File

@ -0,0 +1,16 @@
/* Used in enum.c test */
enum Color {
Red,
Green,
Blue
};
enum Shape {
Square,
Triangle,
Rhombus,
Circle
};
enum Shape aRoundShape = Circle;