[cfe-commits] r105128 - in /cfe/trunk: include/clang/Parse/Action.h include/clang/Sema/CodeCompleteConsumer.h lib/Parse/ParseDecl.cpp lib/Parse/ParseExpr.cpp lib/Parse/ParseStmt.cpp lib/Sema/Sema.h lib/Sema/SemaCodeComplete.cpp test/Index/complete-exprs.c test/Index/complete-type-factors.m

Douglas Gregor dgregor at apple.com
Sat May 29 18:49:25 PDT 2010


Author: dgregor
Date: Sat May 29 20:49:25 2010
New Revision: 105128

URL: http://llvm.org/viewvc/llvm-project?rev=105128&view=rev
Log:
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.

Added:
    cfe/trunk/test/Index/complete-type-factors.m
Modified:
    cfe/trunk/include/clang/Parse/Action.h
    cfe/trunk/include/clang/Sema/CodeCompleteConsumer.h
    cfe/trunk/lib/Parse/ParseDecl.cpp
    cfe/trunk/lib/Parse/ParseExpr.cpp
    cfe/trunk/lib/Parse/ParseStmt.cpp
    cfe/trunk/lib/Sema/Sema.h
    cfe/trunk/lib/Sema/SemaCodeComplete.cpp
    cfe/trunk/test/Index/complete-exprs.c

Modified: cfe/trunk/include/clang/Parse/Action.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Parse/Action.h?rev=105128&r1=105127&r2=105128&view=diff
==============================================================================
--- cfe/trunk/include/clang/Parse/Action.h (original)
+++ cfe/trunk/include/clang/Parse/Action.h Sat May 29 20:49:25 2010
@@ -2729,7 +2729,27 @@
   /// \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.
   ///

Modified: cfe/trunk/include/clang/Sema/CodeCompleteConsumer.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Sema/CodeCompleteConsumer.h?rev=105128&r1=105127&r2=105128&view=diff
==============================================================================
--- cfe/trunk/include/clang/Sema/CodeCompleteConsumer.h (original)
+++ cfe/trunk/include/clang/Sema/CodeCompleteConsumer.h Sat May 29 20:49:25 2010
@@ -59,6 +59,18 @@
   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;

Modified: cfe/trunk/lib/Parse/ParseDecl.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Parse/ParseDecl.cpp?rev=105128&r1=105127&r2=105128&view=diff
==============================================================================
--- cfe/trunk/lib/Parse/ParseDecl.cpp (original)
+++ cfe/trunk/lib/Parse/ParseDecl.cpp Sat May 29 20:49:25 2010
@@ -556,6 +556,13 @@
         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()) {

Modified: cfe/trunk/lib/Parse/ParseExpr.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Parse/ParseExpr.cpp?rev=105128&r1=105127&r2=105128&view=diff
==============================================================================
--- cfe/trunk/lib/Parse/ParseExpr.cpp (original)
+++ cfe/trunk/lib/Parse/ParseExpr.cpp Sat May 29 20:49:25 2010
@@ -343,6 +343,14 @@
       }
     }
     
+    // 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

Modified: cfe/trunk/lib/Parse/ParseStmt.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Parse/ParseStmt.cpp?rev=105128&r1=105127&r2=105128&view=diff
==============================================================================
--- cfe/trunk/lib/Parse/ParseStmt.cpp (original)
+++ cfe/trunk/lib/Parse/ParseStmt.cpp Sat May 29 20:49:25 2010
@@ -1199,6 +1199,13 @@
 
   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);

Modified: cfe/trunk/lib/Sema/Sema.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/Sema.h?rev=105128&r1=105127&r2=105128&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/Sema.h (original)
+++ cfe/trunk/lib/Sema/Sema.h Sat May 29 20:49:25 2010
@@ -4417,6 +4417,7 @@
   //@{
   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 @@
   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);

Modified: cfe/trunk/lib/Sema/SemaCodeComplete.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaCodeComplete.cpp?rev=105128&r1=105127&r2=105128&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/SemaCodeComplete.cpp (original)
+++ cfe/trunk/lib/Sema/SemaCodeComplete.cpp Sat May 29 20:49:25 2010
@@ -119,6 +119,13 @@
     /// 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 @@
     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 @@
   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 @@
   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 @@
     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 @@
   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 @@
     }
   }
   
+  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 @@
       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)

Modified: cfe/trunk/test/Index/complete-exprs.c
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Index/complete-exprs.c?rev=105128&r1=105127&r2=105128&view=diff
==============================================================================
--- cfe/trunk/test/Index/complete-exprs.c (original)
+++ cfe/trunk/test/Index/complete-exprs.c Sat May 29 20:49:25 2010
@@ -9,13 +9,19 @@
 
 // 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)

Added: cfe/trunk/test/Index/complete-type-factors.m
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Index/complete-type-factors.m?rev=105128&view=auto
==============================================================================
--- cfe/trunk/test/Index/complete-type-factors.m (added)
+++ cfe/trunk/test/Index/complete-type-factors.m Sat May 29 20:49:25 2010
@@ -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)





More information about the cfe-commits mailing list