]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - contrib/llvm/tools/clang/lib/AST/DeclarationName.cpp
Update clang to trunk r290819 and resolve conflicts.
[FreeBSD/FreeBSD.git] / contrib / llvm / tools / clang / lib / AST / DeclarationName.cpp
1 //===-- DeclarationName.cpp - Declaration names implementation --*- C++ -*-===//
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 // This file implements the DeclarationName and DeclarationNameTable
11 // classes.
12 //
13 //===----------------------------------------------------------------------===//
14 #include "clang/AST/DeclarationName.h"
15 #include "clang/AST/ASTContext.h"
16 #include "clang/AST/DeclCXX.h"
17 #include "clang/AST/Type.h"
18 #include "clang/AST/TypeLoc.h"
19 #include "clang/AST/TypeOrdering.h"
20 #include "clang/Basic/IdentifierTable.h"
21 #include "llvm/ADT/FoldingSet.h"
22 #include "llvm/Support/ErrorHandling.h"
23 #include "llvm/Support/raw_ostream.h"
24 using namespace clang;
25
26 namespace clang {
27 /// CXXSpecialName - Records the type associated with one of the
28 /// "special" kinds of declaration names in C++, e.g., constructors,
29 /// destructors, and conversion functions.
30 class CXXSpecialName
31   : public DeclarationNameExtra, public llvm::FoldingSetNode {
32 public:
33   /// Type - The type associated with this declaration name.
34   QualType Type;
35
36   /// FETokenInfo - Extra information associated with this declaration
37   /// name that can be used by the front end.
38   void *FETokenInfo;
39
40   void Profile(llvm::FoldingSetNodeID &ID) {
41     ID.AddInteger(ExtraKindOrNumArgs);
42     ID.AddPointer(Type.getAsOpaquePtr());
43   }
44 };
45
46 /// CXXOperatorIdName - Contains extra information for the name of an
47 /// overloaded operator in C++, such as "operator+.
48 class CXXOperatorIdName : public DeclarationNameExtra {
49 public:
50   /// FETokenInfo - Extra information associated with this operator
51   /// name that can be used by the front end.
52   void *FETokenInfo;
53 };
54
55 /// CXXLiteralOperatorName - Contains the actual identifier that makes up the
56 /// name.
57 ///
58 /// This identifier is stored here rather than directly in DeclarationName so as
59 /// to allow Objective-C selectors, which are about a million times more common,
60 /// to consume minimal memory.
61 class CXXLiteralOperatorIdName
62   : public DeclarationNameExtra, public llvm::FoldingSetNode {
63 public:
64   IdentifierInfo *ID;
65
66   /// FETokenInfo - Extra information associated with this operator
67   /// name that can be used by the front end.
68   void *FETokenInfo;
69
70   void Profile(llvm::FoldingSetNodeID &FSID) {
71     FSID.AddPointer(ID);
72   }
73 };
74
75 static int compareInt(unsigned A, unsigned B) {
76   return (A < B ? -1 : (A > B ? 1 : 0));
77 }
78
79 int DeclarationName::compare(DeclarationName LHS, DeclarationName RHS) {
80   if (LHS.getNameKind() != RHS.getNameKind())
81     return (LHS.getNameKind() < RHS.getNameKind() ? -1 : 1);
82   
83   switch (LHS.getNameKind()) {
84   case DeclarationName::Identifier: {
85     IdentifierInfo *LII = LHS.getAsIdentifierInfo();
86     IdentifierInfo *RII = RHS.getAsIdentifierInfo();
87     if (!LII) return RII ? -1 : 0;
88     if (!RII) return 1;
89     
90     return LII->getName().compare(RII->getName());
91   }
92
93   case DeclarationName::ObjCZeroArgSelector:
94   case DeclarationName::ObjCOneArgSelector:
95   case DeclarationName::ObjCMultiArgSelector: {
96     Selector LHSSelector = LHS.getObjCSelector();
97     Selector RHSSelector = RHS.getObjCSelector();
98     // getNumArgs for ZeroArgSelector returns 0, but we still need to compare.
99     if (LHS.getNameKind() == DeclarationName::ObjCZeroArgSelector &&
100         RHS.getNameKind() == DeclarationName::ObjCZeroArgSelector) {
101       return LHSSelector.getAsIdentifierInfo()->getName().compare(
102              RHSSelector.getAsIdentifierInfo()->getName());
103     }
104     unsigned LN = LHSSelector.getNumArgs(), RN = RHSSelector.getNumArgs();
105     for (unsigned I = 0, N = std::min(LN, RN); I != N; ++I) {
106       switch (LHSSelector.getNameForSlot(I).compare(
107                                                RHSSelector.getNameForSlot(I))) {
108       case -1: return -1;
109       case 1: return 1;
110       default: break;
111       }
112     }
113
114     return compareInt(LN, RN);
115   }
116   
117   case DeclarationName::CXXConstructorName:
118   case DeclarationName::CXXDestructorName:
119   case DeclarationName::CXXConversionFunctionName:
120     if (QualTypeOrdering()(LHS.getCXXNameType(), RHS.getCXXNameType()))
121       return -1;
122     if (QualTypeOrdering()(RHS.getCXXNameType(), LHS.getCXXNameType()))
123       return 1;
124     return 0;
125               
126   case DeclarationName::CXXOperatorName:
127     return compareInt(LHS.getCXXOverloadedOperator(),
128                       RHS.getCXXOverloadedOperator());
129
130   case DeclarationName::CXXLiteralOperatorName:
131     return LHS.getCXXLiteralIdentifier()->getName().compare(
132                                    RHS.getCXXLiteralIdentifier()->getName());
133               
134   case DeclarationName::CXXUsingDirective:
135     return 0;
136   }
137
138   llvm_unreachable("Invalid DeclarationName Kind!");
139 }
140
141 static void printCXXConstructorDestructorName(QualType ClassType,
142                                               raw_ostream &OS,
143                                               PrintingPolicy Policy) {
144   // We know we're printing C++ here. Ensure we print types properly.
145   Policy.adjustForCPlusPlus();
146
147   if (const RecordType *ClassRec = ClassType->getAs<RecordType>()) {
148     OS << *ClassRec->getDecl();
149     return;
150   }
151   if (Policy.SuppressTemplateArgsInCXXConstructors) {
152     if (auto *InjTy = ClassType->getAs<InjectedClassNameType>()) {
153       OS << *InjTy->getDecl();
154       return;
155     }
156   }
157   ClassType.print(OS, Policy);
158 }
159
160 void DeclarationName::print(raw_ostream &OS, const PrintingPolicy &Policy) {
161   DeclarationName &N = *this;
162   switch (N.getNameKind()) {
163   case DeclarationName::Identifier:
164     if (const IdentifierInfo *II = N.getAsIdentifierInfo())
165       OS << II->getName();
166     return;
167
168   case DeclarationName::ObjCZeroArgSelector:
169   case DeclarationName::ObjCOneArgSelector:
170   case DeclarationName::ObjCMultiArgSelector:
171     N.getObjCSelector().print(OS);
172     return;
173
174   case DeclarationName::CXXConstructorName:
175     return printCXXConstructorDestructorName(N.getCXXNameType(), OS, Policy);
176
177   case DeclarationName::CXXDestructorName: {
178     OS << '~';
179     return printCXXConstructorDestructorName(N.getCXXNameType(), OS, Policy);
180   }
181
182   case DeclarationName::CXXOperatorName: {
183     static const char* const OperatorNames[NUM_OVERLOADED_OPERATORS] = {
184       nullptr,
185 #define OVERLOADED_OPERATOR(Name,Spelling,Token,Unary,Binary,MemberOnly) \
186       Spelling,
187 #include "clang/Basic/OperatorKinds.def"
188     };
189     const char *OpName = OperatorNames[N.getCXXOverloadedOperator()];
190     assert(OpName && "not an overloaded operator");
191
192     OS << "operator";
193     if (OpName[0] >= 'a' && OpName[0] <= 'z')
194       OS << ' ';
195     OS << OpName;
196     return;
197   }
198
199   case DeclarationName::CXXLiteralOperatorName:
200     OS << "operator\"\"" << N.getCXXLiteralIdentifier()->getName();
201     return;
202
203   case DeclarationName::CXXConversionFunctionName: {
204     OS << "operator ";
205     QualType Type = N.getCXXNameType();
206     if (const RecordType *Rec = Type->getAs<RecordType>()) {
207       OS << *Rec->getDecl();
208       return;
209     }
210     // We know we're printing C++ here, ensure we print 'bool' properly.
211     PrintingPolicy CXXPolicy = Policy;
212     CXXPolicy.adjustForCPlusPlus();
213     Type.print(OS, CXXPolicy);
214     return;
215   }
216   case DeclarationName::CXXUsingDirective:
217     OS << "<using-directive>";
218     return;
219   }
220
221   llvm_unreachable("Unexpected declaration name kind");
222 }
223
224 raw_ostream &operator<<(raw_ostream &OS, DeclarationName N) {
225   LangOptions LO;
226   N.print(OS, PrintingPolicy(LO));
227   return OS;
228 }
229
230 } // end namespace clang
231
232 DeclarationName::NameKind DeclarationName::getNameKind() const {
233   switch (getStoredNameKind()) {
234   case StoredIdentifier:          return Identifier;
235   case StoredObjCZeroArgSelector: return ObjCZeroArgSelector;
236   case StoredObjCOneArgSelector:  return ObjCOneArgSelector;
237
238   case StoredDeclarationNameExtra:
239     switch (getExtra()->ExtraKindOrNumArgs) {
240     case DeclarationNameExtra::CXXConstructor:
241       return CXXConstructorName;
242
243     case DeclarationNameExtra::CXXDestructor:
244       return CXXDestructorName;
245
246     case DeclarationNameExtra::CXXConversionFunction:
247       return CXXConversionFunctionName;
248
249     case DeclarationNameExtra::CXXLiteralOperator:
250       return CXXLiteralOperatorName;
251
252     case DeclarationNameExtra::CXXUsingDirective:
253       return CXXUsingDirective;
254
255     default:
256       // Check if we have one of the CXXOperator* enumeration values.
257       if (getExtra()->ExtraKindOrNumArgs <
258             DeclarationNameExtra::CXXUsingDirective)
259         return CXXOperatorName;
260
261       return ObjCMultiArgSelector;
262     }
263   }
264
265   // Can't actually get here.
266   llvm_unreachable("This should be unreachable!");
267 }
268
269 bool DeclarationName::isDependentName() const {
270   QualType T = getCXXNameType();
271   return !T.isNull() && T->isDependentType();
272 }
273
274 std::string DeclarationName::getAsString() const {
275   std::string Result;
276   llvm::raw_string_ostream OS(Result);
277   OS << *this;
278   return OS.str();
279 }
280
281 QualType DeclarationName::getCXXNameType() const {
282   if (CXXSpecialName *CXXName = getAsCXXSpecialName())
283     return CXXName->Type;
284   else
285     return QualType();
286 }
287
288 OverloadedOperatorKind DeclarationName::getCXXOverloadedOperator() const {
289   if (CXXOperatorIdName *CXXOp = getAsCXXOperatorIdName()) {
290     unsigned value
291       = CXXOp->ExtraKindOrNumArgs - DeclarationNameExtra::CXXConversionFunction;
292     return static_cast<OverloadedOperatorKind>(value);
293   } else {
294     return OO_None;
295   }
296 }
297
298 IdentifierInfo *DeclarationName::getCXXLiteralIdentifier() const {
299   if (CXXLiteralOperatorIdName *CXXLit = getAsCXXLiteralOperatorIdName())
300     return CXXLit->ID;
301   else
302     return nullptr;
303 }
304
305 void *DeclarationName::getFETokenInfoAsVoidSlow() const {
306   switch (getNameKind()) {
307   case Identifier:
308     llvm_unreachable("Handled by getFETokenInfo()");
309
310   case CXXConstructorName:
311   case CXXDestructorName:
312   case CXXConversionFunctionName:
313     return getAsCXXSpecialName()->FETokenInfo;
314
315   case CXXOperatorName:
316     return getAsCXXOperatorIdName()->FETokenInfo;
317
318   case CXXLiteralOperatorName:
319     return getAsCXXLiteralOperatorIdName()->FETokenInfo;
320
321   default:
322     llvm_unreachable("Declaration name has no FETokenInfo");
323   }
324 }
325
326 void DeclarationName::setFETokenInfo(void *T) {
327   switch (getNameKind()) {
328   case Identifier:
329     getAsIdentifierInfo()->setFETokenInfo(T);
330     break;
331
332   case CXXConstructorName:
333   case CXXDestructorName:
334   case CXXConversionFunctionName:
335     getAsCXXSpecialName()->FETokenInfo = T;
336     break;
337
338   case CXXOperatorName:
339     getAsCXXOperatorIdName()->FETokenInfo = T;
340     break;
341
342   case CXXLiteralOperatorName:
343     getAsCXXLiteralOperatorIdName()->FETokenInfo = T;
344     break;
345
346   default:
347     llvm_unreachable("Declaration name has no FETokenInfo");
348   }
349 }
350
351 DeclarationName DeclarationName::getUsingDirectiveName() {
352   // Single instance of DeclarationNameExtra for using-directive
353   static const DeclarationNameExtra UDirExtra =
354     { DeclarationNameExtra::CXXUsingDirective };
355
356   uintptr_t Ptr = reinterpret_cast<uintptr_t>(&UDirExtra);
357   Ptr |= StoredDeclarationNameExtra;
358
359   return DeclarationName(Ptr);
360 }
361
362 LLVM_DUMP_METHOD void DeclarationName::dump() const {
363   llvm::errs() << *this << '\n';
364 }
365
366 DeclarationNameTable::DeclarationNameTable(const ASTContext &C) : Ctx(C) {
367   CXXSpecialNamesImpl = new llvm::FoldingSet<CXXSpecialName>;
368   CXXLiteralOperatorNames = new llvm::FoldingSet<CXXLiteralOperatorIdName>;
369
370   // Initialize the overloaded operator names.
371   CXXOperatorNames = new (Ctx) CXXOperatorIdName[NUM_OVERLOADED_OPERATORS];
372   for (unsigned Op = 0; Op < NUM_OVERLOADED_OPERATORS; ++Op) {
373     CXXOperatorNames[Op].ExtraKindOrNumArgs
374       = Op + DeclarationNameExtra::CXXConversionFunction;
375     CXXOperatorNames[Op].FETokenInfo = nullptr;
376   }
377 }
378
379 DeclarationNameTable::~DeclarationNameTable() {
380   llvm::FoldingSet<CXXSpecialName> *SpecialNames =
381     static_cast<llvm::FoldingSet<CXXSpecialName>*>(CXXSpecialNamesImpl);
382   llvm::FoldingSet<CXXLiteralOperatorIdName> *LiteralNames
383     = static_cast<llvm::FoldingSet<CXXLiteralOperatorIdName>*>
384         (CXXLiteralOperatorNames);
385
386   delete SpecialNames;
387   delete LiteralNames;
388 }
389
390 DeclarationName DeclarationNameTable::getCXXConstructorName(CanQualType Ty) {
391   return getCXXSpecialName(DeclarationName::CXXConstructorName,
392                            Ty.getUnqualifiedType());
393 }
394
395 DeclarationName DeclarationNameTable::getCXXDestructorName(CanQualType Ty) {
396   return getCXXSpecialName(DeclarationName::CXXDestructorName,
397                            Ty.getUnqualifiedType());
398 }
399
400 DeclarationName
401 DeclarationNameTable::getCXXConversionFunctionName(CanQualType Ty) {
402   return getCXXSpecialName(DeclarationName::CXXConversionFunctionName, Ty);
403 }
404
405 DeclarationName
406 DeclarationNameTable::getCXXSpecialName(DeclarationName::NameKind Kind,
407                                         CanQualType Ty) {
408   assert(Kind >= DeclarationName::CXXConstructorName &&
409          Kind <= DeclarationName::CXXConversionFunctionName &&
410          "Kind must be a C++ special name kind");
411   llvm::FoldingSet<CXXSpecialName> *SpecialNames
412     = static_cast<llvm::FoldingSet<CXXSpecialName>*>(CXXSpecialNamesImpl);
413
414   DeclarationNameExtra::ExtraKind EKind;
415   switch (Kind) {
416   case DeclarationName::CXXConstructorName:
417     EKind = DeclarationNameExtra::CXXConstructor;
418     assert(!Ty.hasQualifiers() &&"Constructor type must be unqualified");
419     break;
420   case DeclarationName::CXXDestructorName:
421     EKind = DeclarationNameExtra::CXXDestructor;
422     assert(!Ty.hasQualifiers() && "Destructor type must be unqualified");
423     break;
424   case DeclarationName::CXXConversionFunctionName:
425     EKind = DeclarationNameExtra::CXXConversionFunction;
426     break;
427   default:
428     return DeclarationName();
429   }
430
431   // Unique selector, to guarantee there is one per name.
432   llvm::FoldingSetNodeID ID;
433   ID.AddInteger(EKind);
434   ID.AddPointer(Ty.getAsOpaquePtr());
435
436   void *InsertPos = nullptr;
437   if (CXXSpecialName *Name = SpecialNames->FindNodeOrInsertPos(ID, InsertPos))
438     return DeclarationName(Name);
439
440   CXXSpecialName *SpecialName = new (Ctx) CXXSpecialName;
441   SpecialName->ExtraKindOrNumArgs = EKind;
442   SpecialName->Type = Ty;
443   SpecialName->FETokenInfo = nullptr;
444
445   SpecialNames->InsertNode(SpecialName, InsertPos);
446   return DeclarationName(SpecialName);
447 }
448
449 DeclarationName
450 DeclarationNameTable::getCXXOperatorName(OverloadedOperatorKind Op) {
451   return DeclarationName(&CXXOperatorNames[(unsigned)Op]);
452 }
453
454 DeclarationName
455 DeclarationNameTable::getCXXLiteralOperatorName(IdentifierInfo *II) {
456   llvm::FoldingSet<CXXLiteralOperatorIdName> *LiteralNames
457     = static_cast<llvm::FoldingSet<CXXLiteralOperatorIdName>*>
458                                                       (CXXLiteralOperatorNames);
459
460   llvm::FoldingSetNodeID ID;
461   ID.AddPointer(II);
462
463   void *InsertPos = nullptr;
464   if (CXXLiteralOperatorIdName *Name =
465                                LiteralNames->FindNodeOrInsertPos(ID, InsertPos))
466     return DeclarationName (Name);
467   
468   CXXLiteralOperatorIdName *LiteralName = new (Ctx) CXXLiteralOperatorIdName;
469   LiteralName->ExtraKindOrNumArgs = DeclarationNameExtra::CXXLiteralOperator;
470   LiteralName->ID = II;
471   LiteralName->FETokenInfo = nullptr;
472
473   LiteralNames->InsertNode(LiteralName, InsertPos);
474   return DeclarationName(LiteralName);
475 }
476
477 DeclarationNameLoc::DeclarationNameLoc(DeclarationName Name) {
478   switch (Name.getNameKind()) {
479   case DeclarationName::Identifier:
480     break;
481   case DeclarationName::CXXConstructorName:
482   case DeclarationName::CXXDestructorName:
483   case DeclarationName::CXXConversionFunctionName:
484     NamedType.TInfo = nullptr;
485     break;
486   case DeclarationName::CXXOperatorName:
487     CXXOperatorName.BeginOpNameLoc = SourceLocation().getRawEncoding();
488     CXXOperatorName.EndOpNameLoc = SourceLocation().getRawEncoding();
489     break;
490   case DeclarationName::CXXLiteralOperatorName:
491     CXXLiteralOperatorName.OpNameLoc = SourceLocation().getRawEncoding();
492     break;
493   case DeclarationName::ObjCZeroArgSelector:
494   case DeclarationName::ObjCOneArgSelector:
495   case DeclarationName::ObjCMultiArgSelector:
496     // FIXME: ?
497     break;
498   case DeclarationName::CXXUsingDirective:
499     break;
500   }
501 }
502
503 bool DeclarationNameInfo::containsUnexpandedParameterPack() const {
504   switch (Name.getNameKind()) {
505   case DeclarationName::Identifier:
506   case DeclarationName::ObjCZeroArgSelector:
507   case DeclarationName::ObjCOneArgSelector:
508   case DeclarationName::ObjCMultiArgSelector:
509   case DeclarationName::CXXOperatorName:
510   case DeclarationName::CXXLiteralOperatorName:
511   case DeclarationName::CXXUsingDirective:
512     return false;
513
514   case DeclarationName::CXXConstructorName:
515   case DeclarationName::CXXDestructorName:
516   case DeclarationName::CXXConversionFunctionName:
517     if (TypeSourceInfo *TInfo = LocInfo.NamedType.TInfo)
518       return TInfo->getType()->containsUnexpandedParameterPack();
519
520     return Name.getCXXNameType()->containsUnexpandedParameterPack();
521   }
522   llvm_unreachable("All name kinds handled.");
523 }
524
525 bool DeclarationNameInfo::isInstantiationDependent() const {
526   switch (Name.getNameKind()) {
527   case DeclarationName::Identifier:
528   case DeclarationName::ObjCZeroArgSelector:
529   case DeclarationName::ObjCOneArgSelector:
530   case DeclarationName::ObjCMultiArgSelector:
531   case DeclarationName::CXXOperatorName:
532   case DeclarationName::CXXLiteralOperatorName:
533   case DeclarationName::CXXUsingDirective:
534     return false;
535     
536   case DeclarationName::CXXConstructorName:
537   case DeclarationName::CXXDestructorName:
538   case DeclarationName::CXXConversionFunctionName:
539     if (TypeSourceInfo *TInfo = LocInfo.NamedType.TInfo)
540       return TInfo->getType()->isInstantiationDependentType();
541     
542     return Name.getCXXNameType()->isInstantiationDependentType();
543   }
544   llvm_unreachable("All name kinds handled.");
545 }
546
547 std::string DeclarationNameInfo::getAsString() const {
548   std::string Result;
549   llvm::raw_string_ostream OS(Result);
550   printName(OS);
551   return OS.str();
552 }
553
554 void DeclarationNameInfo::printName(raw_ostream &OS) const {
555   switch (Name.getNameKind()) {
556   case DeclarationName::Identifier:
557   case DeclarationName::ObjCZeroArgSelector:
558   case DeclarationName::ObjCOneArgSelector:
559   case DeclarationName::ObjCMultiArgSelector:
560   case DeclarationName::CXXOperatorName:
561   case DeclarationName::CXXLiteralOperatorName:
562   case DeclarationName::CXXUsingDirective:
563     OS << Name;
564     return;
565
566   case DeclarationName::CXXConstructorName:
567   case DeclarationName::CXXDestructorName:
568   case DeclarationName::CXXConversionFunctionName:
569     if (TypeSourceInfo *TInfo = LocInfo.NamedType.TInfo) {
570       if (Name.getNameKind() == DeclarationName::CXXDestructorName)
571         OS << '~';
572       else if (Name.getNameKind() == DeclarationName::CXXConversionFunctionName)
573         OS << "operator ";
574       LangOptions LO;
575       LO.CPlusPlus = true;
576       LO.Bool = true;
577       OS << TInfo->getType().getAsString(PrintingPolicy(LO));
578     } else
579       OS << Name;
580     return;
581   }
582   llvm_unreachable("Unexpected declaration name kind");
583 }
584
585 SourceLocation DeclarationNameInfo::getEndLoc() const {
586   switch (Name.getNameKind()) {
587   case DeclarationName::Identifier:
588     return NameLoc;
589
590   case DeclarationName::CXXOperatorName: {
591     unsigned raw = LocInfo.CXXOperatorName.EndOpNameLoc;
592     return SourceLocation::getFromRawEncoding(raw);
593   }
594
595   case DeclarationName::CXXLiteralOperatorName: {
596     unsigned raw = LocInfo.CXXLiteralOperatorName.OpNameLoc;
597     return SourceLocation::getFromRawEncoding(raw);
598   }
599
600   case DeclarationName::CXXConstructorName:
601   case DeclarationName::CXXDestructorName:
602   case DeclarationName::CXXConversionFunctionName:
603     if (TypeSourceInfo *TInfo = LocInfo.NamedType.TInfo)
604       return TInfo->getTypeLoc().getEndLoc();
605     else
606       return NameLoc;
607
608     // DNInfo work in progress: FIXME.
609   case DeclarationName::ObjCZeroArgSelector:
610   case DeclarationName::ObjCOneArgSelector:
611   case DeclarationName::ObjCMultiArgSelector:
612   case DeclarationName::CXXUsingDirective:
613     return NameLoc;
614   }
615   llvm_unreachable("Unexpected declaration name kind");
616 }