[cfe-commits] r65244 - in /cfe/trunk: include/clang/AST/ASTContext.h include/clang/AST/Type.h lib/AST/ASTContext.cpp lib/AST/Type.cpp lib/Sema/SemaType.cpp test/SemaObjC/protocol-archane.m

Daniel Dunbar daniel at zuster.org
Sat Feb 21 13:19:04 PST 2009


On Sat, Feb 21, 2009 at 12:17 PM, Steve Naroff <snaroff at apple.com> wrote:
> Author: snaroff
> Date: Sat Feb 21 14:17:11 2009
> New Revision: 65244
>
> URL: http://llvm.org/viewvc/llvm-project?rev=65244&view=rev
> Log:
> Add support for GCC ObjC extension "Class<protocol>". Sigh.
>
> Found while researching <rdar://problem/6497631> Message lookup is sometimes different than gcc's.
>
> Will never be seen in user code. Needed to pass dejagnu testsuite.

So... why do we care? Why not just keep this unsupported? Or at least,
warn about it?

 - Daniel

>
> Modified:
>    cfe/trunk/include/clang/AST/ASTContext.h
>    cfe/trunk/include/clang/AST/Type.h
>    cfe/trunk/lib/AST/ASTContext.cpp
>    cfe/trunk/lib/AST/Type.cpp
>    cfe/trunk/lib/Sema/SemaType.cpp
>    cfe/trunk/test/SemaObjC/protocol-archane.m
>
> Modified: cfe/trunk/include/clang/AST/ASTContext.h
> URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/AST/ASTContext.h?rev=65244&r1=65243&r2=65244&view=diff
>
> ==============================================================================
> --- cfe/trunk/include/clang/AST/ASTContext.h (original)
> +++ cfe/trunk/include/clang/AST/ASTContext.h Sat Feb 21 14:17:11 2009
> @@ -73,6 +73,7 @@
>     ClassTemplateSpecializationTypes;
>   llvm::FoldingSet<ObjCQualifiedInterfaceType> ObjCQualifiedInterfaceTypes;
>   llvm::FoldingSet<ObjCQualifiedIdType> ObjCQualifiedIdTypes;
> +  llvm::FoldingSet<ObjCQualifiedClassType> ObjCQualifiedClassTypes;
>   /// ASTRecordLayouts - A cache mapping from RecordDecls to ASTRecordLayouts.
>   ///  This is lazily created.  This is intentionally not serialized.
>   llvm::DenseMap<const RecordDecl*, const ASTRecordLayout*> ASTRecordLayouts;
> @@ -291,6 +292,10 @@
>   QualType getObjCQualifiedIdType(ObjCProtocolDecl **ProtocolList,
>                                   unsigned NumProtocols);
>
> +  /// getObjCQualifiedClassType - Return an ObjCQualifiedClassType for a
> +  /// given 'Class' and conforming protocol list.
> +  QualType getObjCQualifiedClassType(ObjCProtocolDecl **ProtocolList,
> +                                     unsigned NumProtocols);
>
>   /// getTypeOfType - GCC extension.
>   QualType getTypeOfExpr(Expr *e);
>
> Modified: cfe/trunk/include/clang/AST/Type.h
> URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/AST/Type.h?rev=65244&r1=65243&r2=65244&view=diff
>
> ==============================================================================
> --- cfe/trunk/include/clang/AST/Type.h (original)
> +++ cfe/trunk/include/clang/AST/Type.h Sat Feb 21 14:17:11 2009
> @@ -69,6 +69,7 @@
>   class BuiltinType;
>   class ObjCInterfaceType;
>   class ObjCQualifiedIdType;
> +  class ObjCQualifiedClassType;
>   class ObjCQualifiedInterfaceType;
>   class StmtIteratorBase;
>   class ClassTemplateSpecializationType;
> @@ -384,6 +385,7 @@
>   bool isObjCInterfaceType() const;             // NSString or NSString<foo>
>   bool isObjCQualifiedInterfaceType() const;    // NSString<foo>
>   bool isObjCQualifiedIdType() const;           // id<foo>
> +  bool isObjCQualifiedClassType() const;        // Class<foo>
>   bool isTemplateTypeParmType() const;          // C++ template type parameter
>
>   /// isDependentType - Whether this type is a dependent type, meaning
> @@ -417,6 +419,7 @@
>   const ObjCInterfaceType *getAsObjCInterfaceType() const;
>   const ObjCQualifiedInterfaceType *getAsObjCQualifiedInterfaceType() const;
>   const ObjCQualifiedIdType *getAsObjCQualifiedIdType() const;
> +  const ObjCQualifiedClassType *getAsObjCQualifiedClassType() const;
>   const TemplateTypeParmType *getAsTemplateTypeParmType() const;
>
>   const ClassTemplateSpecializationType *
> @@ -1744,6 +1747,49 @@
>
>  };
>
> +/// ObjCQualifiedClassType - to represent Class<protocol-list>.
> +///
> +/// Duplicate protocols are removed and protocol list is canonicalized to be in
> +/// alphabetical order.
> +class ObjCQualifiedClassType : public Type,
> +                               public llvm::FoldingSetNode {
> +  // List of protocols for this protocol conforming 'id' type
> +  // List is sorted on protocol name. No protocol is enterred more than once.
> +  llvm::SmallVector<ObjCProtocolDecl*, 8> Protocols;
> +
> +  ObjCQualifiedClassType(ObjCProtocolDecl **Protos, unsigned NumP)
> +    : Type(ObjCQualifiedId, QualType()/*these are always canonical*/,
> +           /*Dependent=*/false),
> +  Protocols(Protos, Protos+NumP) { }
> +  friend class ASTContext;  // ASTContext creates these.
> +public:
> +
> +  ObjCProtocolDecl *getProtocols(unsigned i) const {
> +    return Protocols[i];
> +  }
> +  unsigned getNumProtocols() const {
> +    return Protocols.size();
> +  }
> +  ObjCProtocolDecl **getReferencedProtocols() {
> +    return &Protocols[0];
> +  }
> +
> +  typedef llvm::SmallVector<ObjCProtocolDecl*, 8>::const_iterator qual_iterator;
> +  qual_iterator qual_begin() const { return Protocols.begin(); }
> +  qual_iterator qual_end() const   { return Protocols.end(); }
> +
> +  virtual void getAsStringInternal(std::string &InnerString) const;
> +
> +  void Profile(llvm::FoldingSetNodeID &ID);
> +  static void Profile(llvm::FoldingSetNodeID &ID,
> +                      ObjCProtocolDecl **protocols, unsigned NumProtocols);
> +
> +  static bool classof(const Type *T) {
> +    return T->getTypeClass() == ObjCQualifiedId;
> +  }
> +  static bool classof(const ObjCQualifiedClassType *) { return true; }
> +
> +};
>
>  // Inline function definitions.
>
> @@ -1899,6 +1945,9 @@
>  inline bool Type::isObjCQualifiedIdType() const {
>   return isa<ObjCQualifiedIdType>(CanonicalType.getUnqualifiedType());
>  }
> +inline bool Type::isObjCQualifiedClassType() const {
> +  return isa<ObjCQualifiedClassType>(CanonicalType.getUnqualifiedType());
> +}
>  inline bool Type::isTemplateTypeParmType() const {
>   return isa<TemplateTypeParmType>(CanonicalType.getUnqualifiedType());
>  }
>
> Modified: cfe/trunk/lib/AST/ASTContext.cpp
> URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/AST/ASTContext.cpp?rev=65244&r1=65243&r2=65244&view=diff
>
> ==============================================================================
> --- cfe/trunk/lib/AST/ASTContext.cpp (original)
> +++ cfe/trunk/lib/AST/ASTContext.cpp Sat Feb 21 14:17:11 2009
> @@ -1394,6 +1394,29 @@
>   return QualType(QType, 0);
>  }
>
> +/// getObjCQualifiedClassType - Return an ObjCQualifiedIdType for the 'Class'
> +/// decl and the conforming protocol list.
> +QualType ASTContext::getObjCQualifiedClassType(ObjCProtocolDecl **Protocols,
> +                                               unsigned NumProtocols) {
> +  // Sort the protocol list alphabetically to canonicalize it.
> +  SortAndUniqueProtocols(Protocols, NumProtocols);
> +
> +  llvm::FoldingSetNodeID ID;
> +  ObjCQualifiedIdType::Profile(ID, Protocols, NumProtocols);
> +
> +  void *InsertPos = 0;
> +  if (ObjCQualifiedClassType *QT =
> +        ObjCQualifiedClassTypes.FindNodeOrInsertPos(ID, InsertPos))
> +    return QualType(QT, 0);
> +
> +  // No Match;
> +  ObjCQualifiedClassType *QType =
> +    new (*this,8) ObjCQualifiedClassType(Protocols, NumProtocols);
> +  Types.push_back(QType);
> +  ObjCQualifiedClassTypes.InsertNode(QType, InsertPos);
> +  return QualType(QType, 0);
> +}
> +
>  /// getTypeOfExpr - Unlike many "get<Type>" functions, we can't unique
>  /// TypeOfExpr AST's (since expression's are never shared). For example,
>  /// multiple declarations that refer to "typeof(x)" all contain different
>
> Modified: cfe/trunk/lib/AST/Type.cpp
> URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/AST/Type.cpp?rev=65244&r1=65243&r2=65244&view=diff
>
> ==============================================================================
> --- cfe/trunk/lib/AST/Type.cpp (original)
> +++ cfe/trunk/lib/AST/Type.cpp Sat Feb 21 14:17:11 2009
> @@ -869,6 +869,17 @@
>   Profile(ID, &Protocols[0], getNumProtocols());
>  }
>
> +void ObjCQualifiedClassType::Profile(llvm::FoldingSetNodeID &ID,
> +                                     ObjCProtocolDecl **protocols,
> +                                     unsigned NumProtocols) {
> +  for (unsigned i = 0; i != NumProtocols; i++)
> +    ID.AddPointer(protocols[i]);
> +}
> +
> +void ObjCQualifiedClassType::Profile(llvm::FoldingSetNodeID &ID) {
> +  Profile(ID, &Protocols[0], getNumProtocols());
> +}
> +
>  /// LookThroughTypedefs - Return the ultimate type this typedef corresponds to
>  /// potentially looking through *all* consequtive typedefs.  This returns the
>  /// sum of the type qualifiers, so if you have:
> @@ -1345,6 +1356,22 @@
>   InnerString = ObjCQIString + InnerString;
>  }
>
> +void ObjCQualifiedClassType::getAsStringInternal(std::string &InnerString) const
> +{
> +  if (!InnerString.empty())    // Prefix the basic type, e.g. 'typedefname X'.
> +    InnerString = ' ' + InnerString;
> +  std::string ObjCQIString = "Class";
> +  ObjCQIString += '<';
> +  int num = getNumProtocols();
> +  for (int i = 0; i < num; i++) {
> +    ObjCQIString += getProtocols(i)->getNameAsString();
> +    if (i < num-1)
> +      ObjCQIString += ',';
> +  }
> +  ObjCQIString += '>';
> +  InnerString = ObjCQIString + InnerString;
> +}
> +
>  void TagType::getAsStringInternal(std::string &InnerString) const {
>   if (!InnerString.empty())    // Prefix the basic type, e.g. 'typedefname X'.
>     InnerString = ' ' + InnerString;
>
> Modified: cfe/trunk/lib/Sema/SemaType.cpp
> URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaType.cpp?rev=65244&r1=65243&r2=65244&view=diff
>
> ==============================================================================
> --- cfe/trunk/lib/Sema/SemaType.cpp (original)
> +++ cfe/trunk/lib/Sema/SemaType.cpp Sat Feb 21 14:17:11 2009
> @@ -151,6 +151,10 @@
>         // id<protocol-list>
>         Result = Context.getObjCQualifiedIdType((ObjCProtocolDecl**)PQ,
>                                                 DS.getNumProtocolQualifiers());
> +      else if (Result == Context.getObjCClassType())
> +        // Support the following GCC extension: Class<protocol-list>
> +        Result = Context.getObjCQualifiedClassType((ObjCProtocolDecl**)PQ,
> +                                                DS.getNumProtocolQualifiers());
>       else
>         Diag(DS.getSourceRange().getBegin(),
>              diag::warn_ignoring_objc_qualifiers) << DS.getSourceRange();
>
> Modified: cfe/trunk/test/SemaObjC/protocol-archane.m
> URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/SemaObjC/protocol-archane.m?rev=65244&r1=65243&r2=65244&view=diff
>
> ==============================================================================
> --- cfe/trunk/test/SemaObjC/protocol-archane.m (original)
> +++ cfe/trunk/test/SemaObjC/protocol-archane.m Sat Feb 21 14:17:11 2009
> @@ -27,3 +27,8 @@
>
>  // GCC doesn't diagnose this.
>  NotAnObjCObjectType <SomeProtocol> *obj; // expected-warning {{ignoring protocol qualifiers on non-ObjC type}}
> +
> +// GCC extension (sigh). Found while researching rdar://6497631
> +typedef struct objc_class *Class;
> +
> +Class <SomeProtocol> UnfortunateGCCExtension;
>
>
> _______________________________________________
> cfe-commits mailing list
> cfe-commits at cs.uiuc.edu
> http://lists.cs.uiuc.edu/mailman/listinfo/cfe-commits
>



More information about the cfe-commits mailing list