aboutsummaryrefslogtreecommitdiff
path: root/clang/lib/Parse/Parser.cpp
diff options
context:
space:
mode:
authorDouglas Gregor <dgregor@apple.com>2015-07-07 03:58:14 +0000
committerDouglas Gregor <dgregor@apple.com>2015-07-07 03:58:14 +0000
commit9bda6cff20276f67c02d0d2814ef44c2d62ecd89 (patch)
tree42cdccf290e6507ad745f4b0a838e76a6f8e32d0 /clang/lib/Parse/Parser.cpp
parentc5e07f5c115ed486f57db957447086c1b0023385 (diff)
downloadllvm-9bda6cff20276f67c02d0d2814ef44c2d62ecd89.zip
llvm-9bda6cff20276f67c02d0d2814ef44c2d62ecd89.tar.gz
llvm-9bda6cff20276f67c02d0d2814ef44c2d62ecd89.tar.bz2
C++ support for Objective-C lightweight generics.
Teach C++'s tentative parsing to handle specializations of Objective-C class types (e.g., NSArray<NSString *>) as well as Objective-C protocol qualifiers (id<NSCopying>) by extending type-annotation tokens to handle this case. As part of this, remove Objective-C protocol qualifiers from the declaration specifiers, which never really made sense: instead, provide Sema entry points to make them part of the type annotation token. Among other things, this properly diagnoses bogus types such as "<NSCopying> id" which should have been written as "id <NSCopying>". Implements template instantiation support for, e.g., NSArray<T>* in C++. Note that parameterized classes are not templates in the C++ sense, so that cannot (for example) be used as a template argument for a template template parameter. Part of rdar://problem/6294649. llvm-svn: 241545
Diffstat (limited to 'clang/lib/Parse/Parser.cpp')
-rw-r--r--clang/lib/Parse/Parser.cpp55
1 files changed, 48 insertions, 7 deletions
diff --git a/clang/lib/Parse/Parser.cpp b/clang/lib/Parse/Parser.cpp
index e32df95..e76f767 100644
--- a/clang/lib/Parse/Parser.cpp
+++ b/clang/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.