summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorFariborz Jahanian <fjahanian@apple.com>2014-07-25 19:45:01 +0000
committerFariborz Jahanian <fjahanian@apple.com>2014-07-25 19:45:01 +0000
commita57d91c2aede9cb8c5e43ab86cfaebe4e43f0161 (patch)
tree8e3c6ec2d1f652c077adfccb29dd52b7f481465c
parente5b6e0d2313cdd5b906bfeaf3968ff7fdd6438db (diff)
downloadbcm5719-llvm-a57d91c2aede9cb8c5e43ab86cfaebe4e43f0161.tar.gz
bcm5719-llvm-a57d91c2aede9cb8c5e43ab86cfaebe4e43f0161.zip
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
-rw-r--r--clang/include/clang/Basic/DiagnosticGroups.td1
-rw-r--r--clang/include/clang/Basic/DiagnosticSemaKinds.td2
-rw-r--r--clang/lib/Sema/SemaExpr.cpp9
-rw-r--r--clang/lib/Sema/SemaExprObjC.cpp2
-rw-r--r--clang/test/SemaObjC/protocol-expr-1.m2
-rw-r--r--clang/test/SemaObjC/protocol-expr-neg-1.m19
6 files changed, 32 insertions, 3 deletions
diff --git a/clang/include/clang/Basic/DiagnosticGroups.td b/clang/include/clang/Basic/DiagnosticGroups.td
index b66cffeda19..deead56322b 100644
--- a/clang/include/clang/Basic/DiagnosticGroups.td
+++ b/clang/include/clang/Basic/DiagnosticGroups.td
@@ -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">;
diff --git a/clang/include/clang/Basic/DiagnosticSemaKinds.td b/clang/include/clang/Basic/DiagnosticSemaKinds.td
index 5499344bb72..366f6d27666 100644
--- a/clang/include/clang/Basic/DiagnosticSemaKinds.td
+++ b/clang/include/clang/Basic/DiagnosticSemaKinds.td
@@ -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">;
diff --git a/clang/lib/Sema/SemaExpr.cpp b/clang/lib/Sema/SemaExpr.cpp
index 163973bd55f..c2c886c04ea 100644
--- a/clang/lib/Sema/SemaExpr.cpp
+++ b/clang/lib/Sema/SemaExpr.cpp
@@ -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);
diff --git a/clang/lib/Sema/SemaExprObjC.cpp b/clang/lib/Sema/SemaExprObjC.cpp
index 500233203c7..fb2c02b77fe 100644
--- a/clang/lib/Sema/SemaExprObjC.cpp
+++ b/clang/lib/Sema/SemaExprObjC.cpp
@@ -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())
diff --git a/clang/test/SemaObjC/protocol-expr-1.m b/clang/test/SemaObjC/protocol-expr-1.m
index 94a0d9e3e8b..5ff3db474c7 100644
--- a/clang/test/SemaObjC/protocol-expr-1.m
+++ b/clang/test/SemaObjC/protocol-expr-1.m
@@ -1,7 +1,7 @@
// RUN: %clang_cc1 -fsyntax-only -verify %s
// expected-no-diagnostics
-@protocol fproto;
+@protocol fproto @end
@protocol p1
@end
diff --git a/clang/test/SemaObjC/protocol-expr-neg-1.m b/clang/test/SemaObjC/protocol-expr-neg-1.m
index 58ac8c0ca32..aed56c016b0 100644
--- a/clang/test/SemaObjC/protocol-expr-neg-1.m
+++ b/clang/test/SemaObjC/protocol-expr-neg-1.m
@@ -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}}
+}
OpenPOWER on IntegriCloud