From: Chris Lattner Date: Sat, 26 Jul 2008 01:18:38 +0000 (+0000) Subject: Fix hte next wave of problems with protocol qualified ID: X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=3bd934a624660db940612ca3c5dfd7128ede79e5;p=clang Fix hte next wave of problems with protocol qualified ID: 1) reject stuff like "id short" and " short". 2) set the declspec range correctly 3) only parse protocol qualifiers when in objc mode. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@54086 91177308-0d34-0410-b5e6-96231b3b80d8 --- diff --git a/lib/Parse/ParseDecl.cpp b/lib/Parse/ParseDecl.cpp index c9e64f4c22..98c2d897d5 100644 --- a/lib/Parse/ParseDecl.cpp +++ b/lib/Parse/ParseDecl.cpp @@ -395,47 +395,59 @@ void Parser::ParseDeclarationSpecifiers(DeclSpec &DS) { SourceLocation Loc = Tok.getLocation(); switch (Tok.getKind()) { - // typedef-name - case tok::identifier: - // This identifier can only be a typedef name if we haven't already seen - // a type-specifier. Without this check we misparse: - // typedef int X; struct Y { short X; }; as 'short int'. - if (!DS.hasTypeSpecifier()) { - // It has to be available as a typedef too! - if (void *TypeRep = Actions.isTypeName(*Tok.getIdentifierInfo(), - CurScope)) { - isInvalid = DS.SetTypeSpecType(DeclSpec::TST_typedef, Loc, PrevSpec, - TypeRep); - if (isInvalid) - break; - // FIXME: restrict this to "id" and ObjC classnames. - DS.SetRangeEnd(Tok.getLocation()); - ConsumeToken(); // The identifier - if (Tok.is(tok::less)) { - SourceLocation endProtoLoc; - llvm::SmallVector ProtocolRefs; - ParseObjCProtocolReferences(ProtocolRefs, endProtoLoc); - - // FIXME: New'ing this here seems wrong, why not have the action do - // it? - llvm::SmallVector *ProtocolDecl = - new llvm::SmallVector; - DS.setProtocolQualifiers(ProtocolDecl); - Actions.FindProtocolDeclaration(Loc, - &ProtocolRefs[0], ProtocolRefs.size(), - *ProtocolDecl); - } - continue; - } - } - // FALL THROUGH. default: DoneWithDeclSpec: // If this is not a declaration specifier token, we're done reading decl // specifiers. First verify that DeclSpec's are consistent. DS.Finish(Diags, PP.getSourceManager(), getLang()); return; - + + // typedef-name + case tok::identifier: { + // This identifier can only be a typedef name if we haven't already seen + // a type-specifier. Without this check we misparse: + // typedef int X; struct Y { short X; }; as 'short int'. + if (DS.hasTypeSpecifier()) + goto DoneWithDeclSpec; + + // It has to be available as a typedef too! + void *TypeRep = Actions.isTypeName(*Tok.getIdentifierInfo(), CurScope); + if (TypeRep == 0) + goto DoneWithDeclSpec; + + isInvalid = DS.SetTypeSpecType(DeclSpec::TST_typedef, Loc, PrevSpec, + TypeRep); + if (isInvalid) + break; + + DS.SetRangeEnd(Tok.getLocation()); + ConsumeToken(); // The identifier + + // Objective-C supports syntax of the form 'id' where 'id' + // is a specific typedef and 'itf' 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 EndProtoLoc; + llvm::SmallVector ProtocolRefs; + ParseObjCProtocolReferences(ProtocolRefs, EndProtoLoc); + + // FIXME: New'ing this here seems wrong, why not have the action do it? + llvm::SmallVector *ProtocolDecl = + new llvm::SmallVector; + DS.setProtocolQualifiers(ProtocolDecl); + Actions.FindProtocolDeclaration(Loc, + &ProtocolRefs[0], ProtocolRefs.size(), + *ProtocolDecl); + + DS.SetRangeEnd(EndProtoLoc); + + // Do not allow any other declspecs after the protocol qualifier list + // "short" is not allowed. + goto DoneWithDeclSpec; + } // GNU attributes support. case tok::kw___attribute: DS.AddAttributes(ParseAttributes()); @@ -554,10 +566,10 @@ void Parser::ParseDeclarationSpecifiers(DeclSpec &DS) { break; case tok::less: - // GCC supports types like "" as a synonym for + // GCC ObjC supports types like "" as a synonym for // "id". This is hopelessly old fashioned and dangerous, // but we support it. - if (DS.hasTypeSpecifier()) + if (DS.hasTypeSpecifier() || !getLang().ObjC1) goto DoneWithDeclSpec; { @@ -570,9 +582,13 @@ void Parser::ParseDeclarationSpecifiers(DeclSpec &DS) { Actions.FindProtocolDeclaration(Loc, &ProtocolRefs[0], ProtocolRefs.size(), *ProtocolDecl); + DS.SetRangeEnd(EndProtoLoc); + Diag(Loc, diag::warn_objc_protocol_qualifier_missing_id, SourceRange(Loc, EndProtoLoc)); - continue; + // Do not allow any other declspecs after the protocol qualifier list + // "short" is not allowed. + goto DoneWithDeclSpec; } } // If the specifier combination wasn't legal, issue a diagnostic.