Author: rsmith Date: Mon Nov 2 19:19:56 2015 New Revision: 251875 URL: http://llvm.org/viewvc/llvm-project?rev=251875&view=rev Log: 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.
Modified: cfe/trunk/include/clang/Parse/Parser.h cfe/trunk/lib/Parse/ParseObjc.cpp cfe/trunk/test/SemaObjC/parameterized_classes.m Modified: cfe/trunk/include/clang/Parse/Parser.h URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Parse/Parser.h?rev=251875&r1=251874&r2=251875&view=diff ============================================================================== --- cfe/trunk/include/clang/Parse/Parser.h (original) +++ cfe/trunk/include/clang/Parse/Parser.h Mon Nov 2 19:19:56 2015 @@ -1253,12 +1253,12 @@ private: DeclGroupPtrTy ParseObjCAtClassDeclaration(SourceLocation atLoc); Decl *ParseObjCAtInterfaceDeclaration(SourceLocation AtLoc, ParsedAttributes &prefixAttrs); + class ObjCTypeParamListScope; ObjCTypeParamList *parseObjCTypeParamList(); ObjCTypeParamList *parseObjCTypeParamListOrProtocolRefs( - SourceLocation &lAngleLoc, - SmallVectorImpl<IdentifierLocPair> &protocolIdents, - SourceLocation &rAngleLoc, - bool mayBeProtocolList = true); + ObjCTypeParamListScope &Scope, SourceLocation &lAngleLoc, + SmallVectorImpl<IdentifierLocPair> &protocolIdents, + SourceLocation &rAngleLoc, bool mayBeProtocolList = true); void HelperActionsForIvarDeclarations(Decl *interfaceDecl, SourceLocation atLoc, BalancedDelimiterTracker &T, Modified: cfe/trunk/lib/Parse/ParseObjc.cpp URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Parse/ParseObjc.cpp?rev=251875&r1=251874&r2=251875&view=diff ============================================================================== --- cfe/trunk/lib/Parse/ParseObjc.cpp (original) +++ cfe/trunk/lib/Parse/ParseObjc.cpp Mon Nov 2 19:19:56 2015 @@ -94,6 +94,28 @@ Parser::DeclGroupPtrTy Parser::ParseObjC 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(Sour // 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::ParseObjCAtInterfaceDeclar SourceLocation LAngleLoc, EndProtoLoc; SmallVector<IdentifierLocPair, 8> 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::ParseObjCAtInterfaceDeclar ParseObjCInterfaceDeclList(tok::objc_not_keyword, CategoryType); - if (typeParameterList) - Actions.popObjCTypeParamList(getCurScope(), typeParameterList); - return CategoryType; } // Parse a class interface. @@ -370,9 +385,6 @@ Decl *Parser::ParseObjCAtInterfaceDeclar ParseObjCInterfaceDeclList(tok::objc_interface, ClsType); - if (typeParameterList) - Actions.popObjCTypeParamList(getCurScope(), typeParameterList); - return ClsType; } @@ -432,10 +444,9 @@ static void addContextSensitiveTypeNulla /// /// \param rAngleLoc The location of the ending '>'. ObjCTypeParamList *Parser::parseObjCTypeParamListOrProtocolRefs( - SourceLocation &lAngleLoc, - SmallVectorImpl<IdentifierLocPair> &protocolIdents, - SourceLocation &rAngleLoc, - bool mayBeProtocolList) { + ObjCTypeParamListScope &Scope, SourceLocation &lAngleLoc, + SmallVectorImpl<IdentifierLocPair> &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::parseObjCType 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::parseObjCType SourceLocation lAngleLoc; SmallVector<IdentifierLocPair, 1> 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::ParseObjCAtImplementationDeclara SourceLocation lAngleLoc, rAngleLoc; SmallVector<IdentifierLocPair, 8> 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()) { Modified: cfe/trunk/test/SemaObjC/parameterized_classes.m URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/SemaObjC/parameterized_classes.m?rev=251875&r1=251874&r2=251875&view=diff ============================================================================== --- cfe/trunk/test/SemaObjC/parameterized_classes.m (original) +++ cfe/trunk/test/SemaObjC/parameterized_classes.m Mon Nov 2 19:19:56 2015 @@ -174,6 +174,8 @@ __attribute__((objc_root_class)) @implementation PC1<T : id> (Cat2) // expected-error{{@implementation cannot have type parameters}} @end +typedef T undeclaredT; // expected-error{{unknown type name 'T'}} + // -------------------------------------------------------------------------- // Interfaces involving type parameters // -------------------------------------------------------------------------- _______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits