[cfe-commits] r117081 - in /cfe/trunk: include/clang/Parse/Parser.h lib/Parse/ParseDecl.cpp lib/Parse/ParseExprCXX.cpp lib/Parse/ParseObjc.cpp lib/Parse/ParseTentative.cpp test/SemaObjCXX/protocol-lookup.mm
Douglas Gregor
dgregor at apple.com
Thu Oct 21 16:17:00 PDT 2010
Author: dgregor
Date: Thu Oct 21 18:17:00 2010
New Revision: 117081
URL: http://llvm.org/viewvc/llvm-project?rev=117081&view=rev
Log:
Teach the C++ simple-type-specifier parser and tentative parses about
protocol-qualified types such as id<Protocol>.
Modified:
cfe/trunk/include/clang/Parse/Parser.h
cfe/trunk/lib/Parse/ParseDecl.cpp
cfe/trunk/lib/Parse/ParseExprCXX.cpp
cfe/trunk/lib/Parse/ParseObjc.cpp
cfe/trunk/lib/Parse/ParseTentative.cpp
cfe/trunk/test/SemaObjCXX/protocol-lookup.mm
Modified: cfe/trunk/include/clang/Parse/Parser.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Parse/Parser.h?rev=117081&r1=117080&r2=117081&view=diff
==============================================================================
--- cfe/trunk/include/clang/Parse/Parser.h (original)
+++ cfe/trunk/include/clang/Parse/Parser.h Thu Oct 21 18:17:00 2010
@@ -948,6 +948,7 @@
bool WarnOnDeclarations,
SourceLocation &LAngleLoc,
SourceLocation &EndProtoLoc);
+ void ParseObjCProtocolQualifiers(DeclSpec &DS);
void ParseObjCInterfaceDeclList(Decl *interfaceDecl,
tok::ObjCKeywordKind contextKey);
Decl *ParseObjCAtProtocolDeclaration(SourceLocation atLoc,
@@ -1423,6 +1424,7 @@
TPResult TryParseDeclarationSpecifier();
TPResult TryParseSimpleDeclaration();
TPResult TryParseTypeofSpecifier();
+ TPResult TryParseProtocolQualifiers();
TPResult TryParseInitDeclaratorList();
TPResult TryParseDeclarator(bool mayBeAbstract, bool mayHaveIdentifier=true);
TPResult TryParseParameterDeclarationClause();
Modified: cfe/trunk/lib/Parse/ParseDecl.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Parse/ParseDecl.cpp?rev=117081&r1=117080&r2=117081&view=diff
==============================================================================
--- cfe/trunk/lib/Parse/ParseDecl.cpp (original)
+++ cfe/trunk/lib/Parse/ParseDecl.cpp Thu Oct 21 18:17:00 2010
@@ -1093,20 +1093,10 @@
// Objective-C supports syntax of the form 'id<proto1,proto2>' where 'id'
// is a specific typedef and 'itf<proto1,proto2>' where 'itf' is an
- // Objective-C interface. If we don't have Objective-C or a '<', this is
- // just a normal reference to a typedef name.
- if (!Tok.is(tok::less) || !getLang().ObjC1)
- continue;
-
- SourceLocation LAngleLoc, EndProtoLoc;
- llvm::SmallVector<Decl *, 8> ProtocolDecl;
- llvm::SmallVector<SourceLocation, 8> ProtocolLocs;
- ParseObjCProtocolReferences(ProtocolDecl, ProtocolLocs, false,
- LAngleLoc, EndProtoLoc);
- DS.setProtocolQualifiers(ProtocolDecl.data(), ProtocolDecl.size(),
- ProtocolLocs.data(), LAngleLoc);
-
- DS.SetRangeEnd(EndProtoLoc);
+ // Objective-C interface.
+ if (Tok.is(tok::less) && getLang().ObjC1)
+ ParseObjCProtocolQualifiers(DS);
+
continue;
}
@@ -1163,21 +1153,10 @@
// Objective-C supports syntax of the form 'id<proto1,proto2>' where 'id'
// is a specific typedef and 'itf<proto1,proto2>' where 'itf' is an
- // Objective-C interface. If we don't have Objective-C or a '<', this is
- // just a normal reference to a typedef name.
- if (!Tok.is(tok::less) || !getLang().ObjC1)
- continue;
-
- SourceLocation LAngleLoc, EndProtoLoc;
- llvm::SmallVector<Decl *, 8> ProtocolDecl;
- llvm::SmallVector<SourceLocation, 8> ProtocolLocs;
- ParseObjCProtocolReferences(ProtocolDecl, ProtocolLocs, false,
- LAngleLoc, EndProtoLoc);
- DS.setProtocolQualifiers(ProtocolDecl.data(), ProtocolDecl.size(),
- ProtocolLocs.data(), LAngleLoc);
-
- DS.SetRangeEnd(EndProtoLoc);
-
+ // Objective-C interface.
+ if (Tok.is(tok::less) && getLang().ObjC1)
+ ParseObjCProtocolQualifiers(DS);
+
// Need to support trailing type qualifiers (e.g. "id<p> const").
// If a type specifier follows, it will be diagnosed elsewhere.
continue;
@@ -1445,23 +1424,15 @@
if (DS.hasTypeSpecifier() || !getLang().ObjC1)
goto DoneWithDeclSpec;
- {
- SourceLocation LAngleLoc, EndProtoLoc;
- llvm::SmallVector<Decl *, 8> ProtocolDecl;
- llvm::SmallVector<SourceLocation, 8> ProtocolLocs;
- ParseObjCProtocolReferences(ProtocolDecl, ProtocolLocs, false,
- LAngleLoc, EndProtoLoc);
- DS.setProtocolQualifiers(ProtocolDecl.data(), ProtocolDecl.size(),
- ProtocolLocs.data(), LAngleLoc);
- DS.SetRangeEnd(EndProtoLoc);
-
- Diag(Loc, diag::warn_objc_protocol_qualifier_missing_id)
- << FixItHint::CreateInsertion(Loc, "id")
- << SourceRange(Loc, EndProtoLoc);
- // Need to support trailing type qualifiers (e.g. "id<p> const").
- // If a type specifier follows, it will be diagnosed elsewhere.
- continue;
- }
+ ParseObjCProtocolQualifiers(DS);
+
+ Diag(Loc, diag::warn_objc_protocol_qualifier_missing_id)
+ << FixItHint::CreateInsertion(Loc, "id")
+ << SourceRange(Loc, DS.getSourceRange().getEnd());
+
+ // Need to support trailing type qualifiers (e.g. "id<p> const").
+ // If a type specifier follows, it will be diagnosed elsewhere.
+ continue;
}
// If the specifier wasn't legal, issue a diagnostic.
if (isInvalid) {
@@ -1576,18 +1547,9 @@
// is a specific typedef and 'itf<proto1,proto2>' where 'itf' is an
// Objective-C interface. If we don't have Objective-C or a '<', this is
// just a normal reference to a typedef name.
- if (!Tok.is(tok::less) || !getLang().ObjC1)
- return true;
-
- SourceLocation LAngleLoc, EndProtoLoc;
- llvm::SmallVector<Decl *, 8> ProtocolDecl;
- llvm::SmallVector<SourceLocation, 8> ProtocolLocs;
- ParseObjCProtocolReferences(ProtocolDecl, ProtocolLocs, false,
- LAngleLoc, EndProtoLoc);
- DS.setProtocolQualifiers(ProtocolDecl.data(), ProtocolDecl.size(),
- ProtocolLocs.data(), LAngleLoc);
-
- DS.SetRangeEnd(EndProtoLoc);
+ if (Tok.is(tok::less) && getLang().ObjC1)
+ ParseObjCProtocolQualifiers(DS);
+
return true;
}
Modified: cfe/trunk/lib/Parse/ParseExprCXX.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Parse/ParseExprCXX.cpp?rev=117081&r1=117080&r2=117081&view=diff
==============================================================================
--- cfe/trunk/lib/Parse/ParseExprCXX.cpp (original)
+++ cfe/trunk/lib/Parse/ParseExprCXX.cpp Thu Oct 21 18:17:00 2010
@@ -914,7 +914,19 @@
case tok::annot_typename: {
DS.SetTypeSpecType(DeclSpec::TST_typename, Loc, PrevSpec, DiagID,
getTypeAnnotation(Tok));
- break;
+
+ DS.SetRangeEnd(Tok.getAnnotationEndLoc());
+ ConsumeToken();
+
+ // Objective-C supports syntax of the form 'id<proto1,proto2>' where 'id'
+ // is a specific typedef and 'itf<proto1,proto2>' where 'itf' is an
+ // Objective-C interface. If we don't have Objective-C or a '<', this is
+ // just a normal reference to a typedef name.
+ if (Tok.is(tok::less) && getLang().ObjC1)
+ ParseObjCProtocolQualifiers(DS);
+
+ DS.Finish(Diags, PP);
+ return;
}
// builtin types
Modified: cfe/trunk/lib/Parse/ParseObjc.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Parse/ParseObjc.cpp?rev=117081&r1=117080&r2=117081&view=diff
==============================================================================
--- cfe/trunk/lib/Parse/ParseObjc.cpp (original)
+++ cfe/trunk/lib/Parse/ParseObjc.cpp Thu Oct 21 18:17:00 2010
@@ -1039,6 +1039,23 @@
return false;
}
+/// \brief Parse the Objective-C protocol qualifiers that follow a typename
+/// in a decl-specifier-seq, starting at the '<'.
+void Parser::ParseObjCProtocolQualifiers(DeclSpec &DS) {
+ assert(Tok.is(tok::less) && "Protocol qualifiers start with '<'");
+ assert(getLang().ObjC1 && "Protocol qualifiers only exist in Objective-C");
+ SourceLocation LAngleLoc, EndProtoLoc;
+ llvm::SmallVector<Decl *, 8> ProtocolDecl;
+ llvm::SmallVector<SourceLocation, 8> ProtocolLocs;
+ ParseObjCProtocolReferences(ProtocolDecl, ProtocolLocs, false,
+ LAngleLoc, EndProtoLoc);
+ DS.setProtocolQualifiers(ProtocolDecl.data(), ProtocolDecl.size(),
+ ProtocolLocs.data(), LAngleLoc);
+ if (EndProtoLoc.isValid())
+ DS.SetRangeEnd(EndProtoLoc);
+}
+
+
/// objc-class-instance-variables:
/// '{' objc-instance-variable-decl-list[opt] '}'
///
Modified: cfe/trunk/lib/Parse/ParseTentative.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Parse/ParseTentative.cpp?rev=117081&r1=117080&r2=117081&view=diff
==============================================================================
--- cfe/trunk/lib/Parse/ParseTentative.cpp (original)
+++ cfe/trunk/lib/Parse/ParseTentative.cpp Thu Oct 21 18:17:00 2010
@@ -139,9 +139,13 @@
if (Tok.is(tok::kw_typeof))
TryParseTypeofSpecifier();
- else
+ else {
ConsumeToken();
-
+
+ if (getLang().ObjC1 && Tok.is(tok::less))
+ TryParseProtocolQualifiers();
+ }
+
assert(Tok.is(tok::l_paren) && "Expected '('");
TPResult TPR = TryParseInitDeclaratorList();
@@ -242,8 +246,12 @@
// type-specifier-seq
if (Tok.is(tok::kw_typeof))
TryParseTypeofSpecifier();
- else
+ else {
ConsumeToken();
+
+ if (getLang().ObjC1 && Tok.is(tok::less))
+ TryParseProtocolQualifiers();
+ }
assert(Tok.is(tok::l_paren) && "Expected '('");
// declarator
@@ -313,8 +321,13 @@
// type-specifier-seq
if (Tok.is(tok::kw_typeof))
TryParseTypeofSpecifier();
- else
+ else {
ConsumeToken();
+
+ if (getLang().ObjC1 && Tok.is(tok::less))
+ TryParseProtocolQualifiers();
+ }
+
assert(Tok.is(tok::l_paren) && "Expected '('");
// declarator
@@ -808,6 +821,28 @@
// simple-type-specifier:
+ case tok::annot_typename:
+ case_typename:
+ // In Objective-C, we might have a protocol-qualified type.
+ if (getLang().ObjC1 && NextToken().is(tok::less)) {
+ // Tentatively parse the
+ TentativeParsingAction PA(*this);
+ ConsumeToken(); // The type token
+
+ TPResult TPR = TryParseProtocolQualifiers();
+ bool isFollowedByParen = Tok.is(tok::l_paren);
+
+ PA.Revert();
+
+ if (TPR == TPResult::Error())
+ return TPResult::Error();
+
+ if (isFollowedByParen)
+ return TPResult::Ambiguous();
+
+ return TPResult::True();
+ }
+
case tok::kw_char:
case tok::kw_wchar_t:
case tok::kw_char16_t:
@@ -821,8 +856,6 @@
case tok::kw_float:
case tok::kw_double:
case tok::kw_void:
- case tok::annot_typename:
- case_typename:
if (NextToken().is(tok::l_paren))
return TPResult::Ambiguous();
@@ -878,6 +911,30 @@
return TPResult::Ambiguous();
}
+/// [ObjC] protocol-qualifiers:
+//// '<' identifier-list '>'
+Parser::TPResult Parser::TryParseProtocolQualifiers() {
+ assert(Tok.is(tok::less) && "Expected '<' for qualifier list");
+ ConsumeToken();
+ do {
+ if (Tok.isNot(tok::identifier))
+ return TPResult::Error();
+ ConsumeToken();
+
+ if (Tok.is(tok::comma)) {
+ ConsumeToken();
+ continue;
+ }
+
+ if (Tok.is(tok::greater)) {
+ ConsumeToken();
+ return TPResult::Ambiguous();
+ }
+ } while (false);
+
+ return TPResult::Error();
+}
+
Parser::TPResult Parser::TryParseDeclarationSpecifier() {
TPResult TPR = isCXXDeclarationSpecifier();
if (TPR != TPResult::Ambiguous())
@@ -885,8 +942,12 @@
if (Tok.is(tok::kw_typeof))
TryParseTypeofSpecifier();
- else
+ else {
ConsumeToken();
+
+ if (getLang().ObjC1 && Tok.is(tok::less))
+ TryParseProtocolQualifiers();
+ }
assert(Tok.is(tok::l_paren) && "Expected '('!");
return TPResult::Ambiguous();
Modified: cfe/trunk/test/SemaObjCXX/protocol-lookup.mm
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/SemaObjCXX/protocol-lookup.mm?rev=117081&r1=117080&r2=117081&view=diff
==============================================================================
--- cfe/trunk/test/SemaObjCXX/protocol-lookup.mm (original)
+++ cfe/trunk/test/SemaObjCXX/protocol-lookup.mm Thu Oct 21 18:17:00 2010
@@ -49,3 +49,8 @@
@end
+void rdar8575095(id a) {
+ [id<NSObject>(a) retain];
+ id<NSObject> x(id<NSObject>(0));
+ id<NSObject> x2(id<NSObject>(y)); // expected-warning{{parentheses were disambiguated as a function declarator}}
+}
More information about the cfe-commits
mailing list