[cfe-commits] r79248 - in /cfe/trunk: include/clang/AST/ASTContext.h lib/AST/ASTContext.cpp lib/CodeGen/CGObjCGNU.cpp lib/Sema/Sema.cpp lib/Sema/SemaChecking.cpp lib/Sema/SemaDecl.cpp lib/Sema/SemaExpr.cpp

David Chisnall csdavec at swan.ac.uk
Mon Aug 17 09:35:33 PDT 2009


Author: theraven
Date: Mon Aug 17 11:35:33 2009
New Revision: 79248

URL: http://llvm.org/viewvc/llvm-project?rev=79248&view=rev
Log:
Initial patch to support definitions of id and Class from headers in Objective-C code.

This currently breaks test/SemaObjC/id-isa-ref.m and issues some spurious warnings when you attempt to assign a struct objc_class* value to a Class variable.  The test case probably should fail as it's written, because without the definition of Class the compiler should not assume struct objc_class* is a valid receiver type, but it's left broken because it would be nice if we could get that passing too for the special case of isa.

Approved by snaroff.


Modified:
    cfe/trunk/include/clang/AST/ASTContext.h
    cfe/trunk/lib/AST/ASTContext.cpp
    cfe/trunk/lib/CodeGen/CGObjCGNU.cpp
    cfe/trunk/lib/Sema/Sema.cpp
    cfe/trunk/lib/Sema/SemaChecking.cpp
    cfe/trunk/lib/Sema/SemaDecl.cpp
    cfe/trunk/lib/Sema/SemaExpr.cpp

Modified: cfe/trunk/include/clang/AST/ASTContext.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/AST/ASTContext.h?rev=79248&r1=79247&r2=79248&view=diff

==============================================================================
--- cfe/trunk/include/clang/AST/ASTContext.h (original)
+++ cfe/trunk/include/clang/AST/ASTContext.h Mon Aug 17 11:35:33 2009
@@ -202,6 +202,11 @@
   llvm::OwningPtr<ExternalASTSource> ExternalSource;
   clang::PrintingPolicy PrintingPolicy;
 
+  // Typedefs which may be provided defining the structure of Objective-C
+  // pseudo-builtins
+  QualType ObjCIdRedefinitionType;
+  QualType ObjCClassRedefinitionType;
+
   /// \brief Source ranges for all of the comments in the source file,
   /// sorted in order of appearance in the translation unit.
   std::vector<SourceRange> Comments;

Modified: cfe/trunk/lib/AST/ASTContext.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/AST/ASTContext.cpp?rev=79248&r1=79247&r2=79248&view=diff

