From: Richard Smith Date: Tue, 3 Nov 2015 01:19:56 +0000 (+0000) Subject: Switch to using an explicit scope object to ensure we don't forget to pop ObjC X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=6e89fddd0bfb676385bd9bdaec2617e42dac6438;p=clang Switch to using an explicit scope object to ensure we don't forget to pop ObjC type parameters off the scope, and fix the cases where we failed to do so. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@251875 91177308-0d34-0410-b5e6-96231b3b80d8 --- diff --git a/include/clang/Parse/Parser.h b/include/clang/Parse/Parser.h index 66990f6368..67a3b7de54 100644 --- a/include/clang/Parse/Parser.h +++ b/include/clang/Parse/Parser.h @@ -1253,12 +1253,12 @@ private: DeclGroupPtrTy ParseObjCAtClassDeclaration(SourceLocation atLoc); Decl *ParseObjCAtInterfaceDeclaration(SourceLocation AtLoc, ParsedAttributes &prefixAttrs); + class ObjCTypeParamListScope; ObjCTypeParamList *parseObjCTypeParamList(); ObjCTypeParamList *parseObjCTypeParamListOrProtocolRefs( - SourceLocation &lAngleLoc, - SmallVectorImpl &protocolIdents, - SourceLocation &rAngleLoc, - bool mayBeProtocolList = true); + ObjCTypeParamListScope &Scope, SourceLocation &lAngleLoc, + SmallVectorImpl &protocolIdents, + SourceLocation &rAngleLoc, bool mayBeProtocolList = true); void HelperActionsForIvarDeclarations(Decl *interfaceDecl, SourceLocation atLoc, BalancedDelimiterTracker &T, diff --git a/lib/Parse/ParseObjc.cpp b/lib/Parse/ParseObjc.cpp index 763bcc185a..4ac8f42f13 100644 --- a/lib/Parse/ParseObjc.cpp +++ b/lib/Parse/ParseObjc.cpp @@ -94,6 +94,28 @@ Parser::DeclGroupPtrTy Parser::ParseObjCAtDirectives() { return Actions.ConvertDeclToDeclGroup(SingleDecl); } +/// Class to handle popping type parameters when leaving the scope. +class Parser::ObjCTypeParamListScope { + Sema &Actions; + Scope *S; + ObjCTypeParamList *Params; +public: + ObjCTypeParamListScope(Sema &Actions, Scope *S) + : Actions(Actions), S(S), Params(nullptr) {} + ~ObjCTypeParamListScope() { + leave(); + } + void enter(ObjCTypeParamList *P) { + assert(!Params); + Params = P; + } + void leave() { + if (Params) + Actions.popObjCTypeParamList(S, Params); + Params = nullptr; + } +}; + /// /// objc-class-declaration: /// '@' 'class' objc-class-forward-decl (',' objc-class-forward-decl)* ';' @@ -121,11 +143,8 @@ Parser::ParseObjCAtClassDeclaration(SourceLocation atLoc) { // Parse the optional objc-type-parameter-list. ObjCTypeParamList *TypeParams = nullptr; - if (Tok.is(tok::less)) { + if (Tok.is(tok::less)) TypeParams = parseObjCTypeParamList(); - if (TypeParams) - Actions.popObjCTypeParamList(getCurScope(), TypeParams); - } ClassTypeParams.push_back(TypeParams); if (!TryConsumeToken(tok::comma)) break; @@ -221,11 +240,10 @@ Decl *Parser::ParseObjCAtInterfaceDeclaration(SourceLocation AtLoc, SourceLocation LAngleLoc, EndProtoLoc; SmallVector ProtocolIdents; ObjCTypeParamList *typeParameterList = nullptr; - if (Tok.is(tok::less)) { - typeParameterList = parseObjCTypeParamListOrProtocolRefs(LAngleLoc, - ProtocolIdents, - EndProtoLoc); - } + ObjCTypeParamListScope typeParamScope(Actions, getCurScope()); + if (Tok.is(tok::less)) + typeParameterList = parseObjCTypeParamListOrProtocolRefs( + typeParamScope, LAngleLoc, ProtocolIdents, EndProtoLoc); if (Tok.is(tok::l_paren) && !isKnownToBeTypeSpecifier(GetLookAheadToken(1))) { // we have a category. @@ -286,9 +304,6 @@ Decl *Parser::ParseObjCAtInterfaceDeclaration(SourceLocation AtLoc, ParseObjCInterfaceDeclList(tok::objc_not_keyword, CategoryType); - if (typeParameterList) - Actions.popObjCTypeParamList(getCurScope(), typeParameterList); - return CategoryType; } // Parse a class interface. @@ -370,9 +385,6 @@ Decl *Parser::ParseObjCAtInterfaceDeclaration(SourceLocation AtLoc, ParseObjCInterfaceDeclList(tok::objc_interface, ClsType); - if (typeParameterList) - Actions.popObjCTypeParamList(getCurScope(), typeParameterList); - return ClsType; } @@ -432,10 +444,9 @@ static void addContextSensitiveTypeNullability(Parser &P, /// /// \param rAngleLoc The location of the ending '>'. ObjCTypeParamList *Parser::parseObjCTypeParamListOrProtocolRefs( - SourceLocation &lAngleLoc, - SmallVectorImpl &protocolIdents, - SourceLocation &rAngleLoc, - bool mayBeProtocolList) { + ObjCTypeParamListScope &Scope, SourceLocation &lAngleLoc, + SmallVectorImpl &protocolIdents, + SourceLocation &rAngleLoc, bool mayBeProtocolList) { assert(Tok.is(tok::less) && "Not at the beginning of a type parameter list"); // Within the type parameter list, don't treat '>' as an operator. @@ -580,12 +591,13 @@ ObjCTypeParamList *Parser::parseObjCTypeParamListOrProtocolRefs( makeProtocolIdentsIntoTypeParameters(); } - // Form the type parameter list. + // Form the type parameter list and enter its scope. ObjCTypeParamList *list = Actions.actOnObjCTypeParamList( getCurScope(), lAngleLoc, typeParams, rAngleLoc); + Scope.enter(list); // Clear out the angle locations; they're used by the caller to indicate // whether there are any protocol references. @@ -599,8 +611,10 @@ ObjCTypeParamList *Parser::parseObjCTypeParamList() { SourceLocation lAngleLoc; SmallVector protocolIdents; SourceLocation rAngleLoc; - return parseObjCTypeParamListOrProtocolRefs(lAngleLoc, protocolIdents, - rAngleLoc, + + ObjCTypeParamListScope Scope(Actions, getCurScope()); + return parseObjCTypeParamListOrProtocolRefs(Scope, lAngleLoc, protocolIdents, + rAngleLoc, /*mayBeProtocolList=*/false); } @@ -2110,8 +2124,9 @@ Parser::ParseObjCAtImplementationDeclaration(SourceLocation AtLoc) { SourceLocation lAngleLoc, rAngleLoc; SmallVector protocolIdents; SourceLocation diagLoc = Tok.getLocation(); - if (parseObjCTypeParamListOrProtocolRefs(lAngleLoc, protocolIdents, - rAngleLoc)) { + ObjCTypeParamListScope typeParamScope(Actions, getCurScope()); + if (parseObjCTypeParamListOrProtocolRefs(typeParamScope, lAngleLoc, + protocolIdents, rAngleLoc)) { Diag(diagLoc, diag::err_objc_parameterized_implementation) << SourceRange(diagLoc, PrevTokLocation); } else if (lAngleLoc.isValid()) { diff --git a/test/SemaObjC/parameterized_classes.m b/test/SemaObjC/parameterized_classes.m index 644fe3a329..7f380a1054 100644 --- a/test/SemaObjC/parameterized_classes.m +++ b/test/SemaObjC/parameterized_classes.m @@ -174,6 +174,8 @@ __attribute__((objc_root_class)) @implementation PC1 (Cat2) // expected-error{{@implementation cannot have type parameters}} @end +typedef T undeclaredT; // expected-error{{unknown type name 'T'}} + // -------------------------------------------------------------------------- // Interfaces involving type parameters // --------------------------------------------------------------------------