forked from OSchip/llvm-project
Objective-C. Warn if protocol used in an @protocol
expression is a forward declaration as this results in undefined behavior. rdar://17768630 llvm-svn: 213968
This commit is contained in:
parent
e5b6e0d231
commit
a57d91c2ae
|
@ -428,6 +428,7 @@ def DeallocInCategory:DiagGroup<"dealloc-in-category">;
|
|||
def SelectorTypeMismatch : DiagGroup<"selector-type-mismatch">;
|
||||
def Selector : DiagGroup<"selector", [SelectorTypeMismatch]>;
|
||||
def Protocol : DiagGroup<"protocol">;
|
||||
def AtProtocol : DiagGroup<"at-protocol">;
|
||||
def SuperSubClassMismatch : DiagGroup<"super-class-method-mismatch">;
|
||||
def OverridingMethodMismatch : DiagGroup<"overriding-method-mismatch">;
|
||||
def VariadicMacros : DiagGroup<"variadic-macros">;
|
||||
|
|
|
@ -566,6 +566,8 @@ def err_protocol_has_circular_dependency : Error<
|
|||
"protocol has circular dependency">;
|
||||
def err_undeclared_protocol : Error<"cannot find protocol declaration for %0">;
|
||||
def warn_undef_protocolref : Warning<"cannot find protocol definition for %0">;
|
||||
def warn_atprotocol_protocol : Warning<
|
||||
"@protocol is using a forward protocol declaration of %0">, InGroup<AtProtocol>;
|
||||
def warn_readonly_property : Warning<
|
||||
"attribute 'readonly' of property %0 restricts attribute "
|
||||
"'readwrite' of property inherited from %1">;
|
||||
|
|
|
@ -6756,6 +6756,15 @@ Sema::CheckSingleAssignmentConstraints(QualType LHSType, ExprResult &RHS,
|
|||
return Incompatible;
|
||||
}
|
||||
|
||||
Expr *PRE = RHS.get()->IgnoreParenCasts();
|
||||
if (ObjCProtocolExpr *OPE = dyn_cast<ObjCProtocolExpr>(PRE)) {
|
||||
ObjCProtocolDecl *PDecl = OPE->getProtocol();
|
||||
if (PDecl && !PDecl->hasDefinition()) {
|
||||
Diag(PRE->getExprLoc(), diag::warn_atprotocol_protocol) << PDecl->getName();
|
||||
Diag(PDecl->getLocation(), diag::note_entity_declared_at) << PDecl;
|
||||
}
|
||||
}
|
||||
|
||||
CastKind Kind = CK_Invalid;
|
||||
Sema::AssignConvertType result =
|
||||
CheckAssignmentConstraints(LHSType, RHS, Kind);
|
||||
|
|
|
@ -1105,6 +1105,8 @@ ExprResult Sema::ParseObjCProtocolExpression(IdentifierInfo *ProtocolId,
|
|||
Diag(ProtoLoc, diag::err_undeclared_protocol) << ProtocolId;
|
||||
return true;
|
||||
}
|
||||
if (PDecl->hasDefinition())
|
||||
PDecl = PDecl->getDefinition();
|
||||
|
||||
QualType Ty = Context.getObjCProtoType();
|
||||
if (Ty.isNull())
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
// RUN: %clang_cc1 -fsyntax-only -verify %s
|
||||
// expected-no-diagnostics
|
||||
|
||||
@protocol fproto;
|
||||
@protocol fproto @end
|
||||
|
||||
@protocol p1
|
||||
@end
|
||||
|
|
|
@ -2,7 +2,7 @@
|
|||
|
||||
@class Protocol;
|
||||
|
||||
@protocol fproto;
|
||||
@protocol fproto; // expected-note {{'fproto' declared here}}
|
||||
|
||||
@protocol p1
|
||||
@end
|
||||
|
@ -12,8 +12,23 @@
|
|||
int main()
|
||||
{
|
||||
Protocol *proto = @protocol(p1);
|
||||
Protocol *fproto = @protocol(fproto);
|
||||
Protocol *fproto = @protocol(fproto); // expected-warning {{@protocol is using a forward protocol declaration of fproto}}
|
||||
Protocol *pp = @protocol(i); // expected-error {{cannot find protocol declaration for 'i'}}
|
||||
Protocol *p1p = @protocol(cl); // expected-error {{cannot find protocol declaration for 'cl'}}
|
||||
}
|
||||
|
||||
// rdar://17768630
|
||||
@protocol SuperProtocol; // expected-note {{'SuperProtocol' declared here}}
|
||||
@protocol TestProtocol; // expected-note {{'TestProtocol' declared here}}
|
||||
|
||||
@interface I
|
||||
- (int) conformsToProtocol : (Protocol *)protocl;
|
||||
@end
|
||||
|
||||
int doesConform(id foo) {
|
||||
return [foo conformsToProtocol:@protocol(TestProtocol)]; // expected-warning {{@protocol is using a forward protocol declaration of TestProtocol}}
|
||||
}
|
||||
|
||||
int doesConformSuper(id foo) {
|
||||
return [foo conformsToProtocol:@protocol(SuperProtocol)]; // expected-warning {{@protocol is using a forward protocol declaration of SuperProtocol}}
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue