]> granicus.if.org Git - clang/commitdiff
Objective-C. Warn if protocol used in an @protocol
authorFariborz Jahanian <fjahanian@apple.com>
Fri, 25 Jul 2014 19:45:01 +0000 (19:45 +0000)
committerFariborz Jahanian <fjahanian@apple.com>
Fri, 25 Jul 2014 19:45:01 +0000 (19:45 +0000)
expression is a forward declaration as this results
in undefined behavior. rdar://17768630

git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@213968 91177308-0d34-0410-b5e6-96231b3b80d8

include/clang/Basic/DiagnosticGroups.td
include/clang/Basic/DiagnosticSemaKinds.td
lib/Sema/SemaExpr.cpp
lib/Sema/SemaExprObjC.cpp
test/SemaObjC/protocol-expr-1.m
test/SemaObjC/protocol-expr-neg-1.m

index b66cffeda190f15f95abf39f61d43470e2f1f607..deead56322bdc2b5c039d895b1ea544b07535b0d 100644 (file)
@@ -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">;
index 5499344bb722b9dcdd5c6425c3b59cccd6fd6e38..366f6d27666d97f40503704168e1adc69a6b76db 100644 (file)
@@ -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">;
index 163973bd55f781f5eee50ed0592de6d7d055a9ac..c2c886c04ea4fc7f83380c2e48be75574f0b7a4f 100644 (file)
@@ -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);
index 500233203c79546053627a4057a8c330087c063c..fb2c02b77fe843755e86c9d5655a818335e77c6e 100644 (file)
@@ -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())
index 94a0d9e3e8b5955a47ef07cf0ad2feb13f74c4e2..5ff3db474c75fcfe0e19489c54f847e54a12ff4c 100644 (file)
@@ -1,7 +1,7 @@
 // RUN: %clang_cc1 -fsyntax-only -verify %s
 // expected-no-diagnostics
 
-@protocol fproto;
+@protocol fproto @end
 
 @protocol p1 
 @end
index 58ac8c0ca322345564216aae3c84d3dd45789a4f..aed56c016b08c7e5e657ce9561794a02a7cf3008 100644 (file)
@@ -2,7 +2,7 @@
 
 @class Protocol;
 
-@protocol fproto;
+@protocol fproto; // expected-note {{'fproto' declared here}}
 
 @protocol p1 
 @end
 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}}
+}