зеркало из https://github.com/microsoft/clang-1.git
Implement typo correction for a variety of Objective-C-specific
constructs: - Instance variable lookup ("foo->ivar" and, in instance methods, "ivar") - Property name lookup ("foo.prop") - Superclasses - Various places where a class name is required - Protocol names (e.g., id<proto>) This seems to cover many of the common places where typos could occur. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@92449 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
Родитель
368a55d3ce
Коммит
f06cdae9c6
|
@ -2569,6 +2569,17 @@ def err_mem_init_not_member_or_class_suggest : Error<
|
|||
def err_field_designator_unknown_suggest : Error<
|
||||
"field designator %0 does not refer to any field in type %1; did you mean "
|
||||
"%2?">;
|
||||
def err_typecheck_member_reference_ivar_suggest : Error<
|
||||
"%0 does not have a member named %1; did you mean %2?">;
|
||||
def err_property_not_found_suggest : Error<
|
||||
"property %0 not found on object of type %1; did you mean %2?">;
|
||||
def err_undef_interface_suggest : Error<
|
||||
"cannot find interface declaration for %0; did you mean %1?">;
|
||||
def err_undef_superclass_suggest : Error<
|
||||
"cannot find interface declaration for %0, superclass of %1; did you mean "
|
||||
"%2?">;
|
||||
def err_undeclared_protocol_suggest : Error<
|
||||
"cannot find protocol declaration for %0; did you mean %1?">;
|
||||
|
||||
}
|
||||
|
||||
|
|
|
@ -1208,7 +1208,8 @@ public:
|
|||
|
||||
bool CorrectTypo(LookupResult &R, Scope *S, const CXXScopeSpec *SS,
|
||||
DeclContext *MemberContext = 0,
|
||||
bool EnteringContext = false);
|
||||
bool EnteringContext = false,
|
||||
const ObjCObjectPointerType *OPT = 0);
|
||||
|
||||
void FindAssociatedClassesAndNamespaces(Expr **Args, unsigned NumArgs,
|
||||
AssociatedNamespaceSet &AssociatedNamespaces,
|
||||
|
@ -1217,7 +1218,8 @@ public:
|
|||
bool DiagnoseAmbiguousLookup(LookupResult &Result);
|
||||
//@}
|
||||
|
||||
ObjCInterfaceDecl *getObjCInterfaceDecl(IdentifierInfo *Id);
|
||||
ObjCInterfaceDecl *getObjCInterfaceDecl(IdentifierInfo *&Id,
|
||||
SourceLocation RecoverLoc = SourceLocation());
|
||||
NamedDecl *LazilyCreateBuiltin(IdentifierInfo *II, unsigned ID,
|
||||
Scope *S, bool ForRedeclaration,
|
||||
SourceLocation Loc);
|
||||
|
|
|
@ -555,11 +555,35 @@ void Sema::ActOnPopScope(SourceLocation Loc, Scope *S) {
|
|||
|
||||
/// getObjCInterfaceDecl - Look up a for a class declaration in the scope.
|
||||
/// return 0 if one not found.
|
||||
ObjCInterfaceDecl *Sema::getObjCInterfaceDecl(IdentifierInfo *Id) {
|
||||
///
|
||||
/// \param Id the name of the Objective-C class we're looking for. If
|
||||
/// typo-correction fixes this name, the Id will be updated
|
||||
/// to the fixed name.
|
||||
///
|
||||
/// \param RecoverLoc if provided, this routine will attempt to
|
||||
/// recover from a typo in the name of an existing Objective-C class
|
||||
/// and, if successful, will return the lookup that results from
|
||||
/// typo-correction.
|
||||
ObjCInterfaceDecl *Sema::getObjCInterfaceDecl(IdentifierInfo *&Id,
|
||||
SourceLocation RecoverLoc) {
|
||||
// The third "scope" argument is 0 since we aren't enabling lazy built-in
|
||||
// creation from this context.
|
||||
NamedDecl *IDecl = LookupSingleName(TUScope, Id, LookupOrdinaryName);
|
||||
|
||||
if (!IDecl && !RecoverLoc.isInvalid()) {
|
||||
// Perform typo correction at the given location, but only if we
|
||||
// find an Objective-C class name.
|
||||
LookupResult R(*this, Id, RecoverLoc, LookupOrdinaryName);
|
||||
if (CorrectTypo(R, TUScope, 0) &&
|
||||
(IDecl = R.getAsSingle<ObjCInterfaceDecl>())) {
|
||||
Diag(RecoverLoc, diag::err_undef_interface_suggest)
|
||||
<< Id << IDecl->getDeclName()
|
||||
<< CodeModificationHint::CreateReplacement(RecoverLoc,
|
||||
IDecl->getNameAsString());
|
||||
Id = IDecl->getIdentifier();
|
||||
}
|
||||
}
|
||||
|
||||
return dyn_cast_or_null<ObjCInterfaceDecl>(IDecl);
|
||||
}
|
||||
|
||||
|
|
|
@ -12,6 +12,7 @@
|
|||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#include "Sema.h"
|
||||
#include "Lookup.h"
|
||||
#include "clang/Sema/ExternalSemaSource.h"
|
||||
#include "clang/AST/Expr.h"
|
||||
#include "clang/AST/ASTContext.h"
|
||||
|
@ -133,6 +134,17 @@ ActOnStartClassInterface(SourceLocation AtInterfaceLoc,
|
|||
if (SuperName) {
|
||||
// Check if a different kind of symbol declared in this scope.
|
||||
PrevDecl = LookupSingleName(TUScope, SuperName, LookupOrdinaryName);
|
||||
|
||||
if (!PrevDecl) {
|
||||
// Try to correct for a typo in the superclass name.
|
||||
LookupResult R(*this, SuperName, SuperLoc, LookupOrdinaryName);
|
||||
if (CorrectTypo(R, TUScope, 0) &&
|
||||
(PrevDecl = R.getAsSingle<ObjCInterfaceDecl>())) {
|
||||
Diag(SuperLoc, diag::err_undef_superclass_suggest)
|
||||
<< SuperName << ClassName << PrevDecl->getDeclName();
|
||||
}
|
||||
}
|
||||
|
||||
if (PrevDecl == IDecl) {
|
||||
Diag(SuperLoc, diag::err_recursive_superclass)
|
||||
<< SuperName << ClassName << SourceRange(AtInterfaceLoc, ClassLoc);
|
||||
|
@ -316,6 +328,16 @@ Sema::FindProtocolDeclaration(bool WarnOnDeclarations,
|
|||
llvm::SmallVectorImpl<DeclPtrTy> &Protocols) {
|
||||
for (unsigned i = 0; i != NumProtocols; ++i) {
|
||||
ObjCProtocolDecl *PDecl = LookupProtocol(ProtocolId[i].first);
|
||||
if (!PDecl) {
|
||||
LookupResult R(*this, ProtocolId[i].first, ProtocolId[i].second,
|
||||
LookupObjCProtocolName);
|
||||
if (CorrectTypo(R, TUScope, 0) &&
|
||||
(PDecl = R.getAsSingle<ObjCProtocolDecl>())) {
|
||||
Diag(ProtocolId[i].second, diag::err_undeclared_protocol_suggest)
|
||||
<< ProtocolId[i].first << R.getLookupName();
|
||||
}
|
||||
}
|
||||
|
||||
if (!PDecl) {
|
||||
Diag(ProtocolId[i].second, diag::err_undeclared_protocol)
|
||||
<< ProtocolId[i].first;
|
||||
|
@ -568,7 +590,7 @@ ActOnStartCategoryInterface(SourceLocation AtInterfaceLoc,
|
|||
// FIXME: PushOnScopeChains?
|
||||
CurContext->addDecl(CDecl);
|
||||
|
||||
ObjCInterfaceDecl *IDecl = getObjCInterfaceDecl(ClassName);
|
||||
ObjCInterfaceDecl *IDecl = getObjCInterfaceDecl(ClassName, ClassLoc);
|
||||
/// Check that class of this category is already completely declared.
|
||||
if (!IDecl || IDecl->isForwardDecl()) {
|
||||
CDecl->setInvalidDecl();
|
||||
|
@ -616,7 +638,7 @@ Sema::DeclPtrTy Sema::ActOnStartCategoryImplementation(
|
|||
SourceLocation AtCatImplLoc,
|
||||
IdentifierInfo *ClassName, SourceLocation ClassLoc,
|
||||
IdentifierInfo *CatName, SourceLocation CatLoc) {
|
||||
ObjCInterfaceDecl *IDecl = getObjCInterfaceDecl(ClassName);
|
||||
ObjCInterfaceDecl *IDecl = getObjCInterfaceDecl(ClassName, ClassLoc);
|
||||
ObjCCategoryDecl *CatIDecl = 0;
|
||||
if (IDecl) {
|
||||
CatIDecl = IDecl->FindCategoryDeclaration(CatName);
|
||||
|
|
|
@ -1059,6 +1059,16 @@ Sema::OwningExprResult Sema::ActOnIdExpression(Scope *S,
|
|||
|
||||
assert(!R.empty() &&
|
||||
"DiagnoseEmptyLookup returned false but added no results");
|
||||
|
||||
// If we found an Objective-C instance variable, let
|
||||
// LookupInObjCMethod build the appropriate expression to
|
||||
// reference the ivar.
|
||||
if (ObjCIvarDecl *Ivar = R.getAsSingle<ObjCIvarDecl>()) {
|
||||
R.clear();
|
||||
OwningExprResult E(LookupInObjCMethod(R, S, Ivar->getIdentifier()));
|
||||
assert(E.isInvalid() || E.get());
|
||||
return move(E);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -2848,6 +2858,20 @@ Sema::LookupMemberExpr(LookupResult &R, Expr *&BaseExpr,
|
|||
ObjCInterfaceDecl *ClassDeclared;
|
||||
ObjCIvarDecl *IV = IDecl->lookupInstanceVariable(Member, ClassDeclared);
|
||||
|
||||
if (!IV) {
|
||||
// Attempt to correct for typos in ivar names.
|
||||
LookupResult Res(*this, R.getLookupName(), R.getNameLoc(),
|
||||
LookupMemberName);
|
||||
if (CorrectTypo(Res, 0, 0, IDecl) &&
|
||||
(IV = Res.getAsSingle<ObjCIvarDecl>())) {
|
||||
Diag(R.getNameLoc(),
|
||||
diag::err_typecheck_member_reference_ivar_suggest)
|
||||
<< IDecl->getDeclName() << MemberName << IV->getDeclName()
|
||||
<< CodeModificationHint::CreateReplacement(R.getNameLoc(),
|
||||
IV->getNameAsString());
|
||||
}
|
||||
}
|
||||
|
||||
if (IV) {
|
||||
// If the decl being referenced had an error, return an error for this
|
||||
// sub-expr without emitting another error, in order to avoid cascading
|
||||
|
@ -3014,6 +3038,20 @@ Sema::LookupMemberExpr(LookupResult &R, Expr *&BaseExpr,
|
|||
return Owned(new (Context) ObjCImplicitSetterGetterRefExpr(Getter, PType,
|
||||
Setter, MemberLoc, BaseExpr));
|
||||
}
|
||||
|
||||
// Attempt to correct for typos in property names.
|
||||
LookupResult Res(*this, R.getLookupName(), R.getNameLoc(),
|
||||
LookupOrdinaryName);
|
||||
if (CorrectTypo(Res, 0, 0, IFace, false, OPT) &&
|
||||
Res.getAsSingle<ObjCPropertyDecl>()) {
|
||||
Diag(R.getNameLoc(), diag::err_property_not_found_suggest)
|
||||
<< MemberName << BaseType << Res.getLookupName()
|
||||
<< CodeModificationHint::CreateReplacement(R.getNameLoc(),
|
||||
Res.getLookupName().getAsString());
|
||||
return LookupMemberExpr(Res, BaseExpr, IsArrow, OpLoc, SS,
|
||||
FirstQualifierInScope, ObjCImpDecl);
|
||||
}
|
||||
|
||||
return ExprError(Diag(MemberLoc, diag::err_property_not_found)
|
||||
<< MemberName << BaseType);
|
||||
}
|
||||
|
|
|
@ -287,7 +287,8 @@ Action::OwningExprResult Sema::ActOnClassPropertyRefExpr(
|
|||
SourceLocation &receiverNameLoc,
|
||||
SourceLocation &propertyNameLoc) {
|
||||
|
||||
ObjCInterfaceDecl *IFace = getObjCInterfaceDecl(&receiverName);
|
||||
IdentifierInfo *receiverNamePtr = &receiverName;
|
||||
ObjCInterfaceDecl *IFace = getObjCInterfaceDecl(receiverNamePtr);
|
||||
|
||||
// Search for a declared property first.
|
||||
|
||||
|
@ -400,7 +401,7 @@ Sema::ExprResult Sema::ActOnClassMessage(
|
|||
return Diag(receiverLoc, diag::err_undeclared_var_use) << receiverName;
|
||||
}
|
||||
} else
|
||||
ClassDecl = getObjCInterfaceDecl(receiverName);
|
||||
ClassDecl = getObjCInterfaceDecl(receiverName, receiverLoc);
|
||||
|
||||
// The following code allows for the following GCC-ism:
|
||||
//
|
||||
|
|
|
@ -1913,7 +1913,7 @@ static void LookupVisibleDecls(DeclContext *Ctx, LookupResult &Result,
|
|||
}
|
||||
}
|
||||
|
||||
// Traverse the contexts of inherited classes.
|
||||
// Traverse the contexts of inherited C++ classes.
|
||||
if (CXXRecordDecl *Record = dyn_cast<CXXRecordDecl>(Ctx)) {
|
||||
for (CXXRecordDecl::base_class_iterator B = Record->bases_begin(),
|
||||
BEnd = Record->bases_end();
|
||||
|
@ -1955,7 +1955,42 @@ static void LookupVisibleDecls(DeclContext *Ctx, LookupResult &Result,
|
|||
}
|
||||
}
|
||||
|
||||
// FIXME: Look into base classes in Objective-C!
|
||||
// Traverse the contexts of Objective-C classes.
|
||||
if (ObjCInterfaceDecl *IFace = dyn_cast<ObjCInterfaceDecl>(Ctx)) {
|
||||
// Traverse categories.
|
||||
for (ObjCCategoryDecl *Category = IFace->getCategoryList();
|
||||
Category; Category = Category->getNextClassCategory()) {
|
||||
ShadowContextRAII Shadow(Visited);
|
||||
LookupVisibleDecls(Category, Result, QualifiedNameLookup, Consumer,
|
||||
Visited);
|
||||
}
|
||||
|
||||
// Traverse protocols.
|
||||
for (ObjCInterfaceDecl::protocol_iterator I = IFace->protocol_begin(),
|
||||
E = IFace->protocol_end(); I != E; ++I) {
|
||||
ShadowContextRAII Shadow(Visited);
|
||||
LookupVisibleDecls(*I, Result, QualifiedNameLookup, Consumer, Visited);
|
||||
}
|
||||
|
||||
// Traverse the superclass.
|
||||
if (IFace->getSuperClass()) {
|
||||
ShadowContextRAII Shadow(Visited);
|
||||
LookupVisibleDecls(IFace->getSuperClass(), Result, QualifiedNameLookup,
|
||||
Consumer, Visited);
|
||||
}
|
||||
} else if (ObjCProtocolDecl *Protocol = dyn_cast<ObjCProtocolDecl>(Ctx)) {
|
||||
for (ObjCProtocolDecl::protocol_iterator I = Protocol->protocol_begin(),
|
||||
E = Protocol->protocol_end(); I != E; ++I) {
|
||||
ShadowContextRAII Shadow(Visited);
|
||||
LookupVisibleDecls(*I, Result, QualifiedNameLookup, Consumer, Visited);
|
||||
}
|
||||
} else if (ObjCCategoryDecl *Category = dyn_cast<ObjCCategoryDecl>(Ctx)) {
|
||||
for (ObjCCategoryDecl::protocol_iterator I = Category->protocol_begin(),
|
||||
E = Category->protocol_end(); I != E; ++I) {
|
||||
ShadowContextRAII Shadow(Visited);
|
||||
LookupVisibleDecls(*I, Result, QualifiedNameLookup, Consumer, Visited);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void LookupVisibleDecls(Scope *S, LookupResult &Result,
|
||||
|
@ -1975,6 +2010,22 @@ static void LookupVisibleDecls(Scope *S, LookupResult &Result,
|
|||
|
||||
for (DeclContext *Ctx = Entity; Ctx && Ctx->getPrimaryContext() != OuterCtx;
|
||||
Ctx = Ctx->getLookupParent()) {
|
||||
if (ObjCMethodDecl *Method = dyn_cast<ObjCMethodDecl>(Ctx)) {
|
||||
if (Method->isInstanceMethod()) {
|
||||
// For instance methods, look for ivars in the method's interface.
|
||||
LookupResult IvarResult(Result.getSema(), Result.getLookupName(),
|
||||
Result.getNameLoc(), Sema::LookupMemberName);
|
||||
ObjCInterfaceDecl *IFace = Method->getClassInterface();
|
||||
LookupVisibleDecls(IFace, IvarResult, /*QualifiedNameLookup=*/false,
|
||||
Consumer, Visited);
|
||||
}
|
||||
|
||||
// We've already performed all of the name lookup that we need
|
||||
// to for Objective-C methods; the next context will be the
|
||||
// outer scope.
|
||||
break;
|
||||
}
|
||||
|
||||
if (Ctx->isFunctionOrMethod())
|
||||
continue;
|
||||
|
||||
|
@ -2139,11 +2190,15 @@ void TypoCorrectionConsumer::FoundDecl(NamedDecl *ND, NamedDecl *Hiding) {
|
|||
/// \param EnteringContext whether we're entering the context described by
|
||||
/// the nested-name-specifier SS.
|
||||
///
|
||||
/// \param OPT when non-NULL, the search for visible declarations will
|
||||
/// also walk the protocols in the qualified interfaces of \p OPT.
|
||||
///
|
||||
/// \returns true if the typo was corrected, in which case the \p Res
|
||||
/// structure will contain the results of name lookup for the
|
||||
/// corrected name. Otherwise, returns false.
|
||||
bool Sema::CorrectTypo(LookupResult &Res, Scope *S, const CXXScopeSpec *SS,
|
||||
DeclContext *MemberContext, bool EnteringContext) {
|
||||
DeclContext *MemberContext, bool EnteringContext,
|
||||
const ObjCObjectPointerType *OPT) {
|
||||
// We only attempt to correct typos for identifiers.
|
||||
IdentifierInfo *Typo = Res.getLookupName().getAsIdentifierInfo();
|
||||
if (!Typo)
|
||||
|
@ -2160,9 +2215,17 @@ bool Sema::CorrectTypo(LookupResult &Res, Scope *S, const CXXScopeSpec *SS,
|
|||
return false;
|
||||
|
||||
TypoCorrectionConsumer Consumer(Typo);
|
||||
if (MemberContext)
|
||||
if (MemberContext) {
|
||||
LookupVisibleDecls(MemberContext, Res.getLookupKind(), Consumer);
|
||||
else if (SS && SS->isSet()) {
|
||||
|
||||
// Look in qualified interfaces.
|
||||
if (OPT) {
|
||||
for (ObjCObjectPointerType::qual_iterator
|
||||
I = OPT->qual_begin(), E = OPT->qual_end();
|
||||
I != E; ++I)
|
||||
LookupVisibleDecls(*I, Res.getLookupKind(), Consumer);
|
||||
}
|
||||
} else if (SS && SS->isSet()) {
|
||||
DeclContext *DC = computeDeclContext(*SS, EnteringContext);
|
||||
if (!DC)
|
||||
return false;
|
||||
|
@ -2179,10 +2242,22 @@ bool Sema::CorrectTypo(LookupResult &Res, Scope *S, const CXXScopeSpec *SS,
|
|||
// have overloads of that name, though).
|
||||
TypoCorrectionConsumer::iterator I = Consumer.begin();
|
||||
DeclarationName BestName = (*I)->getDeclName();
|
||||
|
||||
// If we've found an Objective-C ivar or property, don't perform
|
||||
// name lookup again; we'll just return the result directly.
|
||||
NamedDecl *FoundBest = 0;
|
||||
if (isa<ObjCIvarDecl>(*I) || isa<ObjCPropertyDecl>(*I))
|
||||
FoundBest = *I;
|
||||
++I;
|
||||
for(TypoCorrectionConsumer::iterator IEnd = Consumer.end(); I != IEnd; ++I) {
|
||||
if (BestName != (*I)->getDeclName())
|
||||
return false;
|
||||
|
||||
// FIXME: If there are both ivars and properties of the same name,
|
||||
// don't return both because the callee can't handle two
|
||||
// results. We really need to separate ivar lookup from property
|
||||
// lookup to avoid this problem.
|
||||
FoundBest = 0;
|
||||
}
|
||||
|
||||
// BestName is the closest viable name to what the user
|
||||
|
@ -2197,8 +2272,16 @@ bool Sema::CorrectTypo(LookupResult &Res, Scope *S, const CXXScopeSpec *SS,
|
|||
// success if we found something that was not ambiguous.
|
||||
Res.clear();
|
||||
Res.setLookupName(BestName);
|
||||
if (MemberContext)
|
||||
|
||||
// If we found an ivar or property, add that result; no further
|
||||
// lookup is required.
|
||||
if (FoundBest)
|
||||
Res.addDecl(FoundBest);
|
||||
// If we're looking into the context of a member, perform qualified
|
||||
// name lookup on the best name.
|
||||
else if (MemberContext)
|
||||
LookupQualifiedName(Res, MemberContext);
|
||||
// Perform lookup as if we had just parsed the best name.
|
||||
else
|
||||
LookupParsedName(Res, S, SS, /*AllowBuiltinCreation=*/false,
|
||||
EnteringContext);
|
||||
|
|
|
@ -1,9 +1,89 @@
|
|||
// RUN: %clang_cc1 -fsyntax-only -verify %s
|
||||
// FIXME: the test below isn't testing quite what we want...
|
||||
// RUN: %clang_cc1 -fsyntax-only -fixit -o - %s | %clang_cc1 -fsyntax-only -pedantic -Werror -x objective-c -
|
||||
|
||||
@interface NSString
|
||||
+ (int)method:(int)x;
|
||||
@end
|
||||
|
||||
void test() {
|
||||
// FIXME: not providing fix-its
|
||||
NSstring *str = @"A string"; // expected-error{{use of undeclared identifier 'NSstring'; did you mean 'NSString'?}}
|
||||
}
|
||||
|
||||
@protocol P1
|
||||
@property int *sprop;
|
||||
@end
|
||||
|
||||
@interface A
|
||||
{
|
||||
int his_ivar;
|
||||
float wibble;
|
||||
}
|
||||
|
||||
@property int his_prop;
|
||||
@end
|
||||
|
||||
@interface B : A <P1>
|
||||
{
|
||||
int her_ivar;
|
||||
}
|
||||
|
||||
@property int her_prop;
|
||||
- (void)inst_method1:(int)a;
|
||||
+ (void)class_method1;
|
||||
@end
|
||||
|
||||
@implementation A
|
||||
@synthesize his_prop = his_ivar;
|
||||
@end
|
||||
|
||||
@implementation B
|
||||
@synthesize her_prop = her_ivar;
|
||||
|
||||
-(void)inst_method1:(int)a {
|
||||
herivar = a; // expected-error{{use of undeclared identifier 'herivar'; did you mean 'her_ivar'?}}
|
||||
hisivar = a; // expected-error{{use of undeclared identifier 'hisivar'; did you mean 'his_ivar'?}}
|
||||
self->herivar = a; // expected-error{{'B' does not have a member named 'herivar'; did you mean 'her_ivar'?}}
|
||||
self->hisivar = a; // expected-error{{'B' does not have a member named 'hisivar'; did you mean 'his_ivar'?}}
|
||||
self.hisprop = 0; // expected-error{{property 'hisprop' not found on object of type 'B *'; did you mean 'his_prop'?}}
|
||||
self.herprop = 0; // expected-error{{property 'herprop' not found on object of type 'B *'; did you mean 'her_prop'?}}
|
||||
self.s_prop = 0; // expected-error{{property 's_prop' not found on object of type 'B *'; did you mean 'sprop'?}}
|
||||
}
|
||||
|
||||
+(void)class_method1 {
|
||||
}
|
||||
@end
|
||||
|
||||
void test_message_send(B* b) {
|
||||
// FIXME: Not providing fix-its
|
||||
[NSstring method:17]; // expected-error{{use of undeclared identifier 'NSstring'; did you mean 'NSString'?}}
|
||||
}
|
||||
|
||||
@interface Collide
|
||||
{
|
||||
@public
|
||||
int value;
|
||||
}
|
||||
|
||||
@property int value;
|
||||
@end
|
||||
|
||||
@implementation Collide
|
||||
@synthesize value = value;
|
||||
@end
|
||||
|
||||
void test2(Collide *a) {
|
||||
a.valu = 17; // expected-error{{property 'valu' not found on object of type 'Collide *'; did you mean 'value'?}}
|
||||
a->vale = 17; // expected-error{{'Collide' does not have a member named 'vale'; did you mean 'value'?}}
|
||||
}
|
||||
|
||||
@interface Derived : Collid // expected-error{{cannot find interface declaration for 'Collid', superclass of 'Derived'; did you mean 'Collide'?}}
|
||||
@end
|
||||
|
||||
@protocol NetworkSocket
|
||||
- (int)send:(void*)buffer bytes:(int)bytes;
|
||||
@end
|
||||
|
||||
@interface IPv8 <Network_Socket> // expected-error{{cannot find protocol declaration for 'Network_Socket'; did you mean 'NetworkSocket'?}}
|
||||
@end
|
||||
|
|
|
@ -29,7 +29,7 @@
|
|||
|
||||
@interface MyClass1 (Category) <p2, p3> @end // expected-warning {{cannot find protocol definition for 'p2'}}
|
||||
|
||||
@interface MyClass (Category) @end // expected-error {{cannot find interface declaration for 'MyClass'}}
|
||||
@interface UnknownClass (Category) @end // expected-error {{cannot find interface declaration for 'UnknownClass'}}
|
||||
|
||||
@class MyClass2;
|
||||
|
||||
|
|
|
@ -4,10 +4,10 @@
|
|||
+ (int) flashCache;
|
||||
@end
|
||||
|
||||
@interface Child (Categ) // expected-error {{cannot find interface declaration for 'Child'}}
|
||||
@interface Child (Categ) // expected-error {{cannot find interface declaration for 'Child'; did you mean '_Child'?}}
|
||||
+ (int) flushCache2;
|
||||
@end
|
||||
|
||||
@implementation Child (Categ) // expected-error {{cannot find interface declaration for 'Child'}}
|
||||
@implementation OtherChild (Categ) // expected-error {{cannot find interface declaration for 'OtherChild'}}
|
||||
+ (int) flushCache2 { [super flashCache]; } // expected-error {{no @interface declaration found in class messaging of 'flushCache2'}}
|
||||
@end
|
||||
|
|
Загрузка…
Ссылка в новой задаче