<html><body style="word-wrap: break-word; -webkit-nbsp-mode: space; -webkit-line-break: after-white-space; "><br><div><div>On Jul 15, 2009, at 5:22 PM, steve naroff wrote:</div><br class="Apple-interchange-newline"><blockquote type="cite"><div><br>On Jul 15, 2009, at 4:45 PM, Fariborz Jahanian wrote:<br><br><blockquote type="cite">Nice. Few comments below.<br></blockquote><blockquote type="cite"><br></blockquote><br>Sure...<br><br><blockquote type="cite">- Fariborz<br></blockquote><blockquote type="cite"><br></blockquote><blockquote type="cite">On Jul 15, 2009, at 11:40 AM, Steve Naroff wrote:<br></blockquote><blockquote type="cite"><br></blockquote><blockquote type="cite"><blockquote type="cite">Author: snaroff<br></blockquote></blockquote><blockquote type="cite"><blockquote type="cite">Date: Wed Jul 15 13:40:39 2009<br></blockquote></blockquote><blockquote type="cite"><blockquote type="cite">New Revision: 75808<br></blockquote></blockquote><blockquote type="cite"><blockquote type="cite"><br></blockquote></blockquote><blockquote type="cite"><blockquote type="cite">URL: <a href="http://llvm.org/viewvc/llvm-project?rev=75808&view=rev">http://llvm.org/viewvc/llvm-project?rev=75808&view=rev</a><br></blockquote></blockquote><blockquote type="cite"><blockquote type="cite">Log:<br></blockquote></blockquote><blockquote type="cite"><blockquote type="cite">Implement the ObjC pseudo built-in types as clang "BuiltinType's". I say pseudo built-in types, since Sema still injects a typedef for recognition (i.e. they aren't truly built-ins from a parser perspective).<br></blockquote></blockquote><blockquote type="cite"><blockquote type="cite"><br></blockquote></blockquote><blockquote type="cite"><blockquote type="cite">This removes the static data/methods on ObjCObjectPointerType while preserving the nice API (no need to fiddle with ASTContext:-).<br></blockquote></blockquote><blockquote type="cite"><blockquote type="cite"><br></blockquote></blockquote><blockquote type="cite"><blockquote type="cite">This patch also adds Type::isObjCBuiltinType().<br></blockquote></blockquote><blockquote type="cite"><blockquote type="cite"><br></blockquote></blockquote><blockquote type="cite"><blockquote type="cite">This should be the last fairly large patch related to recrafting the ObjC type system. The follow-on patches should be fairly small.<br></blockquote></blockquote><blockquote type="cite"><blockquote type="cite"><br></blockquote></blockquote><br><snip><br><br><blockquote type="cite"><blockquote type="cite"> bool isObjCIdType(QualType T) const {<br></blockquote></blockquote><blockquote type="cite"><blockquote type="cite">-    return T == ObjCIdType;<br></blockquote></blockquote><blockquote type="cite"><blockquote type="cite">+    return T == ObjCIdTypedefType;<br></blockquote></blockquote><blockquote type="cite"><blockquote type="cite"> }<br></blockquote></blockquote><blockquote type="cite"><blockquote type="cite"> bool isObjCClassType(QualType T) const {<br></blockquote></blockquote><blockquote type="cite"><blockquote type="cite">-    return T == ObjCClassType;<br></blockquote></blockquote><blockquote type="cite"><blockquote type="cite">+    return T == ObjCClassTypedefType;<br></blockquote></blockquote><blockquote type="cite"><br></blockquote><blockquote type="cite">I am not sure about this and isObjCIdType(). You are comparing against a typedef AST node 'id' and typedef AST node for 'Class'.<br></blockquote><blockquote type="cite">what if 'T' is the builtin type for 'id' or 'Class'? This predicate returns false.<br></blockquote><blockquote type="cite"><br></blockquote><br>All I changed is the name (to avoid confusion with ObjCIdTypedefType/ObjCClassTypedefType).<br><br></div></blockquote><div><br></div><div style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; font: normal normal normal 10px/normal Monaco; "><font class="Apple-style-span" color="#000000" face="Helvetica" size="3"><span class="Apple-style-span" style="background-color: transparent; font-size: 12px;">I meant "to avoid confustion with ObjCBuiltinIdTy/ObjCBuiltinClassTy"</span></font></div><div style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; font: normal normal normal 10px/normal Monaco; "><br></div><blockquote type="cite"><div>Nevertheless, you are correct. From a source code perspective, the only real 'id' or 'Class' type is the Typedef type (injected by Sema). This has always been the case I believe.<br><br>The Builtin type is simply a clever mechanism to preserve the nice API without resorting to static data. More specifically, ASTContext::ObjCBuiltinIdTy and ASTContext::ObjCBuiltinClassTy will *only* be referred to by ObjCIdTypedefType/ObjCClassTypedefType. Without it, I would have had to move many Type predicates to ASTContext (or fiddle with some weird union in ObjCObjectPointerType). This seemed like an elegant solution to the problem...especially since id/Class are in fact builtin now. The more I played with this solution, the more I liked it.<br><br><br><blockquote type="cite"><br></blockquote><blockquote type="cite"><blockquote type="cite"><br></blockquote></blockquote><blockquote type="cite"><blockquote type="cite"> }<br></blockquote></blockquote><blockquote type="cite"><blockquote type="cite"> bool isObjCSelType(QualType T) const {<br></blockquote></blockquote><blockquote type="cite"><blockquote type="cite">   assert(SelStructType && "isObjCSelType used before 'SEL' type is built");<br></blockquote></blockquote><blockquote type="cite"><blockquote type="cite"><br></blockquote></blockquote><blockquote type="cite"><blockquote type="cite">Modified: cfe/trunk/include/clang/AST/Type.h<br></blockquote></blockquote><blockquote type="cite"><blockquote type="cite">URL: <a href="http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/AST/Type.h?rev=75808&r1=75807&r2=75808&view=diff">http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/AST/Type.h?rev=75808&r1=75807&r2=75808&view=diff</a><br></blockquote></blockquote><blockquote type="cite"><blockquote type="cite"><br></blockquote></blockquote><blockquote type="cite"><blockquote type="cite">==============================================================================<br></blockquote></blockquote><blockquote type="cite"><blockquote type="cite">--- cfe/trunk/include/clang/AST/Type.h (original)<br></blockquote></blockquote><blockquote type="cite"><blockquote type="cite">+++ cfe/trunk/include/clang/AST/Type.h Wed Jul 15 13:40:39 2009<br></blockquote></blockquote><blockquote type="cite"><blockquote type="cite">@@ -404,6 +404,7 @@<br></blockquote></blockquote><blockquote type="cite"><blockquote type="cite"> bool isObjCQualifiedIdType() const;           // id<foo><br></blockquote></blockquote><blockquote type="cite"><blockquote type="cite"> bool isObjCIdType() const;                    // id<br></blockquote></blockquote><blockquote type="cite"><blockquote type="cite"> bool isObjCClassType() const;                 // Class<br></blockquote></blockquote><blockquote type="cite"><blockquote type="cite">+  bool isObjCBuiltinType() const;               // 'id' or 'Class'<br></blockquote></blockquote><blockquote type="cite"><blockquote type="cite"> bool isTemplateTypeParmType() const;          // C++ template type parameter<br></blockquote></blockquote><blockquote type="cite"><blockquote type="cite"> bool isNullPtrType() const;                   // C++0x nullptr_t<br></blockquote></blockquote><blockquote type="cite"><blockquote type="cite"><br></blockquote></blockquote><blockquote type="cite"><blockquote type="cite">@@ -592,8 +593,10 @@<br></blockquote></blockquote><blockquote type="cite"><blockquote type="cite">   Overload,  // This represents the type of an overloaded function declaration.<br></blockquote></blockquote><blockquote type="cite"><blockquote type="cite">   Dependent, // This represents the type of a type-dependent expression.<br></blockquote></blockquote><blockquote type="cite"><blockquote type="cite"><br></blockquote></blockquote><blockquote type="cite"><blockquote type="cite">-    UndeducedAuto  // In C++0x, this represents the type of an auto variable<br></blockquote></blockquote><blockquote type="cite"><blockquote type="cite">+    UndeducedAuto, // In C++0x, this represents the type of an auto variable<br></blockquote></blockquote><blockquote type="cite"><blockquote type="cite">                  // that has not been deduced yet.<br></blockquote></blockquote><blockquote type="cite"><blockquote type="cite">+    ObjCId,    // This represents the ObjC 'id' type.<br></blockquote></blockquote><blockquote type="cite"><blockquote type="cite">+    ObjCClass  // This represents the ObjC 'Class' type.<br></blockquote></blockquote><blockquote type="cite"><blockquote type="cite"> };<br></blockquote></blockquote><blockquote type="cite"><blockquote type="cite">private:<br></blockquote></blockquote><blockquote type="cite"><blockquote type="cite"> Kind TypeKind;<br></blockquote></blockquote><blockquote type="cite"><blockquote type="cite">@@ -1899,7 +1902,7 @@<br></blockquote></blockquote><blockquote type="cite"><blockquote type="cite">/// Duplicate protocols are removed and protocol list is canonicalized to be in<br></blockquote></blockquote><blockquote type="cite"><blockquote type="cite">/// alphabetical order.<br></blockquote></blockquote><blockquote type="cite"><blockquote type="cite">class ObjCObjectPointerType : public Type, public llvm::FoldingSetNode {<br></blockquote></blockquote><blockquote type="cite"><blockquote type="cite">-  QualType PointeeType; // will always point to an interface type.<br></blockquote></blockquote><blockquote type="cite"><blockquote type="cite">+  QualType PointeeType; // A builin or interface type.<br></blockquote></blockquote><blockquote type="cite"><blockquote type="cite"><br></blockquote></blockquote><blockquote type="cite"><blockquote type="cite"> // List of protocols for this protocol conforming object type<br></blockquote></blockquote><blockquote type="cite"><blockquote type="cite"> // List is sorted on protocol name. No protocol is entered more than once.<br></blockquote></blockquote><blockquote type="cite"><blockquote type="cite">@@ -1909,20 +1912,10 @@<br></blockquote></blockquote><blockquote type="cite"><blockquote type="cite">   Type(ObjCObjectPointer, QualType(), /*Dependent=*/false),<br></blockquote></blockquote><blockquote type="cite"><blockquote type="cite">   PointeeType(T), Protocols(Protos, Protos+NumP) { }<br></blockquote></blockquote><blockquote type="cite"><blockquote type="cite"> friend class ASTContext;  // ASTContext creates these.<br></blockquote></blockquote><blockquote type="cite"><blockquote type="cite">-  friend class ObjCInterfaceType; // To enable 'id' and 'Class' predicates.<br></blockquote></blockquote><blockquote type="cite"><blockquote type="cite"><br></blockquote></blockquote><blockquote type="cite"><blockquote type="cite">-  static ObjCInterfaceType *IdInterfaceT;<br></blockquote></blockquote><blockquote type="cite"><blockquote type="cite">-  static ObjCInterfaceType *ClassInterfaceT;<br></blockquote></blockquote><blockquote type="cite"><blockquote type="cite">-  static void setIdInterface(QualType T) {<br></blockquote></blockquote><blockquote type="cite"><blockquote type="cite">-    IdInterfaceT =  dyn_cast<ObjCInterfaceType>(T.getTypePtr());<br></blockquote></blockquote><blockquote type="cite"><blockquote type="cite">-  }<br></blockquote></blockquote><blockquote type="cite"><blockquote type="cite">-  static void setClassInterface(QualType T) {<br></blockquote></blockquote><blockquote type="cite"><blockquote type="cite">-    ClassInterfaceT =  dyn_cast<ObjCInterfaceType>(T.getTypePtr());<br></blockquote></blockquote><blockquote type="cite"><blockquote type="cite">-  }<br></blockquote></blockquote><blockquote type="cite"><blockquote type="cite">-  static ObjCInterfaceType *getIdInterface() { return IdInterfaceT; }<br></blockquote></blockquote><blockquote type="cite"><blockquote type="cite">-  static ObjCInterfaceType *getClassInterface() { return ClassInterfaceT; }<br></blockquote></blockquote><blockquote type="cite"><blockquote type="cite">public:<br></blockquote></blockquote><blockquote type="cite"><blockquote type="cite">-  // Get the pointee type. Pointee is required to always be an interface type.<br></blockquote></blockquote><blockquote type="cite"><blockquote type="cite">+  // Get the pointee type. Pointee will either be a built-in type (for 'id' and<br></blockquote></blockquote><blockquote type="cite"><blockquote type="cite">+  // 'Class') or will be an interface type (for user-defined types).<br></blockquote></blockquote><blockquote type="cite"><blockquote type="cite"> // Note: Pointee can be a TypedefType whose canonical type is an interface.<br></blockquote></blockquote><blockquote type="cite"><blockquote type="cite"> // Example: typedef NSObject T; T *var;<br></blockquote></blockquote><blockquote type="cite"><blockquote type="cite"> QualType getPointeeType() const { return PointeeType; }<br></blockquote></blockquote><blockquote type="cite">Name Pointee and comment above is confusing to me. To me Pointee is what a pointer is pointing at.<br></blockquote><blockquote type="cite"><br></blockquote><blockquote type="cite">Here you mean several things as I understand it.<br></blockquote><blockquote type="cite">1) For 'id' and 'Class' it holds the builtin type for 'id' and 'Class' when their container is ObjCObjectPointerType<br></blockquote><blockquote type="cite">for the two typedefs 'id' and 'Class'.<br></blockquote><br>Yes.<br><br><blockquote type="cite"><br></blockquote><blockquote type="cite"><br></blockquote><blockquote type="cite">2) For an interface pointer type; such as, "NSObject *" is Pointee for "NSObject" (as the name implies)?<br></blockquote><blockquote type="cite"><br></blockquote><br>Yes.<br><br><blockquote type="cite">3) For the example  in the comment ( typedef NSObject T; T *var) Pointee referes to "NSObject" right?<br></blockquote><blockquote type="cite"><br></blockquote><br>Nope. Pointee would be a TypedefType whose canonical type is an interface. I say this in the "Note:".<br><br>Do you think I need to rewrite the comment?<br><br><blockquote type="cite">If my assumptions are correct, then Pointee really means two different things for builtin and  user types.<br></blockquote><br>Sure, but that actually makes more sense than what I previously had. For example, the ObjCObjectPointerType::getInterfaceType() method now returns 0 for builtin types (which more closely models the existing language definition, where there are no formal interfaces for 'id'/'Class'). The previous implementation would return an internally synthesized interface for id/Class with no ivars/methods (which was kind of odd). It simplified a very small amount of code internally.<br><br>All that said, the good news is the predicates on ObjCObjectPointerType abstract you from understanding the two different roles (of builtin vs. user defined). Type::isObjCBuiltinType() also helps.<br><br>Thanks again for reviewing this stuff. Your questions/feedback are very helpful.<br><br>Let me know if you have any tweaks you'd like me to make (based on my responses)...<br><br>snaroff<br><br></div></blockquote></div><br></body></html>