blob: 2749100e14a29c0edfbb6888ce4cf1d6dfb4c0bb [file] [log] [blame]
Guy Benyei11169dd2012-12-18 14:30:41 +00001//===--- NSAPI.cpp - NSFoundation APIs ------------------------------------===//
2//
3// The LLVM Compiler Infrastructure
4//
5// This file is distributed under the University of Illinois Open Source
6// License. See LICENSE.TXT for details.
7//
8//===----------------------------------------------------------------------===//
9
10#include "clang/AST/NSAPI.h"
11#include "clang/AST/ASTContext.h"
12#include "clang/AST/Expr.h"
Fariborz Jahanian35ee87d2014-10-06 23:50:37 +000013#include "llvm/ADT/StringSwitch.h"
Guy Benyei11169dd2012-12-18 14:30:41 +000014
15using namespace clang;
16
17NSAPI::NSAPI(ASTContext &ctx)
Craig Topper36250ad2014-05-12 05:36:57 +000018 : Ctx(ctx), ClassIds(), BOOLId(nullptr), NSIntegerId(nullptr),
19 NSUIntegerId(nullptr), NSASCIIStringEncodingId(nullptr),
20 NSUTF8StringEncodingId(nullptr) {}
Guy Benyei11169dd2012-12-18 14:30:41 +000021
22IdentifierInfo *NSAPI::getNSClassId(NSClassIdKindKind K) const {
23 static const char *ClassName[NumClassIds] = {
24 "NSObject",
25 "NSString",
26 "NSArray",
27 "NSMutableArray",
28 "NSDictionary",
29 "NSMutableDictionary",
Alex Denisove1d882c2015-03-04 17:55:52 +000030 "NSNumber",
31 "NSMutableSet",
32 "NSCountedSet",
33 "NSMutableOrderedSet"
Guy Benyei11169dd2012-12-18 14:30:41 +000034 };
35
36 if (!ClassIds[K])
37 return (ClassIds[K] = &Ctx.Idents.get(ClassName[K]));
38
39 return ClassIds[K];
40}
41
42Selector NSAPI::getNSStringSelector(NSStringMethodKind MK) const {
43 if (NSStringSelectors[MK].isNull()) {
44 Selector Sel;
45 switch (MK) {
46 case NSStr_stringWithString:
47 Sel = Ctx.Selectors.getUnarySelector(&Ctx.Idents.get("stringWithString"));
48 break;
49 case NSStr_stringWithUTF8String:
50 Sel = Ctx.Selectors.getUnarySelector(
51 &Ctx.Idents.get("stringWithUTF8String"));
52 break;
Fariborz Jahanianbe7bf722014-08-25 20:22:25 +000053 case NSStr_initWithUTF8String:
54 Sel = Ctx.Selectors.getUnarySelector(
55 &Ctx.Idents.get("initWithUTF8String"));
56 break;
Guy Benyei11169dd2012-12-18 14:30:41 +000057 case NSStr_stringWithCStringEncoding: {
58 IdentifierInfo *KeyIdents[] = {
59 &Ctx.Idents.get("stringWithCString"),
60 &Ctx.Idents.get("encoding")
61 };
62 Sel = Ctx.Selectors.getSelector(2, KeyIdents);
63 break;
64 }
65 case NSStr_stringWithCString:
66 Sel= Ctx.Selectors.getUnarySelector(&Ctx.Idents.get("stringWithCString"));
67 break;
68 case NSStr_initWithString:
69 Sel = Ctx.Selectors.getUnarySelector(&Ctx.Idents.get("initWithString"));
70 break;
71 }
72 return (NSStringSelectors[MK] = Sel);
73 }
74
75 return NSStringSelectors[MK];
76}
77
David Blaikie05785d12013-02-20 22:23:23 +000078Optional<NSAPI::NSStringMethodKind>
Guy Benyei11169dd2012-12-18 14:30:41 +000079NSAPI::getNSStringMethodKind(Selector Sel) const {
80 for (unsigned i = 0; i != NumNSStringMethods; ++i) {
81 NSStringMethodKind MK = NSStringMethodKind(i);
82 if (Sel == getNSStringSelector(MK))
83 return MK;
84 }
85
David Blaikie7a30dc52013-02-21 01:47:18 +000086 return None;
Guy Benyei11169dd2012-12-18 14:30:41 +000087}
88
89Selector NSAPI::getNSArraySelector(NSArrayMethodKind MK) const {
90 if (NSArraySelectors[MK].isNull()) {
91 Selector Sel;
92 switch (MK) {
93 case NSArr_array:
94 Sel = Ctx.Selectors.getNullarySelector(&Ctx.Idents.get("array"));
95 break;
96 case NSArr_arrayWithArray:
97 Sel = Ctx.Selectors.getUnarySelector(&Ctx.Idents.get("arrayWithArray"));
98 break;
99 case NSArr_arrayWithObject:
100 Sel = Ctx.Selectors.getUnarySelector(&Ctx.Idents.get("arrayWithObject"));
101 break;
102 case NSArr_arrayWithObjects:
103 Sel = Ctx.Selectors.getUnarySelector(&Ctx.Idents.get("arrayWithObjects"));
104 break;
105 case NSArr_arrayWithObjectsCount: {
106 IdentifierInfo *KeyIdents[] = {
107 &Ctx.Idents.get("arrayWithObjects"),
108 &Ctx.Idents.get("count")
109 };
110 Sel = Ctx.Selectors.getSelector(2, KeyIdents);
111 break;
112 }
113 case NSArr_initWithArray:
114 Sel = Ctx.Selectors.getUnarySelector(&Ctx.Idents.get("initWithArray"));
115 break;
116 case NSArr_initWithObjects:
117 Sel = Ctx.Selectors.getUnarySelector(&Ctx.Idents.get("initWithObjects"));
118 break;
119 case NSArr_objectAtIndex:
120 Sel = Ctx.Selectors.getUnarySelector(&Ctx.Idents.get("objectAtIndex"));
121 break;
122 case NSMutableArr_replaceObjectAtIndex: {
123 IdentifierInfo *KeyIdents[] = {
124 &Ctx.Idents.get("replaceObjectAtIndex"),
125 &Ctx.Idents.get("withObject")
126 };
127 Sel = Ctx.Selectors.getSelector(2, KeyIdents);
128 break;
129 }
Alex Denisove1d882c2015-03-04 17:55:52 +0000130 case NSMutableArr_addObject:
131 Sel = Ctx.Selectors.getUnarySelector(&Ctx.Idents.get("addObject"));
132 break;
133 case NSMutableArr_insertObjectAtIndex: {
134 IdentifierInfo *KeyIdents[] = {
135 &Ctx.Idents.get("insertObject"),
136 &Ctx.Idents.get("atIndex")
137 };
138 Sel = Ctx.Selectors.getSelector(2, KeyIdents);
139 break;
140 }
141 case NSMutableArr_setObjectAtIndexedSubscript: {
142 IdentifierInfo *KeyIdents[] = {
143 &Ctx.Idents.get("setObject"),
144 &Ctx.Idents.get("atIndexedSubscript")
145 };
146 Sel = Ctx.Selectors.getSelector(2, KeyIdents);
147 break;
148 }
Guy Benyei11169dd2012-12-18 14:30:41 +0000149 }
150 return (NSArraySelectors[MK] = Sel);
151 }
152
153 return NSArraySelectors[MK];
154}
155
David Blaikie05785d12013-02-20 22:23:23 +0000156Optional<NSAPI::NSArrayMethodKind> NSAPI::getNSArrayMethodKind(Selector Sel) {
Guy Benyei11169dd2012-12-18 14:30:41 +0000157 for (unsigned i = 0; i != NumNSArrayMethods; ++i) {
158 NSArrayMethodKind MK = NSArrayMethodKind(i);
159 if (Sel == getNSArraySelector(MK))
160 return MK;
161 }
162
David Blaikie7a30dc52013-02-21 01:47:18 +0000163 return None;
Guy Benyei11169dd2012-12-18 14:30:41 +0000164}
165
166Selector NSAPI::getNSDictionarySelector(
167 NSDictionaryMethodKind MK) const {
168 if (NSDictionarySelectors[MK].isNull()) {
169 Selector Sel;
170 switch (MK) {
171 case NSDict_dictionary:
172 Sel = Ctx.Selectors.getNullarySelector(&Ctx.Idents.get("dictionary"));
173 break;
174 case NSDict_dictionaryWithDictionary:
175 Sel = Ctx.Selectors.getUnarySelector(
176 &Ctx.Idents.get("dictionaryWithDictionary"));
177 break;
178 case NSDict_dictionaryWithObjectForKey: {
179 IdentifierInfo *KeyIdents[] = {
180 &Ctx.Idents.get("dictionaryWithObject"),
181 &Ctx.Idents.get("forKey")
182 };
183 Sel = Ctx.Selectors.getSelector(2, KeyIdents);
184 break;
185 }
186 case NSDict_dictionaryWithObjectsForKeys: {
187 IdentifierInfo *KeyIdents[] = {
188 &Ctx.Idents.get("dictionaryWithObjects"),
189 &Ctx.Idents.get("forKeys")
190 };
191 Sel = Ctx.Selectors.getSelector(2, KeyIdents);
192 break;
193 }
194 case NSDict_dictionaryWithObjectsForKeysCount: {
195 IdentifierInfo *KeyIdents[] = {
196 &Ctx.Idents.get("dictionaryWithObjects"),
197 &Ctx.Idents.get("forKeys"),
198 &Ctx.Idents.get("count")
199 };
200 Sel = Ctx.Selectors.getSelector(3, KeyIdents);
201 break;
202 }
203 case NSDict_dictionaryWithObjectsAndKeys:
204 Sel = Ctx.Selectors.getUnarySelector(
205 &Ctx.Idents.get("dictionaryWithObjectsAndKeys"));
206 break;
207 case NSDict_initWithDictionary:
208 Sel = Ctx.Selectors.getUnarySelector(
209 &Ctx.Idents.get("initWithDictionary"));
210 break;
211 case NSDict_initWithObjectsAndKeys:
212 Sel = Ctx.Selectors.getUnarySelector(
213 &Ctx.Idents.get("initWithObjectsAndKeys"));
214 break;
Argyrios Kyrtzidis6b4f3412013-01-16 23:54:48 +0000215 case NSDict_initWithObjectsForKeys: {
216 IdentifierInfo *KeyIdents[] = {
217 &Ctx.Idents.get("initWithObjects"),
218 &Ctx.Idents.get("forKeys")
219 };
220 Sel = Ctx.Selectors.getSelector(2, KeyIdents);
221 break;
222 }
Guy Benyei11169dd2012-12-18 14:30:41 +0000223 case NSDict_objectForKey:
224 Sel = Ctx.Selectors.getUnarySelector(&Ctx.Idents.get("objectForKey"));
225 break;
226 case NSMutableDict_setObjectForKey: {
227 IdentifierInfo *KeyIdents[] = {
228 &Ctx.Idents.get("setObject"),
229 &Ctx.Idents.get("forKey")
230 };
231 Sel = Ctx.Selectors.getSelector(2, KeyIdents);
232 break;
233 }
Alex Denisove1d882c2015-03-04 17:55:52 +0000234 case NSMutableDict_setObjectForKeyedSubscript: {
235 IdentifierInfo *KeyIdents[] = {
236 &Ctx.Idents.get("setObject"),
237 &Ctx.Idents.get("forKeyedSubscript")
238 };
239 Sel = Ctx.Selectors.getSelector(2, KeyIdents);
240 break;
241 }
242 case NSMutableDict_setValueForKey: {
243 IdentifierInfo *KeyIdents[] = {
244 &Ctx.Idents.get("setValue"),
245 &Ctx.Idents.get("forKey")
246 };
247 Sel = Ctx.Selectors.getSelector(2, KeyIdents);
248 break;
249 }
Guy Benyei11169dd2012-12-18 14:30:41 +0000250 }
251 return (NSDictionarySelectors[MK] = Sel);
252 }
253
254 return NSDictionarySelectors[MK];
255}
256
David Blaikie05785d12013-02-20 22:23:23 +0000257Optional<NSAPI::NSDictionaryMethodKind>
Guy Benyei11169dd2012-12-18 14:30:41 +0000258NSAPI::getNSDictionaryMethodKind(Selector Sel) {
259 for (unsigned i = 0; i != NumNSDictionaryMethods; ++i) {
260 NSDictionaryMethodKind MK = NSDictionaryMethodKind(i);
261 if (Sel == getNSDictionarySelector(MK))
262 return MK;
263 }
264
David Blaikie7a30dc52013-02-21 01:47:18 +0000265 return None;
Guy Benyei11169dd2012-12-18 14:30:41 +0000266}
267
Alex Denisove1d882c2015-03-04 17:55:52 +0000268Selector NSAPI::getNSSetSelector(NSSetMethodKind MK) const {
269 if (NSSetSelectors[MK].isNull()) {
270 Selector Sel;
271 switch (MK) {
272 case NSMutableSet_addObject:
273 Sel = Ctx.Selectors.getUnarySelector(&Ctx.Idents.get("addObject"));
274 break;
275 case NSOrderedSet_insertObjectAtIndex: {
276 IdentifierInfo *KeyIdents[] = {
277 &Ctx.Idents.get("insertObject"),
278 &Ctx.Idents.get("atIndex")
279 };
280 Sel = Ctx.Selectors.getSelector(2, KeyIdents);
281 break;
282 }
283 case NSOrderedSet_setObjectAtIndex: {
284 IdentifierInfo *KeyIdents[] = {
285 &Ctx.Idents.get("setObject"),
286 &Ctx.Idents.get("atIndex")
287 };
288 Sel = Ctx.Selectors.getSelector(2, KeyIdents);
289 break;
290 }
291 case NSOrderedSet_setObjectAtIndexedSubscript: {
292 IdentifierInfo *KeyIdents[] = {
293 &Ctx.Idents.get("setObject"),
294 &Ctx.Idents.get("atIndexedSubscript")
295 };
296 Sel = Ctx.Selectors.getSelector(2, KeyIdents);
297 break;
298 }
299 case NSOrderedSet_replaceObjectAtIndexWithObject: {
300 IdentifierInfo *KeyIdents[] = {
301 &Ctx.Idents.get("replaceObjectAtIndex"),
302 &Ctx.Idents.get("withObject")
303 };
304 Sel = Ctx.Selectors.getSelector(2, KeyIdents);
305 break;
306 }
307 }
308 return (NSSetSelectors[MK] = Sel);
309 }
310
311 return NSSetSelectors[MK];
312}
313
314Optional<NSAPI::NSSetMethodKind>
315NSAPI::getNSSetMethodKind(Selector Sel) {
316 for (unsigned i = 0; i != NumNSSetMethods; ++i) {
317 NSSetMethodKind MK = NSSetMethodKind(i);
318 if (Sel == getNSSetSelector(MK))
319 return MK;
320 }
321
322 return None;
323}
324
Guy Benyei11169dd2012-12-18 14:30:41 +0000325Selector NSAPI::getNSNumberLiteralSelector(NSNumberLiteralMethodKind MK,
326 bool Instance) const {
327 static const char *ClassSelectorName[NumNSNumberLiteralMethods] = {
328 "numberWithChar",
329 "numberWithUnsignedChar",
330 "numberWithShort",
331 "numberWithUnsignedShort",
332 "numberWithInt",
333 "numberWithUnsignedInt",
334 "numberWithLong",
335 "numberWithUnsignedLong",
336 "numberWithLongLong",
337 "numberWithUnsignedLongLong",
338 "numberWithFloat",
339 "numberWithDouble",
340 "numberWithBool",
341 "numberWithInteger",
342 "numberWithUnsignedInteger"
343 };
344 static const char *InstanceSelectorName[NumNSNumberLiteralMethods] = {
345 "initWithChar",
346 "initWithUnsignedChar",
347 "initWithShort",
348 "initWithUnsignedShort",
349 "initWithInt",
350 "initWithUnsignedInt",
351 "initWithLong",
352 "initWithUnsignedLong",
353 "initWithLongLong",
354 "initWithUnsignedLongLong",
355 "initWithFloat",
356 "initWithDouble",
357 "initWithBool",
358 "initWithInteger",
359 "initWithUnsignedInteger"
360 };
361
362 Selector *Sels;
363 const char **Names;
364 if (Instance) {
365 Sels = NSNumberInstanceSelectors;
366 Names = InstanceSelectorName;
367 } else {
368 Sels = NSNumberClassSelectors;
369 Names = ClassSelectorName;
370 }
371
372 if (Sels[MK].isNull())
373 Sels[MK] = Ctx.Selectors.getUnarySelector(&Ctx.Idents.get(Names[MK]));
374 return Sels[MK];
375}
376
David Blaikie05785d12013-02-20 22:23:23 +0000377Optional<NSAPI::NSNumberLiteralMethodKind>
Guy Benyei11169dd2012-12-18 14:30:41 +0000378NSAPI::getNSNumberLiteralMethodKind(Selector Sel) const {
379 for (unsigned i = 0; i != NumNSNumberLiteralMethods; ++i) {
380 NSNumberLiteralMethodKind MK = NSNumberLiteralMethodKind(i);
381 if (isNSNumberLiteralSelector(MK, Sel))
382 return MK;
383 }
384
David Blaikie7a30dc52013-02-21 01:47:18 +0000385 return None;
Guy Benyei11169dd2012-12-18 14:30:41 +0000386}
387
David Blaikie05785d12013-02-20 22:23:23 +0000388Optional<NSAPI::NSNumberLiteralMethodKind>
Guy Benyei11169dd2012-12-18 14:30:41 +0000389NSAPI::getNSNumberFactoryMethodKind(QualType T) const {
390 const BuiltinType *BT = T->getAs<BuiltinType>();
391 if (!BT)
David Blaikie7a30dc52013-02-21 01:47:18 +0000392 return None;
Guy Benyei11169dd2012-12-18 14:30:41 +0000393
394 const TypedefType *TDT = T->getAs<TypedefType>();
395 if (TDT) {
396 QualType TDTTy = QualType(TDT, 0);
397 if (isObjCBOOLType(TDTTy))
398 return NSAPI::NSNumberWithBool;
399 if (isObjCNSIntegerType(TDTTy))
400 return NSAPI::NSNumberWithInteger;
401 if (isObjCNSUIntegerType(TDTTy))
402 return NSAPI::NSNumberWithUnsignedInteger;
403 }
404
405 switch (BT->getKind()) {
406 case BuiltinType::Char_S:
407 case BuiltinType::SChar:
408 return NSAPI::NSNumberWithChar;
409 case BuiltinType::Char_U:
410 case BuiltinType::UChar:
411 return NSAPI::NSNumberWithUnsignedChar;
412 case BuiltinType::Short:
413 return NSAPI::NSNumberWithShort;
414 case BuiltinType::UShort:
415 return NSAPI::NSNumberWithUnsignedShort;
416 case BuiltinType::Int:
417 return NSAPI::NSNumberWithInt;
418 case BuiltinType::UInt:
419 return NSAPI::NSNumberWithUnsignedInt;
420 case BuiltinType::Long:
421 return NSAPI::NSNumberWithLong;
422 case BuiltinType::ULong:
423 return NSAPI::NSNumberWithUnsignedLong;
424 case BuiltinType::LongLong:
425 return NSAPI::NSNumberWithLongLong;
426 case BuiltinType::ULongLong:
427 return NSAPI::NSNumberWithUnsignedLongLong;
428 case BuiltinType::Float:
429 return NSAPI::NSNumberWithFloat;
430 case BuiltinType::Double:
431 return NSAPI::NSNumberWithDouble;
432 case BuiltinType::Bool:
433 return NSAPI::NSNumberWithBool;
434
435 case BuiltinType::Void:
436 case BuiltinType::WChar_U:
437 case BuiltinType::WChar_S:
438 case BuiltinType::Char16:
439 case BuiltinType::Char32:
440 case BuiltinType::Int128:
441 case BuiltinType::LongDouble:
442 case BuiltinType::UInt128:
443 case BuiltinType::NullPtr:
444 case BuiltinType::ObjCClass:
445 case BuiltinType::ObjCId:
446 case BuiltinType::ObjCSel:
Guy Benyeid8a08ea2012-12-18 14:38:23 +0000447 case BuiltinType::OCLImage1d:
448 case BuiltinType::OCLImage1dArray:
449 case BuiltinType::OCLImage1dBuffer:
450 case BuiltinType::OCLImage2d:
451 case BuiltinType::OCLImage2dArray:
452 case BuiltinType::OCLImage3d:
Guy Benyei61054192013-02-07 10:55:47 +0000453 case BuiltinType::OCLSampler:
Guy Benyei1b4fb3e2013-01-20 12:31:11 +0000454 case BuiltinType::OCLEvent:
Guy Benyei11169dd2012-12-18 14:30:41 +0000455 case BuiltinType::BoundMember:
456 case BuiltinType::Dependent:
457 case BuiltinType::Overload:
458 case BuiltinType::UnknownAny:
459 case BuiltinType::ARCUnbridgedCast:
460 case BuiltinType::Half:
461 case BuiltinType::PseudoObject:
462 case BuiltinType::BuiltinFn:
463 break;
464 }
465
David Blaikie7a30dc52013-02-21 01:47:18 +0000466 return None;
Guy Benyei11169dd2012-12-18 14:30:41 +0000467}
468
469/// \brief Returns true if \param T is a typedef of "BOOL" in objective-c.
470bool NSAPI::isObjCBOOLType(QualType T) const {
471 return isObjCTypedef(T, "BOOL", BOOLId);
472}
473/// \brief Returns true if \param T is a typedef of "NSInteger" in objective-c.
474bool NSAPI::isObjCNSIntegerType(QualType T) const {
475 return isObjCTypedef(T, "NSInteger", NSIntegerId);
476}
477/// \brief Returns true if \param T is a typedef of "NSUInteger" in objective-c.
478bool NSAPI::isObjCNSUIntegerType(QualType T) const {
479 return isObjCTypedef(T, "NSUInteger", NSUIntegerId);
480}
481
Fariborz Jahanian35ee87d2014-10-06 23:50:37 +0000482StringRef NSAPI::GetNSIntegralKind(QualType T) const {
483 if (!Ctx.getLangOpts().ObjC1 || T.isNull())
484 return StringRef();
485
486 while (const TypedefType *TDT = T->getAs<TypedefType>()) {
487 StringRef NSIntegralResust =
488 llvm::StringSwitch<StringRef>(
489 TDT->getDecl()->getDeclName().getAsIdentifierInfo()->getName())
490 .Case("int8_t", "int8_t")
491 .Case("int16_t", "int16_t")
492 .Case("int32_t", "int32_t")
493 .Case("NSInteger", "NSInteger")
494 .Case("int64_t", "int64_t")
495 .Case("uint8_t", "uint8_t")
496 .Case("uint16_t", "uint16_t")
497 .Case("uint32_t", "uint32_t")
498 .Case("NSUInteger", "NSUInteger")
499 .Case("uint64_t", "uint64_t")
500 .Default(StringRef());
501 if (!NSIntegralResust.empty())
502 return NSIntegralResust;
503 T = TDT->desugar();
504 }
505 return StringRef();
506}
507
Richard Smith20e883e2015-04-29 23:20:19 +0000508bool NSAPI::isMacroDefined(StringRef Id) const {
509 // FIXME: Check whether the relevant module macros are visible.
510 return Ctx.Idents.get(Id).hasMacroDefinition();
511}
512
Guy Benyei11169dd2012-12-18 14:30:41 +0000513bool NSAPI::isObjCTypedef(QualType T,
514 StringRef name, IdentifierInfo *&II) const {
515 if (!Ctx.getLangOpts().ObjC1)
516 return false;
517 if (T.isNull())
518 return false;
519
520 if (!II)
521 II = &Ctx.Idents.get(name);
522
523 while (const TypedefType *TDT = T->getAs<TypedefType>()) {
524 if (TDT->getDecl()->getDeclName().getAsIdentifierInfo() == II)
525 return true;
526 T = TDT->desugar();
527 }
528
529 return false;
530}
531
532bool NSAPI::isObjCEnumerator(const Expr *E,
533 StringRef name, IdentifierInfo *&II) const {
534 if (!Ctx.getLangOpts().ObjC1)
535 return false;
536 if (!E)
537 return false;
538
539 if (!II)
540 II = &Ctx.Idents.get(name);
541
542 if (const DeclRefExpr *DRE = dyn_cast<DeclRefExpr>(E->IgnoreParenImpCasts()))
543 if (const EnumConstantDecl *
544 EnumD = dyn_cast_or_null<EnumConstantDecl>(DRE->getDecl()))
545 return EnumD->getIdentifier() == II;
546
547 return false;
548}
549
550Selector NSAPI::getOrInitSelector(ArrayRef<StringRef> Ids,
551 Selector &Sel) const {
552 if (Sel.isNull()) {
553 SmallVector<IdentifierInfo *, 4> Idents;
554 for (ArrayRef<StringRef>::const_iterator
555 I = Ids.begin(), E = Ids.end(); I != E; ++I)
556 Idents.push_back(&Ctx.Idents.get(*I));
557 Sel = Ctx.Selectors.getSelector(Idents.size(), Idents.data());
558 }
559 return Sel;
560}