summaryrefslogtreecommitdiffstats
path: root/clang/lib/Parse/ParseObjc.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'clang/lib/Parse/ParseObjc.cpp')
-rw-r--r--clang/lib/Parse/ParseObjc.cpp54
1 files changed, 54 insertions, 0 deletions
diff --git a/clang/lib/Parse/ParseObjc.cpp b/clang/lib/Parse/ParseObjc.cpp
index 0e4574056b0..669c0653df8 100644
--- a/clang/lib/Parse/ParseObjc.cpp
+++ b/clang/lib/Parse/ParseObjc.cpp
@@ -438,8 +438,10 @@ ObjCTypeParamList *Parser::parseObjCTypeParamListOrProtocolRefs(
// type parameters.
SmallVector<Decl *, 4> typeParams;
auto makeProtocolIdentsIntoTypeParameters = [&]() {
+ unsigned index = 0;
for (const auto &pair : protocolIdents) {
DeclResult typeParam = Actions.actOnObjCTypeParam(getCurScope(),
+ index++,
pair.first,
pair.second,
SourceLocation(),
@@ -502,6 +504,7 @@ ObjCTypeParamList *Parser::parseObjCTypeParamListOrProtocolRefs(
// Create the type parameter.
DeclResult typeParam = Actions.actOnObjCTypeParam(getCurScope(),
+ typeParams.size(),
paramName,
paramLoc,
colonLoc,
@@ -1675,6 +1678,45 @@ void Parser::ParseObjCTypeArgsOrProtocolQualifiers(
DS.setObjCTypeArgs(lAngleLoc, typeArgs, rAngleLoc);
}
+void Parser::ParseObjCTypeArgsAndProtocolQualifiers(DeclSpec &DS) {
+ assert(Tok.is(tok::less));
+
+ ParseObjCTypeArgsOrProtocolQualifiers(DS,
+ /*warnOnIncompleteProtocols=*/false);
+
+ // An Objective-C object pointer followed by type arguments
+ // can then be followed again by a set of protocol references, e.g.,
+ // \c NSArray<NSView><NSTextDelegate>
+ if (Tok.is(tok::less)) {
+ if (DS.getProtocolQualifiers()) {
+ Diag(Tok, diag::err_objc_type_args_after_protocols)
+ << SourceRange(DS.getProtocolLAngleLoc(), DS.getLocEnd());
+ SkipUntil(tok::greater, tok::greatergreater);
+ } else {
+ ParseObjCProtocolQualifiers(DS);
+ }
+ }
+}
+
+TypeResult Parser::ParseObjCTypeArgsAndProtocolQualifiers(SourceLocation loc,
+ ParsedType type) {
+ assert(Tok.is(tok::less));
+
+ // Create declaration specifiers and set the type as the type specifier.
+ DeclSpec DS(AttrFactory);
+ const char *prevSpec = nullptr;
+ unsigned diagID;
+ DS.SetTypeSpecType(TST_typename, loc, prevSpec, diagID, type,
+ Actions.getASTContext().getPrintingPolicy());
+
+ // Parse type arguments and protocol qualifiers.
+ ParseObjCTypeArgsAndProtocolQualifiers(DS);
+
+ // Form a declarator to turn this into a type.
+ Declarator D(DS, Declarator::TypeNameContext);
+ return Actions.ActOnTypeName(getCurScope(), D);
+}
+
void Parser::HelperActionsForIvarDeclarations(Decl *interfaceDecl, SourceLocation atLoc,
BalancedDelimiterTracker &T,
SmallVectorImpl<Decl *> &AllIvarDecls,
@@ -2829,6 +2871,18 @@ ExprResult Parser::ParseObjCMessageExpression() {
ConsumeToken(); // the type name
+ // Parse type arguments and protocol qualifiers.
+ if (Tok.is(tok::less)) {
+ TypeResult NewReceiverType
+ = ParseObjCTypeArgsAndProtocolQualifiers(NameLoc, ReceiverType);
+ if (!NewReceiverType.isUsable()) {
+ SkipUntil(tok::r_square, StopAtSemi);
+ return ExprError();
+ }
+
+ ReceiverType = NewReceiverType.get();
+ }
+
return ParseObjCMessageExpressionBody(LBracLoc, SourceLocation(),
ReceiverType, nullptr);
OpenPOWER on IntegriCloud