static unsigned nForwardProtocolDecls = 0;
static unsigned nCategoryDecls = 0;
static unsigned nIvarDecls = 0;
+static unsigned nObjcImplementationDecls = 0;
static bool StatSwitch = false;
nCategoryDecls, (int)sizeof(ObjcCategoryDecl),
int(nCategoryDecls*sizeof(ObjcCategoryDecl)));
+ fprintf(stderr, " %d class implementation decls, %d each (%d bytes)\n",
+ nObjcImplementationDecls, (int)sizeof(ObjcImplementationDecl),
+ int(nObjcImplementationDecls*sizeof(ObjcImplementationDecl)));
+
fprintf(stderr, "Total bytes = %d\n",
int(nFuncs*sizeof(FunctionDecl)+nBlockVars*sizeof(BlockVarDecl)+
nFileVars*sizeof(FileVarDecl)+nParmVars*sizeof(ParmVarDecl)+
case ObjcIvar:
nIvarDecls++;
break;
+ case ObjcImplementation:
+ nObjcImplementationDecls++;
+ break;
}
}
}
Action::DeclTy *
-MinimalAction::ObjcStartClassInterface(SourceLocation AtInterafceLoc,
+MinimalAction::ObjcStartClassInterface(Scope* S, SourceLocation AtInterafceLoc,
IdentifierInfo *ClassName, SourceLocation ClassLoc,
IdentifierInfo *SuperName, SourceLocation SuperLoc,
IdentifierInfo **ProtocolNames, unsigned NumProtocols,
}
Action::DeclTy *
-MinimalAction::ObjcStartProtoInterface(SourceLocation AtProtoInterfaceLoc,
+MinimalAction::ObjcStartProtoInterface(Scope* S,
+ SourceLocation AtProtoInterfaceLoc,
IdentifierInfo *ProtocolName, SourceLocation ProtocolLoc,
IdentifierInfo **ProtoRefNames, unsigned NumProtoRefs) {
if (ParseObjCProtocolReferences(ProtocolRefs))
return 0;
}
- DeclTy *ClsType = Actions.ObjcStartClassInterface(atLoc, nameId, nameLoc,
+ DeclTy *ClsType = Actions.ObjcStartClassInterface(CurScope,
+ atLoc, nameId, nameLoc,
superClassId, superClassLoc, &ProtocolRefs[0],
ProtocolRefs.size(), attrList);
return 0;
}
- DeclTy *ProtoType = Actions.ObjcStartProtoInterface(AtLoc,
+ DeclTy *ProtoType = Actions.ObjcStartProtoInterface(CurScope, AtLoc,
protocolName, nameLoc,
&ProtocolRefs[0],
ProtocolRefs.size());
return 0;
}
// We have a class or category name - consume it.
+ IdentifierInfo *nameId = Tok.getIdentifierInfo();
SourceLocation nameLoc = ConsumeToken(); // consume class or category name
if (Tok.getKind() == tok::l_paren) {
return 0;
}
// We have a class implementation
+ SourceLocation superClassLoc;
+ IdentifierInfo *superClassId = 0;
if (Tok.getKind() == tok::colon) {
// We have a super class
ConsumeToken();
Diag(Tok, diag::err_expected_ident); // missing super class name.
return 0;
}
- ConsumeToken(); // Consume super class name
+ superClassId = Tok.getIdentifierInfo();
+ superClassLoc = ConsumeToken(); // Consume super class name
}
+ DeclTy *ImplClsType = Actions.ObjcStartClassImplementation(CurScope,
+ atLoc,
+ nameId, nameLoc,
+ superClassId, superClassLoc);
+
if (Tok.getKind() == tok::l_brace)
- ParseObjCClassInstanceVariables(0/*FIXME*/); // we have ivars
+ ParseObjCClassInstanceVariables(ImplClsType/*FIXME*/); // we have ivars
return 0;
}
SourceLocation RParenLoc);
// Objective-C declarations.
- virtual DeclTy *ObjcStartClassInterface(SourceLocation AtInterafceLoc,
+ virtual DeclTy *ObjcStartClassInterface(Scope* S,
+ SourceLocation AtInterafceLoc,
IdentifierInfo *ClassName, SourceLocation ClassLoc,
IdentifierInfo *SuperName, SourceLocation SuperLoc,
IdentifierInfo **ProtocolNames, unsigned NumProtocols,
AttributeList *AttrList);
- virtual DeclTy *ObjcStartProtoInterface(SourceLocation AtProtoInterfaceLoc,
+ virtual DeclTy *ObjcStartProtoInterface(Scope* S,
+ SourceLocation AtProtoInterfaceLoc,
IdentifierInfo *ProtocolName, SourceLocation ProtocolLoc,
IdentifierInfo **ProtoRefNames, unsigned NumProtoRefs);
IdentifierInfo *CategoryName, SourceLocation CategoryLoc,
IdentifierInfo **ProtoRefNames, unsigned NumProtoRefs);
+ virtual DeclTy *ObjcStartClassImplementation(Scope* S,
+ SourceLocation AtClassImplLoc,
+ IdentifierInfo *ClassName, SourceLocation ClassLoc,
+ IdentifierInfo *SuperClassname,
+ SourceLocation SuperClassLoc);
+
virtual DeclTy *ObjcClassDeclaration(Scope *S, SourceLocation AtClassLoc,
IdentifierInfo **IdentList,
unsigned NumElts);
return NewTD;
}
-Sema::DeclTy *Sema::ObjcStartClassInterface(SourceLocation AtInterfaceLoc,
+Sema::DeclTy *Sema::ObjcStartClassInterface(Scope* S,
+ SourceLocation AtInterfaceLoc,
IdentifierInfo *ClassName, SourceLocation ClassLoc,
IdentifierInfo *SuperName, SourceLocation SuperLoc,
IdentifierInfo **ProtocolNames, unsigned NumProtocols,
AttributeList *AttrList) {
assert(ClassName && "Missing class identifier");
-
+
+ // Check for another declaration kind with the same name.
+ ScopedDecl *PrevDecl = LookupScopedDecl(ClassName, Decl::IDNS_Ordinary,
+ ClassLoc, S);
+ if (PrevDecl && !isa<ObjcInterfaceDecl>(PrevDecl)
+ && !isa<ObjcProtocolDecl>(PrevDecl)) {
+ Diag(ClassLoc, diag::err_redefinition_different_kind,
+ ClassName->getName());
+ Diag(PrevDecl->getLocation(), diag::err_previous_definition);
+ }
+
ObjcInterfaceDecl* IDecl = Context.getObjCInterfaceDecl(ClassName);
if (IDecl) {
}
if (SuperName) {
- ObjcInterfaceDecl* SuperClassEntry =
- Context.getObjCInterfaceDecl(SuperName);
+ ObjcInterfaceDecl* SuperClassEntry = 0;
+ // Check if a different kind of symbol declared in this scope.
+ PrevDecl = LookupScopedDecl(SuperName, Decl::IDNS_Ordinary,
+ SuperLoc, S);
+ if (PrevDecl && !isa<ObjcInterfaceDecl>(PrevDecl)
+ && !isa<ObjcProtocolDecl>(PrevDecl)) {
+ Diag(SuperLoc, diag::err_redefinition_different_kind,
+ SuperName->getName());
+ Diag(PrevDecl->getLocation(), diag::err_previous_definition);
+ }
+ else {
+ // Check that super class is previously defined
+ SuperClassEntry = Context.getObjCInterfaceDecl(SuperName);
- if (!SuperClassEntry || SuperClassEntry->getIsForwardDecl()) {
- Diag(AtInterfaceLoc, diag::err_undef_superclass, SuperName->getName(),
- ClassName->getName());
+ if (!SuperClassEntry || SuperClassEntry->getIsForwardDecl()) {
+ Diag(AtInterfaceLoc, diag::err_undef_superclass, SuperName->getName(),
+ ClassName->getName());
+ }
}
- else
- IDecl->setSuperClass(SuperClassEntry);
+ IDecl->setSuperClass(SuperClassEntry);
}
/// Check then save referenced protocols
return IDecl;
}
-Sema::DeclTy *Sema::ObjcStartProtoInterface(SourceLocation AtProtoInterfaceLoc,
+Sema::DeclTy *Sema::ObjcStartProtoInterface(Scope* S,
+ SourceLocation AtProtoInterfaceLoc,
IdentifierInfo *ProtocolName, SourceLocation ProtocolLoc,
IdentifierInfo **ProtoRefNames, unsigned NumProtoRefs) {
assert(ProtocolName && "Missing protocol identifier");
return CDecl;
}
+Sema::DeclTy *Sema::ObjcStartClassImplementation(Scope *S,
+ SourceLocation AtClassImplLoc,
+ IdentifierInfo *ClassName, SourceLocation ClassLoc,
+ IdentifierInfo *SuperClassname,
+ SourceLocation SuperClassLoc) {
+ ObjcInterfaceDecl* IDecl = 0;
+ // Check for another declaration kind with the same name.
+ ScopedDecl *PrevDecl = LookupScopedDecl(ClassName, Decl::IDNS_Ordinary,
+ ClassLoc, S);
+ if (PrevDecl && !isa<ObjcInterfaceDecl>(PrevDecl)) {
+ Diag(ClassLoc, diag::err_redefinition_different_kind,
+ ClassName->getName());
+ Diag(PrevDecl->getLocation(), diag::err_previous_definition);
+ }
+ else {
+ // Is there an interface declaration of this class; if not, warn!
+ IDecl = Context.getObjCInterfaceDecl(ClassName);
+ if (!IDecl)
+ Diag(ClassLoc, diag::warn_undef_interface, ClassName->getName());
+ }
+
+ // Check that super class name is valid class name
+ ObjcInterfaceDecl* SDecl = 0;
+ if (SuperClassname) {
+ // Check if a different kind of symbol declared in this scope.
+ PrevDecl = LookupScopedDecl(SuperClassname, Decl::IDNS_Ordinary,
+ SuperClassLoc, S);
+ if (PrevDecl && !isa<ObjcInterfaceDecl>(PrevDecl)
+ && !isa<ObjcProtocolDecl>(PrevDecl)) {
+ Diag(SuperClassLoc, diag::err_redefinition_different_kind,
+ SuperClassname->getName());
+ Diag(PrevDecl->getLocation(), diag::err_previous_definition);
+ }
+ else {
+ SDecl = Context.getObjCInterfaceDecl(SuperClassname);
+ if (!SDecl)
+ Diag(SuperClassLoc, diag::err_undef_superclass,
+ SuperClassname->getName(), ClassName->getName());
+ else if (IDecl && IDecl->getSuperClass() != SDecl) {
+ // This implementation and its interface do not have the same
+ // super class.
+ Diag(SuperClassLoc, diag::err_conflicting_super_class,
+ SuperClassname->getName());
+ Diag(SDecl->getLocation(), diag::err_previous_definition);
+ }
+ }
+ }
+
+ ObjcImplementationDecl* IMPDecl =
+ new ObjcImplementationDecl(AtClassImplLoc, ClassName, SDecl);
+
+ // Check that there is no duplicate implementation of this class.
+ bool err = false;
+ for (unsigned i = 0; i != Context.sizeObjcImplementationClass(); i++) {
+ if (Context.getObjcImplementationClass(i)->getIdentifier() == ClassName) {
+ Diag(ClassLoc, diag::err_dup_implementation_class, ClassName->getName());
+ err = true;
+ break;
+ }
+ }
+ if (!err)
+ Context.setObjcImplementationClass(IMPDecl);
+
+ return IMPDecl;
+}
+
/// ObjcClassDeclaration -
/// Scope will always be top level file scope.
Action::DeclTy *
if (isa<RecordDecl>(static_cast<Decl *>(TagDecl)))
NewFD = new FieldDecl(Loc, II, T);
- else if (isa<ObjcInterfaceDecl>(static_cast<Decl *>(TagDecl)))
+ else if (isa<ObjcInterfaceDecl>(static_cast<Decl *>(TagDecl))
+ || isa<ObjcImplementationDecl>(static_cast<Decl *>(TagDecl)))
NewFD = new ObjcIvarDecl(Loc, II, T);
else
assert(0 && "Sema::ActOnField(): Unknown TagDecl");
08FB7793FE84155DC02AAC07 /* Project object */ = {
isa = PBXProject;
buildConfigurationList = 1DEB923508733DC60010E9CD /* Build configuration list for PBXProject "clang" */;
+ compatibilityVersion = "Xcode 2.4";
hasScannedForEncodings = 1;
mainGroup = 08FB7794FE84155DC02AAC07 /* clang */;
projectDirPath = "";
llvm::DenseMap<const RecordDecl*, const RecordLayout*> RecordLayoutInfo;
llvm::DenseMap<const IdentifierInfo*, ObjcInterfaceDecl*> ClassNameInfo;
llvm::DenseMap<const IdentifierInfo*, ObjcProtocolDecl*> ProtocolNameInfo;
+ llvm::SmallVector<ObjcImplementationDecl*, 8> ImplementationClassInfo;
RecordDecl *CFConstantStringTypeDecl;
public:
ObjcProtocolDecl* ProtocolDecl)
{ ProtocolNameInfo[ProtocolName] = ProtocolDecl; }
+ ObjcImplementationDecl* getObjcImplementationClass(unsigned ix) {
+ return ImplementationClassInfo[ix];
+ }
+ void setObjcImplementationClass(ObjcImplementationDecl* ImplDecl) {
+ ImplementationClassInfo.push_back(ImplDecl);
+ }
+ unsigned sizeObjcImplementationClass() const {
+ return ImplementationClassInfo.size();
+ }
+
//===--------------------------------------------------------------------===//
// Type Operators
//===--------------------------------------------------------------------===//
class ObjcProtocolDecl;
class ObjcCategoryDecl;
-
/// Decl - This represents one declaration (or definition), e.g. a variable,
/// typedef, function, struct, etc.
///
// Concrete sub-classes of TypeDecl
Typedef, Struct, Union, Class, Enum, ObjcInterface, ObjcClass, ObjcMethod,
ObjcProtoMethod, ObjcProtocol, ObjcForwardProtocol, ObjcCategory,
+ ObjcImplementation,
// Concrete sub-class of Decl
Field, ObjcIvar
};
case ParmVariable:
case EnumConstant:
case ObjcInterface:
+ case ObjcProtocol:
return IDNS_Ordinary;
case Struct:
case Union:
}
static bool classof(const ObjcCategoryDecl *D) { return true; }
};
+
+class ObjcImplementationDecl : public ScopedDecl {
+
+ /// Implementation Class's super class.
+ ObjcInterfaceDecl *SuperClass;
+
+ /// Optional Ivars/NumIvars - This is a new[]'d array of pointers to Decls.
+ ObjcIvarDecl **Ivars; // Null if not specified
+ int NumIvars; // -1 if not defined.
+
+ /// implemented instance methods
+ ObjcMethodDecl **InsMethods; // Null if not defined
+ int NumInsMethods; // -1 if not defined
+
+ /// implemented class methods
+ ObjcMethodDecl **ClsMethods; // Null if not defined
+ int NumClsMethods; // -1 if not defined
+
+ public:
+ ObjcImplementationDecl(SourceLocation L, IdentifierInfo *Id,
+ ObjcInterfaceDecl* superDecl)
+ : ScopedDecl(ObjcImplementation, L, Id, 0),
+ SuperClass(superDecl),
+ Ivars(0), NumIvars(-1),
+ InsMethods(0), NumInsMethods(-1), ClsMethods(0), NumClsMethods(-1) {}
+
+ void ObjcAddInstanceVariablesToClass(ObjcIvarDecl **ivars,
+ unsigned numIvars);
+
+ void ObjcAddMethods(ObjcMethodDecl **insMethods, unsigned numInsMembers,
+ ObjcMethodDecl **clsMethods, unsigned numClsMembers);
+
+ ObjcInterfaceDecl *getImplSuperClass() const { return SuperClass; }
+
+ void setImplSuperClass(ObjcInterfaceDecl * superCls)
+ { SuperClass = superCls; }
+
+ static bool classof(const Decl *D) {
+ return D->getKind() == ObjcImplementation;
+ }
+ static bool classof(const ObjcImplementationDecl *D) { return true; }
+};
+
} // end namespace clang
#endif
"cannot find interface declaration for '%0'")
DIAG(err_dup_category_def, ERROR,
"duplicate interface declaration for category '%0(%1)'")
+DIAG(warn_undef_interface, WARNING,
+ "cannot find interface declaration for '%0'")
+DIAG(err_dup_implementation_class, ERROR,
+ "reimplementation of class '%0'")
+DIAG(err_conflicting_super_class, ERROR,
+ "conflicting super class name '%0'")
//===----------------------------------------------------------------------===//
// Semantic Analysis
}
//===----------------------- Obj-C Declarations -------------------------===//
- virtual DeclTy *ObjcStartClassInterface(SourceLocation AtInterafceLoc,
+ virtual DeclTy *ObjcStartClassInterface(Scope* S, SourceLocation AtInterafceLoc,
IdentifierInfo *ClassName, SourceLocation ClassLoc,
IdentifierInfo *SuperName, SourceLocation SuperLoc,
IdentifierInfo **ProtocolNames, unsigned NumProtocols,
DeclTy **allMethods, unsigned allNum) {
return;
}
- virtual DeclTy *ObjcStartProtoInterface(SourceLocation AtProtoInterfaceLoc,
+ virtual DeclTy *ObjcStartProtoInterface(Scope* S,
+ SourceLocation AtProtoInterfaceLoc,
IdentifierInfo *ProtocolName, SourceLocation ProtocolLoc,
IdentifierInfo **ProtoRefNames, unsigned NumProtoRefs) {
return 0;
IdentifierInfo **ProtoRefNames, unsigned NumProtoRefs) {
return 0;
}
+ virtual DeclTy *ObjcStartClassImplementation(Scope* S,
+ SourceLocation AtClassImplLoc,
+ IdentifierInfo *ClassName, SourceLocation ClassLoc,
+ IdentifierInfo *SuperClassname,
+ SourceLocation SuperClassLoc) {
+ return 0;
+ }
virtual DeclTy *ObjcBuildMethodDeclaration(SourceLocation MethodLoc,
tok::TokenKind MethodType, TypeTy *ReturnType,
ObjcKeywordDecl *Keywords, unsigned NumKeywords,
IdentifierInfo **IdentList,
unsigned NumElts);
- virtual DeclTy *ObjcStartClassInterface(SourceLocation AtInterafceLoc,
+ virtual DeclTy *ObjcStartClassInterface(Scope* S, SourceLocation AtInterafceLoc,
IdentifierInfo *ClassName, SourceLocation ClassLoc,
IdentifierInfo *SuperName, SourceLocation SuperLoc,
IdentifierInfo **ProtocolNames, unsigned NumProtocols,
AttributeList *AttrList);
- virtual DeclTy *ObjcStartProtoInterface(SourceLocation AtProtoInterfaceLoc,
+ virtual DeclTy *ObjcStartProtoInterface(Scope *S,
+ SourceLocation AtProtoInterfaceLoc,
IdentifierInfo *ProtocolName, SourceLocation ProtocolLoc,
IdentifierInfo **ProtoRefNames, unsigned NumProtoRefs);
};
--- /dev/null
+@protocol SUPER;
+
+@interface SUPER <SUPER> @end // expected-error {{cannot find protocol definition for 'SUPER', referenced by 'SUPER'}}
+
+typedef int INTF; // expected-error {{previou sdefinition is here}}
+
+@interface INTF @end // expected-error {{redefinition of 'INTF' as different kind of symbol}}
+
+@interface OBJECT @end
+
+@interface INTF1 : OBJECT @end
+
+@interface INTF1 : OBJECT @end // expected-error {{duplicate interface declaration for class 'INTF1'}
+
+typedef int OBJECT; // expected-error {{previous definition is here}}
+
+@interface INTF2 : OBJECT @end // expected-error {{redefinition of 'OBJECT' as different kind of symbol}}
+
+
+@protocol PROTO;
+
+@interface INTF3 : PROTO @end // expected-error {{cannot find interface declaration for 'PROTO', superclass of 'INTF3'}}
+
--- /dev/null
+typedef int INTF3; // expected-error {{previous definition is here}}
+
+@interface SUPER @end // expected-error {{previous definition is here}}
+
+@interface OBJECT @end
+
+@interface INTF : OBJECT
+@end
+
+@implementation INTF @end
+
+@implementation INTF // expected-error {{reimplementation of class 'INTF'}}
+@end
+
+
+@interface INTF1 : OBJECT
+@end
+
+@implementation INTF1 : SUPER // expected-error {{conflicting super class name 'SUPER'}}
+@end
+
+@interface INTF2
+@end
+
+@implementation INTF2 : SUPR // expected-error {{cannot find interface declaration for 'SUPR', superclass of 'INTF2'}}
+@end
+
+@implementation INTF3 @end // expected-error {{redefinition of 'INTF3' as different kind of symbol}}
+
+@implementation INTF4 @end // expected-warning {{cannot find interface declaration for 'INTF4'}}
+