diff --git a/clang/lib/CodeGen/CodeGenTypes.cpp b/clang/lib/CodeGen/CodeGenTypes.cpp index 30a69f1dc22575abae55c8a229d1c0736349e67a..a83c72f2b84cfd48372ac9d7a41a971cf626a55b 100644 --- a/clang/lib/CodeGen/CodeGenTypes.cpp +++ b/clang/lib/CodeGen/CodeGenTypes.cpp @@ -355,13 +355,14 @@ const llvm::Type *CodeGenTypes::ConvertNewType(QualType T) { } case Type::ObjCObjectPointer: { - // Qualified id types don't influence the LLVM type, here we always return - // an opaque type for 'id'. - const llvm::Type *&T = InterfaceTypes[0]; - if (!T) - T = llvm::OpaqueType::get(); - return llvm::PointerType::getUnqual(T); + // Protocol qualifications do not influence the LLVM type, we just return a + // pointer to the underlying interface type. We don't need to worry about + // recursive conversion. + const llvm::Type *T = + ConvertTypeRecursive(cast(Ty).getPointeeType()); + return llvm::PointerType::getUnqual(T); } + case Type::Record: case Type::Enum: { const TagDecl *TD = cast(Ty).getDecl(); diff --git a/clang/test/CodeGenObjC/protocols.m b/clang/test/CodeGenObjC/protocols.m new file mode 100644 index 0000000000000000000000000000000000000000..c510685e521deafd6d0b02bd541da894ffe64e33 --- /dev/null +++ b/clang/test/CodeGenObjC/protocols.m @@ -0,0 +1,50 @@ +// RUN: clang-cc -emit-llvm %s -o %t + +void p(const char*, ...); + +@interface Root +-(int) conformsTo: (id) x; +@end + +@protocol P0; + +@protocol P1 ++(void) classMethodReq0; +-(void) methodReq0; +@optional ++(void) classMethodOpt1; +-(void) methodOpt1; +@required ++(void) classMethodReq2; +-(void) methodReq2; +@end + +@protocol P2 +//@property(readwrite) int x; +@end + +@protocol P3 +-(id ) print0; +-(void) print1; +@end + +void foo(const id a) { + void *p = @protocol(P3); +} + +int main() { + Protocol *P0 = @protocol(P0); + Protocol *P1 = @protocol(P1); + Protocol *P2 = @protocol(P2); + Protocol *P3 = @protocol(P3); + +#define Pbool(X) p(#X ": %s\n", X ? "yes" : "no"); + Pbool([P0 conformsTo: P1]); + Pbool([P1 conformsTo: P0]); + Pbool([P1 conformsTo: P2]); + Pbool([P2 conformsTo: P1]); + Pbool([P3 conformsTo: P1]); + Pbool([P1 conformsTo: P3]); + + return 0; +}