]> granicus.if.org Git - clang/commitdiff
PCH support for all of the predefined Objective-C types, such as id,
authorDouglas Gregor <dgregor@apple.com>
Thu, 23 Apr 2009 22:29:11 +0000 (22:29 +0000)
committerDouglas Gregor <dgregor@apple.com>
Thu, 23 Apr 2009 22:29:11 +0000 (22:29 +0000)
SEL, Class, Protocol, CFConstantString, and
__objcFastEnumerationState. With this, we can now run the Objective-C
methods and properties PCH tests.

git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@69932 91177308-0d34-0410-b5e6-96231b3b80d8

include/clang/AST/ASTContext.h
include/clang/Frontend/PCHBitCodes.h
lib/AST/ASTContext.cpp
lib/AST/DeclarationName.cpp
lib/Frontend/PCHReader.cpp
lib/Frontend/PCHWriter.cpp
lib/Sema/Sema.cpp
lib/Sema/SemaDecl.cpp
test/PCH/objc_methods.m
test/PCH/objc_property.m

index f49b56c62f59913a0c316e95a4f03c3d50362a58..4379854c768229ef75ddf95aba87d5f6d148725c 100644 (file)
@@ -370,6 +370,15 @@ public:
   // constant CFStrings.
   QualType getCFConstantStringType(); 
   
