]> granicus.if.org Git - clang/commitdiff
[index] Fix issue with protocol name locations in conformance list of an ObjC class...
authorArgyrios Kyrtzidis <akyrtzi@gmail.com>
Wed, 9 Nov 2016 02:47:07 +0000 (02:47 +0000)
committerArgyrios Kyrtzidis <akyrtzi@gmail.com>
Wed, 9 Nov 2016 02:47:07 +0000 (02:47 +0000)
The ObjC class protocol list assumes there is an associated location for each protocol but no location is provided
when the protocol list comes from a typedef, and we end up with a buffer overflow when trying to get locations for the protocol names.

Fixes crash of rdar://28980278.

git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@286331 91177308-0d34-0410-b5e6-96231b3b80d8

include/clang/Sema/Sema.h
lib/Parse/ParseObjc.cpp
lib/Sema/SemaDeclObjC.cpp
test/Index/Core/index-source.m

index 0ad20123cc0057720bec2ddd40534fd66fe59a90..6c1059c05cdb9168a439db0d2e0a858918bcc4c7 100644 (file)
@@ -7470,6 +7470,7 @@ public:
                                        SourceRange SuperTypeArgsRange);
   
   void ActOnTypedefedProtocols(SmallVectorImpl<Decl *> &ProtocolRefs,
+                               SmallVectorImpl<SourceLocation> &ProtocolLocs,
                                IdentifierInfo *SuperName,
                                SourceLocation SuperLoc);
 
index 980ea77d84a40c2c749dbbbdd0af5c7fb80c3315..42081a29ad9723dcc7e0495316714081b312ac04 100644 (file)
@@ -369,7 +369,8 @@ Decl *Parser::ParseObjCAtInterfaceDeclaration(SourceLocation AtLoc,
   }
 
   if (Tok.isNot(tok::less))
-    Actions.ActOnTypedefedProtocols(protocols, superClassId, superClassLoc);
+    Actions.ActOnTypedefedProtocols(protocols, protocolLocs,
+                                    superClassId, superClassLoc);
   
   Decl *ClsType =
     Actions.ActOnStartClassInterface(getCurScope(), AtLoc, nameId, nameLoc, 
index 1b030801f23af529e38f797b607d46f1e55e6e1f..17e7141711ee49b7dfc7cfdd90186c81dc7a0b87 100644 (file)
@@ -1028,6 +1028,7 @@ ActOnStartClassInterface(Scope *S, SourceLocation AtInterfaceLoc,
 /// typedef'ed use for a qualified super class and adds them to the list
 /// of the protocols.
 void Sema::ActOnTypedefedProtocols(SmallVectorImpl<Decl *> &ProtocolRefs,
+                                  SmallVectorImpl<SourceLocation> &ProtocolLocs,
                                    IdentifierInfo *SuperName,
                                    SourceLocation SuperLoc) {
   if (!SuperName)
@@ -1040,8 +1041,14 @@ void Sema::ActOnTypedefedProtocols(SmallVectorImpl<Decl *> &ProtocolRefs,
   if (const TypedefNameDecl *TDecl = dyn_cast_or_null<TypedefNameDecl>(IDecl)) {
     QualType T = TDecl->getUnderlyingType();
     if (T->isObjCObjectType())
-      if (const ObjCObjectType *OPT = T->getAs<ObjCObjectType>())
+      if (const ObjCObjectType *OPT = T->getAs<ObjCObjectType>()) {
         ProtocolRefs.append(OPT->qual_begin(), OPT->qual_end());
+        // FIXME: Consider whether this should be an invalid loc since the loc
+        // is not actually pointing to a protocol name reference but to the
+        // typedef reference. Note that the base class name loc is also pointing
+        // at the typedef.
+        ProtocolLocs.append(OPT->getNumProtocols(), SuperLoc);
+      }
   }
 }
 
index 554378ea3cf788bd6031b045aa1e027f1048cc19..fc1b6232cfe85449ce9da7976d2851244443b45e 100644 (file)
@@ -129,3 +129,23 @@ extern int setjmp(jmp_buf);
 // CHECK: [[@LINE+1]]:12 | extension/ObjC | <no-name> | <no-usr> | <no-cgname> | Decl | rel: 0
 @interface NonExistent()
 @end
+
+@interface MyGenCls<ObjectType> : Base
+@end
+
+@protocol MyEnumerating
+@end
+
+// CHECK: [[@LINE+4]]:41 | type-alias/C | MyEnumerator | c:index-source.m@T@MyEnumerator | <no-cgname> | Def | rel: 0
+// CHECK: [[@LINE+3]]:26 | protocol/ObjC | MyEnumerating | c:objc(pl)MyEnumerating | <no-cgname> | Ref | rel: 0
+// CHECK: [[@LINE+2]]:9 | class/ObjC | MyGenCls | c:objc(cs)MyGenCls | _OBJC_CLASS_$_MyGenCls | Ref | rel: 0
+// CHECK: [[@LINE+1]]:18 | class/ObjC | Base | c:objc(cs)Base | _OBJC_CLASS_$_Base | Ref | rel: 0
+typedef MyGenCls<Base *><MyEnumerating> MyEnumerator;
+
+// CHECK: [[@LINE+5]]:12 | class/ObjC | PermanentEnumerator | c:objc(cs)PermanentEnumerator | _OBJC_CLASS_$_PermanentEnumerator | Decl | rel: 0
+// CHECK: [[@LINE+4]]:34 | class/ObjC | MyGenCls | c:objc(cs)MyGenCls | _OBJC_CLASS_$_MyGenCls | Ref,RelBase | rel: 1
+// CHECK-NEXT: RelBase | PermanentEnumerator | c:objc(cs)PermanentEnumerator
+// CHECK: [[@LINE+2]]:34 | protocol/ObjC | MyEnumerating | c:objc(pl)MyEnumerating | <no-cgname> | Ref,RelBase | rel: 1
+// CHECK-NEXT: RelBase | PermanentEnumerator | c:objc(cs)PermanentEnumerator
+@interface PermanentEnumerator : MyEnumerator
+@end