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 /// 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 
     71   void Profile(llvm::FoldingSetNodeID &FSID) {
     72     FSID.AddPointer(ID);
     73   }
     74 };
     75 
     76 static int compareInt(unsigned A, unsigned B) {
     77   return (A < B ? -1 : (A > B ? 1 : 0));
     78 }
     79 
     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 
    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 
    165 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 
    202 bool DeclarationName::isDependentName() const {
    203   QualType T = getCXXNameType();
    204   return !T.isNull() && T->isDependentType();
    205 }
    206 
    207 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 
    214 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 
    284 QualType DeclarationName::getCXXNameType() const {
    285   if (CXXSpecialName *CXXName = getAsCXXSpecialName())
    286     return CXXName->Type;
    287   else
    288     return QualType();
    289 }
    290 
    291 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 
    301 IdentifierInfo *DeclarationName::getCXXLiteralIdentifier() const {
    302   if (CXXLiteralOperatorIdName *CXXLit = getAsCXXLiteralOperatorIdName())
    303     return CXXLit->ID;
    304   else
    305     return 0;
    306 }
    307 
    308 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 
    326 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 
    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 
    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 
    383 void DeclarationName::dump() const {
    384   printName(llvm::errs());
    385   llvm::errs() << '\n';
    386 }
    387 
    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 
    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
    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
    457 DeclarationNameTable::getCXXOperatorName(OverloadedOperatorKind Op) {
    458   return DeclarationName(&CXXOperatorNames[(unsigned)Op]);
    459 }
    460 
    461 DeclarationName
    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>::
    486 getHashValue(clang::DeclarationName N) {
    487   return DenseMapInfo<void*>::getHashValue(N.getAsOpaquePtr());
    488 }
    489 
    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 
    516 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 
    538 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 
    560 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 
    567 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 
    596 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