forked from OSchip/llvm-project
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">;
|
||||
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<
|
||||
|
|
|
@ -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.
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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.
|
||||
|
|
Loading…
Reference in New Issue