Merge remote-tracking branch 'origin/swift-3.1-branch' into stable
* origin/swift-3.1-branch:
[SemaObjC] Be more strict while parsing type arguments and protocols
diff --git a/lib/Parse/ParseDecl.cpp b/lib/Parse/ParseDecl.cpp
index bc510d0..ebf30a7 100644
--- a/lib/Parse/ParseDecl.cpp
+++ b/lib/Parse/ParseDecl.cpp
@@ -5908,7 +5908,8 @@
// To handle this, we check to see if the token after the first
// identifier is a "," or ")". Only then do we parse it as an
// identifier list.
- && (NextToken().is(tok::comma) || NextToken().is(tok::r_paren));
+ && (!Tok.is(tok::eof) &&
+ (NextToken().is(tok::comma) || NextToken().is(tok::r_paren)));
}
/// ParseFunctionDeclaratorIdentifierList - While parsing a function declarator
diff --git a/lib/Parse/ParseObjc.cpp b/lib/Parse/ParseObjc.cpp
index 403688a..a126d8b 100644
--- a/lib/Parse/ParseObjc.cpp
+++ b/lib/Parse/ParseObjc.cpp
@@ -346,9 +346,11 @@
protocols, protocolLocs, EndProtoLoc,
/*consumeLastToken=*/true,
/*warnOnIncompleteProtocols=*/true);
+ if (Tok.is(tok::eof))
+ return nullptr;
}
}
-
+
// Next, we need to check for any protocol references.
if (LAngleLoc.isValid()) {
if (!ProtocolIdents.empty()) {
@@ -1816,6 +1818,8 @@
protocolRAngleLoc,
consumeLastToken,
/*warnOnIncompleteProtocols=*/false);
+ if (Tok.is(tok::eof)) // Nothing else to do here...
+ return;
// An Objective-C object pointer followed by type arguments
// can then be followed again by a set of protocol references, e.g.,
@@ -1864,6 +1868,9 @@
protocols, protocolLocs,
protocolRAngleLoc, consumeLastToken);
+ if (Tok.is(tok::eof))
+ return true; // Invalid type result.
+
// Compute the location of the last token.
if (consumeLastToken)
endLoc = PrevTokLocation;
diff --git a/lib/Parse/Parser.cpp b/lib/Parse/Parser.cpp
index f442bd7..2d35ad6 100644
--- a/lib/Parse/Parser.cpp
+++ b/lib/Parse/Parser.cpp
@@ -1495,6 +1495,8 @@
NewEndLoc);
if (NewType.isUsable())
Ty = NewType.get();
+ else if (Tok.is(tok::eof)) // Nothing to do here, bail out...
+ return ANK_Error;
}
Tok.setKind(tok::annot_typename);
@@ -1726,6 +1728,8 @@
NewEndLoc);
if (NewType.isUsable())
Ty = NewType.get();
+ else if (Tok.is(tok::eof)) // Nothing to do here, bail out...
+ return false;
}
// This is a typename. Replace the current token in-place with an
diff --git a/test/SemaObjC/crash-on-type-args-protocols.m b/test/SemaObjC/crash-on-type-args-protocols.m
new file mode 100644
index 0000000..f7d8478
--- /dev/null
+++ b/test/SemaObjC/crash-on-type-args-protocols.m
@@ -0,0 +1,40 @@
+// RUN: %clang_cc1 -DFIRST -fsyntax-only -verify %s
+// RUN: %clang_cc1 -DSECOND -fsyntax-only -verify %s
+// RUN: %clang_cc1 -DTHIRD -fsyntax-only -verify %s
+// RUN: %clang_cc1 -DFOURTH -fsyntax-only -verify %s
+
+@protocol P;
+@interface NSObject
+@end
+@protocol X
+@end
+@interface X : NSObject <X>
+@end
+
+@class A;
+
+#ifdef FIRST
+id<X> F1(id<[P> v) { // expected-error {{expected a type}} // expected-error {{use of undeclared identifier 'P'}} // expected-error {{use of undeclared identifier 'v'}} // expected-note {{to match this '('}}
+ return 0;
+}
+#endif
+
+#ifdef SECOND
+id<X> F2(id<P[X> v) { // expected-error {{unknown type name 'P'}} // expected-error {{unexpected interface name 'X': expected expression}} // expected-error {{use of undeclared identifier 'v'}} // expected-note {{to match this '('}}
+ return 0;
+}
+#endif
+
+#ifdef THIRD
+id<X> F3(id<P, P *[> v) { // expected-error {{unknown type name 'P'}} // expected-error {{expected expression}} // expected-error {{use of undeclared identifier 'v'}} // expected-note {{to match this '('}}
+ return 0;
+}
+#endif
+
+#ifdef FOURTH
+id<X> F4(id<P, P *(> v { // expected-error {{unknown type name 'P'}} // expected-error {{expected ')'}} // expected-note {{to match this '('}} // expected-note {{to match this '('}}
+ return 0;
+}
+#endif
+
+// expected-error {{expected '>'}} // expected-error {{expected parameter declarator}} // expected-error {{expected ')'}} // expected-error {{expected function body after function declarator}}