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