forked from qt-creator/qt-creator
Fixed semantic checks for Objective-C methods and fast-enumeration.
This commit is contained in:
@@ -2997,7 +2997,7 @@ public:
|
||||
SpecifierAST *attributes;
|
||||
|
||||
public: // annotations
|
||||
Function *symbol;
|
||||
ObjCMethod *symbol;
|
||||
|
||||
public:
|
||||
virtual ObjCMethodPrototypeAST *asObjCMethodPrototype()
|
||||
@@ -3129,6 +3129,9 @@ public:
|
||||
unsigned rparen_token;
|
||||
StatementAST *body_statement;
|
||||
|
||||
public: // annotations
|
||||
Block *symbol;
|
||||
|
||||
public:
|
||||
virtual ObjCFastEnumerationAST *asObjCFastEnumeration()
|
||||
{ return this; }
|
||||
|
||||
@@ -552,7 +552,14 @@ bool CheckDeclaration::visit(ObjCClassDeclarationAST *ast)
|
||||
klass->setEndOffset(tokenAt(ast->lastToken()).offset);
|
||||
ast->symbol = klass;
|
||||
|
||||
// TODO: walk category name, super-class, and protocols (EV)
|
||||
klass->setInterface(ast->interface_token != 0);
|
||||
|
||||
if (ast->category_name) {
|
||||
Name *categoryName = semantic()->check(ast->category_name, _scope);
|
||||
klass->setCategoryName(categoryName);
|
||||
}
|
||||
|
||||
// TODO: super-class, and protocols (EV)
|
||||
_scope->enterSymbol(klass);
|
||||
|
||||
int previousObjCVisibility = semantic()->switchObjCVisibility(Function::Protected);
|
||||
@@ -580,16 +587,25 @@ bool CheckDeclaration::visit(ObjCMethodDeclarationAST *ast)
|
||||
return false;
|
||||
|
||||
FullySpecifiedType ty = semantic()->check(ast->method_prototype, _scope);
|
||||
Function *fun = ty.type()->asFunctionType();
|
||||
if (!fun)
|
||||
ObjCMethod *methodType = ty.type()->asObjCMethodType();
|
||||
if (!methodType)
|
||||
return false;
|
||||
|
||||
Declaration *symbol = control()->newDeclaration(ast->firstToken(), fun->name());
|
||||
Symbol *symbol;
|
||||
if (!ast->function_body) {
|
||||
Declaration *decl = control()->newDeclaration(ast->firstToken(), methodType->name());
|
||||
decl->setType(methodType);
|
||||
symbol = decl;
|
||||
} else {
|
||||
if (!semantic()->skipFunctionBodies()) {
|
||||
semantic()->check(ast->function_body, methodType->members());
|
||||
}
|
||||
|
||||
symbol = methodType;
|
||||
}
|
||||
|
||||
symbol->setStartOffset(tokenAt(ast->firstToken()).offset);
|
||||
symbol->setEndOffset(tokenAt(ast->lastToken()).offset);
|
||||
|
||||
symbol->setType(fun->returnType());
|
||||
|
||||
symbol->setVisibility(semantic()->currentVisibility());
|
||||
|
||||
if (semantic()->isObjCClassMethod(ast->method_prototype->method_type_token))
|
||||
@@ -597,10 +613,6 @@ bool CheckDeclaration::visit(ObjCMethodDeclarationAST *ast)
|
||||
|
||||
_scope->enterSymbol(symbol);
|
||||
|
||||
if (ast->function_body && !semantic()->skipFunctionBodies()) {
|
||||
semantic()->check(ast->function_body, fun->members());
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
@@ -254,14 +254,12 @@ bool CheckDeclarator::visit(ObjCMethodPrototypeAST *ast)
|
||||
|
||||
Name *name = semantic()->check(ast->selector, _scope);
|
||||
|
||||
Function *fun = control()->newFunction(location, name);
|
||||
ast->symbol = fun;
|
||||
fun->setSourceLocation(location);
|
||||
fun->setScope(_scope);
|
||||
fun->setMethodKey(Function::NormalMethod);
|
||||
fun->setVisibility(semantic()->currentVisibility());
|
||||
fun->setPureVirtual(false);
|
||||
fun->setReturnType(returnType);
|
||||
ObjCMethod *method = control()->newObjCMethod(location, name);
|
||||
ast->symbol = method;
|
||||
method->setSourceLocation(location);
|
||||
method->setScope(_scope);
|
||||
method->setVisibility(semantic()->currentVisibility());
|
||||
method->setReturnType(returnType);
|
||||
|
||||
if (ast->selector && ast->selector->asObjCSelectorWithArguments()) {
|
||||
// TODO: check the parameters (EV)
|
||||
@@ -270,11 +268,11 @@ bool CheckDeclarator::visit(ObjCMethodPrototypeAST *ast)
|
||||
for (ObjCMessageArgumentDeclarationListAST *it = ast->arguments; it; it = it->next) {
|
||||
ObjCMessageArgumentDeclarationAST *argDecl = it->argument_declaration;
|
||||
|
||||
semantic()->check(argDecl, fun->arguments());
|
||||
semantic()->check(argDecl, method->arguments());
|
||||
}
|
||||
}
|
||||
|
||||
_fullySpecifiedType = FullySpecifiedType(fun);
|
||||
_fullySpecifiedType = FullySpecifiedType(method);
|
||||
|
||||
// TODO: check which specifiers are allowed here (EV)
|
||||
|
||||
|
||||
@@ -170,6 +170,34 @@ bool CheckStatement::visit(ForeachStatementAST *ast)
|
||||
return false;
|
||||
}
|
||||
|
||||
bool CheckStatement::visit(ObjCFastEnumerationAST *ast)
|
||||
{
|
||||
Block *block = control()->newBlock(ast->for_token);
|
||||
block->setStartOffset(tokenAt(ast->firstToken()).offset);
|
||||
block->setEndOffset(tokenAt(ast->lastToken()).offset);
|
||||
ast->symbol = block;
|
||||
_scope->enterSymbol(block);
|
||||
Scope *previousScope = switchScope(block->members());
|
||||
if (ast->type_specifiers && ast->declarator) {
|
||||
FullySpecifiedType ty = semantic()->check(ast->type_specifiers, _scope);
|
||||
Name *name = 0;
|
||||
ty = semantic()->check(ast->declarator, ty, _scope, &name);
|
||||
unsigned location = ast->declarator->firstToken();
|
||||
if (CoreDeclaratorAST *core_declarator = ast->declarator->core_declarator)
|
||||
location = core_declarator->firstToken();
|
||||
Declaration *decl = control()->newDeclaration(location, name);
|
||||
decl->setType(ty);
|
||||
_scope->enterSymbol(decl);
|
||||
} else {
|
||||
FullySpecifiedType exprTy = semantic()->check(ast->initializer, _scope);
|
||||
(void) exprTy;
|
||||
}
|
||||
|
||||
semantic()->check(ast->body_statement, _scope);
|
||||
(void) switchScope(previousScope);
|
||||
return false;
|
||||
}
|
||||
|
||||
bool CheckStatement::visit(ForStatementAST *ast)
|
||||
{
|
||||
Block *block = control()->newBlock(ast->for_token);
|
||||
|
||||
@@ -76,6 +76,7 @@ protected:
|
||||
virtual bool visit(ExpressionOrDeclarationStatementAST *ast);
|
||||
virtual bool visit(ExpressionStatementAST *ast);
|
||||
virtual bool visit(ForeachStatementAST *ast);
|
||||
virtual bool visit(ObjCFastEnumerationAST *ast);
|
||||
virtual bool visit(ForStatementAST *ast);
|
||||
virtual bool visit(IfStatementAST *ast);
|
||||
virtual bool visit(LabeledStatementAST *ast);
|
||||
|
||||
@@ -125,6 +125,7 @@ public:
|
||||
delete_array_entries(objcProtocols);
|
||||
delete_array_entries(objcForwardClassDeclarations);
|
||||
delete_array_entries(objcForwardProtocolDeclarations);
|
||||
delete_array_entries(objcMethods);
|
||||
}
|
||||
|
||||
NameId *findOrInsertNameId(Identifier *id)
|
||||
@@ -368,6 +369,13 @@ public:
|
||||
return fwd;
|
||||
}
|
||||
|
||||
ObjCMethod *newObjCMethod(unsigned sourceLocation, Name *name)
|
||||
{
|
||||
ObjCMethod *method = new ObjCMethod(translationUnit, sourceLocation, name);
|
||||
objcMethods.push_back(method);
|
||||
return method;
|
||||
}
|
||||
|
||||
Enum *newEnum(unsigned sourceLocation, Name *name)
|
||||
{
|
||||
Enum *e = new Enum(translationUnit,
|
||||
@@ -549,6 +557,7 @@ public:
|
||||
std::vector<ObjCProtocol *> objcProtocols;
|
||||
std::vector<ObjCForwardClassDeclaration *> objcForwardClassDeclarations;
|
||||
std::vector<ObjCForwardProtocolDeclaration *> objcForwardProtocolDeclarations;
|
||||
std::vector<ObjCMethod *> objcMethods;
|
||||
};
|
||||
|
||||
Control::Control()
|
||||
@@ -726,4 +735,7 @@ ObjCProtocol *Control::newObjCProtocol(unsigned sourceLocation, Name *name)
|
||||
ObjCForwardProtocolDeclaration *Control::newObjCForwardProtocolDeclaration(unsigned sourceLocation, Name *name)
|
||||
{ return d->newObjCForwardProtocolDeclaration(sourceLocation, name); }
|
||||
|
||||
ObjCMethod *Control::newObjCMethod(unsigned sourceLocation, Name *name)
|
||||
{ return d->newObjCMethod(sourceLocation, name); }
|
||||
|
||||
CPLUSPLUS_END_NAMESPACE
|
||||
|
||||
@@ -163,6 +163,9 @@ public:
|
||||
/// Creates a new Objective-C protocol forward declaration symbol.
|
||||
ObjCForwardProtocolDeclaration *newObjCForwardProtocolDeclaration(unsigned sourceLocation, Name *name = 0);
|
||||
|
||||
/// Creates a new Objective-C method symbol.
|
||||
ObjCMethod *newObjCMethod(unsigned sourceLocation, Name *name = 0);
|
||||
|
||||
Identifier *findOrInsertIdentifier(const char *chars, unsigned size);
|
||||
Identifier *findOrInsertIdentifier(const char *chars);
|
||||
|
||||
|
||||
@@ -465,4 +465,7 @@ bool Symbol::isObjCProtocol() const
|
||||
bool Symbol::isObjCForwardProtocolDeclaration() const
|
||||
{ return asObjCForwardProtocolDeclaration() != 0; }
|
||||
|
||||
bool Symbol::isObjCMethod() const
|
||||
{ return asObjCMethod() != 0; }
|
||||
|
||||
CPLUSPLUS_END_NAMESPACE
|
||||
|
||||
@@ -210,18 +210,21 @@ public:
|
||||
/// Returns true if this Symbol is a ForwardClassDeclaration.
|
||||
bool isForwardClassDeclaration() const;
|
||||
|
||||
/// Returns true if this Symbol is a Objective-C Class definition.
|
||||
/// Returns true if this Symbol is an Objective-C Class declaration.
|
||||
bool isObjCClass() const;
|
||||
|
||||
/// Returns true if this Symbol is a Objective-C Class forward declaration.
|
||||
/// Returns true if this Symbol is an Objective-C Class forward declaration.
|
||||
bool isObjCForwardClassDeclaration() const;
|
||||
|
||||
/// Returns true if this Symbol is a Objective-C Protocol definition.
|
||||
/// Returns true if this Symbol is an Objective-C Protocol declaration.
|
||||
bool isObjCProtocol() const;
|
||||
|
||||
/// Returns true if this Symbol is a Objective-C Protocol forward declaration.
|
||||
/// Returns true if this Symbol is an Objective-C Protocol forward declaration.
|
||||
bool isObjCForwardProtocolDeclaration() const;
|
||||
|
||||
/// Returns true if this Symbol is an Objective-C method declaration.
|
||||
bool isObjCMethod() const;
|
||||
|
||||
virtual const ScopedSymbol *asScopedSymbol() const { return 0; }
|
||||
virtual const Enum *asEnum() const { return 0; }
|
||||
virtual const Function *asFunction() const { return 0; }
|
||||
@@ -238,6 +241,7 @@ public:
|
||||
virtual const ObjCForwardClassDeclaration *asObjCForwardClassDeclaration() const { return 0; }
|
||||
virtual const ObjCProtocol *asObjCProtocol() const { return 0; }
|
||||
virtual const ObjCForwardProtocolDeclaration *asObjCForwardProtocolDeclaration() const { return 0; }
|
||||
virtual const ObjCMethod *asObjCMethod() const { return 0; }
|
||||
|
||||
virtual ScopedSymbol *asScopedSymbol() { return 0; }
|
||||
virtual Enum *asEnum() { return 0; }
|
||||
@@ -255,6 +259,7 @@ public:
|
||||
virtual ObjCForwardClassDeclaration *asObjCForwardClassDeclaration() { return 0; }
|
||||
virtual ObjCProtocol *asObjCProtocol() { return 0; }
|
||||
virtual ObjCForwardProtocolDeclaration *asObjCForwardProtocolDeclaration() { return 0; }
|
||||
virtual ObjCMethod *asObjCMethod() { return 0; }
|
||||
|
||||
/// Returns this Symbol's type.
|
||||
virtual FullySpecifiedType type() const = 0;
|
||||
|
||||
@@ -85,6 +85,7 @@ public:
|
||||
virtual bool visit(ObjCForwardClassDeclaration *) { return true; }
|
||||
virtual bool visit(ObjCProtocol *) { return true; }
|
||||
virtual bool visit(ObjCForwardProtocolDeclaration *) { return true; }
|
||||
virtual bool visit(ObjCMethod *) { return true; }
|
||||
};
|
||||
|
||||
CPLUSPLUS_END_NAMESPACE
|
||||
|
||||
@@ -554,7 +554,8 @@ void Class::visitSymbol0(SymbolVisitor *visitor)
|
||||
}
|
||||
|
||||
ObjCClass::ObjCClass(TranslationUnit *translationUnit, unsigned sourceLocation, Name *name):
|
||||
ScopedSymbol(translationUnit, sourceLocation, name)
|
||||
ScopedSymbol(translationUnit, sourceLocation, name),
|
||||
_categoryName(0)
|
||||
{
|
||||
}
|
||||
|
||||
@@ -655,4 +656,94 @@ FullySpecifiedType ObjCForwardProtocolDeclaration::type() const
|
||||
void ObjCForwardProtocolDeclaration::visitSymbol0(SymbolVisitor *visitor)
|
||||
{ visitor->visit(this); }
|
||||
|
||||
ObjCMethod::ObjCMethod(TranslationUnit *translationUnit, unsigned sourceLocation, Name *name)
|
||||
: ScopedSymbol(translationUnit, sourceLocation, name),
|
||||
_flags(0)
|
||||
{ _arguments = new Scope(this); }
|
||||
|
||||
ObjCMethod::~ObjCMethod()
|
||||
{
|
||||
delete _arguments;
|
||||
}
|
||||
|
||||
bool ObjCMethod::isEqualTo(const Type *other) const
|
||||
{
|
||||
const ObjCMethod *o = other->asObjCMethodType();
|
||||
if (! o)
|
||||
return false;
|
||||
|
||||
Name *l = identity();
|
||||
Name *r = o->identity();
|
||||
if (l == r || (l && l->isEqualTo(r))) {
|
||||
if (_arguments->symbolCount() != o->_arguments->symbolCount())
|
||||
return false;
|
||||
else if (! _returnType.isEqualTo(o->_returnType))
|
||||
return false;
|
||||
for (unsigned i = 0; i < _arguments->symbolCount(); ++i) {
|
||||
Symbol *l = _arguments->symbolAt(i);
|
||||
Symbol *r = o->_arguments->symbolAt(i);
|
||||
if (! l->type().isEqualTo(r->type()))
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
void ObjCMethod::accept0(TypeVisitor *visitor)
|
||||
{ visitor->visit(this); }
|
||||
|
||||
FullySpecifiedType ObjCMethod::type() const
|
||||
{ return FullySpecifiedType(const_cast<ObjCMethod *>(this)); }
|
||||
|
||||
FullySpecifiedType ObjCMethod::returnType() const
|
||||
{ return _returnType; }
|
||||
|
||||
void ObjCMethod::setReturnType(FullySpecifiedType returnType)
|
||||
{ _returnType = returnType; }
|
||||
|
||||
bool ObjCMethod::hasReturnType() const
|
||||
{
|
||||
const FullySpecifiedType ty = returnType();
|
||||
return ty.isValid() || ty.isSigned() || ty.isUnsigned();
|
||||
}
|
||||
|
||||
unsigned ObjCMethod::argumentCount() const
|
||||
{
|
||||
if (! _arguments)
|
||||
return 0;
|
||||
|
||||
return _arguments->symbolCount();
|
||||
}
|
||||
|
||||
Symbol *ObjCMethod::argumentAt(unsigned index) const
|
||||
{ return _arguments->symbolAt(index); }
|
||||
|
||||
Scope *ObjCMethod::arguments() const
|
||||
{ return _arguments; }
|
||||
|
||||
bool ObjCMethod::hasArguments() const
|
||||
{
|
||||
return ! (argumentCount() == 0 ||
|
||||
(argumentCount() == 1 && argumentAt(0)->type()->isVoidType()));
|
||||
}
|
||||
|
||||
bool ObjCMethod::isVariadic() const
|
||||
{ return f._isVariadic; }
|
||||
|
||||
void ObjCMethod::setVariadic(bool isVariadic)
|
||||
{ f._isVariadic = isVariadic; }
|
||||
|
||||
void ObjCMethod::visitSymbol0(SymbolVisitor *visitor)
|
||||
{
|
||||
if (visitor->visit(this)) {
|
||||
for (unsigned i = 0; i < _arguments->symbolCount(); ++i) {
|
||||
visitSymbol(_arguments->symbolAt(i), visitor);
|
||||
}
|
||||
for (unsigned i = 0; i < memberCount(); ++i) {
|
||||
visitSymbol(memberAt(i), visitor);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
CPLUSPLUS_END_NAMESPACE
|
||||
|
||||
@@ -543,6 +543,13 @@ public:
|
||||
ObjCClass(TranslationUnit *translationUnit, unsigned sourceLocation, Name *name);
|
||||
virtual ~ObjCClass();
|
||||
|
||||
bool isInterface() const { return _isInterface; }
|
||||
void setInterface(bool isInterface) { _isInterface = isInterface; }
|
||||
|
||||
bool isCategory() const { return _categoryName != 0; }
|
||||
Name *categoryName() const { return _categoryName; }
|
||||
void setCategoryName(Name *categoryName) { _categoryName = categoryName; }
|
||||
|
||||
// Symbol's interface
|
||||
virtual FullySpecifiedType type() const;
|
||||
|
||||
@@ -566,10 +573,68 @@ protected:
|
||||
virtual void accept0(TypeVisitor *visitor);
|
||||
|
||||
private:
|
||||
bool _isInterface;
|
||||
Name *_categoryName;
|
||||
Array<ObjCClass *> _baseClasses;
|
||||
Array<ObjCProtocol *> _protocols;
|
||||
};
|
||||
|
||||
class CPLUSPLUS_EXPORT ObjCMethod: public ScopedSymbol, public Type
|
||||
{
|
||||
public:
|
||||
ObjCMethod(TranslationUnit *translationUnit, unsigned sourceLocation, Name *name);
|
||||
virtual ~ObjCMethod();
|
||||
|
||||
FullySpecifiedType returnType() const;
|
||||
void setReturnType(FullySpecifiedType returnType);
|
||||
|
||||
/** Convenience function that returns whether the function returns something (including void). */
|
||||
bool hasReturnType() const;
|
||||
|
||||
unsigned argumentCount() const;
|
||||
Symbol *argumentAt(unsigned index) const;
|
||||
Scope *arguments() const;
|
||||
|
||||
/** Convenience function that returns whether the function receives any arguments. */
|
||||
bool hasArguments() const;
|
||||
|
||||
bool isVariadic() const;
|
||||
void setVariadic(bool isVariadic);
|
||||
|
||||
// Symbol's interface
|
||||
virtual FullySpecifiedType type() const;
|
||||
|
||||
// Type's interface
|
||||
virtual bool isEqualTo(const Type *other) const;
|
||||
|
||||
virtual const ObjCMethod *asObjCMethod() const
|
||||
{ return this; }
|
||||
|
||||
virtual ObjCMethod *asObjCMethod()
|
||||
{ return this; }
|
||||
|
||||
virtual const ObjCMethod *asObjCMethodType() const
|
||||
{ return this; }
|
||||
|
||||
virtual ObjCMethod *asObjCMethodType()
|
||||
{ return this; }
|
||||
|
||||
protected:
|
||||
virtual void visitSymbol0(SymbolVisitor *visitor);
|
||||
virtual void accept0(TypeVisitor *visitor);
|
||||
|
||||
private:
|
||||
FullySpecifiedType _returnType;
|
||||
struct Flags {
|
||||
unsigned _isVariadic: 1;
|
||||
};
|
||||
union {
|
||||
unsigned _flags;
|
||||
Flags f;
|
||||
};
|
||||
Scope *_arguments;
|
||||
};
|
||||
|
||||
CPLUSPLUS_END_NAMESPACE
|
||||
CPLUSPLUS_END_HEADER
|
||||
|
||||
|
||||
@@ -107,6 +107,9 @@ bool Type::isObjCClassType() const
|
||||
bool Type::isObjCProtocolType() const
|
||||
{ return asObjCProtocolType() != 0; }
|
||||
|
||||
bool Type::isObjCMethodType() const
|
||||
{ return asObjCMethodType() != 0; }
|
||||
|
||||
void Type::accept(TypeVisitor *visitor)
|
||||
{
|
||||
if (visitor->preVisit(this))
|
||||
|
||||
@@ -79,6 +79,7 @@ public:
|
||||
bool isForwardClassDeclarationType() const;
|
||||
bool isObjCClassType() const;
|
||||
bool isObjCProtocolType() const;
|
||||
bool isObjCMethodType() const;
|
||||
|
||||
virtual const VoidType *asVoidType() const { return 0; }
|
||||
virtual const IntegerType *asIntegerType() const { return 0; }
|
||||
@@ -95,6 +96,7 @@ public:
|
||||
virtual const ForwardClassDeclaration *asForwardClassDeclarationType() const { return 0; }
|
||||
virtual const ObjCClass *asObjCClassType() const { return 0; }
|
||||
virtual const ObjCProtocol *asObjCProtocolType() const { return 0; }
|
||||
virtual const ObjCMethod *asObjCMethodType() const { return 0; }
|
||||
|
||||
virtual VoidType *asVoidType() { return 0; }
|
||||
virtual IntegerType *asIntegerType() { return 0; }
|
||||
@@ -110,7 +112,8 @@ public:
|
||||
virtual Enum *asEnumType() { return 0; }
|
||||
virtual ForwardClassDeclaration *asForwardClassDeclarationType() { return 0; }
|
||||
virtual ObjCClass *asObjCClassType() { return 0; }
|
||||
virtual ObjCProtocol *asObjCProtocoTypel() { return 0; }
|
||||
virtual ObjCProtocol *asObjCProtocolType() { return 0; }
|
||||
virtual ObjCMethod *asObjCMethodType() { return 0; }
|
||||
|
||||
void accept(TypeVisitor *visitor);
|
||||
static void accept(Type *type, TypeVisitor *visitor);
|
||||
|
||||
@@ -83,6 +83,7 @@ public:
|
||||
virtual void visit(ForwardClassDeclaration *) {}
|
||||
virtual void visit(ObjCClass *) {}
|
||||
virtual void visit(ObjCProtocol *) {}
|
||||
virtual void visit(ObjCMethod *) {}
|
||||
};
|
||||
|
||||
CPLUSPLUS_END_NAMESPACE
|
||||
|
||||
Reference in New Issue
Block a user