==============================================================================
--- cfe/trunk/lib/AST/ASTContext.cpp (original)
+++ cfe/trunk/lib/AST/ASTContext.cpp Mon Aug 17 11:35:33 2009
@@ -43,6 +43,8 @@
   LoadedExternalComments(false), FreeMemory(FreeMem), Target(t), 
   Idents(idents), Selectors(sels),
   BuiltinInfo(builtins), ExternalSource(0), PrintingPolicy(LOpts) {  
+  ObjCIdRedefinitionType = QualType();
+  ObjCClassRedefinitionType = QualType();
   if (size_reserve > 0) Types.reserve(size_reserve);    
   TUDecl = TranslationUnitDecl::Create(*this);
   InitBuiltinTypes();

Modified: cfe/trunk/lib/CodeGen/CGObjCGNU.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/CGObjCGNU.cpp?rev=79248&r1=79247&r2=79248&view=diff

==============================================================================
--- cfe/trunk/lib/CodeGen/CGObjCGNU.cpp (original)
+++ cfe/trunk/lib/CodeGen/CGObjCGNU.cpp Mon Aug 17 11:35:33 2009
@@ -53,6 +53,7 @@
   const llvm::PointerType *PtrToInt8Ty;
   const llvm::FunctionType *IMPTy;
   const llvm::PointerType *IdTy;
+  QualType ASTIdTy;
   const llvm::IntegerType *IntTy;
   const llvm::PointerType *PtrTy;
   const llvm::IntegerType *LongTy;
@@ -226,8 +227,8 @@
   PtrTy = PtrToInt8Ty;
  
   // Object type
-  IdTy = cast<llvm::PointerType>(
-		  CGM.getTypes().ConvertType(CGM.getContext().getObjCIdType()));
+  ASTIdTy = CGM.getContext().getObjCIdType();
+  IdTy = cast<llvm::PointerType>(CGM.getTypes().ConvertType(ASTIdTy));
  
   // IMP type
   std::vector<const llvm::Type*> IMPArgs;
@@ -257,8 +258,8 @@
   llvm::GlobalAlias *&US = UntypedSelectors[Sel.getAsString()];
   if (US == 0)
     US = new llvm::GlobalAlias(llvm::PointerType::getUnqual(SelectorTy),
-                               llvm::GlobalValue::InternalLinkage,
-                               ".objc_untyped_selector_alias",
+                               llvm::GlobalValue::PrivateLinkage,
+                               ".objc_untyped_selector_alias"+Sel.getAsString(),
                                NULL, &TheModule);
   
   return Builder.CreateLoad(US);
@@ -282,7 +283,7 @@
   // If it isn't, cache it.
   llvm::GlobalAlias *Sel = new llvm::GlobalAlias(
           llvm::PointerType::getUnqual(SelectorTy),
-          llvm::GlobalValue::InternalLinkage, SelName,
+          llvm::GlobalValue::PrivateLinkage, ".objc_selector_alias" + SelName,
           NULL, &TheModule);
   TypedSelectors[Selector] = Sel;
 
@@ -348,8 +349,8 @@
   CallArgList ActualArgs;
 
   ActualArgs.push_back(
-	  std::make_pair(RValue::get(CGF.Builder.CreateBitCast(Receiver, IdTy)), 
-	  CGF.getContext().getObjCIdType()));
+      std::make_pair(RValue::get(CGF.Builder.CreateBitCast(Receiver, IdTy)),
+      ASTIdTy));
   ActualArgs.push_back(std::make_pair(RValue::get(cmd),
                                       CGF.getContext().getObjCSelType()));
   ActualArgs.insert(ActualArgs.end(), CallArgs.begin(), CallArgs.end());
@@ -436,6 +437,7 @@
                                bool IsClassMessage,
                                const CallArgList &CallArgs,
                                const ObjCMethodDecl *Method) {
+  IdTy = cast<llvm::PointerType>(CGM.getTypes().ConvertType(ASTIdTy));
   llvm::Value *cmd;
   if (Method)
     cmd = GetSelector(CGF.Builder, Method);
@@ -444,8 +446,7 @@
   CallArgList ActualArgs;
 
   ActualArgs.push_back(
-    std::make_pair(RValue::get(CGF.Builder.CreateBitCast(Receiver, IdTy)), 
-    CGF.getContext().getObjCIdType()));
+    std::make_pair(RValue::get(CGF.Builder.CreateBitCast(Receiver, IdTy)), ASTIdTy));
   ActualArgs.push_back(std::make_pair(RValue::get(cmd),
                                       CGF.getContext().getObjCSelType()));
   ActualArgs.insert(ActualArgs.end(), CallArgs.begin(), CallArgs.end());
