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   llvm_unreachable("This should be unreachable!");
    197 }
    198 
    199 bool DeclarationName::isDependentName() const {
    200   QualType T = getCXXNameType();
    201   return !T.isNull() && T->isDependentType();
    202 }
    203 
    204 std::string DeclarationName::getAsString() const {
    205   std::string Result;
    206   llvm::raw_string_ostream OS(Result);
    207   printName(OS);
    208   return OS.str();
    209 }
    210 
    211 void DeclarationName::printName(raw_ostream &OS) const {
    212   switch (getNameKind()) {
    213   case Identifier:
    214     if (const IdentifierInfo *II = getAsIdentifierInfo())
    215       OS << II->getName();
    216     return;
    217 
    218   case ObjCZeroArgSelector:
    219   case ObjCOneArgSelector:
    220   case ObjCMultiArgSelector:
    221     OS << getObjCSelector().getAsString();
    222     return;
    223 
    224   case CXXConstructorName: {
    225     QualType ClassType = getCXXNameType();
    226     if (const RecordType *ClassRec = ClassType->getAs<RecordType>())
    227       OS << *ClassRec->getDecl();
    228     else
    229       OS << ClassType.getAsString();
    230     return;
    231   }
    232 
    233   case CXXDestructorName: {
    234     OS << '~';
    235     QualType Type = getCXXNameType();
    236     if (const RecordType *Rec = Type->getAs<RecordType>())
    237       OS << *Rec->getDecl();
    238     else
    239       OS << Type.getAsString();
    240     return;
    241   }
    242 
    243   case CXXOperatorName: {
    244     static const char* const OperatorNames[NUM_OVERLOADED_OPERATORS] = {
    245       0,
    246 #define OVERLOADED_OPERATOR(Name,Spelling,Token,Unary,Binary,MemberOnly) \
    247       Spelling,
    248 #include "clang/Basic/OperatorKinds.def"
    249     };
    250     const char *OpName = OperatorNames[getCXXOverloadedOperator()];
    251     assert(OpName && "not an overloaded operator");
    252 
    253     OS << "operator";
    254     if (OpName[0] >= 'a' && OpName[0] <= 'z')
    255       OS << ' ';
    256     OS << OpName;
    257     return;
    258   }
    259 
    260   case CXXLiteralOperatorName:
    261     OS << "operator \"\" " << getCXXLiteralIdentifier()->getName();
    262     return;
    263 
    264   case CXXConversionFunctionName: {
    265     OS << "operator ";
    266     QualType Type = getCXXNameType();
    267     if (const RecordType *Rec = Type->getAs<RecordType>())
    268       OS << *Rec->getDecl();
    269     else
    270       OS << Type.getAsString();
    271     return;
    272   }
    273   case CXXUsingDirective:
    274     OS << "<using-directive>";
    275     return;
    276   }
    277 
    278   llvm_unreachable("Unexpected declaration name kind");
    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 0;
    303 }
    304 
    305 Selector DeclarationName::getObjCSelector() const {
    306   switch (getNameKind()) {
    307   case ObjCZeroArgSelector:
    308     return Selector(reinterpret_cast<IdentifierInfo *>(Ptr & ~PtrMask), 0);
    309 
    310   case ObjCOneArgSelector:
    311     return Selector(reinterpret_cast<IdentifierInfo *>(Ptr & ~PtrMask), 1);
    312 
    313   case ObjCMultiArgSelector:
    314     return Selector(reinterpret_cast<MultiKeywordSelector *>(Ptr & ~PtrMask));
    315 
    316   default:
    317     break;
    318   }
    319 
    320   return Selector();
    321 }
    322 
    323 void *DeclarationName::getFETokenInfoAsVoid() const {
    324   switch (getNameKind()) {
    325   case Identifier:
    326     return getAsIdentifierInfo()->getFETokenInfo<void>();
    327 
    328   case CXXConstructorName:
    329   case CXXDestructorName:
    330   case CXXConversionFunctionName:
    331     return getAsCXXSpecialName()->FETokenInfo;
    332 
    333   case CXXOperatorName:
    334     return getAsCXXOperatorIdName()->FETokenInfo;
    335 
    336   case CXXLiteralOperatorName:
    337     return getCXXLiteralIdentifier()->getFETokenInfo<void>();
    338 
    339   default:
    340     llvm_unreachable("Declaration name has no FETokenInfo");
    341   }
    342 }
    343 
    344 void DeclarationName::setFETokenInfo(void *T) {
    345   switch (getNameKind()) {
    346   case Identifier:
    347     getAsIdentifierInfo()->setFETokenInfo(T);
    348     break;
    349 
    350   case CXXConstructorName:
    351   case CXXDestructorName:
    352   case CXXConversionFunctionName:
    353     getAsCXXSpecialName()->FETokenInfo = T;
    354     break;
    355 
    356   case CXXOperatorName:
    357     getAsCXXOperatorIdName()->FETokenInfo = T;
    358     break;
    359 
    360   case CXXLiteralOperatorName:
    361     getCXXLiteralIdentifier()->setFETokenInfo(T);
    362     break;
    363 
    364   default:
    365     llvm_unreachable("Declaration name has no FETokenInfo");
    366   }
    367 }
    368 
    369 DeclarationName DeclarationName::getUsingDirectiveName() {
    370   // Single instance of DeclarationNameExtra for using-directive
    371   static const DeclarationNameExtra UDirExtra =
    372     { DeclarationNameExtra::CXXUsingDirective };
    373 
    374   uintptr_t Ptr = reinterpret_cast<uintptr_t>(&UDirExtra);
    375   Ptr |= StoredDeclarationNameExtra;
    376 
    377   return DeclarationName(Ptr);
    378 }
    379 
    380 void DeclarationName::dump() const {
    381   printName(llvm::errs());
    382   llvm::errs() << '\n';
    383 }
    384 
    385 DeclarationNameTable::DeclarationNameTable(const ASTContext &C) : Ctx(C) {
    386   CXXSpecialNamesImpl = new llvm::FoldingSet<CXXSpecialName>;
    387   CXXLiteralOperatorNames = new llvm::FoldingSet<CXXLiteralOperatorIdName>;
    388 
    389   // Initialize the overloaded operator names.
    390   CXXOperatorNames = new (Ctx) CXXOperatorIdName[NUM_OVERLOADED_OPERATORS];
    391   for (unsigned Op = 0; Op < NUM_OVERLOADED_OPERATORS; ++Op) {
    392     CXXOperatorNames[Op].ExtraKindOrNumArgs
    393       = Op + DeclarationNameExtra::CXXConversionFunction;
    394     CXXOperatorNames[Op].FETokenInfo = 0;
    395   }
    396 }
    397 
    398 DeclarationNameTable::~DeclarationNameTable() {
    399   llvm::FoldingSet<CXXSpecialName> *SpecialNames =
    400     static_cast<llvm::FoldingSet<CXXSpecialName>*>(CXXSpecialNamesImpl);
    401   llvm::FoldingSet<CXXLiteralOperatorIdName> *LiteralNames
    402     = static_cast<llvm::FoldingSet<CXXLiteralOperatorIdName>*>
    403         (CXXLiteralOperatorNames);
    404 
    405   delete SpecialNames;
    406   delete LiteralNames;
    407 }
    408 
    409 DeclarationName
    410 DeclarationNameTable::getCXXSpecialName(DeclarationName::NameKind Kind,
    411                                         CanQualType Ty) {
    412   assert(Kind >= DeclarationName::CXXConstructorName &&
    413          Kind <= DeclarationName::CXXConversionFunctionName &&
    414          "Kind must be a C++ special name kind");
    415   llvm::FoldingSet<CXXSpecialName> *SpecialNames
    416     = static_cast<llvm::FoldingSet<CXXSpecialName>*>(CXXSpecialNamesImpl);
    417 
    418   DeclarationNameExtra::ExtraKind EKind;
    419   switch (Kind) {
    420   case DeclarationName::CXXConstructorName:
    421     EKind = DeclarationNameExtra::CXXConstructor;
    422     assert(!Ty.hasQualifiers() &&"Constructor type must be unqualified");
    423     break;
    424   case DeclarationName::CXXDestructorName:
    425     EKind = DeclarationNameExtra::CXXDestructor;
    426     assert(!Ty.hasQualifiers() && "Destructor type must be unqualified");
    427     break;
    428   case DeclarationName::CXXConversionFunctionName:
    429     EKind = DeclarationNameExtra::CXXConversionFunction;
    430     break;
    431   default:
    432     return DeclarationName();
    433   }
    434 
    435   // Unique selector, to guarantee there is one per name.
    436   llvm::FoldingSetNodeID ID;
    437   ID.AddInteger(EKind);
    438   ID.AddPointer(Ty.getAsOpaquePtr());
    439 
    440   void *InsertPos = 0;
    441   if (CXXSpecialName *Name = SpecialNames->FindNodeOrInsertPos(ID, InsertPos))
    442     return DeclarationName(Name);
    443 
    444   CXXSpecialName *SpecialName = new (Ctx) CXXSpecialName;
    445   SpecialName->ExtraKindOrNumArgs = EKind;
    446   SpecialName->Type = Ty;
    447   SpecialName->FETokenInfo = 0;
    448 
    449   SpecialNames->InsertNode(SpecialName, InsertPos);
    450   return DeclarationName(SpecialName);
    451 }
    452 
    453 DeclarationName
    454 DeclarationNameTable::getCXXOperatorName(OverloadedOperatorKind Op) {
    455   return DeclarationName(&CXXOperatorNames[(unsigned)Op]);
    456 }
    457 
    458 DeclarationName
    459 DeclarationNameTable::getCXXLiteralOperatorName(IdentifierInfo *II) {
    460   llvm::FoldingSet<CXXLiteralOperatorIdName> *LiteralNames
    461     = static_cast<llvm::FoldingSet<CXXLiteralOperatorIdName>*>
    462                                                       (CXXLiteralOperatorNames);
    463 
    464   llvm::FoldingSetNodeID ID;
    465   ID.AddPointer(II);
    466 
    467   void *InsertPos = 0;
    468   if (CXXLiteralOperatorIdName *Name =
    469                                LiteralNames->FindNodeOrInsertPos(ID, InsertPos))
    470     return DeclarationName (Name);
    471 
    472   CXXLiteralOperatorIdName *LiteralName = new (Ctx) CXXLiteralOperatorIdName;
    473   LiteralName->ExtraKindOrNumArgs = DeclarationNameExtra::CXXLiteralOperator;
    474   LiteralName->ID = II;
    475 
    476   LiteralNames->InsertNode(LiteralName, InsertPos);
    477   return DeclarationName(LiteralName);
    478 }
    479 
    480 unsigned
    481 llvm::DenseMapInfo<clang::DeclarationName>::
    482 getHashValue(clang::DeclarationName N) {
    483   return DenseMapInfo<void*>::getHashValue(N.getAsOpaquePtr());
    484 }
    485 
    486 DeclarationNameLoc::DeclarationNameLoc(DeclarationName Name) {
    487   switch (Name.getNameKind()) {
    488   case DeclarationName::Identifier:
    489     break;
    490   case DeclarationName::CXXConstructorName:
    491   case DeclarationName::CXXDestructorName:
    492   case DeclarationName::CXXConversionFunctionName:
    493     NamedType.TInfo = 0;
    494     break;
    495   case DeclarationName::CXXOperatorName:
    496     CXXOperatorName.BeginOpNameLoc = SourceLocation().getRawEncoding();
    497     CXXOperatorName.EndOpNameLoc = SourceLocation().getRawEncoding();
    498     break;
    499   case DeclarationName::CXXLiteralOperatorName:
    500     CXXLiteralOperatorName.OpNameLoc = SourceLocation().getRawEncoding();
    501     break;
    502   case DeclarationName::ObjCZeroArgSelector:
    503   case DeclarationName::ObjCOneArgSelector:
    504   case DeclarationName::ObjCMultiArgSelector:
    505     // FIXME: ?
    506     break;
    507   case DeclarationName::CXXUsingDirective:
    508     break;
    509   }
    510 }
    511 
    512 bool DeclarationNameInfo::containsUnexpandedParameterPack() const {
    513   switch (Name.getNameKind()) {
    514   case DeclarationName::Identifier:
    515   case DeclarationName::ObjCZeroArgSelector:
    516   case DeclarationName::ObjCOneArgSelector:
    517   case DeclarationName::ObjCMultiArgSelector:
    518   case DeclarationName::CXXOperatorName:
    519   case DeclarationName::CXXLiteralOperatorName:
    520   case DeclarationName::CXXUsingDirective:
    521     return false;
    522 
    523   case DeclarationName::CXXConstructorName:
    524   case DeclarationName::CXXDestructorName:
    525   case DeclarationName::CXXConversionFunctionName:
    526     if (TypeSourceInfo *TInfo = LocInfo.NamedType.TInfo)
    527       return TInfo->getType()->containsUnexpandedParameterPack();
    528 
    529     return Name.getCXXNameType()->containsUnexpandedParameterPack();
    530   }
    531   llvm_unreachable("All name kinds handled.");
    532 }
    533 
    534 bool DeclarationNameInfo::isInstantiationDependent() const {
    535   switch (Name.getNameKind()) {
    536   case DeclarationName::Identifier:
    537   case DeclarationName::ObjCZeroArgSelector:
    538   case DeclarationName::ObjCOneArgSelector:
    539   case DeclarationName::ObjCMultiArgSelector:
    540   case DeclarationName::CXXOperatorName:
    541   case DeclarationName::CXXLiteralOperatorName:
    542   case DeclarationName::CXXUsingDirective:
    543     return false;
    544 
    545   case DeclarationName::CXXConstructorName:
    546   case DeclarationName::CXXDestructorName:
    547   case DeclarationName::CXXConversionFunctionName:
    548     if (TypeSourceInfo *TInfo = LocInfo.NamedType.TInfo)
    549       return TInfo->getType()->isInstantiationDependentType();
    550 
    551     return Name.getCXXNameType()->isInstantiationDependentType();
    552   }
    553   llvm_unreachable("All name kinds handled.");
    554 }
    555 
    556 std::string DeclarationNameInfo::getAsString() const {
    557   std::string Result;
    558   llvm::raw_string_ostream OS(Result);
    559   printName(OS);
    560   return OS.str();
    561 }
    562 
    563 void DeclarationNameInfo::printName(raw_ostream &OS) const {
    564   switch (Name.getNameKind()) {
    565   case DeclarationName::Identifier:
    566   case DeclarationName::ObjCZeroArgSelector:
    567   case DeclarationName::ObjCOneArgSelector:
    568   case DeclarationName::ObjCMultiArgSelector:
    569   case DeclarationName::CXXOperatorName:
    570   case DeclarationName::CXXLiteralOperatorName:
    571   case DeclarationName::CXXUsingDirective:
    572     Name.printName(OS);
    573     return;
    574 
    575   case DeclarationName::CXXConstructorName:
    576   case DeclarationName::CXXDestructorName:
    577   case DeclarationName::CXXConversionFunctionName:
    578     if (TypeSourceInfo *TInfo = LocInfo.NamedType.TInfo) {
    579       if (Name.getNameKind() == DeclarationName::CXXDestructorName)
    580         OS << '~';
    581       else if (Name.getNameKind() == DeclarationName::CXXConversionFunctionName)
    582         OS << "operator ";
    583       OS << TInfo->getType().getAsString();
    584     }
    585     else
    586       Name.printName(OS);
    587     return;
    588   }
    589   llvm_unreachable("Unexpected declaration name kind");
    590 }
    591 
    592 SourceLocation DeclarationNameInfo::getEndLoc() const {
    593   switch (Name.getNameKind()) {
    594   case DeclarationName::Identifier:
    595     return NameLoc;
    596 
    597   case DeclarationName::CXXOperatorName: {
    598     unsigned raw = LocInfo.CXXOperatorName.EndOpNameLoc;
    599     return SourceLocation::getFromRawEncoding(raw);
    600   }
    601 
    602   case DeclarationName::CXXLiteralOperatorName: {
    603     unsigned raw = LocInfo.CXXLiteralOperatorName.OpNameLoc;
    604     return SourceLocation::getFromRawEncoding(raw);
    605   }
    606 
    607   case DeclarationName::CXXConstructorName:
    608   case DeclarationName::CXXDestructorName:
    609   case DeclarationName::CXXConversionFunctionName:
    610     if (TypeSourceInfo *TInfo = LocInfo.NamedType.TInfo)
    611       return TInfo->getTypeLoc().getEndLoc();
    612     else
    613       return NameLoc;
    614 
    615     // DNInfo work in progress: FIXME.
    616   case DeclarationName::ObjCZeroArgSelector:
    617   case DeclarationName::ObjCOneArgSelector:
    618   case DeclarationName::ObjCMultiArgSelector:
    619   case DeclarationName::CXXUsingDirective:
    620     return NameLoc;
    621   }
    622   llvm_unreachable("Unexpected declaration name kind");
    623 }
    624