forked from OSchip/llvm-project
Implement AST importing of Objective-C instance variables.
Check superclasses when merging two Objective-C @interfaces. llvm-svn: 96420
This commit is contained in:
parent
a845f654fa
commit
7244b0bb86
|
@ -53,6 +53,13 @@ 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">;
|
||||
|
||||
def err_odr_ivar_type_inconsistent : Error<
|
||||
"instance variable %0 declared with incompatible types in different "
|
||||
"translation units (%1 vs. %2)">;
|
||||
def err_odr_objc_superclass_inconsistent : Error<
|
||||
"class %0 has incompatible superclasses">;
|
||||
def note_odr_objc_superclass : Note<"inherits from superclass %0 here">;
|
||||
def note_odr_objc_missing_superclass : Note<"no corresponding superclass here">;
|
||||
|
||||
def err_unsupported_ast_node: Error<"cannot import unsupported AST node %0">;
|
||||
}
|
||||
|
|
|
@ -90,6 +90,7 @@ namespace {
|
|||
Decl *VisitEnumConstantDecl(EnumConstantDecl *D);
|
||||
Decl *VisitFunctionDecl(FunctionDecl *D);
|
||||
Decl *VisitFieldDecl(FieldDecl *D);
|
||||
Decl *VisitObjCIvarDecl(ObjCIvarDecl *D);
|
||||
Decl *VisitVarDecl(VarDecl *D);
|
||||
Decl *VisitParmVarDecl(ParmVarDecl *D);
|
||||
Decl *VisitObjCInterfaceDecl(ObjCInterfaceDecl *D);
|
||||
|
@ -1821,6 +1822,54 @@ Decl *ASTNodeImporter::VisitFieldDecl(FieldDecl *D) {
|
|||
return ToField;
|
||||
}
|
||||
|
||||
Decl *ASTNodeImporter::VisitObjCIvarDecl(ObjCIvarDecl *D) {
|
||||
// Import the major distinguishing characteristics of an ivar.
|
||||
DeclContext *DC, *LexicalDC;
|
||||
DeclarationName Name;
|
||||
SourceLocation Loc;
|
||||
if (ImportDeclParts(D, DC, LexicalDC, Name, Loc))
|
||||
return 0;
|
||||
|
||||
// Determine whether we've already imported this ivar
|
||||
for (DeclContext::lookup_result Lookup = DC->lookup(Name);
|
||||
Lookup.first != Lookup.second;
|
||||
++Lookup.first) {
|
||||
if (ObjCIvarDecl *FoundIvar = dyn_cast<ObjCIvarDecl>(*Lookup.first)) {
|
||||
if (Importer.IsStructurallyEquivalent(D->getType(),
|
||||
FoundIvar->getType())) {
|
||||
Importer.Imported(D, FoundIvar);
|
||||
return FoundIvar;
|
||||
}
|
||||
|
||||
Importer.ToDiag(Loc, diag::err_odr_ivar_type_inconsistent)
|
||||
<< Name << D->getType() << FoundIvar->getType();
|
||||
Importer.ToDiag(FoundIvar->getLocation(), diag::note_odr_value_here)
|
||||
<< FoundIvar->getType();
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
// Import the type.
|
||||
QualType T = Importer.Import(D->getType());
|
||||
if (T.isNull())
|
||||
return 0;
|
||||
|
||||
TypeSourceInfo *TInfo = Importer.Import(D->getTypeSourceInfo());
|
||||
Expr *BitWidth = Importer.Import(D->getBitWidth());
|
||||
if (!BitWidth && D->getBitWidth())
|
||||
return 0;
|
||||
|
||||
ObjCIvarDecl *ToIvar = ObjCIvarDecl::Create(Importer.getToContext(), DC,
|
||||
Loc, Name.getAsIdentifierInfo(),
|
||||
T, TInfo, D->getAccessControl(),
|
||||
BitWidth);
|
||||
ToIvar->setLexicalDeclContext(LexicalDC);
|
||||
Importer.Imported(D, ToIvar);
|
||||
LexicalDC->addDecl(ToIvar);
|
||||
return ToIvar;
|
||||
|
||||
}
|
||||
|
||||
Decl *ASTNodeImporter::VisitVarDecl(VarDecl *D) {
|
||||
// Import the major distinguishing characteristics of a variable.
|
||||
DeclContext *DC, *LexicalDC;
|
||||
|
@ -1997,9 +2046,6 @@ Decl *ASTNodeImporter::VisitObjCInterfaceDecl(ObjCInterfaceDecl *D) {
|
|||
}
|
||||
Importer.Imported(D, ToIface);
|
||||
|
||||
// Import superclass
|
||||
// FIXME: If we're merging, make sure that both decls have the same
|
||||
// superclass.
|
||||
if (D->getSuperClass()) {
|
||||
ObjCInterfaceDecl *Super
|
||||
= cast_or_null<ObjCInterfaceDecl>(Importer.Import(D->getSuperClass()));
|
||||
|
@ -2037,6 +2083,33 @@ Decl *ASTNodeImporter::VisitObjCInterfaceDecl(ObjCInterfaceDecl *D) {
|
|||
ToIface->setAtEndRange(Importer.Import(D->getAtEndRange()));
|
||||
} else {
|
||||
Importer.Imported(D, ToIface);
|
||||
|
||||
// Check for consistency of superclasses.
|
||||
DeclarationName FromSuperName, ToSuperName;
|
||||
if (D->getSuperClass())
|
||||
FromSuperName = Importer.Import(D->getSuperClass()->getDeclName());
|
||||
if (ToIface->getSuperClass())
|
||||
ToSuperName = ToIface->getSuperClass()->getDeclName();
|
||||
if (FromSuperName != ToSuperName) {
|
||||
Importer.ToDiag(ToIface->getLocation(),
|
||||
diag::err_odr_objc_superclass_inconsistent)
|
||||
<< ToIface->getDeclName();
|
||||
if (ToIface->getSuperClass())
|
||||
Importer.ToDiag(ToIface->getSuperClassLoc(),
|
||||
diag::note_odr_objc_superclass)
|
||||
<< ToIface->getSuperClass()->getDeclName();
|
||||
else
|
||||
Importer.ToDiag(ToIface->getLocation(),
|
||||
diag::note_odr_objc_missing_superclass);
|
||||
if (D->getSuperClass())
|
||||
Importer.FromDiag(D->getSuperClassLoc(),
|
||||
diag::note_odr_objc_superclass)
|
||||
<< D->getSuperClass()->getDeclName();
|
||||
else
|
||||
Importer.FromDiag(D->getLocation(),
|
||||
diag::note_odr_objc_missing_superclass);
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
// Import all of the members of this class.
|
||||
|
|
|
@ -1,7 +1,23 @@
|
|||
// Matches
|
||||
@interface I1
|
||||
@interface I1 {
|
||||
int ivar1;
|
||||
}
|
||||
@end
|
||||
|
||||
// Matches
|
||||
@interface I2 : I1
|
||||
@interface I2 : I1 {
|
||||
float ivar2;
|
||||
}
|
||||
@end
|
||||
|
||||
// Ivar mismatch
|
||||
@interface I3 {
|
||||
int ivar1;
|
||||
int ivar2;
|
||||
}
|
||||
@end
|
||||
|
||||
// Superclass mismatch
|
||||
@interface I4 : I2 {
|
||||
}
|
||||
@end
|
||||
|
|
|
@ -1,7 +1,23 @@
|
|||
// Matches
|
||||
@interface I1
|
||||
@interface I1 {
|
||||
int ivar1;
|
||||
}
|
||||
@end
|
||||
|
||||
// Matches
|
||||
@interface I2 : I1
|
||||
@interface I2 : I1 {
|
||||
float ivar2;
|
||||
}
|
||||
@end
|
||||
|
||||
// Ivar mismatch
|
||||
@interface I3 {
|
||||
int ivar1;
|
||||
float ivar2;
|
||||
}
|
||||
@end
|
||||
|
||||
// Superclass mismatch
|
||||
@interface I4 : I1 {
|
||||
}
|
||||
@end
|
||||
|
|
|
@ -1,6 +1,11 @@
|
|||
// RUN: %clang_cc1 -emit-pch -o %t.1.ast %S/Inputs/interface1.m
|
||||
// RUN: %clang_cc1 -emit-pch -o %t.2.ast %S/Inputs/interface2.m
|
||||
// RUN: %clang_cc1 -ast-merge %t.1.ast -ast-merge %t.2.ast -fsyntax-only %s 2>&1
|
||||
// RUN: %clang_cc1 -ast-merge %t.1.ast -ast-merge %t.2.ast -fsyntax-only %s 2>&1 | FileCheck %s
|
||||
|
||||
// FIXME: FileCheck!
|
||||
// CHECK: interface2.m:16:9: error: instance variable 'ivar2' declared with incompatible types in different translation units ('float' vs. 'int')
|
||||
// CHECK: interface1.m:16:7: note: declared here with type 'int'
|
||||
// CHECK: interface1.m:21:1: error: class 'I4' has incompatible superclasses
|
||||
// CHECK: interface1.m:21:17: note: inherits from superclass 'I2' here
|
||||
// CHECK: interface2.m:21:17: note: inherits from superclass 'I1' here
|
||||
// CHECK: 5 diagnostics generated
|
||||
|
||||
|
|
Loading…
Reference in New Issue