From 400f5125e2432d648f2c8a31b36a7f318a880c47 Mon Sep 17 00:00:00 2001 From: Argyrios Kyrtzidis Date: Sun, 4 Jul 2010 21:44:47 +0000 Subject: [PATCH] Fix a regression of a previous commit of mine (rdar://8158953). Some of the invariant checks for creating Record/Enum types don't hold true during PCH reading. Introduce more suitable ASTContext::getRecordType() and getEnumType(). git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@107598 91177308-0d34-0410-b5e6-96231b3b80d8 --- include/clang/AST/ASTContext.h | 4 ++++ include/clang/AST/Decl.h | 14 ++++++++++++++ lib/AST/ASTContext.cpp | 28 ++++++++++++++++++++++++++-- lib/Frontend/PCHReader.cpp | 4 ++-- test/PCH/types.c | 2 +- test/PCH/types.h | 5 +++++ 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(TagDecl::getCanonicalDecl()); } + const EnumDecl *getPreviousDeclaration() const { + return cast_or_null(TagDecl::getPreviousDeclaration()); + } + EnumDecl *getPreviousDeclaration() { + return cast_or_null(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(TagDecl::getPreviousDeclaration()); + } + RecordDecl *getPreviousDeclaration() { + return cast_or_null(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(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(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(GetDecl(Record[0]))); + return Context->getRecordType(cast(GetDecl(Record[0]))); case pch::TYPE_ENUM: if (Record.size() != 1) { Error("incorrect encoding of enum type"); return QualType(); } - return Context->getTypeDeclType(cast(GetDecl(Record[0]))); + return Context->getEnumType(cast(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 }; -- 2.40.0