diff options
Diffstat (limited to 'contrib/llvm/tools/clang/lib/Sema/SemaCodeComplete.cpp')
-rw-r--r-- | contrib/llvm/tools/clang/lib/Sema/SemaCodeComplete.cpp | 316 |
1 files changed, 233 insertions, 83 deletions
diff --git a/contrib/llvm/tools/clang/lib/Sema/SemaCodeComplete.cpp b/contrib/llvm/tools/clang/lib/Sema/SemaCodeComplete.cpp index 94cfc4b..4de7d42 100644 --- a/contrib/llvm/tools/clang/lib/Sema/SemaCodeComplete.cpp +++ b/contrib/llvm/tools/clang/lib/Sema/SemaCodeComplete.cpp @@ -1334,8 +1334,9 @@ static void AddTypeSpecifierResults(const LangOptions &LangOpts, Builder.AddChunk(CodeCompletionString::CK_RightParen); Results.AddResult(Result(Builder.TakeString())); } - } - + } else + Results.AddResult(Result("__auto_type", CCP_Type)); + // GNU extensions if (LangOpts.GNUMode) { // FIXME: Enable when we actually support decimal floating point. @@ -1370,6 +1371,21 @@ static void AddStorageSpecifiers(Sema::ParserCompletionContext CCC, // in C++0x as a type specifier. Results.AddResult(Result("extern")); Results.AddResult(Result("static")); + + if (LangOpts.CPlusPlus11) { + CodeCompletionAllocator &Allocator = Results.getAllocator(); + CodeCompletionBuilder Builder(Allocator, Results.getCodeCompletionTUInfo()); + + // alignas + Builder.AddTypedTextChunk("alignas"); + Builder.AddChunk(CodeCompletionString::CK_LeftParen); + Builder.AddPlaceholderChunk("expression"); + Builder.AddChunk(CodeCompletionString::CK_RightParen); + Results.AddResult(Result(Builder.TakeString())); + + Results.AddResult(Result("constexpr")); + Results.AddResult(Result("thread_local")); + } } static void AddFunctionSpecifiers(Sema::ParserCompletionContext CCC, @@ -1527,6 +1543,21 @@ static void addThisCompletion(Sema &S, ResultBuilder &Results) { Results.AddResult(CodeCompletionResult(Builder.TakeString())); } +static void AddStaticAssertResult(CodeCompletionBuilder &Builder, + ResultBuilder &Results, + const LangOptions &LangOpts) { + if (!LangOpts.CPlusPlus11) + return; + + Builder.AddTypedTextChunk("static_assert"); + Builder.AddChunk(CodeCompletionString::CK_LeftParen); + Builder.AddPlaceholderChunk("expression"); + Builder.AddChunk(CodeCompletionString::CK_Comma); + Builder.AddPlaceholderChunk("message"); + Builder.AddChunk(CodeCompletionString::CK_RightParen); + Results.AddResult(CodeCompletionResult(Builder.TakeString())); +} + /// \brief Add language constructs that show up for "ordinary" names. static void AddOrdinaryNameResults(Sema::ParserCompletionContext CCC, Scope *S, @@ -1611,6 +1642,8 @@ static void AddOrdinaryNameResults(Sema::ParserCompletionContext CCC, Results.AddResult(Result(Builder.TakeString())); } + AddStaticAssertResult(Builder, Results, SemaRef.getLangOpts()); + if (CCC == Sema::PCC_Class) { AddTypedefResult(Results); @@ -1824,13 +1857,17 @@ static void AddOrdinaryNameResults(Sema::ParserCompletionContext CCC, Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace); Builder.AddPlaceholderChunk("identifier"); Results.AddResult(Result(Builder.TakeString())); + + AddStaticAssertResult(Builder, Results, SemaRef.getLangOpts()); } + LLVM_FALLTHROUGH; // Fall through (for statement expressions). case Sema::PCC_ForInit: case Sema::PCC_Condition: AddStorageSpecifiers(CCC, SemaRef.getLangOpts(), Results); // Fall through: conditions and statements can have expressions. + LLVM_FALLTHROUGH; case Sema::PCC_ParenthesizedExpression: if (SemaRef.getLangOpts().ObjCAutoRefCount && @@ -1860,6 +1897,7 @@ static void AddOrdinaryNameResults(Sema::ParserCompletionContext CCC, Results.AddResult(Result(Builder.TakeString())); } // Fall through + LLVM_FALLTHROUGH; case Sema::PCC_Expression: { if (SemaRef.getLangOpts().CPlusPlus) { @@ -2253,6 +2291,15 @@ static std::string FormatFunctionParameter(const PrintingPolicy &Policy, FunctionProtoTypeLoc BlockProto; findTypeLocationForBlockDecl(Param->getTypeSourceInfo(), Block, BlockProto, SuppressBlock); + // Try to retrieve the block type information from the property if this is a + // parameter in a setter. + if (!Block && ObjCMethodParam && + cast<ObjCMethodDecl>(Param->getDeclContext())->isPropertyAccessor()) { + if (const auto *PD = cast<ObjCMethodDecl>(Param->getDeclContext()) + ->findPropertyDecl(/*CheckOverrides=*/false)) + findTypeLocationForBlockDecl(PD->getTypeSourceInfo(), Block, BlockProto, + SuppressBlock); + } if (!Block) { // We were unable to find a FunctionProtoTypeLoc with parameter names @@ -2351,6 +2398,34 @@ formatBlockPlaceholder(const PrintingPolicy &Policy, const NamedDecl *BlockDecl, return Result; } +static std::string GetDefaultValueString(const ParmVarDecl *Param, + const SourceManager &SM, + const LangOptions &LangOpts) { + const SourceRange SrcRange = Param->getDefaultArgRange(); + CharSourceRange CharSrcRange = CharSourceRange::getTokenRange(SrcRange); + bool Invalid = CharSrcRange.isInvalid(); + if (Invalid) + return ""; + StringRef srcText = Lexer::getSourceText(CharSrcRange, SM, LangOpts, &Invalid); + if (Invalid) + return ""; + + if (srcText.empty() || srcText == "=") { + // Lexer can't determine the value. + // This happens if the code is incorrect (for example class is forward declared). + return ""; + } + std::string DefValue(srcText.str()); + // FIXME: remove this check if the Lexer::getSourceText value is fixed and + // this value always has (or always does not have) '=' in front of it + if (DefValue.at(0) != '=') { + // If we don't have '=' in front of value. + // Lexer returns built-in types values without '=' and user-defined types values with it. + return " = " + DefValue; + } + return " " + DefValue; +} + /// \brief Add function parameter chunks to the given code completion string. static void AddFunctionParameterChunks(Preprocessor &PP, const PrintingPolicy &Policy, @@ -2384,6 +2459,8 @@ static void AddFunctionParameterChunks(Preprocessor &PP, // Format the placeholder string. std::string PlaceholderStr = FormatFunctionParameter(Policy, Param); + if (Param->hasDefaultArg()) + PlaceholderStr += GetDefaultValueString(Param, PP.getSourceManager(), PP.getLangOpts()); if (Function->isVariadic() && P == N - 1) PlaceholderStr += ", ..."; @@ -2585,6 +2662,7 @@ static void AddTypedNameChunk(ASTContext &Context, const PrintingPolicy &Policy, Result.getAllocator().CopyString(ND->getNameAsString())); break; + case DeclarationName::CXXDeductionGuideName: case DeclarationName::CXXUsingDirective: case DeclarationName::ObjCZeroArgSelector: case DeclarationName::ObjCOneArgSelector: @@ -2690,7 +2768,7 @@ CodeCompletionResult::CreateCodeCompletionString(ASTContext &Ctx, // Format a function-like macro with placeholders for the arguments. Result.AddChunk(CodeCompletionString::CK_LeftParen); - MacroInfo::arg_iterator A = MI->arg_begin(), AEnd = MI->arg_end(); + MacroInfo::param_iterator A = MI->param_begin(), AEnd = MI->param_end(); // C99 variadic macros add __VA_ARGS__ at the end. Skip it. if (MI->isC99Varargs()) { @@ -2701,8 +2779,8 @@ CodeCompletionResult::CreateCodeCompletionString(ASTContext &Ctx, } } - for (MacroInfo::arg_iterator A = MI->arg_begin(); A != AEnd; ++A) { - if (A != MI->arg_begin()) + for (MacroInfo::param_iterator A = MI->param_begin(); A != AEnd; ++A) { + if (A != MI->param_begin()) Result.AddChunk(CodeCompletionString::CK_Comma); if (MI->isVariadic() && (A+1) == AEnd) { @@ -2964,10 +3042,14 @@ static void AddOverloadParameterChunks(ASTContext &Context, // Format the placeholder string. std::string Placeholder; - if (Function) - Placeholder = FormatFunctionParameter(Policy, Function->getParamDecl(P)); - else + if (Function) { + const ParmVarDecl *Param = Function->getParamDecl(P); + Placeholder = FormatFunctionParameter(Policy, Param); + if (Param->hasDefaultArg()) + Placeholder += GetDefaultValueString(Param, Context.getSourceManager(), Context.getLangOpts()); + } else { Placeholder = Prototype->getParamType(P).getAsString(Policy); + } if (P == CurrentArg) Result.AddCurrentParameterChunk( @@ -3482,6 +3564,11 @@ void Sema::CodeCompleteDeclSpec(Scope *S, DeclSpec &DS, Results.AddResult(Result("restrict")); if (getLangOpts().CPlusPlus) { + if (getLangOpts().CPlusPlus11 && + (DS.getTypeSpecType() == DeclSpec::TST_class || + DS.getTypeSpecType() == DeclSpec::TST_struct)) + Results.AddResult("final"); + if (AllowNonIdentifiers) { Results.AddResult(Result("operator")); } @@ -3819,6 +3906,41 @@ static void AddObjCProperties( } } +static void AddRecordMembersCompletionResults(Sema &SemaRef, + ResultBuilder &Results, Scope *S, + QualType BaseType, + RecordDecl *RD) { + // Indicate that we are performing a member access, and the cv-qualifiers + // for the base object type. + Results.setObjectTypeQualifiers(BaseType.getQualifiers()); + + // Access to a C/C++ class, struct, or union. + Results.allowNestedNameSpecifiers(); + CodeCompletionDeclConsumer Consumer(Results, SemaRef.CurContext); + SemaRef.LookupVisibleDecls(RD, Sema::LookupMemberName, Consumer, + SemaRef.CodeCompleter->includeGlobals(), + /*IncludeDependentBases=*/true); + + if (SemaRef.getLangOpts().CPlusPlus) { + if (!Results.empty()) { + // The "template" keyword can follow "->" or "." in the grammar. + // However, we only want to suggest the template keyword if something + // is dependent. + bool IsDependent = BaseType->isDependentType(); + if (!IsDependent) { + for (Scope *DepScope = S; DepScope; DepScope = DepScope->getParent()) + if (DeclContext *Ctx = DepScope->getEntity()) { + IsDependent = Ctx->isDependentContext(); + break; + } + } + + if (IsDependent) + Results.AddResult(CodeCompletionResult("template")); + } + } +} + void Sema::CodeCompleteMemberReferenceExpr(Scope *S, Expr *Base, SourceLocation OpLoc, bool IsArrow, bool IsBaseExprStatement) { @@ -3829,8 +3951,6 @@ void Sema::CodeCompleteMemberReferenceExpr(Scope *S, Expr *Base, if (ConvertedBase.isInvalid()) return; Base = ConvertedBase.get(); - - typedef CodeCompletionResult Result; QualType BaseType = Base->getType(); @@ -3865,34 +3985,18 @@ void Sema::CodeCompleteMemberReferenceExpr(Scope *S, Expr *Base, &ResultBuilder::IsMember); Results.EnterNewScope(); if (const RecordType *Record = BaseType->getAs<RecordType>()) { - // Indicate that we are performing a member access, and the cv-qualifiers - // for the base object type. - Results.setObjectTypeQualifiers(BaseType.getQualifiers()); - - // Access to a C/C++ class, struct, or union. - Results.allowNestedNameSpecifiers(); - CodeCompletionDeclConsumer Consumer(Results, CurContext); - LookupVisibleDecls(Record->getDecl(), LookupMemberName, Consumer, - CodeCompleter->includeGlobals()); - - if (getLangOpts().CPlusPlus) { - if (!Results.empty()) { - // The "template" keyword can follow "->" or "." in the grammar. - // However, we only want to suggest the template keyword if something - // is dependent. - bool IsDependent = BaseType->isDependentType(); - if (!IsDependent) { - for (Scope *DepScope = S; DepScope; DepScope = DepScope->getParent()) - if (DeclContext *Ctx = DepScope->getEntity()) { - IsDependent = Ctx->isDependentContext(); - break; - } - } - - if (IsDependent) - Results.AddResult(Result("template")); - } - } + AddRecordMembersCompletionResults(*this, Results, S, BaseType, + Record->getDecl()); + } else if (const auto *TST = BaseType->getAs<TemplateSpecializationType>()) { + TemplateName TN = TST->getTemplateName(); + if (const auto *TD = + dyn_cast_or_null<ClassTemplateDecl>(TN.getAsTemplateDecl())) { + CXXRecordDecl *RD = TD->getTemplatedDecl(); + AddRecordMembersCompletionResults(*this, Results, S, BaseType, RD); + } + } else if (const auto *ICNT = BaseType->getAs<InjectedClassNameType>()) { + if (auto *RD = ICNT->getDecl()) + AddRecordMembersCompletionResults(*this, Results, S, BaseType, RD); } else if (!IsArrow && BaseType->isObjCObjectPointerType()) { // Objective-C property reference. AddedPropertiesSet AddedProperties; @@ -4012,30 +4116,54 @@ void Sema::CodeCompleteTag(Scope *S, unsigned TagSpec) { Results.data(),Results.size()); } -void Sema::CodeCompleteTypeQualifiers(DeclSpec &DS) { - ResultBuilder Results(*this, CodeCompleter->getAllocator(), - CodeCompleter->getCodeCompletionTUInfo(), - CodeCompletionContext::CCC_TypeQualifiers); - Results.EnterNewScope(); +static void AddTypeQualifierResults(DeclSpec &DS, ResultBuilder &Results, + const LangOptions &LangOpts) { if (!(DS.getTypeQualifiers() & DeclSpec::TQ_const)) Results.AddResult("const"); if (!(DS.getTypeQualifiers() & DeclSpec::TQ_volatile)) Results.AddResult("volatile"); - if (getLangOpts().C99 && - !(DS.getTypeQualifiers() & DeclSpec::TQ_restrict)) + if (LangOpts.C99 && !(DS.getTypeQualifiers() & DeclSpec::TQ_restrict)) Results.AddResult("restrict"); - if (getLangOpts().C11 && - !(DS.getTypeQualifiers() & DeclSpec::TQ_atomic)) + if (LangOpts.C11 && !(DS.getTypeQualifiers() & DeclSpec::TQ_atomic)) Results.AddResult("_Atomic"); - if (getLangOpts().MSVCCompat && - !(DS.getTypeQualifiers() & DeclSpec::TQ_unaligned)) + if (LangOpts.MSVCCompat && !(DS.getTypeQualifiers() & DeclSpec::TQ_unaligned)) Results.AddResult("__unaligned"); +} + +void Sema::CodeCompleteTypeQualifiers(DeclSpec &DS) { + ResultBuilder Results(*this, CodeCompleter->getAllocator(), + CodeCompleter->getCodeCompletionTUInfo(), + CodeCompletionContext::CCC_TypeQualifiers); + Results.EnterNewScope(); + AddTypeQualifierResults(DS, Results, LangOpts); Results.ExitScope(); HandleCodeCompleteResults(this, CodeCompleter, Results.getCompletionContext(), Results.data(), Results.size()); } +void Sema::CodeCompleteFunctionQualifiers(DeclSpec &DS, Declarator &D, + const VirtSpecifiers *VS) { + ResultBuilder Results(*this, CodeCompleter->getAllocator(), + CodeCompleter->getCodeCompletionTUInfo(), + CodeCompletionContext::CCC_TypeQualifiers); + Results.EnterNewScope(); + AddTypeQualifierResults(DS, Results, LangOpts); + if (LangOpts.CPlusPlus11) { + Results.AddResult("noexcept"); + if (D.getContext() == Declarator::MemberContext && !D.isCtorOrDtor() && + !D.isStaticMember()) { + if (!VS || !VS->isFinalSpecified()) + Results.AddResult("final"); + if (!VS || !VS->isOverrideSpecified()) + Results.AddResult("override"); + } + } + Results.ExitScope(); + HandleCodeCompleteResults(this, CodeCompleter, Results.getCompletionContext(), + Results.data(), Results.size()); +} + void Sema::CodeCompleteBracketDeclarator(Scope *S) { CodeCompleteExpression(S, QualType(getASTContext().getSizeType())); } @@ -4244,7 +4372,10 @@ void Sema::CodeCompleteCall(Scope *S, Expr *Fn, ArrayRef<Expr *> Args) { UME->copyTemplateArgumentsInto(TemplateArgsBuffer); TemplateArgs = &TemplateArgsBuffer; } - SmallVector<Expr *, 12> ArgExprs(1, UME->getBase()); + + // Add the base as first argument (use a nullptr if the base is implicit). + SmallVector<Expr *, 12> ArgExprs( + 1, UME->isImplicitAccess() ? nullptr : UME->getBase()); ArgExprs.append(Args.begin(), Args.end()); UnresolvedSet<8> Decls; Decls.append(UME->decls_begin(), UME->decls_end()); @@ -4445,8 +4576,10 @@ void Sema::CodeCompleteQualifiedId(Scope *S, CXXScopeSpec &SS, bool EnteringContext) { if (!SS.getScopeRep() || !CodeCompleter) return; - - DeclContext *Ctx = computeDeclContext(SS, EnteringContext); + + // Always pretend to enter a context to ensure that a dependent type + // resolves to a dependent record. + DeclContext *Ctx = computeDeclContext(SS, /*EnteringContext=*/true); if (!Ctx) return; @@ -4476,7 +4609,9 @@ void Sema::CodeCompleteQualifiedId(Scope *S, CXXScopeSpec &SS, Results.ExitScope(); CodeCompletionDeclConsumer Consumer(Results, CurContext); - LookupVisibleDecls(Ctx, LookupOrdinaryName, Consumer); + LookupVisibleDecls(Ctx, LookupOrdinaryName, Consumer, + /*IncludeGlobalScope=*/true, + /*IncludeDependentBases=*/true); HandleCodeCompleteResults(this, CodeCompleter, Results.getCompletionContext(), @@ -5230,24 +5365,22 @@ namespace { /// when it has the same number of parameters as we have selector identifiers. /// /// \param Results the structure into which we'll add results. -static void AddObjCMethods(ObjCContainerDecl *Container, - bool WantInstanceMethods, - ObjCMethodKind WantKind, +static void AddObjCMethods(ObjCContainerDecl *Container, + bool WantInstanceMethods, ObjCMethodKind WantKind, ArrayRef<IdentifierInfo *> SelIdents, DeclContext *CurContext, - VisitedSelectorSet &Selectors, - bool AllowSameLength, - ResultBuilder &Results, - bool InOriginalClass = true) { + VisitedSelectorSet &Selectors, bool AllowSameLength, + ResultBuilder &Results, bool InOriginalClass = true, + bool IsRootClass = false) { typedef CodeCompletionResult Result; Container = getContainerDef(Container); ObjCInterfaceDecl *IFace = dyn_cast<ObjCInterfaceDecl>(Container); - bool isRootClass = IFace && !IFace->getSuperClass(); + IsRootClass = IsRootClass || (IFace && !IFace->getSuperClass()); for (auto *M : Container->methods()) { // The instance methods on the root class can be messaged via the // metaclass. if (M->isInstanceMethod() == WantInstanceMethods || - (isRootClass && !WantInstanceMethods)) { + (IsRootClass && !WantInstanceMethods)) { // Check whether the selector identifiers we've been given are a // subset of the identifiers for this particular method. if (!isAcceptableObjCMethod(M, WantKind, SelIdents, AllowSameLength)) @@ -5273,8 +5406,8 @@ static void AddObjCMethods(ObjCContainerDecl *Container, for (ObjCList<ObjCProtocolDecl>::iterator I = Protocols.begin(), E = Protocols.end(); I != E; ++I) - AddObjCMethods(*I, WantInstanceMethods, WantKind, SelIdents, - CurContext, Selectors, AllowSameLength, Results, false); + AddObjCMethods(*I, WantInstanceMethods, WantKind, SelIdents, CurContext, + Selectors, AllowSameLength, Results, false, IsRootClass); } } @@ -5283,43 +5416,43 @@ static void AddObjCMethods(ObjCContainerDecl *Container, // Add methods in protocols. for (auto *I : IFace->protocols()) - AddObjCMethods(I, WantInstanceMethods, WantKind, SelIdents, - CurContext, Selectors, AllowSameLength, Results, false); - + AddObjCMethods(I, WantInstanceMethods, WantKind, SelIdents, CurContext, + Selectors, AllowSameLength, Results, false, IsRootClass); + // Add methods in categories. for (auto *CatDecl : IFace->known_categories()) { AddObjCMethods(CatDecl, WantInstanceMethods, WantKind, SelIdents, - CurContext, Selectors, AllowSameLength, - Results, InOriginalClass); - + CurContext, Selectors, AllowSameLength, Results, + InOriginalClass, IsRootClass); + // Add a categories protocol methods. const ObjCList<ObjCProtocolDecl> &Protocols = CatDecl->getReferencedProtocols(); for (ObjCList<ObjCProtocolDecl>::iterator I = Protocols.begin(), E = Protocols.end(); I != E; ++I) - AddObjCMethods(*I, WantInstanceMethods, WantKind, SelIdents, - CurContext, Selectors, AllowSameLength, - Results, false); - + AddObjCMethods(*I, WantInstanceMethods, WantKind, SelIdents, CurContext, + Selectors, AllowSameLength, Results, false, IsRootClass); + // Add methods in category implementations. if (ObjCCategoryImplDecl *Impl = CatDecl->getImplementation()) - AddObjCMethods(Impl, WantInstanceMethods, WantKind, SelIdents, - CurContext, Selectors, AllowSameLength, - Results, InOriginalClass); + AddObjCMethods(Impl, WantInstanceMethods, WantKind, SelIdents, CurContext, + Selectors, AllowSameLength, Results, InOriginalClass, + IsRootClass); } // Add methods in superclass. + // Avoid passing in IsRootClass since root classes won't have super classes. if (IFace->getSuperClass()) - AddObjCMethods(IFace->getSuperClass(), WantInstanceMethods, WantKind, - SelIdents, CurContext, Selectors, - AllowSameLength, Results, false); + AddObjCMethods(IFace->getSuperClass(), WantInstanceMethods, WantKind, + SelIdents, CurContext, Selectors, AllowSameLength, Results, + /*IsRootClass=*/false); // Add methods in our implementation, if any. if (ObjCImplementationDecl *Impl = IFace->getImplementation()) - AddObjCMethods(Impl, WantInstanceMethods, WantKind, SelIdents, - CurContext, Selectors, AllowSameLength, - Results, InOriginalClass); + AddObjCMethods(Impl, WantInstanceMethods, WantKind, SelIdents, CurContext, + Selectors, AllowSameLength, Results, InOriginalClass, + IsRootClass); } @@ -7736,6 +7869,23 @@ void Sema::CodeCompleteNaturalLanguage() { nullptr, 0); } +void Sema::CodeCompleteAvailabilityPlatformName() { + ResultBuilder Results(*this, CodeCompleter->getAllocator(), + CodeCompleter->getCodeCompletionTUInfo(), + CodeCompletionContext::CCC_Other); + Results.EnterNewScope(); + static const char *Platforms[] = {"macOS", "iOS", "watchOS", "tvOS"}; + for (const char *Platform : llvm::makeArrayRef(Platforms)) { + Results.AddResult(CodeCompletionResult(Platform)); + Results.AddResult(CodeCompletionResult(Results.getAllocator().CopyString( + Twine(Platform) + "ApplicationExtension"))); + } + Results.ExitScope(); + HandleCodeCompleteResults(this, CodeCompleter, + CodeCompletionContext::CCC_Other, Results.data(), + Results.size()); +} + void Sema::GatherGlobalCodeCompletions(CodeCompletionAllocator &Allocator, CodeCompletionTUInfo &CCTUInfo, SmallVectorImpl<CodeCompletionResult> &Results) { |