]> granicus.if.org Git - clang/commitdiff
Fix a regression of a previous commit of mine (rdar://8158953).
authorArgyrios Kyrtzidis <akyrtzi@gmail.com>
Sun, 4 Jul 2010 21:44:47 +0000 (21:44 +0000)
committerArgyrios Kyrtzidis <akyrtzi@gmail.com>
Sun, 4 Jul 2010 21:44:47 +0000 (21:44 +0000)
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
include/clang/AST/Decl.h
lib/AST/ASTContext.cpp
lib/Frontend/PCHReader.cpp
test/PCH/types.c
test/PCH/types.h

index 816d59512c3bfcad6424e9534dc0bbad1ad74d62..3799451360f414d736f2c9bb338e26e273dc59c2 100644 (file)
@@ -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,
index c35a399263cadf11e3f662dc92850ecd83de09e1..b31f0385c3ca4802878b365e8189be132da600af 100644 (file)
@@ -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; }
index 4fb9d369de316e9c11b9a50eef0ce3485f048455..1439ed14c064ee23a68a8209afc402fc494e3542 100644 (file)
@@ -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,
index 27ca86f2f18610db6dfbfe413e33e817c1aba641..aaa80fefafa5c44d4914f66610ad8746d355fa9b 100644 (file)
@@ -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;
index c21b33a4ee519ee28ccec7b8316ea003a1c0cb7a..73a2205b78b6ce40f34b679d6278b472020a2e91 100644 (file)
@@ -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;
index df9f5c8607f707b4fedb9b4bc2d4fe09ea450609..ab42331fe4133357a765ae02417ba7e8d21be5c9 100644 (file)
@@ -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 };