Implement AST importing of Objective-C instance variables.

Check superclasses when merging two Objective-C @interfaces.

llvm-svn: 96420
This commit is contained in:
Douglas Gregor 2010-02-17 00:34:30 +00:00
parent a845f654fa
commit 7244b0bb86
5 changed files with 127 additions and 10 deletions

View File

@ -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">;
}

View File

@ -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.

View File

@ -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

View File

@ -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

View File

@ -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