aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--include/clang/AST/ASTContext.h4
-rw-r--r--include/clang/AST/Decl.h14
-rw-r--r--lib/AST/ASTContext.cpp28
-rw-r--r--lib/Frontend/PCHReader.cpp4
-rw-r--r--test/PCH/types.c2
-rw-r--r--test/PCH/types.h5
6 files changed, 52 insertions, 5 deletions
diff --git a/include/clang/AST/ASTContext.h b/include/clang/AST/ASTContext.h
index 816d59512c..3799451360 100644
--- a/include/clang/AST/ASTContext.h
+++ b/include/clang/AST/ASTContext.h
@@ -622,6 +622,10 @@ public:
/// specified typename decl.
QualType getTypedefType(const TypedefDecl *Decl, QualType Canon = QualType());
+ QualType getRecordType(const RecordDecl *Decl);
+
+ QualType getEnumType(const EnumDecl *Decl);
+
QualType getInjectedClassNameType(CXXRecordDecl *Decl, QualType TST);
QualType getSubstTemplateTypeParmType(const TemplateTypeParmType *Replaced,
diff --git a/include/clang/AST/Decl.h b/include/clang/AST/Decl.h
index c35a399263..b31f0385c3 100644
--- a/include/clang/AST/Decl.h
+++ b/include/clang/AST/Decl.h
@@ -1993,6 +1993,13 @@ public:
return cast<EnumDecl>(TagDecl::getCanonicalDecl());
}
+ const EnumDecl *getPreviousDeclaration() const {
+ return cast_or_null<EnumDecl>(TagDecl::getPreviousDeclaration());
+ }
+ EnumDecl *getPreviousDeclaration() {
+ return cast_or_null<EnumDecl>(TagDecl::getPreviousDeclaration());
+ }
+
static EnumDecl *Create(ASTContext &C, DeclContext *DC,
SourceLocation L, IdentifierInfo *Id,
SourceLocation TKL, EnumDecl *PrevDecl);
@@ -2116,6 +2123,13 @@ public:
RecordDecl* PrevDecl = 0);
static RecordDecl *Create(ASTContext &C, EmptyShell Empty);
+ const RecordDecl *getPreviousDeclaration() const {
+ return cast_or_null<RecordDecl>(TagDecl::getPreviousDeclaration());
+ }
+ RecordDecl *getPreviousDeclaration() {
+ return cast_or_null<RecordDecl>(TagDecl::getPreviousDeclaration());
+ }
+
virtual void Destroy(ASTContext& C);
bool hasFlexibleArrayMember() const { return HasFlexibleArrayMember; }
diff --git a/lib/AST/ASTContext.cpp b/lib/AST/ASTContext.cpp
index 4fb9d369de..1439ed14c0 100644
--- a/lib/AST/ASTContext.cpp
+++ b/lib/AST/ASTContext.cpp
@@ -1802,11 +1802,11 @@ QualType ASTContext::getTypeDeclTypeSlow(const TypeDecl *Decl) {
assert(!Record->getPreviousDeclaration() &&
"struct/union has previous declaration");
assert(!NeedsInjectedClassNameType(Record));
- Decl->TypeForDecl = new (*this, TypeAlignment) RecordType(Record);
+ return getRecordType(Record);
} else if (const EnumDecl *Enum = dyn_cast<EnumDecl>(Decl)) {
assert(!Enum->getPreviousDeclaration() &&
"enum has previous declaration");
- Decl->TypeForDecl = new (*this, TypeAlignment) EnumType(Enum);
+ return getEnumType(Enum);
} else if (const UnresolvedUsingTypenameDecl *Using =
dyn_cast<UnresolvedUsingTypenameDecl>(Decl)) {
Decl->TypeForDecl = new (*this, TypeAlignment) UnresolvedUsingType(Using);
@@ -1831,6 +1831,30 @@ ASTContext::getTypedefType(const TypedefDecl *Decl, QualType Canonical) {
return QualType(Decl->TypeForDecl, 0);
}
+QualType ASTContext::getRecordType(const RecordDecl *Decl) {
+ if (Decl->TypeForDecl) return QualType(Decl->TypeForDecl, 0);
+
+ if (const RecordDecl *PrevDecl = Decl->getPreviousDeclaration())
+ if (PrevDecl->TypeForDecl)
+ return QualType(Decl->TypeForDecl = PrevDecl->TypeForDecl, 0);
+
+ Decl->TypeForDecl = new (*this, TypeAlignment) RecordType(Decl);
+ Types.push_back(Decl->TypeForDecl);
+ return QualType(Decl->TypeForDecl, 0);
+}
+
+QualType ASTContext::getEnumType(const EnumDecl *Decl) {
+ if (Decl->TypeForDecl) return QualType(Decl->TypeForDecl, 0);
+
+ if (const EnumDecl *PrevDecl = Decl->getPreviousDeclaration())
+ if (PrevDecl->TypeForDecl)
+ return QualType(Decl->TypeForDecl = PrevDecl->TypeForDecl, 0);
+
+ Decl->TypeForDecl = new (*this, TypeAlignment) EnumType(Decl);
+ Types.push_back(Decl->TypeForDecl);
+ return QualType(Decl->TypeForDecl, 0);
+}
+
/// \brief Retrieve a substitution-result type.
QualType
ASTContext::getSubstTemplateTypeParmType(const TemplateTypeParmType *Parm,
diff --git a/lib/Frontend/PCHReader.cpp b/lib/Frontend/PCHReader.cpp
index 27ca86f2f1..aaa80fefaf 100644
--- a/lib/Frontend/PCHReader.cpp
+++ b/lib/Frontend/PCHReader.cpp
@@ -2149,14 +2149,14 @@ QualType PCHReader::ReadTypeRecord(uint64_t Offset) {
Error("incorrect encoding of record type");
return QualType();
}
- return Context->getTypeDeclType(cast<RecordDecl>(GetDecl(Record[0])));
+ return Context->getRecordType(cast<RecordDecl>(GetDecl(Record[0])));
case pch::TYPE_ENUM:
if (Record.size() != 1) {
Error("incorrect encoding of enum type");
return QualType();
}
- return Context->getTypeDeclType(cast<EnumDecl>(GetDecl(Record[0])));
+ return Context->getEnumType(cast<EnumDecl>(GetDecl(Record[0])));
case pch::TYPE_ELABORATED: {
unsigned Idx = 0;
diff --git a/test/PCH/types.c b/test/PCH/types.c
index c21b33a4ee..73a2205b78 100644
--- a/test/PCH/types.c
+++ b/test/PCH/types.c
@@ -3,7 +3,7 @@
// Test with pch.
// RUN: %clang_cc1 -emit-pch -fblocks -o %t %S/types.h
-// RUN: %clang_cc1 -fblocks -include-pch %t -fsyntax-only -verify %s
+// RUN: %clang_cc1 -fblocks -include-pch %t -fsyntax-only -verify %s -ast-print
typedef int INT;
INT int_value;
diff --git a/test/PCH/types.h b/test/PCH/types.h
index df9f5c8607..ab42331fe4 100644
--- a/test/PCH/types.h
+++ b/test/PCH/types.h
@@ -42,3 +42,8 @@ typedef typeof(17) typeof_17;
// TYPE_TYPEOF
typedef typeof(int_ptr *) int_ptr_ptr2;
+
+struct S2;
+struct S2 {};
+enum E;
+enum E { myenum };