Implement AST import for Objective-C property implementations
(@synthesize and @dynamic). llvm-svn: 121159
This commit is contained in:
parent
2a43368a03
commit
14a49e2fbe
|
@ -56,6 +56,8 @@ def note_odr_number_of_bases : Note<
|
||||||
"class has %0 base %plural{1:class|:classes}0">;
|
"class has %0 base %plural{1:class|:classes}0">;
|
||||||
def note_odr_enumerator : Note<"enumerator %0 with value %1 here">;
|
def note_odr_enumerator : Note<"enumerator %0 with value %1 here">;
|
||||||
def note_odr_missing_enumerator : Note<"no corresponding enumerator here">;
|
def note_odr_missing_enumerator : Note<"no corresponding enumerator here">;
|
||||||
|
|
||||||
|
// Importing Objective-C ASTs
|
||||||
def err_odr_ivar_type_inconsistent : Error<
|
def err_odr_ivar_type_inconsistent : Error<
|
||||||
"instance variable %0 declared with incompatible types in different "
|
"instance variable %0 declared with incompatible types in different "
|
||||||
"translation units (%1 vs. %2)">;
|
"translation units (%1 vs. %2)">;
|
||||||
|
@ -80,6 +82,18 @@ def note_odr_objc_method_here : Note<
|
||||||
def err_odr_objc_property_type_inconsistent : Error<
|
def err_odr_objc_property_type_inconsistent : Error<
|
||||||
"property %0 declared with incompatible types in different "
|
"property %0 declared with incompatible types in different "
|
||||||
"translation units (%1 vs. %2)">;
|
"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<
|
def err_odr_different_num_template_parameters : Error<
|
||||||
"template parameter lists have a different number of parameters (%0 vs %1)">;
|
"template parameter lists have a different number of parameters (%0 vs %1)">;
|
||||||
def note_odr_template_parameter_list : Note<
|
def note_odr_template_parameter_list : Note<
|
||||||
|
|
|
@ -118,6 +118,7 @@ namespace {
|
||||||
Decl *VisitObjCCategoryImplDecl(ObjCCategoryImplDecl *D);
|
Decl *VisitObjCCategoryImplDecl(ObjCCategoryImplDecl *D);
|
||||||
Decl *VisitObjCImplementationDecl(ObjCImplementationDecl *D);
|
Decl *VisitObjCImplementationDecl(ObjCImplementationDecl *D);
|
||||||
Decl *VisitObjCPropertyDecl(ObjCPropertyDecl *D);
|
Decl *VisitObjCPropertyDecl(ObjCPropertyDecl *D);
|
||||||
|
Decl *VisitObjCPropertyImplDecl(ObjCPropertyImplDecl *D);
|
||||||
Decl *VisitObjCForwardProtocolDecl(ObjCForwardProtocolDecl *D);
|
Decl *VisitObjCForwardProtocolDecl(ObjCForwardProtocolDecl *D);
|
||||||
Decl *VisitObjCClassDecl(ObjCClassDecl *D);
|
Decl *VisitObjCClassDecl(ObjCClassDecl *D);
|
||||||
Decl *VisitTemplateTypeParmDecl(TemplateTypeParmDecl *D);
|
Decl *VisitTemplateTypeParmDecl(TemplateTypeParmDecl *D);
|
||||||
|
@ -3195,6 +3196,87 @@ Decl *ASTNodeImporter::VisitObjCPropertyDecl(ObjCPropertyDecl *D) {
|
||||||
return ToProperty;
|
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 *
|
Decl *
|
||||||
ASTNodeImporter::VisitObjCForwardProtocolDecl(ObjCForwardProtocolDecl *D) {
|
ASTNodeImporter::VisitObjCForwardProtocolDecl(ObjCForwardProtocolDecl *D) {
|
||||||
// Import the context of this declaration.
|
// Import the context of this declaration.
|
||||||
|
|
|
@ -10,3 +10,22 @@
|
||||||
@property (readonly) float Prop1;
|
@property (readonly) float Prop1;
|
||||||
@end
|
@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
|
||||||
|
|
|
@ -11,3 +11,23 @@
|
||||||
@interface I2
|
@interface I2
|
||||||
@property (readonly) int Prop1;
|
@property (readonly) int Prop1;
|
||||||
@end
|
@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
|
||||||
|
|
|
@ -6,4 +6,8 @@
|
||||||
// CHECK: property1.m:10:28: note: declared here with type 'float'
|
// 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: 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: 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.
|
||||||
|
|
Loading…
Reference in New Issue