]> granicus.if.org Git - clang/commitdiff
Implement a more sensible strategy for ObjC built-in types (addressing a long standin...
authorSteve Naroff <snaroff@apple.com>
Wed, 31 Oct 2007 18:42:27 +0000 (18:42 +0000)
committerSteve Naroff <snaroff@apple.com>
Wed, 31 Oct 2007 18:42:27 +0000 (18:42 +0000)
This removes several gross hacks to work around the previous "lazy" behavior.

Two notes:
- MinimalActions still needs to be taught about the built-in types (This breaks one of the -noop test cases). I started this, then added a FIXME.
- I didn't convert Sema::GetObjcProtoType() yet.

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

Lex/Preprocessor.cpp
Parse/MinimalAction.cpp
Sema/Sema.cpp
Sema/Sema.h
Sema/SemaDecl.cpp
Sema/SemaExpr.cpp
clang.xcodeproj/project.pbxproj
include/clang/Parse/Action.h

index c1f4970f30d94bc2cbbd378761618618ab84ac6e..0d3ac521d05638efb687a58c673fcbeab69bf975 100644 (file)
@@ -369,33 +369,7 @@ static void InitializePredefinedMacros(Preprocessor &PP,
     DefineBuiltinMacro(Buf, "__OBJC__=1");
   if (PP.getLangOptions().ObjC2)
     DefineBuiltinMacro(Buf, "__OBJC2__=1");
-  if (PP.getLangOptions().ObjC1) {
-    const char *ObjcType;
-    // Predefine all the ObjC goodies (traditionally declared in <objc/objc.h>).
-    // We define the following header guard for source compatibility. It has
-    // the effect of ignoring any explicit inclusion of <objc/objc.h>:-)
-    DefineBuiltinMacro(Buf, "_OBJC_OBJC_H_=1");
-    DefineBuiltinMacro(Buf, "OBJC_EXPORT=extern");
-    DefineBuiltinMacro(Buf, "OBJC_IMPORT=extern");
-    ObjcType = "typedef struct objc_class *Class;\n";
-    Buf.insert(Buf.end(), ObjcType, ObjcType+strlen(ObjcType));
-    ObjcType = "typedef struct objc_object { Class isa; } *id;\n";
-    Buf.insert(Buf.end(), ObjcType, ObjcType+strlen(ObjcType));
-    ObjcType = "typedef struct objc_selector *SEL;\n";
-    Buf.insert(Buf.end(), ObjcType, ObjcType+strlen(ObjcType));
-    ObjcType = "typedef id (*IMP)(id, SEL, ...);\n";
-    Buf.insert(Buf.end(), ObjcType, ObjcType+strlen(ObjcType));
-    ObjcType = "typedef signed char BOOL;\n";
-    Buf.insert(Buf.end(), ObjcType, ObjcType+strlen(ObjcType));
-    DefineBuiltinMacro(Buf, "YES=(BOOL)1");
-    DefineBuiltinMacro(Buf, "NO=(BOOL)0");
-    DefineBuiltinMacro(Buf, "Nil=0");
-    DefineBuiltinMacro(Buf, "nil=0");
-    ObjcType = "extern const char *sel_getName(SEL sel);\n";
-    Buf.insert(Buf.end(), ObjcType, ObjcType+strlen(ObjcType));
-    ObjcType = "extern SEL sel_getUid(const char *str);\n";
-    Buf.insert(Buf.end(), ObjcType, ObjcType+strlen(ObjcType));
-  }
+
   // Add __builtin_va_list typedef.
   {
     const char *VAList = PP.getTargetInfo().getVAListDeclaration();
index d4391413220a7ac6e0de8f14295ace43df549810..bc7c41bec398e734a85c59f2cdeb2b3a2b6dd9ea 100644 (file)
@@ -28,6 +28,11 @@ struct TypeNameInfo {
   }
 };
 
+void MinimalAction:: ActOnTranslationUnitScope(SourceLocation Loc, Scope *S) {
+  TUScope = S;
+  // FIXME: add id/SEL/Class. We need to get our paws on the identifier table.
+}
+
 /// isTypeName - This looks at the IdentifierInfo::FETokenInfo field to
 /// determine whether the name is a type name (objc class name or typedef) or
 /// not in this scope.
index 92d17e1e99bd5f953d2f65f850c47fe7881441e3..323483586bca690c0c11603a3f425e21e5f5e79f 100644 (file)
 #include "clang/AST/ASTContext.h"
 #include "clang/Lex/Preprocessor.h"
 #include "clang/Basic/Diagnostic.h"
+#include "clang/Parse/Scope.h"
 
 using namespace clang;
 
-void Sema::ActOnTranslationUnitScope(SourceLocation Loc, Scope *S) {
-  TUScope = S;
+bool Sema::isBuiltinObjcType(TypedefDecl *TD) {
+  const char *typeName = TD->getIdentifier()->getName();
+  return strcmp(typeName, "id") == 0 || strcmp(typeName, "Class") == 0 ||
+         strcmp(typeName, "SEL") == 0;
 }
 
-/// GetObjcIdType - The following method assumes that "id" is imported
-/// via <objc/objc.h>. This is the way GCC worked for almost 20 years.
-/// In GCC 4.0, "id" is now a built-in type. Unfortunately, typedefs *cannot* be
-/// redefined (even if they are identical). To allow a built-in types to coexist
-/// with <objc/objc.h>, GCC has a special hack on decls (DECL_IN_SYSTEM_HEADER).
-/// For now, we will *not* install id as a built-in. FIXME: reconsider this.
-QualType Sema::GetObjcIdType(SourceLocation Loc) {
-  assert(TUScope && "GetObjcIdType(): Top-level scope is null");
-  if (!Context.getObjcIdType().isNull())
-    return Context.getObjcIdType();
+void Sema::ActOnTranslationUnitScope(SourceLocation Loc, Scope *S) {
+  TUScope = S;
+  if (PP.getLangOptions().ObjC1) {
+    TypedefType *t;
     
-  IdentifierInfo *IdIdent = &Context.Idents.get("id");
-  ScopedDecl *IdDecl = LookupScopedDecl(IdIdent, Decl::IDNS_Ordinary, 
-                                        SourceLocation(), TUScope);
-  TypedefDecl *ObjcIdTypedef = dyn_cast_or_null<TypedefDecl>(IdDecl);
-  if (!ObjcIdTypedef) {
-    Diag(Loc, diag::err_missing_id_definition);
-    return QualType();
+    // Add the built-in ObjC types.
+    t = dyn_cast<TypedefType>(Context.getObjcIdType().getTypePtr());
+    t->getDecl()->getIdentifier()->setFETokenInfo(t->getDecl());
+    TUScope->AddDecl(t->getDecl());
+    t = dyn_cast<TypedefType>(Context.getObjcClassType().getTypePtr());
+    t->getDecl()->getIdentifier()->setFETokenInfo(t->getDecl());
+    TUScope->AddDecl(t->getDecl());
+    t = dyn_cast<TypedefType>(Context.getObjcSelType().getTypePtr());
+    t->getDecl()->getIdentifier()->setFETokenInfo(t->getDecl());
+    TUScope->AddDecl(t->getDecl());
   }
-  Context.setObjcIdType(ObjcIdTypedef);
-  return Context.getObjcIdType();
-}
-
-/// GetObjcSelType - See comments for Sema::GetObjcIdType above; replace "id"
-/// with "SEL".
-QualType Sema::GetObjcSelType(SourceLocation Loc) {
-  assert(TUScope && "GetObjcSelType(): Top-level scope is null");
-  if (Context.getObjcSelType().isNull()) {
-    IdentifierInfo *SelIdent = &Context.Idents.get("SEL");
-    ScopedDecl *SelDecl = LookupScopedDecl(SelIdent, Decl::IDNS_Ordinary, 
-                                          SourceLocation(), TUScope);
-    TypedefDecl *ObjcSelTypedef = dyn_cast_or_null<TypedefDecl>(SelDecl);
-    if (!ObjcSelTypedef) {
-      Diag(Loc, diag::err_missing_sel_definition);
-      return QualType();
-    }
-    Context.setObjcSelType(ObjcSelTypedef);
-  }
-  return Context.getObjcSelType();
 }
 
+/// FIXME: remove this.
 /// GetObjcProtoType - See comments for Sema::GetObjcIdType above; replace "id"
 /// with "Protocol".
 QualType Sema::GetObjcProtoType(SourceLocation Loc) {
@@ -82,25 +63,6 @@ QualType Sema::GetObjcProtoType(SourceLocation Loc) {
   return Context.getObjcProtoType();
 }
 
-/// GetObjcClassType - See comments for Sema::GetObjcIdType above; replace "id"
-/// with "Protocol".
-QualType Sema::GetObjcClassType(SourceLocation Loc) {
-  assert(TUScope && "GetObjcClassType(): Top-level scope is null");
-  if (!Context.getObjcClassType().isNull())
-    return Context.getObjcClassType();
-    
-  IdentifierInfo *ClassIdent = &Context.Idents.get("Class");
-  ScopedDecl *ClassDecl = LookupScopedDecl(ClassIdent, Decl::IDNS_Ordinary, 
-                                        SourceLocation(), TUScope);
-  TypedefDecl *ObjcClassTypedef = dyn_cast_or_null<TypedefDecl>(ClassDecl);
-  if (!ObjcClassTypedef) {
-    Diag(Loc, diag::err_missing_class_definition);
-    return QualType();
-  }
-  Context.setObjcClassType(ObjcClassTypedef);
-  return Context.getObjcClassType();
-}
-
 Sema::Sema(Preprocessor &pp, ASTContext &ctxt, std::vector<Decl*> &prevInGroup)
   : PP(pp), Context(ctxt), CurFunctionDecl(0), LastInGroupList(prevInGroup) {
   
@@ -118,7 +80,38 @@ Sema::Sema(Preprocessor &pp, ASTContext &ctxt, std::vector<Decl*> &prevInGroup)
   KnownFunctionIDs[ id_vfprintf ] = &IT.get("vfprintf");
   KnownFunctionIDs[ id_vsprintf ] = &IT.get("vsprintf");
   KnownFunctionIDs[ id_vprintf ] = &IT.get("vprintf");
-  
+
+  if (PP.getLangOptions().ObjC1) {
+    // Synthesize "typedef struct objc_class *Class;"
+    RecordDecl *ClassTag = new RecordDecl(Decl::Struct, SourceLocation(), 
+                                          &IT.get("objc_class"), 0);
+    QualType ClassT = Context.getPointerType(Context.getTagDeclType(ClassTag));
+    TypedefDecl *ClassTypedef = new TypedefDecl(SourceLocation(),
+                                                &Context.Idents.get("Class"),
+                                                ClassT, 0);
+    Context.setObjcClassType(ClassTypedef);
+    
+    // Synthesize "typedef struct objc_object { Class isa; } *id;"
+    RecordDecl *ObjectTag = new RecordDecl(Decl::Struct, SourceLocation(), 
+                                          &IT.get("objc_object"), 0);
+    FieldDecl *IsaDecl = new FieldDecl(SourceLocation(), 0, 
+                                       Context.getObjcClassType());
+    ObjectTag->defineBody(&IsaDecl, 1);
+    QualType ObjT = Context.getPointerType(Context.getTagDeclType(ObjectTag));
+    TypedefDecl *IdTypedef = new TypedefDecl(SourceLocation(),
+                                             &Context.Idents.get("id"),
+                                             ObjT, 0);
+    Context.setObjcIdType(IdTypedef);
+    
+    // Synthesize "typedef struct objc_selector *SEL;"
+    RecordDecl *SelTag = new RecordDecl(Decl::Struct, SourceLocation(), 
+                                          &IT.get("objc_selector"), 0);
+    QualType SelT = Context.getPointerType(Context.getTagDeclType(SelTag));
+    TypedefDecl *SelTypedef = new TypedefDecl(SourceLocation(),
+                                              &Context.Idents.get("SEL"),
+                                              SelT, 0);
+    Context.setObjcSelType(SelTypedef);
+  }
   TUScope = 0;
 }
 
index 13ba636d5293c4701561329e41d022a6deb2ed0b..3b8b5e98b37d11f6f87a30276befad62d42b629e 100644 (file)
@@ -275,17 +275,11 @@ private:
   bool MatchTwoMethodDeclarations(const ObjcMethodDecl *Method, 
                                   const ObjcMethodDecl *PrevMethod); 
 
-  /// GetObjcIdType - Getter for the build-in "id" type.
-  QualType GetObjcIdType(SourceLocation Loc = SourceLocation());
-  
-  /// GetObjcSelType - Getter for the build-in "SEL" type.
-  QualType GetObjcSelType(SourceLocation Loc = SourceLocation());
-  
   /// GetObjcSelType - Getter for the build-in "Protocol *" type.
   QualType GetObjcProtoType(SourceLocation Loc = SourceLocation());
   
-  // GetObjcClassType - Getter for the built-in "Class" type.
-  QualType GetObjcClassType(SourceLocation Loc = SourceLocation());
+  /// isBuiltinObjcType - Returns true of the type is "id", "SEL", "Class".
+  bool isBuiltinObjcType(TypedefDecl *TD);
 
   /// AddInstanceMethodToGlobalPool - All instance methods in a translation
   /// unit are added to a global pool. This allows us to efficiently associate
index 32e5d12b3f49571ffb6d1f997bc32ad9fb196c4f..ea73db508879709fff802e42886799161129fac5 100644 (file)
@@ -25,6 +25,7 @@
 #include "llvm/ADT/SmallString.h"
 #include "llvm/ADT/SmallSet.h"
 #include "llvm/ADT/DenseSet.h"
+#include "clang/Lex/Preprocessor.h"
 using namespace clang;
 
 Sema::DeclTy *Sema::isTypeName(const IdentifierInfo &II, Scope *S) const {
@@ -210,6 +211,11 @@ TypedefDecl *Sema::MergeTypeDefDecl(TypedefDecl *New, ScopedDecl *OldD) {
     return New;
   }
   
+  // Allow multiple definitions for ObjC built-in typedefs.
+  // FIXME: Verify the underlying types are equivalent!
+  if (PP.getLangOptions().ObjC1 && isBuiltinObjcType(New))
+    return Old;
+    
   // TODO: CHECK FOR CONFLICTS, multiple decls with same name in one scope.
   // TODO: This is totally simplistic.  It should handle merging functions
   // together etc, merging extern int X; int X; ...
@@ -1193,17 +1199,7 @@ Sema::DeclTy *Sema::ActOnStartCategoryImplementation(
   /// Check that class of this category is already completely declared.
   if (!IDecl || IDecl->isForwardDecl())
     Diag(ClassLoc, diag::err_undef_interface, ClassName->getName());
-  
-  // We cannot build type 'id' lazily. It is needed when checking if a 
-  // type is an 'id' (via call to isObjcIdType) even if there is no
-  // need for the default 'id' type.
-  // FIXME: Depending on the need to compare to 'id', this may have to go
-  // somewhere else. At this time, this is a good enough place to do type
-  // encoding of methods and ivars for the rewrite client.
-  GetObjcIdType(AtCatImplLoc);
-  GetObjcClassType(AtCatImplLoc);
-  GetObjcSelType(AtCatImplLoc);
-  
+
   /// TODO: Check that CatName, category name, is not used in another
   // implementation.
   return CDecl;
@@ -1273,16 +1269,6 @@ Sema::DeclTy *Sema::ActOnStartClassImplementation(
   if (!ObjcImplementations.insert(ClassName))
     Diag(ClassLoc, diag::err_dup_implementation_class, ClassName->getName());
 
-  // We cannot build type 'id' laziliy. It is needed when checking if a 
-  // type is an 'id' (via call to isObjcIdType) even if there is no
-  // need for the dafult 'id' type.
-  // FIXME: Depending on the need to compare to 'id', this may have to go
-  // somewhere else. At this time, this is a good enough place to do type
-  // encoding of methods and ivars for the rewrite client.
-  GetObjcIdType(AtClassImplLoc);
-  GetObjcClassType(AtClassImplLoc); 
-  GetObjcSelType(AtClassImplLoc);
-  
   return IMPDecl;
 }
 
@@ -1992,7 +1978,7 @@ Sema::DeclTy *Sema::ActOnMethodDeclaration(
     if (ArgTypes[i])
       argType = QualType::getFromOpaquePtr(ArgTypes[i]);
     else
-      argType = GetObjcIdType(MethodLoc);
+      argType = Context.getObjcIdType();
     ParmVarDecl* Param = new ParmVarDecl(SourceLocation(/*FIXME*/), ArgNames[i], 
                                          argType, VarDecl::None, 0);
     Params.push_back(Param);
@@ -2002,7 +1988,7 @@ Sema::DeclTy *Sema::ActOnMethodDeclaration(
   if (ReturnType)
     resultDeclType = QualType::getFromOpaquePtr(ReturnType);
   else // get the type for "id".
-    resultDeclType = GetObjcIdType(MethodLoc);
+    resultDeclType = Context.getObjcIdType();
 
   ObjcMethodDecl* ObjcMethod =  new ObjcMethodDecl(MethodLoc, EndLoc, Sel,
                                       resultDeclType, 0, -1, AttrList, 
index aac6ca321871b7491cb1644a5d31ee71e1f3267d..1eacd48f3d05133c8f064c8c99153576ea16fe72 100644 (file)
@@ -1959,17 +1959,6 @@ Sema::ExprResult Sema::ParseObjCEncodeExpression(SourceLocation AtLoc,
                                                  SourceLocation RParenLoc) {
   QualType EncodedType = QualType::getFromOpaquePtr(Ty);
 
-  // We cannot build type 'id' lazily. It is needed when checking if a 
-  // type is an 'id' (via call to isObjcIdType) even if there is no
-  // need for the default 'id' type.
-  // FIXME: Depending on the need to compare to 'id', this may have to go
-  // somewhere else. At this time, this is a good enough place to do type
-  // encoding of methods and ivars for the rewrite client.
-  // The same is true for the 'Class' and 'SEL' types.
-  GetObjcIdType(EncodeLoc);
-  GetObjcClassType(EncodeLoc);
-  GetObjcSelType(EncodeLoc);
-  
   QualType t = Context.getPointerType(Context.CharTy);
   return new ObjCEncodeExpr(t, EncodedType, AtLoc, RParenLoc);
 }
@@ -1979,7 +1968,7 @@ Sema::ExprResult Sema::ParseObjCSelectorExpression(Selector Sel,
                                                    SourceLocation SelLoc,
                                                    SourceLocation LParenLoc,
                                                    SourceLocation RParenLoc) {
-  QualType t = GetObjcSelType(AtLoc);
+  QualType t = Context.getObjcSelType();
   return new ObjCSelectorExpr(t, Sel, AtLoc, RParenLoc);
 }
 
@@ -2076,7 +2065,7 @@ Sema::ExprResult Sema::ActOnClassMessage(
   if (!Method) {
     Diag(lbrac, diag::warn_method_not_found, std::string("+"), Sel.getName(),
          SourceRange(lbrac, rbrac));
-    returnType = GetObjcIdType();
+    returnType = Context.getObjcIdType();
   } else {
     returnType = Method->getResultType();
     if (Sel.getNumArgs()) {
@@ -2084,7 +2073,6 @@ Sema::ExprResult Sema::ActOnClassMessage(
         return true;
     }
   }
-  GetObjcSelType(lbrac); // FIXME: a hack to install the sel type.
   return new ObjCMessageExpr(receiverName, Sel, returnType, lbrac, rbrac,
                              ArgExprs);
 }
@@ -2103,12 +2091,12 @@ Sema::ExprResult Sema::ActOnInstanceMessage(
   QualType receiverType = RExpr->getType();
   QualType returnType;
   
-  if (receiverType == GetObjcIdType()) {
+  if (receiverType == Context.getObjcIdType()) {
     ObjcMethodDecl *Method = InstanceMethodPool[Sel].Method;
     if (!Method) {
       Diag(lbrac, diag::warn_method_not_found, std::string("-"), Sel.getName(),
            SourceRange(lbrac, rbrac));
-      returnType = GetObjcIdType();
+      returnType = Context.getObjcIdType();
     } else {
       returnType = Method->getResultType();
       if (Sel.getNumArgs())
@@ -2134,7 +2122,7 @@ Sema::ExprResult Sema::ActOnInstanceMessage(
     if (!Method) {
       Diag(lbrac, diag::warn_method_not_found, std::string("-"), Sel.getName(),
            SourceRange(lbrac, rbrac));
-      returnType = GetObjcIdType();
+      returnType = Context.getObjcIdType();
     } else {
       returnType = Method->getResultType();
       if (Sel.getNumArgs())
@@ -2142,6 +2130,5 @@ Sema::ExprResult Sema::ActOnInstanceMessage(
           return true;
     }
   }
-  GetObjcSelType(lbrac); // FIXME: a hack to install the sel type.
   return new ObjCMessageExpr(RExpr, Sel, returnType, lbrac, rbrac, ArgExprs);
 }
index fe4cf8d85be8296188b8454e3723b21a50eb5906..de41b4628d0c47ae944965792f26798c623eb63f 100644 (file)
                08FB7793FE84155DC02AAC07 /* Project object */ = {
                        isa = PBXProject;
                        buildConfigurationList = 1DEB923508733DC60010E9CD /* Build configuration list for PBXProject "clang" */;
-                       compatibilityVersion = "Xcode 2.4";
                        hasScannedForEncodings = 1;
                        mainGroup = 08FB7794FE84155DC02AAC07 /* clang */;
                        projectDirPath = "";
index 2097601c6be1b4022b9101efd5ac9953880a41f3..43290f2add981f3473664f50130e77c598afbd83 100644 (file)
@@ -645,9 +645,7 @@ public:
   /// ActOnPopScope - When a scope is popped, if any typedefs are now 
   /// out-of-scope, they are removed from the IdentifierInfo::FETokenInfo field.
   virtual void ActOnPopScope(SourceLocation Loc, Scope *S);
-  virtual void ActOnTranslationUnitScope(SourceLocation Loc, Scope *S) {
-    TUScope = S;
-  }
+  virtual void ActOnTranslationUnitScope(SourceLocation Loc, Scope *S);
   
   virtual DeclTy *ActOnForwardClassDeclaration(SourceLocation AtClassLoc,
                                                IdentifierInfo **IdentList,