CodeCompleteConsumer.cpp 20 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663
  1. //===--- CodeCompleteConsumer.cpp - Code Completion Interface ---*- 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 CodeCompleteConsumer class.
  11. //
  12. //===----------------------------------------------------------------------===//
  13. #include "clang/Sema/CodeCompleteConsumer.h"
  14. #include "clang-c/Index.h"
  15. #include "clang/AST/DeclCXX.h"
  16. #include "clang/AST/DeclObjC.h"
  17. #include "clang/AST/DeclTemplate.h"
  18. #include "clang/Sema/Scope.h"
  19. #include "clang/Sema/Sema.h"
  20. #include "clang/Lex/Preprocessor.h"
  21. #include "llvm/ADT/STLExtras.h"
  22. #include "llvm/ADT/SmallString.h"
  23. #include "llvm/ADT/Twine.h"
  24. #include "llvm/Support/raw_ostream.h"
  25. #include <algorithm>
  26. #include <cstring>
  27. #include <functional>
  28. using namespace clang;
  29. //===----------------------------------------------------------------------===//
  30. // Code completion context implementation
  31. //===----------------------------------------------------------------------===//
  32. bool CodeCompletionContext::wantConstructorResults() const {
  33. switch (Kind) {
  34. case CCC_Recovery:
  35. case CCC_Statement:
  36. case CCC_Expression:
  37. case CCC_ObjCMessageReceiver:
  38. case CCC_ParenthesizedExpression:
  39. return true;
  40. case CCC_TopLevel:
  41. case CCC_ObjCInterface:
  42. case CCC_ObjCImplementation:
  43. case CCC_ObjCIvarList:
  44. case CCC_ClassStructUnion:
  45. case CCC_DotMemberAccess:
  46. case CCC_ArrowMemberAccess:
  47. case CCC_ObjCPropertyAccess:
  48. case CCC_EnumTag:
  49. case CCC_UnionTag:
  50. case CCC_ClassOrStructTag:
  51. case CCC_ObjCProtocolName:
  52. case CCC_Namespace:
  53. case CCC_Type:
  54. case CCC_Name:
  55. case CCC_PotentiallyQualifiedName:
  56. case CCC_MacroName:
  57. case CCC_MacroNameUse:
  58. case CCC_PreprocessorExpression:
  59. case CCC_PreprocessorDirective:
  60. case CCC_NaturalLanguage:
  61. case CCC_SelectorName:
  62. case CCC_TypeQualifiers:
  63. case CCC_Other:
  64. case CCC_OtherWithMacros:
  65. case CCC_ObjCInstanceMessage:
  66. case CCC_ObjCClassMessage:
  67. case CCC_ObjCInterfaceName:
  68. case CCC_ObjCCategoryName:
  69. return false;
  70. }
  71. llvm_unreachable("Invalid CodeCompletionContext::Kind!");
  72. }
  73. //===----------------------------------------------------------------------===//
  74. // Code completion string implementation
  75. //===----------------------------------------------------------------------===//
  76. CodeCompletionString::Chunk::Chunk(ChunkKind Kind, const char *Text)
  77. : Kind(Kind), Text("")
  78. {
  79. switch (Kind) {
  80. case CK_TypedText:
  81. case CK_Text:
  82. case CK_Placeholder:
  83. case CK_Informative:
  84. case CK_ResultType:
  85. case CK_CurrentParameter:
  86. this->Text = Text;
  87. break;
  88. case CK_Optional:
  89. llvm_unreachable("Optional strings cannot be created from text");
  90. case CK_LeftParen:
  91. this->Text = "(";
  92. break;
  93. case CK_RightParen:
  94. this->Text = ")";
  95. break;
  96. case CK_LeftBracket:
  97. this->Text = "[";
  98. break;
  99. case CK_RightBracket:
  100. this->Text = "]";
  101. break;
  102. case CK_LeftBrace:
  103. this->Text = "{";
  104. break;
  105. case CK_RightBrace:
  106. this->Text = "}";
  107. break;
  108. case CK_LeftAngle:
  109. this->Text = "<";
  110. break;
  111. case CK_RightAngle:
  112. this->Text = ">";
  113. break;
  114. case CK_Comma:
  115. this->Text = ", ";
  116. break;
  117. case CK_Colon:
  118. this->Text = ":";
  119. break;
  120. case CK_SemiColon:
  121. this->Text = ";";
  122. break;
  123. case CK_Equal:
  124. this->Text = " = ";
  125. break;
  126. case CK_HorizontalSpace:
  127. this->Text = " ";
  128. break;
  129. case CK_VerticalSpace:
  130. this->Text = "\n";
  131. break;
  132. }
  133. }
  134. CodeCompletionString::Chunk
  135. CodeCompletionString::Chunk::CreateText(const char *Text) {
  136. return Chunk(CK_Text, Text);
  137. }
  138. CodeCompletionString::Chunk
  139. CodeCompletionString::Chunk::CreateOptional(CodeCompletionString *Optional) {
  140. Chunk Result;
  141. Result.Kind = CK_Optional;
  142. Result.Optional = Optional;
  143. return Result;
  144. }
  145. CodeCompletionString::Chunk
  146. CodeCompletionString::Chunk::CreatePlaceholder(const char *Placeholder) {
  147. return Chunk(CK_Placeholder, Placeholder);
  148. }
  149. CodeCompletionString::Chunk
  150. CodeCompletionString::Chunk::CreateInformative(const char *Informative) {
  151. return Chunk(CK_Informative, Informative);
  152. }
  153. CodeCompletionString::Chunk
  154. CodeCompletionString::Chunk::CreateResultType(const char *ResultType) {
  155. return Chunk(CK_ResultType, ResultType);
  156. }
  157. CodeCompletionString::Chunk
  158. CodeCompletionString::Chunk::CreateCurrentParameter(
  159. const char *CurrentParameter) {
  160. return Chunk(CK_CurrentParameter, CurrentParameter);
  161. }
  162. CodeCompletionString::CodeCompletionString(const Chunk *Chunks,
  163. unsigned NumChunks,
  164. unsigned Priority,
  165. CXAvailabilityKind Availability,
  166. const char **Annotations,
  167. unsigned NumAnnotations,
  168. StringRef ParentName,
  169. const char *BriefComment)
  170. : NumChunks(NumChunks), NumAnnotations(NumAnnotations),
  171. Priority(Priority), Availability(Availability),
  172. ParentName(ParentName), BriefComment(BriefComment)
  173. {
  174. assert(NumChunks <= 0xffff);
  175. assert(NumAnnotations <= 0xffff);
  176. Chunk *StoredChunks = reinterpret_cast<Chunk *>(this + 1);
  177. for (unsigned I = 0; I != NumChunks; ++I)
  178. StoredChunks[I] = Chunks[I];
  179. const char **StoredAnnotations = reinterpret_cast<const char **>(StoredChunks + NumChunks);
  180. for (unsigned I = 0; I != NumAnnotations; ++I)
  181. StoredAnnotations[I] = Annotations[I];
  182. }
  183. unsigned CodeCompletionString::getAnnotationCount() const {
  184. return NumAnnotations;
  185. }
  186. const char *CodeCompletionString::getAnnotation(unsigned AnnotationNr) const {
  187. if (AnnotationNr < NumAnnotations)
  188. return reinterpret_cast<const char * const*>(end())[AnnotationNr];
  189. else
  190. return nullptr;
  191. }
  192. std::string CodeCompletionString::getAsString() const {
  193. std::string Result;
  194. llvm::raw_string_ostream OS(Result);
  195. for (iterator C = begin(), CEnd = end(); C != CEnd; ++C) {
  196. switch (C->Kind) {
  197. case CK_Optional: OS << "{#" << C->Optional->getAsString() << "#}"; break;
  198. case CK_Placeholder: OS << "<#" << C->Text << "#>"; break;
  199. case CK_Informative:
  200. case CK_ResultType:
  201. OS << "[#" << C->Text << "#]";
  202. break;
  203. case CK_CurrentParameter: OS << "<#" << C->Text << "#>"; break;
  204. default: OS << C->Text; break;
  205. }
  206. }
  207. return OS.str();
  208. }
  209. const char *CodeCompletionString::getTypedText() const {
  210. for (iterator C = begin(), CEnd = end(); C != CEnd; ++C)
  211. if (C->Kind == CK_TypedText)
  212. return C->Text;
  213. return nullptr;
  214. }
  215. const char *CodeCompletionAllocator::CopyString(const Twine &String) {
  216. SmallString<128> Data;
  217. StringRef Ref = String.toStringRef(Data);
  218. // FIXME: It would be more efficient to teach Twine to tell us its size and
  219. // then add a routine there to fill in an allocated char* with the contents
  220. // of the string.
  221. char *Mem = (char *)Allocate(Ref.size() + 1, 1);
  222. std::copy(Ref.begin(), Ref.end(), Mem);
  223. Mem[Ref.size()] = 0;
  224. return Mem;
  225. }
  226. StringRef CodeCompletionTUInfo::getParentName(const DeclContext *DC) {
  227. const NamedDecl *ND = dyn_cast<NamedDecl>(DC);
  228. if (!ND)
  229. return StringRef();
  230. // Check whether we've already cached the parent name.
  231. StringRef &CachedParentName = ParentNames[DC];
  232. if (!CachedParentName.empty())
  233. return CachedParentName;
  234. // If we already processed this DeclContext and assigned empty to it, the
  235. // data pointer will be non-null.
  236. if (CachedParentName.data() != nullptr)
  237. return StringRef();
  238. // Find the interesting names.
  239. SmallVector<const DeclContext *, 2> Contexts;
  240. while (DC && !DC->isFunctionOrMethod()) {
  241. if (const NamedDecl *ND = dyn_cast<NamedDecl>(DC)) {
  242. if (ND->getIdentifier())
  243. Contexts.push_back(DC);
  244. }
  245. DC = DC->getParent();
  246. }
  247. {
  248. SmallString<128> S;
  249. llvm::raw_svector_ostream OS(S);
  250. bool First = true;
  251. for (unsigned I = Contexts.size(); I != 0; --I) {
  252. if (First)
  253. First = false;
  254. else {
  255. OS << "::";
  256. }
  257. const DeclContext *CurDC = Contexts[I-1];
  258. if (const ObjCCategoryImplDecl *CatImpl = dyn_cast<ObjCCategoryImplDecl>(CurDC))
  259. CurDC = CatImpl->getCategoryDecl();
  260. if (const ObjCCategoryDecl *Cat = dyn_cast<ObjCCategoryDecl>(CurDC)) {
  261. const ObjCInterfaceDecl *Interface = Cat->getClassInterface();
  262. if (!Interface) {
  263. // Assign an empty StringRef but with non-null data to distinguish
  264. // between empty because we didn't process the DeclContext yet.
  265. CachedParentName = StringRef((const char *)(uintptr_t)~0U, 0);
  266. return StringRef();
  267. }
  268. OS << Interface->getName() << '(' << Cat->getName() << ')';
  269. } else {
  270. OS << cast<NamedDecl>(CurDC)->getName();
  271. }
  272. }
  273. CachedParentName = AllocatorRef->CopyString(OS.str());
  274. }
  275. return CachedParentName;
  276. }
  277. CodeCompletionString *CodeCompletionBuilder::TakeString() {
  278. void *Mem = getAllocator().Allocate(
  279. sizeof(CodeCompletionString) + sizeof(Chunk) * Chunks.size() +
  280. sizeof(const char *) * Annotations.size(),
  281. alignof(CodeCompletionString));
  282. CodeCompletionString *Result
  283. = new (Mem) CodeCompletionString(Chunks.data(), Chunks.size(),
  284. Priority, Availability,
  285. Annotations.data(), Annotations.size(),
  286. ParentName, BriefComment);
  287. Chunks.clear();
  288. return Result;
  289. }
  290. void CodeCompletionBuilder::AddTypedTextChunk(const char *Text) {
  291. Chunks.push_back(Chunk(CodeCompletionString::CK_TypedText, Text));
  292. }
  293. void CodeCompletionBuilder::AddTextChunk(const char *Text) {
  294. Chunks.push_back(Chunk::CreateText(Text));
  295. }
  296. void CodeCompletionBuilder::AddOptionalChunk(CodeCompletionString *Optional) {
  297. Chunks.push_back(Chunk::CreateOptional(Optional));
  298. }
  299. void CodeCompletionBuilder::AddPlaceholderChunk(const char *Placeholder) {
  300. Chunks.push_back(Chunk::CreatePlaceholder(Placeholder));
  301. }
  302. void CodeCompletionBuilder::AddInformativeChunk(const char *Text) {
  303. Chunks.push_back(Chunk::CreateInformative(Text));
  304. }
  305. void CodeCompletionBuilder::AddResultTypeChunk(const char *ResultType) {
  306. Chunks.push_back(Chunk::CreateResultType(ResultType));
  307. }
  308. void
  309. CodeCompletionBuilder::AddCurrentParameterChunk(const char *CurrentParameter) {
  310. Chunks.push_back(Chunk::CreateCurrentParameter(CurrentParameter));
  311. }
  312. void CodeCompletionBuilder::AddChunk(CodeCompletionString::ChunkKind CK,
  313. const char *Text) {
  314. Chunks.push_back(Chunk(CK, Text));
  315. }
  316. void CodeCompletionBuilder::addParentContext(const DeclContext *DC) {
  317. if (DC->isTranslationUnit()) {
  318. return;
  319. }
  320. if (DC->isFunctionOrMethod())
  321. return;
  322. const NamedDecl *ND = dyn_cast<NamedDecl>(DC);
  323. if (!ND)
  324. return;
  325. ParentName = getCodeCompletionTUInfo().getParentName(DC);
  326. }
  327. void CodeCompletionBuilder::addBriefComment(StringRef Comment) {
  328. BriefComment = Allocator.CopyString(Comment);
  329. }
  330. //===----------------------------------------------------------------------===//
  331. // Code completion overload candidate implementation
  332. //===----------------------------------------------------------------------===//
  333. FunctionDecl *
  334. CodeCompleteConsumer::OverloadCandidate::getFunction() const {
  335. if (getKind() == CK_Function)
  336. return Function;
  337. else if (getKind() == CK_FunctionTemplate)
  338. return FunctionTemplate->getTemplatedDecl();
  339. else
  340. return nullptr;
  341. }
  342. const FunctionType *
  343. CodeCompleteConsumer::OverloadCandidate::getFunctionType() const {
  344. switch (Kind) {
  345. case CK_Function:
  346. return Function->getType()->getAs<FunctionType>();
  347. case CK_FunctionTemplate:
  348. return FunctionTemplate->getTemplatedDecl()->getType()
  349. ->getAs<FunctionType>();
  350. case CK_FunctionType:
  351. return Type;
  352. }
  353. llvm_unreachable("Invalid CandidateKind!");
  354. }
  355. //===----------------------------------------------------------------------===//
  356. // Code completion consumer implementation
  357. //===----------------------------------------------------------------------===//
  358. CodeCompleteConsumer::~CodeCompleteConsumer() { }
  359. bool PrintingCodeCompleteConsumer::isResultFilteredOut(StringRef Filter,
  360. CodeCompletionResult Result) {
  361. switch (Result.Kind) {
  362. case CodeCompletionResult::RK_Declaration: {
  363. return !(Result.Declaration->getIdentifier() &&
  364. Result.Declaration->getIdentifier()->getName().startswith(Filter));
  365. }
  366. case CodeCompletionResult::RK_Keyword: {
  367. return !StringRef(Result.Keyword).startswith(Filter);
  368. }
  369. case CodeCompletionResult::RK_Macro: {
  370. return !Result.Macro->getName().startswith(Filter);
  371. }
  372. case CodeCompletionResult::RK_Pattern: {
  373. return !StringRef(Result.Pattern->getAsString()).startswith(Filter);
  374. }
  375. }
  376. llvm_unreachable("Unknown code completion result Kind.");
  377. }
  378. void
  379. PrintingCodeCompleteConsumer::ProcessCodeCompleteResults(Sema &SemaRef,
  380. CodeCompletionContext Context,
  381. CodeCompletionResult *Results,
  382. unsigned NumResults) {
  383. std::stable_sort(Results, Results + NumResults);
  384. StringRef Filter = SemaRef.getPreprocessor().getCodeCompletionFilter();
  385. // Print the results.
  386. for (unsigned I = 0; I != NumResults; ++I) {
  387. if(!Filter.empty() && isResultFilteredOut(Filter, Results[I]))
  388. continue;
  389. OS << "COMPLETION: ";
  390. switch (Results[I].Kind) {
  391. case CodeCompletionResult::RK_Declaration:
  392. OS << *Results[I].Declaration;
  393. if (Results[I].Hidden)
  394. OS << " (Hidden)";
  395. if (CodeCompletionString *CCS
  396. = Results[I].CreateCodeCompletionString(SemaRef, Context,
  397. getAllocator(),
  398. CCTUInfo,
  399. includeBriefComments())) {
  400. OS << " : " << CCS->getAsString();
  401. if (const char *BriefComment = CCS->getBriefComment())
  402. OS << " : " << BriefComment;
  403. }
  404. OS << '\n';
  405. break;
  406. case CodeCompletionResult::RK_Keyword:
  407. OS << Results[I].Keyword << '\n';
  408. break;
  409. case CodeCompletionResult::RK_Macro: {
  410. OS << Results[I].Macro->getName();
  411. if (CodeCompletionString *CCS
  412. = Results[I].CreateCodeCompletionString(SemaRef, Context,
  413. getAllocator(),
  414. CCTUInfo,
  415. includeBriefComments())) {
  416. OS << " : " << CCS->getAsString();
  417. }
  418. OS << '\n';
  419. break;
  420. }
  421. case CodeCompletionResult::RK_Pattern: {
  422. OS << "Pattern : "
  423. << Results[I].Pattern->getAsString() << '\n';
  424. break;
  425. }
  426. }
  427. }
  428. }
  429. // This function is used solely to preserve the former presentation of overloads
  430. // by "clang -cc1 -code-completion-at", since CodeCompletionString::getAsString
  431. // needs to be improved for printing the newer and more detailed overload
  432. // chunks.
  433. static std::string getOverloadAsString(const CodeCompletionString &CCS) {
  434. std::string Result;
  435. llvm::raw_string_ostream OS(Result);
  436. for (auto &C : CCS) {
  437. switch (C.Kind) {
  438. case CodeCompletionString::CK_Informative:
  439. case CodeCompletionString::CK_ResultType:
  440. OS << "[#" << C.Text << "#]";
  441. break;
  442. case CodeCompletionString::CK_CurrentParameter:
  443. OS << "<#" << C.Text << "#>";
  444. break;
  445. default: OS << C.Text; break;
  446. }
  447. }
  448. return OS.str();
  449. }
  450. void
  451. PrintingCodeCompleteConsumer::ProcessOverloadCandidates(Sema &SemaRef,
  452. unsigned CurrentArg,
  453. OverloadCandidate *Candidates,
  454. unsigned NumCandidates) {
  455. for (unsigned I = 0; I != NumCandidates; ++I) {
  456. if (CodeCompletionString *CCS
  457. = Candidates[I].CreateSignatureString(CurrentArg, SemaRef,
  458. getAllocator(), CCTUInfo,
  459. includeBriefComments())) {
  460. OS << "OVERLOAD: " << getOverloadAsString(*CCS) << "\n";
  461. }
  462. }
  463. }
  464. /// \brief Retrieve the effective availability of the given declaration.
  465. static AvailabilityResult getDeclAvailability(const Decl *D) {
  466. AvailabilityResult AR = D->getAvailability();
  467. if (isa<EnumConstantDecl>(D))
  468. AR = std::max(AR, cast<Decl>(D->getDeclContext())->getAvailability());
  469. return AR;
  470. }
  471. void CodeCompletionResult::computeCursorKindAndAvailability(bool Accessible) {
  472. switch (Kind) {
  473. case RK_Pattern:
  474. if (!Declaration) {
  475. // Do nothing: Patterns can come with cursor kinds!
  476. break;
  477. }
  478. // Fall through
  479. case RK_Declaration: {
  480. // Set the availability based on attributes.
  481. switch (getDeclAvailability(Declaration)) {
  482. case AR_Available:
  483. case AR_NotYetIntroduced:
  484. Availability = CXAvailability_Available;
  485. break;
  486. case AR_Deprecated:
  487. Availability = CXAvailability_Deprecated;
  488. break;
  489. case AR_Unavailable:
  490. Availability = CXAvailability_NotAvailable;
  491. break;
  492. }
  493. if (const FunctionDecl *Function = dyn_cast<FunctionDecl>(Declaration))
  494. if (Function->isDeleted())
  495. Availability = CXAvailability_NotAvailable;
  496. CursorKind = getCursorKindForDecl(Declaration);
  497. if (CursorKind == CXCursor_UnexposedDecl) {
  498. // FIXME: Forward declarations of Objective-C classes and protocols
  499. // are not directly exposed, but we want code completion to treat them
  500. // like a definition.
  501. if (isa<ObjCInterfaceDecl>(Declaration))
  502. CursorKind = CXCursor_ObjCInterfaceDecl;
  503. else if (isa<ObjCProtocolDecl>(Declaration))
  504. CursorKind = CXCursor_ObjCProtocolDecl;
  505. else
  506. CursorKind = CXCursor_NotImplemented;
  507. }
  508. break;
  509. }
  510. case RK_Macro:
  511. case RK_Keyword:
  512. llvm_unreachable("Macro and keyword kinds are handled by the constructors");
  513. }
  514. if (!Accessible)
  515. Availability = CXAvailability_NotAccessible;
  516. }
  517. /// \brief Retrieve the name that should be used to order a result.
  518. ///
  519. /// If the name needs to be constructed as a string, that string will be
  520. /// saved into Saved and the returned StringRef will refer to it.
  521. static StringRef getOrderedName(const CodeCompletionResult &R,
  522. std::string &Saved) {
  523. switch (R.Kind) {
  524. case CodeCompletionResult::RK_Keyword:
  525. return R.Keyword;
  526. case CodeCompletionResult::RK_Pattern:
  527. return R.Pattern->getTypedText();
  528. case CodeCompletionResult::RK_Macro:
  529. return R.Macro->getName();
  530. case CodeCompletionResult::RK_Declaration:
  531. // Handle declarations below.
  532. break;
  533. }
  534. DeclarationName Name = R.Declaration->getDeclName();
  535. // If the name is a simple identifier (by far the common case), or a
  536. // zero-argument selector, just return a reference to that identifier.
  537. if (IdentifierInfo *Id = Name.getAsIdentifierInfo())
  538. return Id->getName();
  539. if (Name.isObjCZeroArgSelector())
  540. if (IdentifierInfo *Id
  541. = Name.getObjCSelector().getIdentifierInfoForSlot(0))
  542. return Id->getName();
  543. Saved = Name.getAsString();
  544. return Saved;
  545. }
  546. bool clang::operator<(const CodeCompletionResult &X,
  547. const CodeCompletionResult &Y) {
  548. std::string XSaved, YSaved;
  549. StringRef XStr = getOrderedName(X, XSaved);
  550. StringRef YStr = getOrderedName(Y, YSaved);
  551. int cmp = XStr.compare_lower(YStr);
  552. if (cmp)
  553. return cmp < 0;
  554. // If case-insensitive comparison fails, try case-sensitive comparison.
  555. cmp = XStr.compare(YStr);
  556. if (cmp)
  557. return cmp < 0;
  558. return false;
  559. }