+  /// Get the structure type used to representation CFStrings, or NULL
+  /// if it hasn't yet been built.
+  QualType getRawCFConstantStringType() {
+    if (CFConstantStringTypeDecl)
+      return getTagDeclType(CFConstantStringTypeDecl);
+    return QualType();
+  }
+  void setCFConstantStringType(QualType T);
+
   // This setter/getter represents the ObjC type for an NSConstantString.
   void setObjCConstantStringInterface(ObjCInterfaceDecl *Decl);
   QualType getObjCConstantStringInterface() const { 
@@ -379,6 +388,16 @@ public:
   //// This gets the struct used to keep track of fast enumerations.
   QualType getObjCFastEnumerationStateType();
   
+  /// Get the ObjCFastEnumerationState type, or NULL if it hasn't yet
+  /// been built.
+  QualType getRawObjCFastEnumerationStateType() {
+    if (ObjCFastEnumerationStateTypeDecl)
+      return getTagDeclType(ObjCFastEnumerationStateTypeDecl);
+    return QualType();
+  }
+
+  void setObjCFastEnumerationStateType(QualType T);
+
   /// getObjCEncodingForType - Emit the ObjC type encoding for the
   /// given type into \arg S. If \arg NameFields is specified then
   /// record field names are also encoded.
@@ -410,9 +429,9 @@ public:
   /// This setter/getter represents the ObjC 'id' type. It is setup lazily, by
   /// Sema.  id is always a (typedef for a) pointer type, a pointer to a struct.
   QualType getObjCIdType() const { return ObjCIdType; }
-  void setObjCIdType(TypedefDecl *Decl);
+  void setObjCIdType(QualType T);
   
-  void setObjCSelType(TypedefDecl *Decl);
+  void setObjCSelType(QualType T);
   QualType getObjCSelType() const { return ObjCSelType; }
   
   void setObjCProtoType(QualType QT);
@@ -422,7 +441,7 @@ public:
   /// Sema.  'Class' is always a (typedef for a) pointer type, a pointer to a
   /// struct.
   QualType getObjCClassType() const { return ObjCClassType; }
-  void setObjCClassType(TypedefDecl *Decl);
+  void setObjCClassType(QualType T);
   
   void setBuiltinVaListType(QualType T);
   QualType getBuiltinVaListType() const { return BuiltinVaListType; }
index 998b1109b4e1bd83f42192ad544ccad611b01bb5..c7c201ddd50d88928c82cd0d773dd295730280ca 100644 (file)
@@ -342,7 +342,19 @@ namespace clang {
     /// SPECIAL_TYPES record.
     enum SpecialTypeIDs {
       /// \brief __builtin_va_list
-      SPECIAL_TYPE_BUILTIN_VA_LIST = 0
+      SPECIAL_TYPE_BUILTIN_VA_LIST             = 0,
+      /// \brief Objective-C "id" type
+      SPECIAL_TYPE_OBJC_ID                     = 1,
+      /// \brief Objective-C selector type
+      SPECIAL_TYPE_OBJC_SELECTOR               = 2,
+      /// \brief Objective-C Protocol type
+      SPECIAL_TYPE_OBJC_PROTOCOL               = 3,
+      /// \brief Objective-C Class type
+      SPECIAL_TYPE_OBJC_CLASS                  = 4,
+      /// \brief CFConstantString type
+      SPECIAL_TYPE_CF_CONSTANT_STRING          = 5,
+      /// \brief Objective-C fast enumeration state type
+      SPECIAL_TYPE_OBJC_FAST_ENUMERATION_STATE = 6
     };
 
     /// \brief Record codes for each kind of declaration.
index 3895b134f4686089d6a7e1198a7fc701f84484be..3466d7040d4716c66b657ffd39e7a36ec986128e 100644 (file)
@@ -2000,6 +2000,12 @@ QualType ASTContext::getCFConstantStringType() {
   return getTagDeclType(CFConstantStringTypeDecl);
 }
 
+void ASTContext::setCFConstantStringType(QualType T) {
+  const RecordType *Rec = T->getAsRecordType();
+  assert(Rec && "Invalid CFConstantStringType");
+  CFConstantStringTypeDecl = Rec->getDecl();
+}
+
 QualType ASTContext::getObjCFastEnumerationStateType()
 {
   if (!ObjCFastEnumerationStateTypeDecl) {
@@ -2030,6 +2036,12 @@ QualType ASTContext::getObjCFastEnumerationStateType()
   return getTagDeclType(ObjCFastEnumerationStateTypeDecl);
 }
 
+void ASTContext::setObjCFastEnumerationStateType(QualType T) {
+  const RecordType *Rec = T->getAsRecordType();
+  assert(Rec && "Invalid ObjCFAstEnumerationStateType");
+  ObjCFastEnumerationStateTypeDecl = Rec->getDecl();
+}
+
 // This returns true if a type has been typedefed to BOOL:
 // typedef <type> BOOL;
 static bool isTypeTypedefedAsBOOL(QualType T) {
@@ -2520,9 +2532,15 @@ void ASTContext::setBuiltinVaListType(QualType T)
   BuiltinVaListType = T;
 }
 
-void ASTContext::setObjCIdType(TypedefDecl *TD)
+void ASTContext::setObjCIdType(QualType T)
 {
-  ObjCIdType = getTypedefType(TD);
+  ObjCIdType = T;
+
+  const TypedefType *TT = T->getAsTypedefType();
+  if (!TT)
+    return;
+
+  TypedefDecl *TD = TT->getDecl();
 
   // typedef struct objc_object *id;
   const PointerType *ptr = TD->getUnderlyingType()->getAsPointerType();
@@ -2536,9 +2554,14 @@ void ASTContext::setObjCIdType(TypedefDecl *TD)
   IdStructType = rec;
 }
 
-void ASTContext::setObjCSelType(TypedefDecl *TD)
+void ASTContext::setObjCSelType(QualType T)
 {
-  ObjCSelType = getTypedefType(TD);
+  ObjCSelType = T;
+
+  const TypedefType *TT = T->getAsTypedefType();
+  if (!TT)
+    return;
+  TypedefDecl *TD = TT->getDecl();
 
   // typedef struct objc_selector *SEL;
   const PointerType *ptr = TD->getUnderlyingType()->getAsPointerType();
@@ -2555,9 +2578,14 @@ void ASTContext::setObjCProtoType(QualType QT)
   ObjCProtoType = QT;
 }
 
-void ASTContext::setObjCClassType(TypedefDecl *TD)
+void ASTContext::setObjCClassType(QualType T)
 {
-  ObjCClassType = getTypedefType(TD);
+  ObjCClassType = T;
+
+  const TypedefType *TT = T->getAsTypedefType();
+  if (!TT)
+    return;
+  TypedefDecl *TD = TT->getDecl();
 
   // typedef struct objc_class *Class;
   const PointerType *ptr = TD->getUnderlyingType()->getAsPointerType();
index 5cc0aab5ee3f4e55cd4404044649c5cd9e47063c..15461bb99b80825ffa8e6df3b3b6458d5470f8de 100644 (file)
@@ -59,6 +59,11 @@ bool operator<(DeclarationName LHS, DeclarationName RHS) {
 } // end namespace clang
 
 DeclarationName::DeclarationName(Selector Sel) {
+  if (!Sel.getAsOpaquePtr()) {
+    Ptr = StoredObjCZeroArgSelector;
+    return;
+  }
+
   switch (Sel.getNumArgs()) {
   case 0:
     Ptr = reinterpret_cast<uintptr_t>(Sel.getAsIdentifierInfo());
index d225c68392f29463897e01ac2103ee56267a5bc3..2caab328d9a8b9827047e3de660b57adaa1736d5 100644 (file)
@@ -1948,7 +1948,19 @@ PCHReader::PCHReadResult PCHReader::ReadPCH(const std::string &FileName) {
   // Load the special types.
   Context.setBuiltinVaListType(
     GetType(SpecialTypes[pch::SPECIAL_TYPE_BUILTIN_VA_LIST]));
-
+  if (unsigned Id = SpecialTypes[pch::SPECIAL_TYPE_OBJC_ID])
+    Context.setObjCIdType(GetType(Id));
+  if (unsigned Sel = SpecialTypes[pch::SPECIAL_TYPE_OBJC_SELECTOR])
+    Context.setObjCSelType(GetType(Sel));
+  if (unsigned Proto = SpecialTypes[pch::SPECIAL_TYPE_OBJC_PROTOCOL])
+    Context.setObjCProtoType(GetType(Proto));
+  if (unsigned Class = SpecialTypes[pch::SPECIAL_TYPE_OBJC_CLASS])
+    Context.setObjCClassType(GetType(Class));
+  if (unsigned String = SpecialTypes[pch::SPECIAL_TYPE_CF_CONSTANT_STRING])
+    Context.setCFConstantStringType(GetType(String));
+  if (unsigned FastEnum 
+        = SpecialTypes[pch::SPECIAL_TYPE_OBJC_FAST_ENUMERATION_STATE])
+    Context.setObjCFastEnumerationStateType(GetType(FastEnum));
   // If we saw the preprocessor block, read it now.
   if (PreprocessorBlockOffset) {
     SavedStreamPosition SavedPos(Stream);
index 0c640e7b052645ddaf51627c5cfb5731e75d26e2..9a60625d1f06c09c34c0ceb273a6135944b7059e 100644 (file)
@@ -2105,6 +2105,12 @@ void PCHWriter::WritePCH(Sema &SemaRef) {
   // Write the record of special types.
   Record.clear();
   AddTypeRef(Context.getBuiltinVaListType(), Record);
+  AddTypeRef(Context.getObjCIdType(), Record);
+  AddTypeRef(Context.getObjCSelType(), Record);
+  AddTypeRef(Context.getObjCProtoType(), Record);
+  AddTypeRef(Context.getObjCClassType(), Record);
+  AddTypeRef(Context.getRawCFConstantStringType(), Record);
+  AddTypeRef(Context.getRawObjCFastEnumerationStateType(), Record);
   Stream.EmitRecord(pch::SPECIAL_TYPES, Record);
 
   // Write the record containing external, unnamed definitions.
index a5b30cc72aca7c4354d5d28f25a720eeb8cebb31..3702c89cf60f1ba78a306ba25638864933f43884 100644 (file)
@@ -110,46 +110,54 @@ void Sema::ActOnTranslationUnitScope(SourceLocation Loc, Scope *S) {
   PushDeclContext(S, Context.getTranslationUnitDecl());
   if (!PP.getLangOptions().ObjC1) return;
   
-  // Synthesize "typedef struct objc_selector *SEL;"
-  RecordDecl *SelTag = CreateStructDecl(Context, "objc_selector");
-  PushOnScopeChains(SelTag, TUScope);
+  if (Context.getObjCSelType().isNull()) {
+    // Synthesize "typedef struct objc_selector *SEL;"
+    RecordDecl *SelTag = CreateStructDecl(Context, "objc_selector");
+    PushOnScopeChains(SelTag, TUScope);
   
-  QualType SelT = Context.getPointerType(Context.getTagDeclType(SelTag));
-  TypedefDecl *SelTypedef = TypedefDecl::Create(Context, CurContext,
-                                                SourceLocation(),
-                                                &Context.Idents.get("SEL"),
-                                                SelT);
-  PushOnScopeChains(SelTypedef, TUScope);
-  Context.setObjCSelType(SelTypedef);
+    QualType SelT = Context.getPointerType(Context.getTagDeclType(SelTag));
+    TypedefDecl *SelTypedef = TypedefDecl::Create(Context, CurContext,
+                                                  SourceLocation(),
+                                                  &Context.Idents.get("SEL"),
+                                                  SelT);
+    PushOnScopeChains(SelTypedef, TUScope);
+    Context.setObjCSelType(Context.getTypeDeclType(SelTypedef));
+  }
+
+  if (Context.getObjCClassType().isNull()) {
+    RecordDecl *ClassTag = CreateStructDecl(Context, "objc_class");
+    QualType ClassT = Context.getPointerType(Context.getTagDeclType(ClassTag));
+    TypedefDecl *ClassTypedef = 
+      TypedefDecl::Create(Context, CurContext, SourceLocation(),
+                          &Context.Idents.get("Class"), ClassT);
+    PushOnScopeChains(ClassTag, TUScope);
+    PushOnScopeChains(ClassTypedef, TUScope);
+    Context.setObjCClassType(Context.getTypeDeclType(ClassTypedef));
+  }
 
-  // FIXME: Make sure these don't leak!
-  RecordDecl *ClassTag = CreateStructDecl(Context, "objc_class");
-  QualType ClassT = Context.getPointerType(Context.getTagDeclType(ClassTag));
-  TypedefDecl *ClassTypedef = 
-    TypedefDecl::Create(Context, CurContext, SourceLocation(),
-                        &Context.Idents.get("Class"), ClassT);
-  PushOnScopeChains(ClassTag, TUScope);
-  PushOnScopeChains(ClassTypedef, TUScope);
-  Context.setObjCClassType(ClassTypedef);
   // Synthesize "@class Protocol;
-  ObjCInterfaceDecl *ProtocolDecl =
-    ObjCInterfaceDecl::Create(Context, CurContext, SourceLocation(),
-                              &Context.Idents.get("Protocol"), 
-                              SourceLocation(), true);
-  Context.setObjCProtoType(Context.getObjCInterfaceType(ProtocolDecl));
-  PushOnScopeChains(ProtocolDecl, TUScope);
-  
-  // Synthesize "typedef struct objc_object { Class isa; } *id;"
-  RecordDecl *ObjectTag = CreateStructDecl(Context, "objc_object");
+  if (Context.getObjCProtoType().isNull()) {
+    ObjCInterfaceDecl *ProtocolDecl =
+      ObjCInterfaceDecl::Create(Context, CurContext, SourceLocation(),
+                                &Context.Idents.get("Protocol"), 
+                                SourceLocation(), true);
+    Context.setObjCProtoType(Context.getObjCInterfaceType(ProtocolDecl));
+    PushOnScopeChains(ProtocolDecl, TUScope);
+  }
 
-  QualType ObjT = Context.getPointerType(Context.getTagDeclType(ObjectTag));
-  PushOnScopeChains(ObjectTag, TUScope);
-  TypedefDecl *IdTypedef = TypedefDecl::Create(Context, CurContext,
-                                               SourceLocation(),
-                                               &Context.Idents.get("id"),
-                                               ObjT);
-  PushOnScopeChains(IdTypedef, TUScope);
-  Context.setObjCIdType(IdTypedef);
+  // Synthesize "typedef struct objc_object { Class isa; } *id;"
+  if (Context.getObjCIdType().isNull()) {
+    RecordDecl *ObjectTag = CreateStructDecl(Context, "objc_object");
+    
+    QualType ObjT = Context.getPointerType(Context.getTagDeclType(ObjectTag));
+    PushOnScopeChains(ObjectTag, TUScope);
+    TypedefDecl *IdTypedef = TypedefDecl::Create(Context, CurContext,
+                                                 SourceLocation(),
+                                                 &Context.Idents.get("id"),
+                                                 ObjT);
+    PushOnScopeChains(IdTypedef, TUScope);
+    Context.setObjCIdType(Context.getTypeDeclType(IdTypedef));
+  }
 }
 
 Sema::Sema(Preprocessor &pp, ASTContext &ctxt, ASTConsumer &consumer,
index b3592086ddd643cd1afdd81807488d08665e5708..e81e8832724323bbe393458d19145103a642f34a 100644 (file)
@@ -473,19 +473,19 @@ bool Sema::MergeTypeDefDecl(TypedefDecl *New, Decl *OldD) {
     case 2: 
       if (!TypeID->isStr("id"))
         break;
-      Context.setObjCIdType(New);
+      Context.setObjCIdType(Context.getTypeDeclType(New));
       objc_types = true;
       break;
     case 5:
       if (!TypeID->isStr("Class"))
         break;
-      Context.setObjCClassType(New);
+      Context.setObjCClassType(Context.getTypeDeclType(New));
       objc_types = true;
       return false;
     case 3:
       if (!TypeID->isStr("SEL"))
         break;
-      Context.setObjCSelType(New);
+      Context.setObjCSelType(Context.getTypeDeclType(New));
       objc_types = true;
       return false;
     case 8:
index 2122ff6061244b5883b7ecf20756523bbfc78cf8..1a198b18d380d6f57190de9dff755217b5e772aa 100644 (file)
@@ -11,8 +11,6 @@ void func() {
 // FIXME:
 // AliasForTestPCH *zz;
  
-#if 0
  xx = [TestPCH alloc];
  [xx instMethod];
-#endif
 }
index 83bde783a3c01f5270581266b2778e7ba44b098b..5cf6de7593756d6295bad3950243220c3c3599fa 100644 (file)
@@ -1,9 +1,9 @@
 // Test this without pch.
-// FIXME: clang-cc -include %S/objc_property.h -fsyntax-only -verify %s &&
+// RUN: clang-cc -include %S/objc_property.h -fsyntax-only -verify %s &&
 
 // Test with pch.
-// FIXME: clang-cc -x=objective-c -emit-pch -o %t %S/objc_property.h &&
-// FIXME: clang-cc -include-pch %t -fsyntax-only -verify %s 
+// RUN: clang-cc -x=objective-c -emit-pch -o %t %S/objc_property.h &&
+// RUN: clang-cc -include-pch %t -fsyntax-only -verify %s 
 
 void func() {
  TestProperties *xx = [TestProperties alloc];