]> granicus.if.org Git - clang/commitdiff
Switch to using an explicit scope object to ensure we don't forget to pop ObjC
authorRichard Smith <richard-llvm@metafoo.co.uk>
Tue, 3 Nov 2015 01:19:56 +0000 (01:19 +0000)
committerRichard Smith <richard-llvm@metafoo.co.uk>
Tue, 3 Nov 2015 01:19:56 +0000 (01:19 +0000)
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

include/clang/Parse/Parser.h
lib/Parse/ParseObjc.cpp
test/SemaObjC/parameterized_classes.m

index 66990f6368c427465bb5d6067f35383a01dde0ab..67a3b7de54e63ad51b5ff5f8637543221745f5d6 100644 (file)
@@ -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,
index 763bcc185aad7ad678d5833b160db752bfd86678..4ac8f42f1361acd8e19eedb2947a0356a8e8c0e5 100644 (file)
@@ -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<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::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<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::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<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::ParseObjCAtImplementationDeclaration(SourceLocation AtLoc) {
     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()) {
index 644fe3a329af36b221000a5eb63b6211a15d4966..7f380a10547aef871ca376e77a75f0b272d5fae5 100644 (file)
@@ -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
 // --------------------------------------------------------------------------