From c057794adb7ffd2bf493de58828eb04aed1f6d41 Mon Sep 17 00:00:00 2001 From: Fariborz Jahanian Date: Fri, 22 Apr 2011 22:02:28 +0000 Subject: [PATCH] Fixes an instance method meta-data generation bug in ObjC NeXt runtime where method pointer registered in metadata belongs to an unrelated method. Ast part of this fix, I turned at @end missing warning (for class implementations) into an error as we can never be sure that meta-data being generated is correct. // rdar://9072317 llvm-svn: 130019 --- .../clang/Basic/DiagnosticParseKinds.td | 2 +- .../clang/Basic/DiagnosticSemaKinds.td | 2 +- clang/lib/CodeGen/CGObjCMac.cpp | 8 +++++ clang/lib/Parse/ParseObjc.cpp | 2 +- clang/lib/Sema/SemaDeclObjC.cpp | 2 +- .../CodeGenObjC/instance-method-metadata.m | 34 +++++++++++++++++++ .../test/CodeGenObjC/missing-atend-metadata.m | 24 ------------- clang/test/Index/rdar-8288645-invalid-code.mm | 2 +- clang/test/Parser/objc-missing-impl.m | 2 +- clang/test/SemaObjC/missing-atend-metadata.m | 22 ++++++++++++ 10 files changed, 70 insertions(+), 30 deletions(-) create mode 100644 clang/test/CodeGenObjC/instance-method-metadata.m delete mode 100644 clang/test/CodeGenObjC/missing-atend-metadata.m create mode 100644 clang/test/SemaObjC/missing-atend-metadata.m diff --git a/clang/include/clang/Basic/DiagnosticParseKinds.td b/clang/include/clang/Basic/DiagnosticParseKinds.td index 4032944a2d5a..a297fd1ddcdc 100644 --- a/clang/include/clang/Basic/DiagnosticParseKinds.td +++ b/clang/include/clang/Basic/DiagnosticParseKinds.td @@ -286,7 +286,7 @@ def err_missing_id_definition : Error<"cannot find definition of 'id'">; def err_missing_proto_definition : Error< "cannot find definition of 'Protocol'">; def err_missing_class_definition : Error<"cannot find definition of 'Class'">; -def warn_expected_implementation : Warning< +def err_expected_implementation : Error< "@end must appear in an @implementation context">; def error_property_ivar_decl : Error< "property synthesize requires specification of an ivar">; diff --git a/clang/include/clang/Basic/DiagnosticSemaKinds.td b/clang/include/clang/Basic/DiagnosticSemaKinds.td index 86d5c2099f88..dbc30c0dfb65 100644 --- a/clang/include/clang/Basic/DiagnosticSemaKinds.td +++ b/clang/include/clang/Basic/DiagnosticSemaKinds.td @@ -393,7 +393,7 @@ def note_declared_at : Note<"declared here">; def note_method_declared_at : Note<"method declared here">; def err_setter_type_void : Error<"type of setter must be void">; def err_duplicate_method_decl : Error<"duplicate declaration of method %0">; -def warn_missing_atend : Warning<"'@end' is missing in implementation context">; +def err_missing_atend : Error<"'@end' is missing in implementation context">; def err_objc_var_decl_inclass : Error<"cannot declare variable inside @interface or @protocol">; def error_missing_method_context : Error< diff --git a/clang/lib/CodeGen/CGObjCMac.cpp b/clang/lib/CodeGen/CGObjCMac.cpp index 9466c77ed37e..3447daf5c2fd 100644 --- a/clang/lib/CodeGen/CGObjCMac.cpp +++ b/clang/lib/CodeGen/CGObjCMac.cpp @@ -2069,6 +2069,8 @@ void CGObjCMac::GenerateCategory(const ObjCCategoryImplDecl *OCD) { 4, true); DefinedCategories.push_back(GV); DefinedCategoryNames.insert(ExtName.str()); + // method definition entries must be clear for next implementation. + MethodDefinitions.clear(); } // FIXME: Get from somewhere? @@ -2196,6 +2198,8 @@ void CGObjCMac::GenerateClass(const ObjCImplementationDecl *ID) { else GV = CreateMetadataVar(Name, Init, Section, 4, true); DefinedClasses.push_back(GV); + // method definition entries must be clear for next implementation. + MethodDefinitions.clear(); } llvm::Constant *CGObjCMac::EmitMetaClass(const ObjCImplementationDecl *ID, @@ -4978,6 +4982,8 @@ void CGObjCNonFragileABIMac::GenerateClass(const ObjCImplementationDecl *ID) { // Force the definition of the EHType if necessary. if (flags & CLS_EXCEPTION) GetInterfaceEHType(ID->getClassInterface(), true); + // Make sure method definition entries are all clear for next implementation. + MethodDefinitions.clear(); } /// GenerateProtocolRef - This routine is called to generate code for @@ -5106,6 +5112,8 @@ void CGObjCNonFragileABIMac::GenerateCategory(const ObjCCategoryImplDecl *OCD) { // Determine if this category is also "non-lazy". if (ImplementationIsNonLazy(OCD)) DefinedNonLazyCategories.push_back(GCATV); + // method definition entries must be clear for next implementation. + MethodDefinitions.clear(); } /// GetMethodConstant - Return a struct objc_method constant for the diff --git a/clang/lib/Parse/ParseObjc.cpp b/clang/lib/Parse/ParseObjc.cpp index b42cf9f0ae11..fdbedc54d1cd 100644 --- a/clang/lib/Parse/ParseObjc.cpp +++ b/clang/lib/Parse/ParseObjc.cpp @@ -1387,7 +1387,7 @@ Decl *Parser::ParseObjCAtEndDeclaration(SourceRange atEnd) { } else { // missing @implementation - Diag(atEnd.getBegin(), diag::warn_expected_implementation); + Diag(atEnd.getBegin(), diag::err_expected_implementation); } return Result; } diff --git a/clang/lib/Sema/SemaDeclObjC.cpp b/clang/lib/Sema/SemaDeclObjC.cpp index 4fc1e6912ecf..01d37f47b2c1 100644 --- a/clang/lib/Sema/SemaDeclObjC.cpp +++ b/clang/lib/Sema/SemaDeclObjC.cpp @@ -1536,7 +1536,7 @@ void Sema::ActOnAtEnd(Scope *S, SourceRange AtEnd, SourceLocation L = ClassDecl->getLocation(); AtEnd.setBegin(L); AtEnd.setEnd(L); - Diag(L, diag::warn_missing_atend); + Diag(L, diag::err_missing_atend); } // FIXME: Remove these and use the ObjCContainerDecl/DeclContext. diff --git a/clang/test/CodeGenObjC/instance-method-metadata.m b/clang/test/CodeGenObjC/instance-method-metadata.m new file mode 100644 index 000000000000..ae87c7a85345 --- /dev/null +++ b/clang/test/CodeGenObjC/instance-method-metadata.m @@ -0,0 +1,34 @@ +// RUN: %clang_cc1 -triple x86_64-apple-darwin10 -fobjc-nonfragile-abi -S -o %t %s +// RUN: FileCheck < %t %s + +// rdar://9072317 + +/** The problem looks like clang getting confused when a single translation unit + contains a protocol with a property and two classes that implement that protocol + and synthesize the property. +*/ + +@protocol Proto +@property (assign) id prop; +@end + +@interface NSObject @end + +@interface Foo : NSObject { int x; } @end + +@interface Bar : NSObject @end + +@implementation Foo +@synthesize prop; +@end + +@implementation Bar +@synthesize prop; +@end + +// CHECK: l_OBJC_$_INSTANCE_METHODS_Bar: +// CHECK-NEXT .long 24 +// CHECK-NEXT .long 2 +// CHECK-NEXT .quad L_OBJC_METH_VAR_NAME_ +// CHECK-NEXT .quad L_OBJC_METH_VAR_TYPE_ +// CHECK-NEXT .quad "-[Bar prop]" diff --git a/clang/test/CodeGenObjC/missing-atend-metadata.m b/clang/test/CodeGenObjC/missing-atend-metadata.m deleted file mode 100644 index 50e597c8d1a8..000000000000 --- a/clang/test/CodeGenObjC/missing-atend-metadata.m +++ /dev/null @@ -1,24 +0,0 @@ -// RUN: %clang_cc1 -triple i386-apple-darwin9 -emit-llvm %s -o - | FileCheck %s - -@interface I0 -@end - -@implementation I0 // expected-warning {{'@end' is missing in implementation context}} -- meth { return 0; } - -@interface I1 : I0 -@end - -@implementation I1 // expected-warning {{'@end' is missing in implementation context}} --(void) im0 { self = [super init]; } - -@interface I2 : I0 -- I2meth; -@end - -@implementation I2 // expected-warning {{'@end' is missing in implementation context}} -- I2meth { return 0; } - -@implementation I2(CAT) // expected-warning {{'@end' is missing in implementation context}} - -// CHECK: @"\01L_OBJC_CLASS_I1" = internal global diff --git a/clang/test/Index/rdar-8288645-invalid-code.mm b/clang/test/Index/rdar-8288645-invalid-code.mm index 3405f0a93270..74e2365edcfe 100644 --- a/clang/test/Index/rdar-8288645-invalid-code.mm +++ b/clang/test/Index/rdar-8288645-invalid-code.mm @@ -5,4 +5,4 @@ extern "C" { @implementation Foo - (id)initWithBar:(Baz)pepper { // CHECK: warning: cannot find interface declaration for 'Foo' -// CHECK: warning: '@end' is missing in implementation context +// CHECK: error: '@end' is missing in implementation context diff --git a/clang/test/Parser/objc-missing-impl.m b/clang/test/Parser/objc-missing-impl.m index 05d9d6c0b232..e9c37ab1b158 100644 --- a/clang/test/Parser/objc-missing-impl.m +++ b/clang/test/Parser/objc-missing-impl.m @@ -1,2 +1,2 @@ // RUN: %clang_cc1 -fsyntax-only -verify %s -@end // expected-warning {{@end must appear in an @implementation context}} +@end // expected-error {{@end must appear in an @implementation context}} diff --git a/clang/test/SemaObjC/missing-atend-metadata.m b/clang/test/SemaObjC/missing-atend-metadata.m new file mode 100644 index 000000000000..434706d3fafc --- /dev/null +++ b/clang/test/SemaObjC/missing-atend-metadata.m @@ -0,0 +1,22 @@ +// RUN: %clang_cc1 -triple i386-apple-darwin9 -fsyntax-only -verify %s + +@interface I0 +@end + +@implementation I0 // expected-error {{'@end' is missing in implementation context}} +- meth { return 0; } + +@interface I1 : I0 +@end + +@implementation I1 // expected-error {{'@end' is missing in implementation context}} +-(void) im0 { self = [super init]; } // expected-warning {{nstance method '-init' not found }} + +@interface I2 : I0 +- I2meth; +@end + +@implementation I2 // expected-error {{'@end' is missing in implementation context}} +- I2meth { return 0; } + +@implementation I2(CAT) // expected-error {{'@end' is missing in implementation context}}