diff options
author | Anders Carlsson <andersca@mac.com> | 2007-10-31 02:53:19 +0000 |
---|---|---|
committer | Anders Carlsson <andersca@mac.com> | 2007-10-31 02:53:19 +0000 |
commit | 8baaca50f07d0c10bba69c8d88c1b9078c92d06d (patch) | |
tree | cb6a289add9d8d9e1d53faa13d1125d6fbad17e7 | |
parent | 8967e9e6c30b61fa9399dd38d6e383651ddbc54d (diff) |
Encode Class, SEL and Objective-C objects.
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@43540 91177308-0d34-0410-b5e6-96231b3b80d8
-rw-r--r-- | AST/ASTContext.cpp | 25 | ||||
-rw-r--r-- | Sema/Sema.cpp | 19 | ||||
-rw-r--r-- | Sema/Sema.h | 3 | ||||
-rw-r--r-- | Sema/SemaExpr.cpp | 11 | ||||
-rw-r--r-- | include/clang/AST/ASTContext.h | 16 | ||||
-rw-r--r-- | include/clang/Basic/DiagnosticKinds.def | 2 |
6 files changed, 75 insertions, 1 deletions
diff --git a/AST/ASTContext.cpp b/AST/ASTContext.cpp index 93ec288270..ec7cd7b558 100644 --- a/AST/ASTContext.cpp +++ b/AST/ASTContext.cpp @@ -152,6 +152,9 @@ void ASTContext::InitBuiltinTypes() { BuiltinVaListType = QualType(); ObjcIdType = QualType(); IdStructType = 0; + ObjcClassType = QualType(); + ClassStructType = 0; + ObjcConstantStringType = QualType(); // void * type @@ -1008,9 +1011,15 @@ void ASTContext::getObjcEncodingForType(QualType T, std::string& S) const S += encoding; } else if (const PointerType *PT = T->getAsPointerType()) { QualType PointeeTy = PT->getPointeeType(); - if (isObjcIdType(PointeeTy)) { + if (isObjcIdType(PointeeTy) || PointeeTy->isObjcInterfaceType()) { S += '@'; return; + } else if (isObjcClassType(PointeeTy)) { + S += '#'; + return; + } else if (isObjcSelType(PointeeTy)) { + S += ':'; + return; } if (PointeeTy->isCharType()) { @@ -1086,6 +1095,20 @@ void ASTContext::setObjcProtoType(TypedefDecl *TD) ProtoStructType = TD->getUnderlyingType()->getAsStructureType(); } +void ASTContext::setObjcClassType(TypedefDecl *TD) +{ + assert(ObjcClassType.isNull() && "'Class' type already set!"); + + ObjcClassType = getTypedefType(TD); + + // typedef struct objc_class *Class; + const PointerType *ptr = TD->getUnderlyingType()->getAsPointerType(); + assert(ptr && "'Class' incorrectly typed"); + const RecordType *rec = ptr->getPointeeType()->getAsStructureType(); + assert(rec && "'Class' incorrectly typed"); + ClassStructType = rec; +} + void ASTContext::setObjcConstantStringInterface(ObjcInterfaceDecl *Decl) { assert(ObjcConstantStringType.isNull() && "'NSConstantString' type already set!"); diff --git a/Sema/Sema.cpp b/Sema/Sema.cpp index 2be198de43..92d17e1e99 100644 --- a/Sema/Sema.cpp +++ b/Sema/Sema.cpp @@ -82,6 +82,25 @@ 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) { diff --git a/Sema/Sema.h b/Sema/Sema.h index 9db00fb1c2..13ba636d52 100644 --- a/Sema/Sema.h +++ b/Sema/Sema.h @@ -284,6 +284,9 @@ private: /// 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()); + /// AddInstanceMethodToGlobalPool - All instance methods in a translation /// unit are added to a global pool. This allows us to efficiently associate /// a selector with a method declaraation for purposes of typechecking diff --git a/Sema/SemaExpr.cpp b/Sema/SemaExpr.cpp index ee3510785b..aac6ca3218 100644 --- a/Sema/SemaExpr.cpp +++ b/Sema/SemaExpr.cpp @@ -1959,6 +1959,17 @@ 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); } diff --git a/include/clang/AST/ASTContext.h b/include/clang/AST/ASTContext.h index dda0490f24..043ffb30c9 100644 --- a/include/clang/AST/ASTContext.h +++ b/include/clang/AST/ASTContext.h @@ -59,6 +59,10 @@ class ASTContext { /// ObjcProtoType - another psuedo built-in typedef type (set by Sema). QualType ObjcProtoType; const RecordType *ProtoStructType; + + /// ObjcClassType - another psuedo built-in typedef type (set by Sema). + QualType ObjcClassType; + const RecordType *ClassStructType; QualType ObjcConstantStringType; RecordDecl *CFConstantStringTypeDecl; @@ -196,6 +200,9 @@ public: void setObjcProtoType(TypedefDecl *Decl); QualType getObjcProtoType() const { return ObjcProtoType; } + void setObjcClassType(TypedefDecl *Decl); + QualType getObjcClassType() const { return ObjcClassType; } + void setBuiltinVaListType(QualType T); QualType getBuiltinVaListType() const { return BuiltinVaListType; } @@ -264,6 +271,15 @@ public: assert(IdStructType && "isObjcIdType used before 'id' type is built"); return T->getAsStructureType() == IdStructType; } + bool isObjcClassType(QualType T) const { + assert(ClassStructType && "isObjcClassType used before 'Class' type is built"); + return T->getAsStructureType() == ClassStructType; + } + bool isObjcSelType(QualType T) const { + assert(SelStructType && "isObjcSelType used before 'SEL' type is built"); + return T->getAsStructureType() == SelStructType; + } + private: ASTContext(const ASTContext&); // DO NOT IMPLEMENT void operator=(const ASTContext&); // DO NOT IMPLEMENT diff --git a/include/clang/Basic/DiagnosticKinds.def b/include/clang/Basic/DiagnosticKinds.def index bbdb6bc517..8a65b7310e 100644 --- a/include/clang/Basic/DiagnosticKinds.def +++ b/include/clang/Basic/DiagnosticKinds.def @@ -450,6 +450,8 @@ DIAG(err_missing_id_definition, ERROR, "cannot find definition of 'id'") DIAG(err_missing_proto_definition, ERROR, "cannot find definition of 'Protocol'") +DIAG(err_missing_class_definition, ERROR, + "cannot find definition of 'Class'") DIAG(warn_previous_alias_decl, WARNING, "previously declared alias is ignored") DIAG(warn_previous_declaration, WARNING, |