@@ -495,6 +496,8 @@
     const llvm::SmallVectorImpl<Selector> &MethodSels, 
     const llvm::SmallVectorImpl<llvm::Constant *> &MethodTypes, 
     bool isClassMethodList) {
+  if (MethodSels.empty())
+    return NULLPtr;
   // Get the method structure type.  
   llvm::StructType *ObjCMethodTy = llvm::StructType::get(VMContext,
     PtrToInt8Ty, // Really a selector, but the runtime creates it us.
@@ -1257,7 +1260,7 @@
   ASTContext &Ctx = CGM.getContext();
   // void objc_enumerationMutation (id)
   llvm::SmallVector<QualType,16> Params;
-  Params.push_back(Ctx.getObjCIdType());
+  Params.push_back(ASTIdTy);
   const llvm::FunctionType *FTy =
     Types.GetFunctionType(Types.getFunctionInfo(Ctx.VoidTy, Params), false);
   return CGM.CreateRuntimeFunction(FTy, "objc_enumerationMutation");

Modified: cfe/trunk/lib/Sema/Sema.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/Sema.cpp?rev=79248&r1=79247&r2=79248&view=diff

==============================================================================
--- cfe/trunk/lib/Sema/Sema.cpp (original)
+++ cfe/trunk/lib/Sema/Sema.cpp Mon Aug 17 11:35:33 2009
@@ -159,6 +159,7 @@
       );
     PushOnScopeChains(IdTypedef, TUScope);
     Context.setObjCIdType(Context.getTypeDeclType(IdTypedef));
+    Context.ObjCIdRedefinitionType = Context.getObjCIdType();
   }
   // Create the built-in typedef for 'Class'.
   if (Context.getObjCClassType().isNull()) {
@@ -169,6 +170,7 @@
       );
     PushOnScopeChains(ClassTypedef, TUScope);
     Context.setObjCClassType(Context.getTypeDeclType(ClassTypedef));
+    Context.ObjCClassRedefinitionType = Context.getObjCClassType();
   }
 }
 

Modified: cfe/trunk/lib/Sema/SemaChecking.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaChecking.cpp?rev=79248&r1=79247&r2=79248&view=diff

