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