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;
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();
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;
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;
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);
// 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;
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());
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);
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());
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.
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");
);
PushOnScopeChains(IdTypedef, TUScope);
Context.setObjCIdType(Context.getTypeDeclType(IdTypedef));
+ Context.ObjCIdRedefinitionType = Context.getObjCIdType();
}
// Create the built-in typedef for 'Class'.
if (Context.getObjCClassType().isNull()) {
);
PushOnScopeChains(ClassTypedef, TUScope);
Context.setObjCClassType(Context.getTypeDeclType(ClassTypedef));
+ Context.ObjCClassRedefinitionType = Context.getObjCClassType();
}
}
/// * 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");
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;
#include "clang/Parse/Scope.h"
using namespace clang;
+
/// \brief Determine whether the use of this declaration is valid, and
/// emit any corresponding diagnostics.
///
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
<< 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() ||
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()) {
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();
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,