aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--include/clang/AST/Decl.h8
-rw-r--r--include/clang/Frontend/PCHBitCodes.h4
-rw-r--r--include/clang/Frontend/PCHReader.h8
-rw-r--r--include/clang/Frontend/PCHWriter.h3
-rw-r--r--lib/Frontend/PCHReader.cpp60
-rw-r--r--lib/Frontend/PCHWriter.cpp29
-rw-r--r--test/PCH/enum.c15
-rw-r--r--test/PCH/enum.h16
8 files changed, 140 insertions, 3 deletions
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<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; }
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<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);
}
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;