diff options
Diffstat (limited to 'lib/Parse/Parser.cpp')
-rw-r--r-- | lib/Parse/Parser.cpp | 55 |
1 files changed, 48 insertions, 7 deletions
diff --git a/lib/Parse/Parser.cpp b/lib/Parse/Parser.cpp index e32df95548d9..e76f767786f0 100644 --- a/lib/Parse/Parser.cpp +++ b/lib/Parse/Parser.cpp @@ -1413,14 +1413,35 @@ Parser::TryAnnotateName(bool IsAddressOfOperand, // It's not something we know about. Leave it unannotated. break; - case Sema::NC_Type: - Tok.setKind(tok::annot_typename); - setTypeAnnotation(Tok, Classification.getType()); - Tok.setAnnotationEndLoc(NameLoc); + case Sema::NC_Type: { + SourceLocation BeginLoc = NameLoc; if (SS.isNotEmpty()) - Tok.setLocation(SS.getBeginLoc()); + BeginLoc = SS.getBeginLoc(); + + /// An Objective-C object type followed by '<' is a specialization of + /// a parameterized class type or a protocol-qualified type. + ParsedType Ty = Classification.getType(); + if (getLangOpts().ObjC1 && NextToken().is(tok::less) && + (Ty.get()->isObjCObjectType() || + Ty.get()->isObjCObjectPointerType())) { + // Consume the name. + SourceLocation IdentifierLoc = ConsumeToken(); + SourceLocation NewEndLoc; + TypeResult NewType + = parseObjCTypeArgsAndProtocolQualifiers(IdentifierLoc, Ty, + /*consumeLastToken=*/false, + NewEndLoc); + if (NewType.isUsable()) + Ty = NewType.get(); + } + + Tok.setKind(tok::annot_typename); + setTypeAnnotation(Tok, Ty); + Tok.setAnnotationEndLoc(Tok.getLocation()); + Tok.setLocation(BeginLoc); PP.AnnotateCachedTokens(Tok); return ANK_Success; + } case Sema::NC_Expression: Tok.setKind(tok::annot_primary_expr); @@ -1627,13 +1648,33 @@ bool Parser::TryAnnotateTypeOrScopeTokenAfterScopeSpec(bool EnteringContext, // A FixIt was applied as a result of typo correction if (CorrectedII) Tok.setIdentifierInfo(CorrectedII); + + SourceLocation BeginLoc = Tok.getLocation(); + if (SS.isNotEmpty()) // it was a C++ qualified type name. + BeginLoc = SS.getBeginLoc(); + + /// An Objective-C object type followed by '<' is a specialization of + /// a parameterized class type or a protocol-qualified type. + if (getLangOpts().ObjC1 && NextToken().is(tok::less) && + (Ty.get()->isObjCObjectType() || + Ty.get()->isObjCObjectPointerType())) { + // Consume the name. + SourceLocation IdentifierLoc = ConsumeToken(); + SourceLocation NewEndLoc; + TypeResult NewType + = parseObjCTypeArgsAndProtocolQualifiers(IdentifierLoc, Ty, + /*consumeLastToken=*/false, + NewEndLoc); + if (NewType.isUsable()) + Ty = NewType.get(); + } + // This is a typename. Replace the current token in-place with an // annotation type token. Tok.setKind(tok::annot_typename); setTypeAnnotation(Tok, Ty); Tok.setAnnotationEndLoc(Tok.getLocation()); - if (SS.isNotEmpty()) // it was a C++ qualified type name. - Tok.setLocation(SS.getBeginLoc()); + Tok.setLocation(BeginLoc); // In case the tokens were cached, have Preprocessor replace // them with the annotation token. |