Implement AST import for Objective-C property implementations

(@synthesize and @dynamic).

llvm-svn: 121159
This commit is contained in:
Douglas Gregor 2010-12-07 18:32:03 +00:00
parent 2a43368a03
commit 14a49e2fbe
5 changed files with 140 additions and 1 deletions

View File

@ -56,6 +56,8 @@ def note_odr_number_of_bases : Note<
"class has %0 base %plural{1:class|:classes}0">;
def note_odr_enumerator : Note<"enumerator %0 with value %1 here">;
def note_odr_missing_enumerator : Note<"no corresponding enumerator here">;
// Importing Objective-C ASTs
def err_odr_ivar_type_inconsistent : Error<
"instance variable %0 declared with incompatible types in different "
"translation units (%1 vs. %2)">;
@ -80,6 +82,18 @@ def note_odr_objc_method_here : Note<
def err_odr_objc_property_type_inconsistent : Error<
"property %0 declared with incompatible types in different "
"translation units (%1 vs. %2)">;
def err_odr_objc_property_impl_kind_inconsistent : Error<
"property %0 is implemented with %select{@synthesize|@dynamic}1 in one "
"translation but %select{@dynamic|@synthesize}1 in another translation unit">;
def note_odr_objc_property_impl_kind : Note<
"property %0 is implemented with %select{@synthesize|@dynamic}1 here">;
def err_odr_objc_synthesize_ivar_inconsistent : Error<
"property %0 is synthesized to different ivars in different translation "
"units (%1 vs. %2)">;
def note_odr_objc_synthesize_ivar_here : Note<
"property is synthesized to ivar %0 here">;
// Importing C++ ASTs
def err_odr_different_num_template_parameters : Error<
"template parameter lists have a different number of parameters (%0 vs %1)">;
def note_odr_template_parameter_list : Note<

View File

