diff options
| author | 2019-01-27 16:42:12 +0000 | |
|---|---|---|
| committer | 2019-01-27 16:42:12 +0000 | |
| commit | b773203fb58f3ef282fb69c832d8710cab5bc82d (patch) | |
| tree | e75913f147570fbd75169647b144df85b88a038c /gnu/llvm/tools/clang/lib/Sema/CodeCompleteConsumer.cpp | |
| parent | tweak errno in previous (diff) | |
| download | wireguard-openbsd-b773203fb58f3ef282fb69c832d8710cab5bc82d.tar.xz wireguard-openbsd-b773203fb58f3ef282fb69c832d8710cab5bc82d.zip | |
Import LLVM 7.0.1 release including clang, lld and lldb.
Diffstat (limited to 'gnu/llvm/tools/clang/lib/Sema/CodeCompleteConsumer.cpp')
| -rw-r--r-- | gnu/llvm/tools/clang/lib/Sema/CodeCompleteConsumer.cpp | 270 |
1 files changed, 181 insertions, 89 deletions
diff --git a/gnu/llvm/tools/clang/lib/Sema/CodeCompleteConsumer.cpp b/gnu/llvm/tools/clang/lib/Sema/CodeCompleteConsumer.cpp index 3431ddcf70a..8af54b99393 100644 --- a/gnu/llvm/tools/clang/lib/Sema/CodeCompleteConsumer.cpp +++ b/gnu/llvm/tools/clang/lib/Sema/CodeCompleteConsumer.cpp @@ -1,4 +1,4 @@ -//===--- CodeCompleteConsumer.cpp - Code Completion Interface ---*- C++ -*-===// +//===- CodeCompleteConsumer.cpp - Code Completion Interface ---------------===// // // The LLVM Compiler Infrastructure // @@ -10,21 +10,30 @@ // This file implements the CodeCompleteConsumer class. // //===----------------------------------------------------------------------===// + #include "clang/Sema/CodeCompleteConsumer.h" #include "clang-c/Index.h" -#include "clang/AST/DeclCXX.h" +#include "clang/AST/Decl.h" +#include "clang/AST/DeclBase.h" #include "clang/AST/DeclObjC.h" #include "clang/AST/DeclTemplate.h" -#include "clang/Sema/Scope.h" +#include "clang/AST/DeclarationName.h" +#include "clang/AST/Type.h" +#include "clang/Basic/IdentifierTable.h" #include "clang/Sema/Sema.h" #include "clang/Lex/Preprocessor.h" -#include "llvm/ADT/STLExtras.h" #include "llvm/ADT/SmallString.h" +#include "llvm/ADT/SmallVector.h" +#include "llvm/ADT/StringRef.h" #include "llvm/ADT/Twine.h" +#include "llvm/Support/Casting.h" +#include "llvm/Support/Compiler.h" +#include "llvm/Support/ErrorHandling.h" #include "llvm/Support/raw_ostream.h" #include <algorithm> -#include <cstring> -#include <functional> +#include <cassert> +#include <cstdint> +#include <string> using namespace clang; @@ -33,14 +42,14 @@ using namespace clang; //===----------------------------------------------------------------------===// bool CodeCompletionContext::wantConstructorResults() const { - switch (Kind) { + switch (CCKind) { case CCC_Recovery: case CCC_Statement: case CCC_Expression: case CCC_ObjCMessageReceiver: case CCC_ParenthesizedExpression: return true; - + case CCC_TopLevel: case CCC_ObjCInterface: case CCC_ObjCImplementation: @@ -76,12 +85,87 @@ bool CodeCompletionContext::wantConstructorResults() const { llvm_unreachable("Invalid CodeCompletionContext::Kind!"); } +StringRef clang::getCompletionKindString(CodeCompletionContext::Kind Kind) { + using CCKind = CodeCompletionContext::Kind; + switch (Kind) { + case CCKind::CCC_Other: + return "Other"; + case CCKind::CCC_OtherWithMacros: + return "OtherWithMacros"; + case CCKind::CCC_TopLevel: + return "TopLevel"; + case CCKind::CCC_ObjCInterface: + return "ObjCInterface"; + case CCKind::CCC_ObjCImplementation: + return "ObjCImplementation"; + case CCKind::CCC_ObjCIvarList: + return "ObjCIvarList"; + case CCKind::CCC_ClassStructUnion: + return "ClassStructUnion"; + case CCKind::CCC_Statement: + return "Statement"; + case CCKind::CCC_Expression: + return "Expression"; + case CCKind::CCC_ObjCMessageReceiver: + return "ObjCMessageReceiver"; + case CCKind::CCC_DotMemberAccess: + return "DotMemberAccess"; + case CCKind::CCC_ArrowMemberAccess: + return "ArrowMemberAccess"; + case CCKind::CCC_ObjCPropertyAccess: + return "ObjCPropertyAccess"; + case CCKind::CCC_EnumTag: + return "EnumTag"; + case CCKind::CCC_UnionTag: + return "UnionTag"; + case CCKind::CCC_ClassOrStructTag: + return "ClassOrStructTag"; + case CCKind::CCC_ObjCProtocolName: + return "ObjCProtocolName"; + case CCKind::CCC_Namespace: + return "Namespace"; + case CCKind::CCC_Type: + return "Type"; + case CCKind::CCC_Name: + return "Name"; + case CCKind::CCC_PotentiallyQualifiedName: + return "PotentiallyQualifiedName"; + case CCKind::CCC_MacroName: + return "MacroName"; + case CCKind::CCC_MacroNameUse: + return "MacroNameUse"; + case CCKind::CCC_PreprocessorExpression: + return "PreprocessorExpression"; + case CCKind::CCC_PreprocessorDirective: + return "PreprocessorDirective"; + case CCKind::CCC_NaturalLanguage: + return "NaturalLanguage"; + case CCKind::CCC_SelectorName: + return "SelectorName"; + case CCKind::CCC_TypeQualifiers: + return "TypeQualifiers"; + case CCKind::CCC_ParenthesizedExpression: + return "ParenthesizedExpression"; + case CCKind::CCC_ObjCInstanceMessage: + return "ObjCInstanceMessage"; + case CCKind::CCC_ObjCClassMessage: + return "ObjCClassMessage"; + case CCKind::CCC_ObjCInterfaceName: + return "ObjCInterfaceName"; + case CCKind::CCC_ObjCCategoryName: + return "ObjCCategoryName"; + case CCKind::CCC_Recovery: + return "Recovery"; + } + llvm_unreachable("Invalid CodeCompletionContext::Kind!"); +} + //===----------------------------------------------------------------------===// // Code completion string implementation //===----------------------------------------------------------------------===// -CodeCompletionString::Chunk::Chunk(ChunkKind Kind, const char *Text) - : Kind(Kind), Text("") -{ + +CodeCompletionString::Chunk::Chunk(ChunkKind Kind, const char *Text) + : Kind(Kind), Text("") { switch (Kind) { case CK_TypedText: case CK_Text: @@ -94,7 +178,7 @@ CodeCompletionString::Chunk::Chunk(ChunkKind Kind, const char *Text) case CK_Optional: llvm_unreachable("Optional strings cannot be created from text"); - + case CK_LeftParen: this->Text = "("; break; @@ -106,11 +190,11 @@ CodeCompletionString::Chunk::Chunk(ChunkKind Kind, const char *Text) case CK_LeftBracket: this->Text = "["; break; - + case CK_RightBracket: this->Text = "]"; break; - + case CK_LeftBrace: this->Text = "{"; break; @@ -122,11 +206,11 @@ CodeCompletionString::Chunk::Chunk(ChunkKind Kind, const char *Text) case CK_LeftAngle: this->Text = "<"; break; - + case CK_RightAngle: this->Text = ">"; break; - + case CK_Comma: this->Text = ", "; break; @@ -158,7 +242,7 @@ CodeCompletionString::Chunk::CreateText(const char *Text) { return Chunk(CK_Text, Text); } -CodeCompletionString::Chunk +CodeCompletionString::Chunk CodeCompletionString::Chunk::CreateOptional(CodeCompletionString *Optional) { Chunk Result; Result.Kind = CK_Optional; @@ -166,39 +250,38 @@ CodeCompletionString::Chunk::CreateOptional(CodeCompletionString *Optional) { return Result; } -CodeCompletionString::Chunk +CodeCompletionString::Chunk CodeCompletionString::Chunk::CreatePlaceholder(const char *Placeholder) { return Chunk(CK_Placeholder, Placeholder); } -CodeCompletionString::Chunk +CodeCompletionString::Chunk CodeCompletionString::Chunk::CreateInformative(const char *Informative) { return Chunk(CK_Informative, Informative); } -CodeCompletionString::Chunk +CodeCompletionString::Chunk CodeCompletionString::Chunk::CreateResultType(const char *ResultType) { return Chunk(CK_ResultType, ResultType); } -CodeCompletionString::Chunk +CodeCompletionString::Chunk CodeCompletionString::Chunk::CreateCurrentParameter( const char *CurrentParameter) { return Chunk(CK_CurrentParameter, CurrentParameter); } -CodeCompletionString::CodeCompletionString(const Chunk *Chunks, +CodeCompletionString::CodeCompletionString(const Chunk *Chunks, unsigned NumChunks, - unsigned Priority, + unsigned Priority, CXAvailabilityKind Availability, const char **Annotations, unsigned NumAnnotations, StringRef ParentName, const char *BriefComment) - : NumChunks(NumChunks), NumAnnotations(NumAnnotations), - Priority(Priority), Availability(Availability), - ParentName(ParentName), BriefComment(BriefComment) -{ + : NumChunks(NumChunks), NumAnnotations(NumAnnotations), + Priority(Priority), Availability(Availability), + ParentName(ParentName), BriefComment(BriefComment) { assert(NumChunks <= 0xffff); assert(NumAnnotations <= 0xffff); @@ -222,21 +305,20 @@ const char *CodeCompletionString::getAnnotation(unsigned AnnotationNr) const { return nullptr; } - std::string CodeCompletionString::getAsString() const { std::string Result; llvm::raw_string_ostream OS(Result); - + for (iterator C = begin(), CEnd = end(); C != CEnd; ++C) { switch (C->Kind) { case CK_Optional: OS << "{#" << C->Optional->getAsString() << "#}"; break; case CK_Placeholder: OS << "<#" << C->Text << "#>"; break; - - case CK_Informative: + + case CK_Informative: case CK_ResultType: - OS << "[#" << C->Text << "#]"; + OS << "[#" << C->Text << "#]"; break; - + case CK_CurrentParameter: OS << "<#" << C->Text << "#>"; break; default: OS << C->Text; break; } @@ -267,8 +349,8 @@ const char *CodeCompletionAllocator::CopyString(const Twine &String) { StringRef CodeCompletionTUInfo::getParentName(const DeclContext *DC) { const NamedDecl *ND = dyn_cast<NamedDecl>(DC); if (!ND) - return StringRef(); - + return {}; + // Check whether we've already cached the parent name. StringRef &CachedParentName = ParentNames[DC]; if (!CachedParentName.empty()) @@ -277,7 +359,7 @@ StringRef CodeCompletionTUInfo::getParentName(const DeclContext *DC) { // If we already processed this DeclContext and assigned empty to it, the // data pointer will be non-null. if (CachedParentName.data() != nullptr) - return StringRef(); + return {}; // Find the interesting names. SmallVector<const DeclContext *, 2> Contexts; @@ -286,7 +368,7 @@ StringRef CodeCompletionTUInfo::getParentName(const DeclContext *DC) { if (ND->getIdentifier()) Contexts.push_back(DC); } - + DC = DC->getParent(); } @@ -300,26 +382,26 @@ StringRef CodeCompletionTUInfo::getParentName(const DeclContext *DC) { else { OS << "::"; } - + const DeclContext *CurDC = Contexts[I-1]; if (const ObjCCategoryImplDecl *CatImpl = dyn_cast<ObjCCategoryImplDecl>(CurDC)) CurDC = CatImpl->getCategoryDecl(); - + if (const ObjCCategoryDecl *Cat = dyn_cast<ObjCCategoryDecl>(CurDC)) { const ObjCInterfaceDecl *Interface = Cat->getClassInterface(); if (!Interface) { // Assign an empty StringRef but with non-null data to distinguish // between empty because we didn't process the DeclContext yet. CachedParentName = StringRef((const char *)(uintptr_t)~0U, 0); - return StringRef(); + return {}; } - + OS << Interface->getName() << '(' << Cat->getName() << ')'; } else { OS << cast<NamedDecl>(CurDC)->getName(); } } - + CachedParentName = AllocatorRef->CopyString(OS.str()); } @@ -331,7 +413,7 @@ CodeCompletionString *CodeCompletionBuilder::TakeString() { sizeof(CodeCompletionString) + sizeof(Chunk) * Chunks.size() + sizeof(const char *) * Annotations.size(), alignof(CodeCompletionString)); - CodeCompletionString *Result + CodeCompletionString *Result = new (Mem) CodeCompletionString(Chunks.data(), Chunks.size(), Priority, Availability, Annotations.data(), Annotations.size(), @@ -375,17 +457,16 @@ void CodeCompletionBuilder::AddChunk(CodeCompletionString::ChunkKind CK, } void CodeCompletionBuilder::addParentContext(const DeclContext *DC) { - if (DC->isTranslationUnit()) { + if (DC->isTranslationUnit()) return; - } - + if (DC->isFunctionOrMethod()) return; - + const NamedDecl *ND = dyn_cast<NamedDecl>(DC); if (!ND) return; - + ParentName = getCodeCompletionTUInfo().getParentName(DC); } @@ -411,11 +492,11 @@ CodeCompleteConsumer::OverloadCandidate::getFunctionType() const { switch (Kind) { case CK_Function: return Function->getType()->getAs<FunctionType>(); - + case CK_FunctionTemplate: return FunctionTemplate->getTemplatedDecl()->getType() ->getAs<FunctionType>(); - + case CK_FunctionType: return Type; } @@ -427,35 +508,31 @@ CodeCompleteConsumer::OverloadCandidate::getFunctionType() const { // Code completion consumer implementation //===----------------------------------------------------------------------===// -CodeCompleteConsumer::~CodeCompleteConsumer() { } +CodeCompleteConsumer::~CodeCompleteConsumer() = default; bool PrintingCodeCompleteConsumer::isResultFilteredOut(StringRef Filter, CodeCompletionResult Result) { switch (Result.Kind) { - case CodeCompletionResult::RK_Declaration: { + case CodeCompletionResult::RK_Declaration: return !(Result.Declaration->getIdentifier() && Result.Declaration->getIdentifier()->getName().startswith(Filter)); - } - case CodeCompletionResult::RK_Keyword: { + case CodeCompletionResult::RK_Keyword: return !StringRef(Result.Keyword).startswith(Filter); - } - case CodeCompletionResult::RK_Macro: { + case CodeCompletionResult::RK_Macro: return !Result.Macro->getName().startswith(Filter); - } - case CodeCompletionResult::RK_Pattern: { + case CodeCompletionResult::RK_Pattern: return !StringRef(Result.Pattern->getAsString()).startswith(Filter); } - } llvm_unreachable("Unknown code completion result Kind."); } -void +void PrintingCodeCompleteConsumer::ProcessCodeCompleteResults(Sema &SemaRef, CodeCompletionContext Context, CodeCompletionResult *Results, unsigned NumResults) { std::stable_sort(Results, Results + NumResults); - + StringRef Filter = SemaRef.getPreprocessor().getCodeCompletionFilter(); // Print the results. @@ -468,7 +545,7 @@ PrintingCodeCompleteConsumer::ProcessCodeCompleteResults(Sema &SemaRef, OS << *Results[I].Declaration; if (Results[I].Hidden) OS << " (Hidden)"; - if (CodeCompletionString *CCS + if (CodeCompletionString *CCS = Results[I].CreateCodeCompletionString(SemaRef, Context, getAllocator(), CCTUInfo, @@ -477,17 +554,34 @@ PrintingCodeCompleteConsumer::ProcessCodeCompleteResults(Sema &SemaRef, if (const char *BriefComment = CCS->getBriefComment()) OS << " : " << BriefComment; } - + for (const FixItHint &FixIt : Results[I].FixIts) { + const SourceLocation BLoc = FixIt.RemoveRange.getBegin(); + const SourceLocation ELoc = FixIt.RemoveRange.getEnd(); + + SourceManager &SM = SemaRef.SourceMgr; + std::pair<FileID, unsigned> BInfo = SM.getDecomposedLoc(BLoc); + std::pair<FileID, unsigned> EInfo = SM.getDecomposedLoc(ELoc); + // Adjust for token ranges. + if (FixIt.RemoveRange.isTokenRange()) + EInfo.second += Lexer::MeasureTokenLength(ELoc, SM, SemaRef.LangOpts); + + OS << " (requires fix-it:" + << " {" << SM.getLineNumber(BInfo.first, BInfo.second) << ':' + << SM.getColumnNumber(BInfo.first, BInfo.second) << '-' + << SM.getLineNumber(EInfo.first, EInfo.second) << ':' + << SM.getColumnNumber(EInfo.first, EInfo.second) << "}" + << " to \"" << FixIt.CodeToInsert << "\")"; + } OS << '\n'; break; - + case CodeCompletionResult::RK_Keyword: OS << Results[I].Keyword << '\n'; break; - - case CodeCompletionResult::RK_Macro: { + + case CodeCompletionResult::RK_Macro: OS << Results[I].Macro->getName(); - if (CodeCompletionString *CCS + if (CodeCompletionString *CCS = Results[I].CreateCodeCompletionString(SemaRef, Context, getAllocator(), CCTUInfo, @@ -496,14 +590,12 @@ PrintingCodeCompleteConsumer::ProcessCodeCompleteResults(Sema &SemaRef, } OS << '\n'; break; - } - - case CodeCompletionResult::RK_Pattern: { - OS << "Pattern : " + + case CodeCompletionResult::RK_Pattern: + OS << "Pattern : " << Results[I].Pattern->getAsString() << '\n'; break; } - } } } @@ -532,7 +624,7 @@ static std::string getOverloadAsString(const CodeCompletionString &CCS) { return OS.str(); } -void +void PrintingCodeCompleteConsumer::ProcessOverloadCandidates(Sema &SemaRef, unsigned CurrentArg, OverloadCandidate *Candidates, @@ -547,7 +639,7 @@ PrintingCodeCompleteConsumer::ProcessOverloadCandidates(Sema &SemaRef, } } -/// \brief Retrieve the effective availability of the given declaration. +/// Retrieve the effective availability of the given declaration. static AvailabilityResult getDeclAvailability(const Decl *D) { AvailabilityResult AR = D->getAvailability(); if (isa<EnumConstantDecl>(D)) @@ -563,19 +655,19 @@ void CodeCompletionResult::computeCursorKindAndAvailability(bool Accessible) { break; } LLVM_FALLTHROUGH; - + case RK_Declaration: { // Set the availability based on attributes. switch (getDeclAvailability(Declaration)) { case AR_Available: case AR_NotYetIntroduced: - Availability = CXAvailability_Available; + Availability = CXAvailability_Available; break; - + case AR_Deprecated: Availability = CXAvailability_Deprecated; break; - + case AR_Unavailable: Availability = CXAvailability_NotAvailable; break; @@ -584,11 +676,11 @@ void CodeCompletionResult::computeCursorKindAndAvailability(bool Accessible) { if (const FunctionDecl *Function = dyn_cast<FunctionDecl>(Declaration)) if (Function->isDeleted()) Availability = CXAvailability_NotAvailable; - + CursorKind = getCursorKindForDecl(Declaration); if (CursorKind == CXCursor_UnexposedDecl) { - // FIXME: Forward declarations of Objective-C classes and protocols - // are not directly exposed, but we want code completion to treat them + // FIXME: Forward declarations of Objective-C classes and protocols + // are not directly exposed, but we want code completion to treat them // like a definition. if (isa<ObjCInterfaceDecl>(Declaration)) CursorKind = CXCursor_ObjCInterfaceDecl; @@ -609,7 +701,7 @@ void CodeCompletionResult::computeCursorKindAndAvailability(bool Accessible) { Availability = CXAvailability_NotAccessible; } -/// \brief Retrieve the name that should be used to order a result. +/// Retrieve the name that should be used to order a result. /// /// If the name needs to be constructed as a string, that string will be /// saved into Saved and the returned StringRef will refer to it. @@ -625,9 +717,9 @@ StringRef CodeCompletionResult::getOrderedName(std::string &Saved) const { // Handle declarations below. break; } - + DeclarationName Name = Declaration->getDeclName(); - + // If the name is a simple identifier (by far the common case), or a // zero-argument selector, just return a reference to that identifier. if (IdentifierInfo *Id = Name.getAsIdentifierInfo()) @@ -636,12 +728,12 @@ StringRef CodeCompletionResult::getOrderedName(std::string &Saved) const { if (IdentifierInfo *Id = Name.getObjCSelector().getIdentifierInfoForSlot(0)) return Id->getName(); - + Saved = Name.getAsString(); return Saved; } - -bool clang::operator<(const CodeCompletionResult &X, + +bool clang::operator<(const CodeCompletionResult &X, const CodeCompletionResult &Y) { std::string XSaved, YSaved; StringRef XStr = X.getOrderedName(XSaved); @@ -649,11 +741,11 @@ bool clang::operator<(const CodeCompletionResult &X, int cmp = XStr.compare_lower(YStr); if (cmp) return cmp < 0; - + // If case-insensitive comparison fails, try case-sensitive comparison. cmp = XStr.compare(YStr); if (cmp) return cmp < 0; - + return false; } |