==============================================================================
--- cfe/trunk/lib/Sema/SemaChecking.cpp (original)
+++ cfe/trunk/lib/Sema/SemaChecking.cpp Mon Aug 17 11:35:33 2009
@@ -1257,7 +1257,7 @@
 ///   * taking the address of an array element where the array is on the stack
 static DeclRefExpr* EvalAddr(Expr *E) {
   // We should only be called for evaluating pointer expressions.
-  assert((E->getType()->isPointerType() ||
+  assert((E->getType()->isAnyPointerType() ||
           E->getType()->isBlockPointerType() ||
           E->getType()->isObjCQualifiedIdType()) &&
          "EvalAddr only works on pointers");

Modified: cfe/trunk/lib/Sema/SemaDecl.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaDecl.cpp?rev=79248&r1=79247&r2=79248&view=diff

==============================================================================
--- cfe/trunk/lib/Sema/SemaDecl.cpp (original)
+++ cfe/trunk/lib/Sema/SemaDecl.cpp Mon Aug 17 11:35:33 2009
@@ -534,12 +534,14 @@
     case 2: 
       if (!TypeID->isStr("id"))
         break;
+      Context.ObjCIdRedefinitionType = New->getUnderlyingType();
       // Install the built-in type for 'id', ignoring the current definition.
       New->setTypeForDecl(Context.getObjCIdType().getTypePtr());
       return;
     case 5:
       if (!TypeID->isStr("Class"))
         break;
+      Context.ObjCClassRedefinitionType = New->getUnderlyingType();
       // Install the built-in type for 'Class', ignoring the current definition.
       New->setTypeForDecl(Context.getObjCClassType().getTypePtr());
       return;

Modified: cfe/trunk/lib/Sema/SemaExpr.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaExpr.cpp?rev=79248&r1=79247&r2=79248&view=diff

==============================================================================
--- cfe/trunk/lib/Sema/SemaExpr.cpp (original)
+++ cfe/trunk/lib/Sema/SemaExpr.cpp Mon Aug 17 11:35:33 2009
@@ -26,6 +26,7 @@
 #include "clang/Parse/Scope.h"
 using namespace clang;
 
+
 /// \brief Determine whether the use of this declaration is valid, and
 /// emit any corresponding diagnostics.
 ///
@@ -2127,6 +2128,20 @@
   DefaultFunctionArrayConversion(BaseExpr);
 
   QualType BaseType = BaseExpr->getType();
+  // If this is an Objective-C pseudo-builtin and a definition is provided then
+  // use that.
+  if (BaseType->isObjCIdType()) {
+    // We have an 'id' type. Rather than fall through, we check if this
+    // is a reference to 'isa'.
+    if (BaseType != Context.ObjCIdRedefinitionType) {
+      BaseType = Context.ObjCIdRedefinitionType;
+      ImpCastExprToType(BaseExpr, BaseType);
+    }
+  } else if (BaseType->isObjCClassType() &&
+      BaseType != Context.ObjCClassRedefinitionType) {
+    BaseType = Context.ObjCClassRedefinitionType;
+    ImpCastExprToType(BaseExpr, BaseType);
+  }
   assert(!BaseType.isNull() && "no type for member expression");
 
   // Get the type being accessed in BaseType.  If this is an arrow, the BaseExpr
@@ -2402,11 +2417,6 @@
                          << IDecl->getDeclName() << &Member
                          << BaseExpr->getSourceRange());
     }
-    // We have an 'id' type. Rather than fall through, we check if this
-    // is a reference to 'isa'.
-    if (Member.isStr("isa"))
-      return Owned(new (Context) ObjCIsaExpr(BaseExpr, true, MemberLoc,
-                                             Context.getObjCIdType()));
   }
   // Handle properties on 'id' and qualified "id".
   if (OpKind == tok::period && (BaseType->isObjCIdType() || 
@@ -3266,6 +3276,30 @@
     ImpCastExprToType(LHS, RHSTy); // promote the null to a pointer.
     return RHSTy;
   }
+  // Handle things like Class and struct objc_class*.  Here we case the result
+  // to the pseudo-builtin, because that will be implicitly cast back to the
+  // redefinition type if an attempt is made to access its fields.
+  if (LHSTy->isObjCClassType() &&
+      (RHSTy.getDesugaredType() == Context.ObjCClassRedefinitionType)) {
+    ImpCastExprToType(RHS, LHSTy);
+    return LHSTy;
+  }
+  if (RHSTy->isObjCClassType() &&
+      (LHSTy.getDesugaredType() == Context.ObjCClassRedefinitionType)) {
+    ImpCastExprToType(LHS, RHSTy);
+    return RHSTy;
+  }
+  // And the same for struct objc_object* / id
+  if (LHSTy->isObjCIdType() &&
+      (RHSTy.getDesugaredType() == Context.ObjCIdRedefinitionType)) {
+    ImpCastExprToType(RHS, LHSTy);
+    return LHSTy;
+  }
+  if (RHSTy->isObjCIdType() &&
+      (LHSTy.getDesugaredType() == Context.ObjCIdRedefinitionType)) {
+    ImpCastExprToType(LHS, RHSTy);
+    return RHSTy;
+  }
   // Handle block pointer types.
   if (LHSTy->isBlockPointerType() || RHSTy->isBlockPointerType()) {
     if (!LHSTy->isBlockPointerType() || !RHSTy->isBlockPointerType()) {
@@ -3484,6 +3518,13 @@
 Sema::CheckPointerTypesForAssignment(QualType lhsType, QualType rhsType) {
   QualType lhptee, rhptee;
 
+  if ((lhsType->isObjCClassType() &&
+       (rhsType.getDesugaredType() == Context.ObjCClassRedefinitionType)) ||
+     (rhsType->isObjCClassType() &&
+       (lhsType.getDesugaredType() == Context.ObjCClassRedefinitionType))) {
+      return Compatible;
+  }
+
   // get the "pointed to" type (ignoring qualifiers at the top level)
   lhptee = lhsType->getAs<PointerType>()->getPointeeType();
   rhptee = rhsType->getAs<PointerType>()->getPointeeType();
@@ -3607,6 +3648,13 @@
   if (lhsType == rhsType)
     return Compatible; // Common case: fast path an exact match.
 
+  if ((lhsType->isObjCClassType() &&
+       (rhsType.getDesugaredType() == Context.ObjCClassRedefinitionType)) ||
+     (rhsType->isObjCClassType() &&
+       (lhsType.getDesugaredType() == Context.ObjCClassRedefinitionType))) {
+      return Compatible;
+  }
+
   // If the left-hand side is a reference type, then we are in a
   // (rare!) case where we've allowed the use of references in C,
   // e.g., as a parameter type in a built-in function. In this case,





More information about the cfe-commits mailing list