@ -118,6 +118,7 @@ namespace {
Decl *VisitObjCCategoryImplDecl(ObjCCategoryImplDecl *D);
Decl *VisitObjCImplementationDecl(ObjCImplementationDecl *D);
Decl *VisitObjCPropertyDecl(ObjCPropertyDecl *D);
Decl *VisitObjCPropertyImplDecl(ObjCPropertyImplDecl *D);
Decl *VisitObjCForwardProtocolDecl(ObjCForwardProtocolDecl *D);
Decl *VisitObjCClassDecl(ObjCClassDecl *D);
Decl *VisitTemplateTypeParmDecl(TemplateTypeParmDecl *D);
@ -3195,6 +3196,87 @@ Decl *ASTNodeImporter::VisitObjCPropertyDecl(ObjCPropertyDecl *D) {
return ToProperty;
}
Decl *ASTNodeImporter::VisitObjCPropertyImplDecl(ObjCPropertyImplDecl *D) {
ObjCPropertyDecl *Property = cast_or_null<ObjCPropertyDecl>(
Importer.Import(D->getPropertyDecl()));
if (!Property)
return 0;
DeclContext *DC = Importer.ImportContext(D->getDeclContext());
if (!DC)
return 0;
// Import the lexical declaration context.
DeclContext *LexicalDC = DC;
if (D->getDeclContext() != D->getLexicalDeclContext()) {
LexicalDC = Importer.ImportContext(D->getLexicalDeclContext());
if (!LexicalDC)
return 0;
}
ObjCImplDecl *InImpl = dyn_cast<ObjCImplDecl>(LexicalDC);
if (!InImpl)
return 0;
// Import the ivar (for an @synthesize).
ObjCIvarDecl *Ivar = 0;
if (D->getPropertyIvarDecl()) {
Ivar = cast_or_null<ObjCIvarDecl>(
Importer.Import(D->getPropertyIvarDecl()));
if (!Ivar)
return 0;
}
ObjCPropertyImplDecl *ToImpl
= InImpl->FindPropertyImplDecl(Property->getIdentifier());
if (!ToImpl) {
ToImpl = ObjCPropertyImplDecl::Create(Importer.getToContext(), DC,
Importer.Import(D->getLocStart()),
Importer.Import(D->getLocation()),
Property,
D->getPropertyImplementation(),
Ivar,
Importer.Import(D->getPropertyIvarDeclLoc()));
ToImpl->setLexicalDeclContext(LexicalDC);
Importer.Imported(D, ToImpl);
LexicalDC->addDecl(ToImpl);
} else {
// Check that we have the same kind of property implementation (@synthesize
// vs. @dynamic).
if (D->getPropertyImplementation() != ToImpl->getPropertyImplementation()) {
Importer.ToDiag(ToImpl->getLocation(),
diag::err_odr_objc_property_impl_kind_inconsistent)
<< Property->getDeclName()
<< (ToImpl->getPropertyImplementation()
== ObjCPropertyImplDecl::Dynamic);
Importer.FromDiag(D->getLocation(),
diag::note_odr_objc_property_impl_kind)
<< D->getPropertyDecl()->getDeclName()
<< (D->getPropertyImplementation() == ObjCPropertyImplDecl::Dynamic);
return 0;
}
// For @synthesize, check that we have the same
if (D->getPropertyImplementation() == ObjCPropertyImplDecl::Synthesize &&
Ivar != ToImpl->getPropertyIvarDecl()) {
Importer.ToDiag(ToImpl->getPropertyIvarDeclLoc(),
diag::err_odr_objc_synthesize_ivar_inconsistent)
<< Property->getDeclName()
<< ToImpl->getPropertyIvarDecl()->getDeclName()
<< Ivar->getDeclName();
Importer.FromDiag(D->getPropertyIvarDeclLoc(),
diag::note_odr_objc_synthesize_ivar_here)
<< D->getPropertyIvarDecl()->getDeclName();
return 0;
}
// Merge the existing implementation with the new implementation.
Importer.Imported(D, ToImpl);
}
return ToImpl;
}
Decl *
ASTNodeImporter::VisitObjCForwardProtocolDecl(ObjCForwardProtocolDecl *D) {
// Import the context of this declaration.

View File

@ -10,3 +10,22 @@
@property (readonly) float Prop1;
@end
// Properties with implementations
@interface I3 {
int ivar1;
int ivar2;
int ivar3;
int Prop4;
}
@property int Prop1;
@property int Prop2;
@property int Prop3;
@property int Prop4;
@end
@implementation I3
@synthesize Prop1 = ivar1;
@synthesize Prop2 = ivar3;
@dynamic Prop3;
@synthesize Prop4;
@end

View File

@ -11,3 +11,23 @@
@interface I2
@property (readonly) int Prop1;
@end
// Properties with implementations
@interface I3 {
int ivar1;
int ivar2;
int ivar3;
int Prop4;
}
@property int Prop1;
@property int Prop2;
@property int Prop3;
@property int Prop4;
@end
@implementation I3
@synthesize Prop2 = ivar2;
@synthesize Prop1 = ivar1;
@synthesize Prop3 = ivar3;
@synthesize Prop4 = Prop4;
@end

View File

@ -6,4 +6,8 @@
// CHECK: property1.m:10:28: note: declared here with type 'float'
// CHECK: property2.m:12:26: error: instance method 'Prop1' has incompatible result types in different translation units ('int' vs. 'float')
// CHECK: property1.m:10:28: note: instance method 'Prop1' also declared here
// CHECK: 2 errors generated.
// CHECK: property1.m:28:21: error: property 'Prop2' is synthesized to different ivars in different translation units ('ivar3' vs. 'ivar2')
// CHECK: property2.m:29:21: note: property is synthesized to ivar 'ivar2' here
// CHECK: property1.m:29:10: error: property 'Prop3' is implemented with @dynamic in one translation but @synthesize in another translation unit
// CHECK: property2.m:31:13: note: property 'Prop3' is implemented with @synthesize here
// CHECK: 4 errors generated.