This patch implements objective-c's 'SEL' type as a built-in
type and fixes a long-standing code gen. crash reported in
at least two PRs and a radar. (radar 7405040 and pr5025).
There are couple of remaining issues that I would like for
Ted. and Doug to look at:
Ted, please look at failure in Analysis/MissingDealloc.m.
I have temporarily added an expected-warning to make the
test pass. This tests has a declaration of 'SEL' type which
may not co-exist with the new changes.
Doug, please look at a FIXME in PCHWriter.cpp/PCHReader.cpp.
I think the changes which I have ifdef'ed out are correct. They
need be considered for in a few Indexer/PCH test cases.
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@89561 91177308-0d34-0410-b5e6-96231b3b80d8
diff --git a/lib/AST/ASTContext.cpp b/lib/AST/ASTContext.cpp
index 6121580..12b1092 100644
--- a/lib/AST/ASTContext.cpp
+++ b/lib/AST/ASTContext.cpp
@@ -48,6 +48,7 @@
BuiltinInfo(builtins), ExternalSource(0), PrintingPolicy(LOpts) {
ObjCIdRedefinitionType = QualType();
ObjCClassRedefinitionType = QualType();
+ ObjCSELRedefinitionType = QualType();
if (size_reserve > 0) Types.reserve(size_reserve);
TUDecl = TranslationUnitDecl::Create(*this);
InitBuiltinTypes();
@@ -220,10 +221,12 @@
// "Builtin" typedefs set by Sema::ActOnTranslationUnitScope().
ObjCIdTypedefType = QualType();
ObjCClassTypedefType = QualType();
+ ObjCSelTypedefType = QualType();
- // Builtin types for 'id' and 'Class'.
+ // Builtin types for 'id', 'Class', and 'SEL'.
InitBuiltinType(ObjCBuiltinIdTy, BuiltinType::ObjCId);
InitBuiltinType(ObjCBuiltinClassTy, BuiltinType::ObjCClass);
+ InitBuiltinType(ObjCBuiltinSelTy, BuiltinType::ObjCSel);
ObjCConstantStringType = QualType();
@@ -3644,21 +3647,7 @@
}
void ASTContext::setObjCSelType(QualType T) {
- ObjCSelType = T;
-
- const TypedefType *TT = T->getAs<TypedefType>();
- if (!TT)
- return;
- TypedefDecl *TD = TT->getDecl();
-
- // typedef struct objc_selector *SEL;
- const PointerType *ptr = TD->getUnderlyingType()->getAs<PointerType>();
- if (!ptr)
- return;
- const RecordType *rec = ptr->getPointeeType()->getAsStructureType();
- if (!rec)
- return;
- SelStructType = rec;
+ ObjCSelTypedefType = T;
}
void ASTContext::setObjCProtoType(QualType QT) {
diff --git a/lib/AST/TypePrinter.cpp b/lib/AST/TypePrinter.cpp
index a482333..6e66fbf 100644
--- a/lib/AST/TypePrinter.cpp
+++ b/lib/AST/TypePrinter.cpp
@@ -535,6 +535,8 @@
ObjCQIString = "id";
else if (T->isObjCClassType() || T->isObjCQualifiedClassType())
ObjCQIString = "Class";
+ else if (T->isObjCSelType())
+ ObjCQIString = "SEL";
else
ObjCQIString = T->getInterfaceDecl()->getNameAsString();
diff --git a/lib/CodeGen/CodeGenTypes.cpp b/lib/CodeGen/CodeGenTypes.cpp
index 1dd2971..c89879f 100644
--- a/lib/CodeGen/CodeGenTypes.cpp
+++ b/lib/CodeGen/CodeGenTypes.cpp
@@ -203,6 +203,7 @@
case BuiltinType::Void:
case BuiltinType::ObjCId:
case BuiltinType::ObjCClass:
+ case BuiltinType::ObjCSel:
// LLVM void type can only be used as the result of a function call. Just
// map to the same as char.
return llvm::IntegerType::get(getLLVMContext(), 8);
diff --git a/lib/CodeGen/Mangle.cpp b/lib/CodeGen/Mangle.cpp
index 1cd9c6f..6dacd35 100644
--- a/lib/CodeGen/Mangle.cpp
+++ b/lib/CodeGen/Mangle.cpp
@@ -751,6 +751,7 @@
break;
case BuiltinType::ObjCId: Out << "11objc_object"; break;
case BuiltinType::ObjCClass: Out << "10objc_class"; break;
+ case BuiltinType::ObjCSel: Out << "13objc_selector"; break;
}
}
diff --git a/lib/Frontend/PCHReader.cpp b/lib/Frontend/PCHReader.cpp
index c9679b7..9c771e0 100644
--- a/lib/Frontend/PCHReader.cpp
+++ b/lib/Frontend/PCHReader.cpp
@@ -1554,6 +1554,12 @@
if (unsigned ObjCClassRedef
= SpecialTypes[pch::SPECIAL_TYPE_OBJC_CLASS_REDEFINITION])
Context->ObjCClassRedefinitionType = GetType(ObjCClassRedef);
+#if 0
+ // FIXME. Accommodate for this in several PCH/Index tests
+ if (unsigned ObjCSelRedef
+ = SpecialTypes[pch::SPECIAL_TYPE_OBJC_SEL_REDEFINITION])
+ Context->ObjCSELRedefinitionType = GetType(ObjCSelRedef);
+#endif
if (unsigned String = SpecialTypes[pch::SPECIAL_TYPE_BLOCK_DESCRIPTOR])
Context->setBlockDescriptorType(GetType(String));
if (unsigned String
@@ -2155,6 +2161,7 @@
case pch::PREDEF_TYPE_CHAR32_ID: T = Context->Char32Ty; break;
case pch::PREDEF_TYPE_OBJC_ID: T = Context->ObjCBuiltinIdTy; break;
case pch::PREDEF_TYPE_OBJC_CLASS: T = Context->ObjCBuiltinClassTy; break;
+ case pch::PREDEF_TYPE_OBJC_SEL: T = Context->ObjCBuiltinSelTy; break;
}
assert(!T.isNull() && "Unknown predefined type");
diff --git a/lib/Frontend/PCHWriter.cpp b/lib/Frontend/PCHWriter.cpp
index e3f6c62..d60af61 100644
--- a/lib/Frontend/PCHWriter.cpp
+++ b/lib/Frontend/PCHWriter.cpp
@@ -1990,6 +1990,10 @@
AddTypeRef(Context.getsigjmp_bufType(), Record);
AddTypeRef(Context.ObjCIdRedefinitionType, Record);
AddTypeRef(Context.ObjCClassRedefinitionType, Record);
+#if 0
+ // FIXME. Accommodate for this in several PCH/Indexer tests
+ AddTypeRef(Context.ObjCSELRedefinitionType, Record);
+#endif
AddTypeRef(Context.getRawBlockdescriptorType(), Record);
AddTypeRef(Context.getRawBlockdescriptorExtendedType(), Record);
Stream.EmitRecord(pch::SPECIAL_TYPES, Record);
@@ -2205,6 +2209,7 @@
case BuiltinType::Dependent: ID = pch::PREDEF_TYPE_DEPENDENT_ID; break;
case BuiltinType::ObjCId: ID = pch::PREDEF_TYPE_OBJC_ID; break;
case BuiltinType::ObjCClass: ID = pch::PREDEF_TYPE_OBJC_CLASS; break;
+ case BuiltinType::ObjCSel: ID = pch::PREDEF_TYPE_OBJC_SEL; break;
case BuiltinType::UndeducedAuto:
assert(0 && "Should not see undeduced auto here");
break;
diff --git a/lib/Sema/Sema.cpp b/lib/Sema/Sema.cpp
index fe2d744..62c2e25 100644
--- a/lib/Sema/Sema.cpp
+++ b/lib/Sema/Sema.cpp
@@ -299,17 +299,15 @@
// Built-in ObjC types may already be set by PCHReader (hence isNull checks).
if (Context.getObjCSelType().isNull()) {
- // Synthesize "typedef struct objc_selector *SEL;"
- RecordDecl *SelTag = CreateStructDecl(Context, "objc_selector");
- PushOnScopeChains(SelTag, TUScope);
-
- QualType SelT = Context.getPointerType(Context.getTagDeclType(SelTag));
+ // Create the built-in typedef for 'SEL'.
+ QualType SelT = Context.getObjCObjectPointerType(Context.ObjCBuiltinSelTy);
DeclaratorInfo *SelInfo = Context.getTrivialDeclaratorInfo(SelT);
TypedefDecl *SelTypedef
= TypedefDecl::Create(Context, CurContext, SourceLocation(),
&Context.Idents.get("SEL"), SelInfo);
PushOnScopeChains(SelTypedef, TUScope);
Context.setObjCSelType(Context.getTypeDeclType(SelTypedef));
+ Context.ObjCSELRedefinitionType = Context.getObjCSelType();
}
// Synthesize "@class Protocol;
diff --git a/lib/Sema/SemaDecl.cpp b/lib/Sema/SemaDecl.cpp
index f8ebe16..9c60bf3 100644
--- a/lib/Sema/SemaDecl.cpp
+++ b/lib/Sema/SemaDecl.cpp
@@ -681,7 +681,9 @@
case 3:
if (!TypeID->isStr("SEL"))
break;
- Context.setObjCSelType(Context.getTypeDeclType(New));
+ Context.ObjCSELRedefinitionType = New->getUnderlyingType();
+ // Install the built-in type for 'SEL', ignoring the current definition.
+ New->setTypeForDecl(Context.getObjCSelType().getTypePtr());
return;
case 8:
if (!TypeID->isStr("Protocol"))