diff options
author | Douglas Gregor <dgregor@apple.com> | 2010-05-30 01:49:25 +0000 |
---|---|---|
committer | Douglas Gregor <dgregor@apple.com> | 2010-05-30 01:49:25 +0000 |
commit | 7aa6b229fe38bd9577223f21ad0ce57c23258ae4 (patch) | |
tree | fc599ed41df4720f7bc3bbdf2def407a8fb976ef | |
parent | 0e15c9aef62a835c6d111dee723d22fbba5398b8 (diff) | |
download | bcm5719-llvm-7aa6b229fe38bd9577223f21ad0ce57c23258ae4.tar.gz bcm5719-llvm-7aa6b229fe38bd9577223f21ad0ce57c23258ae4.zip |
Teach code completion to adjust its completion priorities based on the
type that we expect to see at a given point in the grammar, e.g., when
initializing a variable, returning a result, or calling a function. We
don't prune the candidate set at all, just adjust priorities to favor
things that should type-check, using an ultra-simplified type system.
llvm-svn: 105128
-rw-r--r-- | clang/include/clang/Parse/Action.h | 22 | ||||
-rw-r--r-- | clang/include/clang/Sema/CodeCompleteConsumer.h | 12 | ||||
-rw-r--r-- | clang/lib/Parse/ParseDecl.cpp | 7 | ||||
-rw-r--r-- | clang/lib/Parse/ParseExpr.cpp | 8 | ||||
-rw-r--r-- | clang/lib/Parse/ParseStmt.cpp | 7 | ||||
-rw-r--r-- | clang/lib/Sema/Sema.h | 5 | ||||
-rw-r--r-- | clang/lib/Sema/SemaCodeComplete.cpp | 268 | ||||
-rw-r--r-- | clang/test/Index/complete-exprs.c | 16 | ||||
-rw-r--r-- | clang/test/Index/complete-type-factors.m | 117 |
9 files changed, 426 insertions, 36 deletions
diff --git a/clang/include/clang/Parse/Action.h b/clang/include/clang/Parse/Action.h index d5488e8210f..74b3b5b7641 100644 --- a/clang/include/clang/Parse/Action.h +++ b/clang/include/clang/Parse/Action.h @@ -2729,7 +2729,27 @@ public: /// \param NumArgs the number of arguments in \p Args. virtual void CodeCompleteCall(Scope *S, ExprTy *Fn, ExprTy **Args, unsigned NumArgs) { } - + + /// \brief Code completion for the initializer of a variable declaration. + /// + /// \param S The scope in which the initializer occurs. + /// + /// \param D The declaration being initialized. + virtual void CodeCompleteInitializer(Scope *S, DeclPtrTy D) { } + + /// \brief Code completion after the "return" keyword within a function. + /// + /// \param S The scope in which the return statement occurs. + virtual void CodeCompleteReturn(Scope *S) { } + + /// \brief Code completion for the right-hand side of an assignment or + /// compound assignment operator. + /// + /// \param S The scope in which the assignment occurs. + /// + /// \param LHS The left-hand side of the assignment expression. + virtual void CodeCompleteAssignmentRHS(Scope *S, ExprTy *LHS) { } + /// \brief Code completion for a C++ nested-name-specifier that precedes a /// qualified-id of some form. /// diff --git a/clang/include/clang/Sema/CodeCompleteConsumer.h b/clang/include/clang/Sema/CodeCompleteConsumer.h index 1f1c0cc1132..fd000b83df1 100644 --- a/clang/include/clang/Sema/CodeCompleteConsumer.h +++ b/clang/include/clang/Sema/CodeCompleteConsumer.h @@ -59,6 +59,18 @@ enum { CCD_InBaseClass = 2 }; +/// \brief Priority value factors by which we will divide or multiply the +/// priority of a code-completion result. +enum { + /// \brief Divide by this factor when a code-completion result's type exactly + /// matches the type we expect. + CCF_ExactTypeMatch = 4, + /// \brief Divide by this factor when a code-completion result's type is + /// similar to the type we expect (e.g., both arithmetic types, both + /// Objective-C object pointer types). + CCF_SimilarTypeMatch = 2 +}; + class FunctionDecl; class FunctionType; class FunctionTemplateDecl; diff --git a/clang/lib/Parse/ParseDecl.cpp b/clang/lib/Parse/ParseDecl.cpp index 76da13500a4..5d52d8b58c6 100644 --- a/clang/lib/Parse/ParseDecl.cpp +++ b/clang/lib/Parse/ParseDecl.cpp @@ -556,6 +556,13 @@ Parser::DeclPtrTy Parser::ParseDeclarationAfterDeclarator(Declarator &D, Actions.ActOnCXXEnterDeclInitializer(CurScope, ThisDecl); } + if (Tok.is(tok::code_completion)) { + Actions.CodeCompleteInitializer(CurScope, ThisDecl); + ConsumeCodeCompletionToken(); + SkipUntil(tok::comma, true, true); + return ThisDecl; + } + OwningExprResult Init(ParseInitializer()); if (getLang().CPlusPlus && D.getCXXScopeSpec().isSet()) { diff --git a/clang/lib/Parse/ParseExpr.cpp b/clang/lib/Parse/ParseExpr.cpp index 0059a9a0fe4..7be1a1994e6 100644 --- a/clang/lib/Parse/ParseExpr.cpp +++ b/clang/lib/Parse/ParseExpr.cpp @@ -343,6 +343,14 @@ Parser::ParseRHSOfBinaryExpression(OwningExprResult LHS, prec::Level MinPrec) { } } + // Code completion for the right-hand side of an assignment expression + // goes through a special hook that takes the left-hand side into account. + if (Tok.is(tok::code_completion) && NextTokPrec == prec::Assignment) { + Actions.CodeCompleteAssignmentRHS(CurScope, LHS.get()); + ConsumeCodeCompletionToken(); + return ExprError(); + } + // Parse another leaf here for the RHS of the operator. // ParseCastExpression works here because all RHS expressions in C have it // as a prefix, at least. However, in C++, an assignment-expression could diff --git a/clang/lib/Parse/ParseStmt.cpp b/clang/lib/Parse/ParseStmt.cpp index 1ca6a0c1c41..f0930a0a1a4 100644 --- a/clang/lib/Parse/ParseStmt.cpp +++ b/clang/lib/Parse/ParseStmt.cpp @@ -1199,6 +1199,13 @@ Parser::OwningStmtResult Parser::ParseReturnStatement(AttributeList *Attr) { OwningExprResult R(Actions); if (Tok.isNot(tok::semi)) { + if (Tok.is(tok::code_completion)) { + Actions.CodeCompleteReturn(CurScope); + ConsumeCodeCompletionToken(); + SkipUntil(tok::semi, false, true); + return StmtError(); + } + R = ParseExpression(); if (R.isInvalid()) { // Skip to the semicolon, but don't consume it. SkipUntil(tok::semi, false, true); diff --git a/clang/lib/Sema/Sema.h b/clang/lib/Sema/Sema.h index 0870cf4646c..7338915ffc4 100644 --- a/clang/lib/Sema/Sema.h +++ b/clang/lib/Sema/Sema.h @@ -4417,6 +4417,7 @@ public: //@{ virtual void CodeCompleteOrdinaryName(Scope *S, CodeCompletionContext CompletionContext); + virtual void CodeCompleteExpression(Scope *S, QualType T); virtual void CodeCompleteMemberReferenceExpr(Scope *S, ExprTy *Base, SourceLocation OpLoc, bool IsArrow); @@ -4424,6 +4425,10 @@ public: virtual void CodeCompleteCase(Scope *S); virtual void CodeCompleteCall(Scope *S, ExprTy *Fn, ExprTy **Args, unsigned NumArgs); + virtual void CodeCompleteInitializer(Scope *S, DeclPtrTy D); + virtual void CodeCompleteReturn(Scope *S); + virtual void CodeCompleteAssignmentRHS(Scope *S, ExprTy *LHS); + virtual void CodeCompleteQualifiedId(Scope *S, CXXScopeSpec &SS, bool EnteringContext); virtual void CodeCompleteUsing(Scope *S); diff --git a/clang/lib/Sema/SemaCodeComplete.cpp b/clang/lib/Sema/SemaCodeComplete.cpp index 876aecbd30a..339c46fde87 100644 --- a/clang/lib/Sema/SemaCodeComplete.cpp +++ b/clang/lib/Sema/SemaCodeComplete.cpp @@ -119,6 +119,13 @@ namespace { /// nested-name-specifiers that would otherwise be filtered out. bool AllowNestedNameSpecifiers; + /// \brief If set, the type that we would prefer our resulting value + /// declarations to have. + /// + /// Closely matching the preferred type gives a boost to a result's + /// priority. + CanQualType PreferredType; + /// \brief A list of shadow maps, which is used to model name hiding at /// different levels of, e.g., the inheritance hierarchy. std::list<ShadowMap> ShadowMaps; @@ -147,6 +154,11 @@ namespace { unsigned size() const { return Results.size(); } bool empty() const { return Results.empty(); } + /// \brief Specify the preferred type. + void setPreferredType(QualType T) { + PreferredType = SemaRef.Context.getCanonicalType(T); + } + /// \brief Specify whether nested-name-specifiers are allowed. void allowNestedNameSpecifiers(bool Allow = true) { AllowNestedNameSpecifiers = Allow; @@ -565,6 +577,118 @@ void ResultBuilder::MaybeAddResult(Result R, DeclContext *CurContext) { Results.push_back(R); } +enum SimplifiedTypeClass { + STC_Arithmetic, + STC_Array, + STC_Block, + STC_Function, + STC_ObjectiveC, + STC_Other, + STC_Pointer, + STC_Record, + STC_Void +}; + +/// \brief A simplified classification of types used to determine whether two +/// types are "similar enough" when adjusting priorities. +static SimplifiedTypeClass getSimplifiedTypeClass(CanQualType T) { + switch (T->getTypeClass()) { + case Type::Builtin: + switch (cast<BuiltinType>(T)->getKind()) { + case BuiltinType::Void: + return STC_Void; + + case BuiltinType::NullPtr: + return STC_Pointer; + + case BuiltinType::Overload: + case BuiltinType::Dependent: + case BuiltinType::UndeducedAuto: + return STC_Other; + + case BuiltinType::ObjCId: + case BuiltinType::ObjCClass: + case BuiltinType::ObjCSel: + return STC_ObjectiveC; + + default: + return STC_Arithmetic; + } + return STC_Other; + + case Type::Complex: + return STC_Arithmetic; + + case Type::Pointer: + return STC_Pointer; + + case Type::BlockPointer: + return STC_Block; + + case Type::LValueReference: + case Type::RValueReference: + return getSimplifiedTypeClass(T->getAs<ReferenceType>()->getPointeeType()); + + case Type::ConstantArray: + case Type::IncompleteArray: + case Type::VariableArray: + case Type::DependentSizedArray: + return STC_Array; + + case Type::DependentSizedExtVector: + case Type::Vector: + case Type::ExtVector: + return STC_Arithmetic; + + case Type::FunctionProto: + case Type::FunctionNoProto: + return STC_Function; + + case Type::Record: + return STC_Record; + + case Type::Enum: + return STC_Arithmetic; + + case Type::ObjCObject: + case Type::ObjCInterface: + case Type::ObjCObjectPointer: + return STC_ObjectiveC; + + default: + return STC_Other; + } +} + +/// \brief Get the type that a given expression will have if this declaration +/// is used as an expression in its "typical" code-completion form. +static QualType getDeclUsageType(ASTContext &C, NamedDecl *ND) { + ND = cast<NamedDecl>(ND->getUnderlyingDecl()); + + if (TypeDecl *Type = dyn_cast<TypeDecl>(ND)) + return C.getTypeDeclType(Type); + if (ObjCInterfaceDecl *Iface = dyn_cast<ObjCInterfaceDecl>(ND)) + return C.getObjCInterfaceType(Iface); + + QualType T; + if (FunctionDecl *Function = dyn_cast<FunctionDecl>(ND)) + T = Function->getResultType(); + else if (ObjCMethodDecl *Method = dyn_cast<ObjCMethodDecl>(ND)) + T = Method->getResultType(); + else if (FunctionTemplateDecl *FunTmpl = dyn_cast<FunctionTemplateDecl>(ND)) + T = FunTmpl->getTemplatedDecl()->getResultType(); + else if (EnumConstantDecl *Enumerator = dyn_cast<EnumConstantDecl>(ND)) + T = C.getTypeDeclType(cast<EnumDecl>(Enumerator->getDeclContext())); + else if (ObjCPropertyDecl *Property = dyn_cast<ObjCPropertyDecl>(ND)) + T = Property->getType(); + else if (ValueDecl *Value = dyn_cast<ValueDecl>(ND)) + T = Value->getType(); + else + return QualType(); + + return T.getNonReferenceType(); +} + void ResultBuilder::AddResult(Result R, DeclContext *CurContext, NamedDecl *Hiding, bool InBaseClass = false) { if (R.Kind != Result::RK_Declaration) { @@ -618,6 +742,21 @@ void ResultBuilder::AddResult(Result R, DeclContext *CurContext, if (InBaseClass) R.Priority += CCD_InBaseClass; + if (!PreferredType.isNull()) { + if (ValueDecl *Value = dyn_cast<ValueDecl>(R.Declaration)) { + CanQualType T = SemaRef.Context.getCanonicalType( + getDeclUsageType(SemaRef.Context, Value)); + // Check for exactly-matching types (modulo qualifiers). + if (SemaRef.Context.hasSameUnqualifiedType(PreferredType, T)) + R.Priority /= CCF_ExactTypeMatch; + // Check for nearly-matching types, based on classification of each. + else if ((getSimplifiedTypeClass(PreferredType) + == getSimplifiedTypeClass(T)) && + !(PreferredType->isEnumeralType() && T->isEnumeralType())) + R.Priority /= CCF_SimilarTypeMatch; + } + } + // Insert this result into the set of results. Results.push_back(R); } @@ -755,35 +894,6 @@ bool ResultBuilder::IsMember(NamedDecl *ND) const { isa<ObjCPropertyDecl>(ND); } -/// \brief Get the type that a given expression will have if this declaration -/// is used as an expression in its "typical" code-completion form. -static QualType getDeclUsageType(ASTContext &C, NamedDecl *ND) { - ND = cast<NamedDecl>(ND->getUnderlyingDecl()); - - if (TypeDecl *Type = dyn_cast<TypeDecl>(ND)) - return C.getTypeDeclType(Type); - if (ObjCInterfaceDecl *Iface = dyn_cast<ObjCInterfaceDecl>(ND)) - return C.getObjCInterfaceType(Iface); - - QualType T; - if (FunctionDecl *Function = dyn_cast<FunctionDecl>(ND)) - T = Function->getResultType(); - else if (ObjCMethodDecl *Method = dyn_cast<ObjCMethodDecl>(ND)) - T = Method->getResultType(); - else if (FunctionTemplateDecl *FunTmpl = dyn_cast<FunctionTemplateDecl>(ND)) - T = FunTmpl->getTemplatedDecl()->getResultType(); - else if (EnumConstantDecl *Enumerator = dyn_cast<EnumConstantDecl>(ND)) - T = C.getTypeDeclType(cast<EnumDecl>(Enumerator->getDeclContext())); - else if (ObjCPropertyDecl *Property = dyn_cast<ObjCPropertyDecl>(ND)) - T = Property->getType(); - else if (ValueDecl *Value = dyn_cast<ValueDecl>(ND)) - T = Value->getType(); - else - return QualType(); - - return T.getNonReferenceType(); -} - static bool isObjCReceiverType(ASTContext &C, QualType T) { T = C.getCanonicalType(T); switch (T->getTypeClass()) { @@ -2131,6 +2241,31 @@ void Sema::CodeCompleteOrdinaryName(Scope *S, HandleCodeCompleteResults(this, CodeCompleter, Results.data(),Results.size()); } +/// \brief Perform code-completion in an expression context when we know what +/// type we're looking for. +void Sema::CodeCompleteExpression(Scope *S, QualType T) { + typedef CodeCompleteConsumer::Result Result; + ResultBuilder Results(*this); + + if (WantTypesInContext(CCC_Expression, getLangOptions())) + Results.setFilter(&ResultBuilder::IsOrdinaryName); + else + Results.setFilter(&ResultBuilder::IsOrdinaryNonTypeName); + Results.setPreferredType(T.getNonReferenceType()); + + CodeCompletionDeclConsumer Consumer(Results, CurContext); + LookupVisibleDecls(S, LookupOrdinaryName, Consumer); + + Results.EnterNewScope(); + AddOrdinaryNameResults(CCC_Expression, S, *this, Results); + Results.ExitScope(); + + if (CodeCompleter->includeMacros()) + AddMacroResults(PP, Results); + HandleCodeCompleteResults(this, CodeCompleter, Results.data(),Results.size()); +} + + static void AddObjCProperties(ObjCContainerDecl *Container, bool AllowCategories, DeclContext *CurContext, @@ -2447,6 +2582,8 @@ void Sema::CodeCompleteCall(Scope *S, ExprTy *FnIn, } } + QualType ParamType; + if (!CandidateSet.empty()) { // Sort the overload candidate set by placing the best overloads first. std::stable_sort(CandidateSet.begin(), CandidateSet.end(), @@ -2459,14 +2596,85 @@ void Sema::CodeCompleteCall(Scope *S, ExprTy *FnIn, if (Cand->Viable) Results.push_back(ResultCandidate(Cand->Function)); } + + // From the viable candidates, try to determine the type of this parameter. + for (unsigned I = 0, N = Results.size(); I != N; ++I) { + if (const FunctionType *FType = Results[I].getFunctionType()) + if (const FunctionProtoType *Proto = dyn_cast<FunctionProtoType>(FType)) + if (NumArgs < Proto->getNumArgs()) { + if (ParamType.isNull()) + ParamType = Proto->getArgType(NumArgs); + else if (!Context.hasSameUnqualifiedType( + ParamType.getNonReferenceType(), + Proto->getArgType(NumArgs).getNonReferenceType())) { + ParamType = QualType(); + break; + } + } + } + } else { + // Try to determine the parameter type from the type of the expression + // being called. + QualType FunctionType = Fn->getType(); + if (const PointerType *Ptr = FunctionType->getAs<PointerType>()) + FunctionType = Ptr->getPointeeType(); + else if (const BlockPointerType *BlockPtr + = FunctionType->getAs<BlockPointerType>()) + FunctionType = BlockPtr->getPointeeType(); + else if (const MemberPointerType *MemPtr + = FunctionType->getAs<MemberPointerType>()) + FunctionType = MemPtr->getPointeeType(); + + if (const FunctionProtoType *Proto + = FunctionType->getAs<FunctionProtoType>()) { + if (NumArgs < Proto->getNumArgs()) + ParamType = Proto->getArgType(NumArgs); + } } - CodeCompleteOrdinaryName(S, CCC_Expression); + if (ParamType.isNull()) + CodeCompleteOrdinaryName(S, CCC_Expression); + else + CodeCompleteExpression(S, ParamType); + if (!Results.empty()) CodeCompleter->ProcessOverloadCandidates(*this, NumArgs, Results.data(), Results.size()); } +void Sema::CodeCompleteInitializer(Scope *S, DeclPtrTy D) { + ValueDecl *VD = dyn_cast_or_null<ValueDecl>(D.getAs<Decl>()); + if (!VD) { + CodeCompleteOrdinaryName(S, CCC_Expression); + return; + } + + CodeCompleteExpression(S, VD->getType()); +} + +void Sema::CodeCompleteReturn(Scope *S) { + QualType ResultType; + if (isa<BlockDecl>(CurContext)) { + if (BlockScopeInfo *BSI = getCurBlock()) + ResultType = BSI->ReturnType; + } else if (FunctionDecl *Function = dyn_cast<FunctionDecl>(CurContext)) + ResultType = Function->getResultType(); + else if (ObjCMethodDecl *Method = dyn_cast<ObjCMethodDecl>(CurContext)) + ResultType = Method->getResultType(); + + if (ResultType.isNull()) + CodeCompleteOrdinaryName(S, CCC_Expression); + else + CodeCompleteExpression(S, ResultType); +} + +void Sema::CodeCompleteAssignmentRHS(Scope *S, ExprTy *LHS) { + if (LHS) + CodeCompleteExpression(S, static_cast<Expr *>(LHS)->getType()); + else + CodeCompleteOrdinaryName(S, CCC_Expression); +} + void Sema::CodeCompleteQualifiedId(Scope *S, CXXScopeSpec &SS, bool EnteringContext) { if (!SS.getScopeRep() || !CodeCompleter) diff --git a/clang/test/Index/complete-exprs.c b/clang/test/Index/complete-exprs.c index 773301681c5..1b55c78be2e 100644 --- a/clang/test/Index/complete-exprs.c +++ b/clang/test/Index/complete-exprs.c @@ -9,13 +9,19 @@ int test(int i, int j, int k, int l) { // RUN: c-index-test -code-completion-at=%s:7:9 -Xclang -code-completion-patterns %s | FileCheck -check-prefix=CHECK-CC1 %s // CHECK-CC1: macro definition:{TypedText __VERSION__} (70) -// CHECK-CC1: FunctionDecl:{ResultType int}{TypedText f}{LeftParen (}{Placeholder int}{RightParen )} (50) +// CHECK-CC1: FunctionDecl:{ResultType int}{TypedText f}{LeftParen (}{Placeholder int}{RightParen )} (12) // CHECK-CC1-NOT: NotImplemented:{TypedText float} (40) -// CHECK-CC1: ParmDecl:{ResultType int}{TypedText j} (8) +// CHECK-CC1: ParmDecl:{ResultType int}{TypedText j} (2) // CHECK-CC1: NotImplemented:{TypedText sizeof}{LeftParen (}{Placeholder expression-or-type}{RightParen )} (30) -// RUN: c-index-test -code-completion-at=%s:7:14 -Xclang -code-completion-patterns %s | FileCheck -check-prefix=CHECK-CC1 %s -// RUN: c-index-test -code-completion-at=%s:7:18 -Xclang -code-completion-patterns %s | FileCheck -check-prefix=CHECK-CC1 %s -// RUN: c-index-test -code-completion-at=%s:7:22 -Xclang -code-completion-patterns %s | FileCheck -check-prefix=CHECK-CC1 %s +// RUN: c-index-test -code-completion-at=%s:7:14 -Xclang -code-completion-patterns %s | FileCheck -check-prefix=CHECK-CC3 %s +// CHECK-CC3: macro definition:{TypedText __VERSION__} (70) +// CHECK-CC3: FunctionDecl:{ResultType int}{TypedText f}{LeftParen (}{Placeholder int}{RightParen )} (50) +// CHECK-CC3-NOT: NotImplemented:{TypedText float} (40) +// CHECK-CC3: ParmDecl:{ResultType int}{TypedText j} (8) +// CHECK-CC3: NotImplemented:{TypedText sizeof}{LeftParen (}{Placeholder expressio + +// RUN: c-index-test -code-completion-at=%s:7:18 -Xclang -code-completion-patterns %s | FileCheck -check-prefix=CHECK-CC3 %s +// RUN: c-index-test -code-completion-at=%s:7:22 -Xclang -code-completion-patterns %s | FileCheck -check-prefix=CHECK-CC3 %s // RUN: c-index-test -code-completion-at=%s:7:2 -Xclang -code-completion-patterns %s | FileCheck -check-prefix=CHECK-CC2 %s // CHECK-CC2: macro definition:{TypedText __VERSION__} (70) // CHECK-CC2: FunctionDecl:{ResultType int}{TypedText f}{LeftParen (}{Placeholder int}{RightParen )} (50) diff --git a/clang/test/Index/complete-type-factors.m b/clang/test/Index/complete-type-factors.m new file mode 100644 index 00000000000..3f56b38c1cd --- /dev/null +++ b/clang/test/Index/complete-type-factors.m @@ -0,0 +1,117 @@ +/* Run lines are at the end, since line/column matter in this test. */ + +enum Color { + Red, Green, Blue +}; + +enum Priority { + Low, + High +}; + +int func1(enum Color); +enum Priority func2(int); +void func3(float); +enum Priority test1(enum Priority priority, enum Color color, int integer) { + int i = integer; + enum Color c = color; + return priority; + func1(c); + void (^block)(enum Color, int); + block(c, 17); + c = color; +} + +// FIXME: It would be great for message sends to have the same +// benefits as function calls, but we don't quite have the +// infrastructure yet. + +// RUN: c-index-test -code-completion-at=%s:16:11 -Xclang -code-completion-patterns %s | FileCheck -check-prefix=CHECK-CC1 %s +// CHECK-CC1: EnumConstantDecl:{ResultType enum Color}{TypedText Blue} (30) +// CHECK-CC1: ParmDecl:{ResultType enum Color}{TypedText color} (4) +// CHECK-CC1: FunctionDecl:{ResultType int}{TypedText func1}{LeftParen (}{Placeholder enum Color}{RightParen )} (12) +// CHECK-CC1: FunctionDecl:{ResultType enum Priority}{TypedText func2}{LeftParen (}{Placeholder int}{RightParen )} (25) +// CHECK-CC1: EnumConstantDecl:{ResultType enum Color}{TypedText Green} (30) +// CHECK-CC1: EnumConstantDecl:{ResultType enum Priority}{TypedText High} (30) +// CHECK-CC1: VarDecl:{ResultType int}{TypedText i} (2) +// CHECK-CC1: ParmDecl:{ResultType int}{TypedText integer} (2) +// CHECK-CC1: EnumConstantDecl:{ResultType enum Priority}{TypedText Low} (30) +// CHECK-CC1: macro definition:{TypedText OBJC_NEW_PROPERTIES} (70) +// CHECK-CC1: macro definition:{TypedText OBJC_ZEROCOST_EXCEPTIONS} (70) +// CHECK-CC1: ParmDecl:{ResultType enum Priority}{TypedText priority} (4) +// CHECK-CC1: EnumConstantDecl:{ResultType enum Color}{TypedText Red} (30) +// CHECK-CC1: NotImplemented:{TypedText sizeof}{LeftParen (}{Placeholder expression-or-type}{RightParen )} (30) +// CHECK-CC1: FunctionDecl:{ResultType enum Priority}{TypedText test1}{LeftParen (}{Placeholder enum Priority priority}{Comma , }{Placeholder enum Color color}{Comma , }{Placeholder int integer}{RightParen )} (25) +// RUN: c-index-test -code-completion-at=%s:17:18 -Xclang -code-completion-patterns %s | FileCheck -check-prefix=CHECK-CC2 %s +// CHECK-CC2: EnumConstantDecl:{ResultType enum Color}{TypedText Blue} (15) +// CHECK-CC2: VarDecl:{ResultType enum Color}{TypedText c} (2) +// CHECK-CC2: ParmDecl:{ResultType enum Color}{TypedText color} (2) +// CHECK-CC2: FunctionDecl:{ResultType int}{TypedText func1}{LeftParen (}{Placeholder enum Color}{RightParen )} (25) +// CHECK-CC2: FunctionDecl:{ResultType enum Priority}{TypedText func2}{LeftParen (}{Placeholder int}{RightParen )} (50) +// CHECK-CC2: EnumConstantDecl:{ResultType enum Color}{TypedText Green} (15) +// CHECK-CC2: EnumConstantDecl:{ResultType enum Priority}{TypedText High} (60) +// CHECK-CC2: VarDecl:{ResultType int}{TypedText i} (4) +// CHECK-CC2: ParmDecl:{ResultType int}{TypedText integer} (4) +// CHECK-CC2: EnumConstantDecl:{ResultType enum Priority}{TypedText Low} (60) +// CHECK-CC2: macro definition:{TypedText OBJC_NEW_PROPERTIES} (70) +// CHECK-CC2: macro definition:{TypedText OBJC_ZEROCOST_EXCEPTIONS} (70) +// CHECK-CC2: ParmDecl:{ResultType enum Priority}{TypedText priority} (8) +// CHECK-CC2: EnumConstantDecl:{ResultType enum Color}{TypedText Red} (15) +// CHECK-CC2: NotImplemented:{TypedText sizeof}{LeftParen (}{Placeholder expression-or-type}{RightParen )} (30) +// CHECK-CC2: FunctionDecl:{ResultType enum Priority}{TypedText test1}{LeftParen (}{Placeholder enum Priority priority}{Comma , }{Placeholder enum Color color}{Comma , }{Placeholder int integer}{RightParen )} (50) +// RUN: c-index-test -code-completion-at=%s:18:10 -Xclang -code-completion-patterns %s | FileCheck -check-prefix=CHECK-CC3 %s +// CHECK-CC3: EnumConstantDecl:{ResultType enum Color}{TypedText Blue} (60) +// CHECK-CC3: VarDecl:{ResultType enum Color}{TypedText c} (8) +// CHECK-CC3: ParmDecl:{ResultType enum Color}{TypedText color} (8) +// CHECK-CC3: FunctionDecl:{ResultType int}{TypedText func1}{LeftParen (}{Placeholder enum Color}{RightParen )} (25) +// CHECK-CC3: FunctionDecl:{ResultType enum Priority}{TypedText func2}{LeftParen (}{Placeholder int}{RightParen )} (12) +// CHECK-CC3: FunctionDecl:{ResultType void}{TypedText func3}{LeftParen (}{Placeholder float}{RightParen )} (50) +// CHECK-CC3: EnumConstantDecl:{ResultType enum Color}{TypedText Green} (60) +// CHECK-CC3: EnumConstantDecl:{ResultType enum Priority}{TypedText High} (15) +// CHECK-CC3: VarDecl:{ResultType int}{TypedText i} (4) +// CHECK-CC3: ParmDecl:{ResultType int}{TypedText integer} (4) +// CHECK-CC3: EnumConstantDecl:{ResultType enum Priority}{TypedText Low} (15) +// CHECK-CC3: macro definition:{TypedText OBJC_NEW_PROPERTIES} (70) +// CHECK-CC3: macro definition:{TypedText OBJC_ZEROCOST_EXCEPTIONS} (70) +// CHECK-CC3: ParmDecl:{ResultType enum Priority}{TypedText priority} (2) +// CHECK-CC3: EnumConstantDecl:{ResultType enum Color}{TypedText Red} (60) +// CHECK-CC3: NotImplemented:{TypedText sizeof}{LeftParen (}{Placeholder expression-or-type}{RightParen )} (30) +// CHECK-CC3: FunctionDecl:{ResultType enum Priority}{TypedText test1}{LeftParen (}{Placeholder enum Priority priority}{Comma , }{Placeholder enum Color color}{Comma , }{Placeholder int integer}{RightParen )} (12) +// RUN: c-index-test -code-completion-at=%s:19:9 -Xclang -code-completion-patterns %s | FileCheck -check-prefix=CHECK-CC4 %s +// CHECK-CC4: EnumConstantDecl:{ResultType enum Color}{TypedText Blue} (15) +// CHECK-CC4: VarDecl:{ResultType enum Color}{TypedText c} (2) +// CHECK-CC4: ParmDecl:{ResultType enum Color}{TypedText color} (2) +// CHECK-CC4: FunctionDecl:{ResultType int}{TypedText func1}{LeftParen (}{Placeholder enum Color}{RightParen )} (25) +// CHECK-CC4: FunctionDecl:{ResultType enum Priority}{TypedText func2}{LeftParen (}{Placeholder int}{RightParen )} (50) +// CHECK-CC4: FunctionDecl:{ResultType void}{TypedText func3}{LeftParen (}{Placeholder float}{RightParen )} (50) +// CHECK-CC4: EnumConstantDecl:{ResultType enum Color}{TypedText Green} (15) +// CHECK-CC4: EnumConstantDecl:{ResultType enum Priority}{TypedText High} (60) +// CHECK-CC4: VarDecl:{ResultType int}{TypedText i} (4) +// CHECK-CC4: ParmDecl:{ResultType int}{TypedText integer} (4) +// CHECK-CC4: EnumConstantDecl:{ResultType enum Priority}{TypedText Low} (60) +// CHECK-CC4: macro definition:{TypedText OBJC_NEW_PROPERTIES} (70) +// CHECK-CC4: macro definition:{TypedText OBJC_ZEROCOST_EXCEPTIONS} (70) +// CHECK-CC4: ParmDecl:{ResultType enum Priority}{TypedText priority} (8) +// CHECK-CC4: EnumConstantDecl:{ResultType enum Color}{TypedText Red} (15) +// CHECK-CC4: NotImplemented:{TypedText sizeof}{LeftParen (}{Placeholder expression-or-type}{RightParen )} (30) +// CHECK-CC4: FunctionDecl:{ResultType enum Priority}{TypedText test1}{LeftParen (}{Placeholder enum Priority priority}{Comma , }{Placeholder enum Color color}{Comma , }{Placeholder int integer}{RightParen )} (50) +// RUN: c-index-test -code-completion-at=%s:21:9 -Xclang -code-completion-patterns %s | FileCheck -check-prefix=CHECK-CC4 %s +// RUN: c-index-test -code-completion-at=%s:22:7 -Xclang -code-completion-patterns %s | FileCheck -check-prefix=CHECK-CC6 %s +// CHECK-CC6: VarDecl:{ResultType void (^)(enum Color, int)}{TypedText block} (8) +// CHECK-CC6: EnumConstantDecl:{ResultType enum Color}{TypedText Blue} (15) +// CHECK-CC6: VarDecl:{ResultType enum Color}{TypedText c} (2) +// CHECK-CC6: ParmDecl:{ResultType enum Color}{TypedText color} (2) +// CHECK-CC6: FunctionDecl:{ResultType int}{TypedText func1}{LeftParen (}{Placeholder enum Color}{RightParen )} (25) +// CHECK-CC6: FunctionDecl:{ResultType enum Priority}{TypedText func2}{LeftParen (}{Placeholder int}{RightParen )} (50) +// CHECK-CC6: FunctionDecl:{ResultType void}{TypedText func3}{LeftParen (}{Placeholder float}{RightParen )} (50) +// CHECK-CC6: EnumConstantDecl:{ResultType enum Color}{TypedText Green} (15) +// CHECK-CC6: EnumConstantDecl:{ResultType enum Priority}{TypedText High} (60) +// CHECK-CC6: VarDecl:{ResultType int}{TypedText i} (4) +// CHECK-CC6: ParmDecl:{ResultType int}{TypedText integer} (4) +// CHECK-CC6: EnumConstantDecl:{ResultType enum Priority}{TypedText Low} (60) +// CHECK-CC6: macro definition:{TypedText OBJC_NEW_PROPERTIES} (70) +// CHECK-CC6: macro definition:{TypedText OBJC_ZEROCOST_EXCEPTIONS} (70) +// CHECK-CC6: ParmDecl:{ResultType enum Priority}{TypedText priority} (8) +// CHECK-CC6: EnumConstantDecl:{ResultType enum Color}{TypedText Red} (15) +// CHECK-CC6: NotImplemented:{TypedText sizeof}{LeftParen (}{Placeholder expression-or-type}{RightParen )} (30) +// CHECK-CC6: FunctionDecl:{ResultType enum Priority}{TypedText test1}{LeftParen (}{Placeholder enum Priority priority}{Comma , }{Placeholder enum Color color}{Comma , }{Placeholder int integer}{RightParen )} (50) |