[cfe-commits] r107929 - in /cfe/trunk: include/clang/Parse/Action.h include/clang/Sema/CodeCompleteConsumer.h lib/Parse/ParseObjc.cpp lib/Sema/Sema.h lib/Sema/SemaCodeComplete.cpp test/Index/complete-method-decls.m

Douglas Gregor dgregor at apple.com
Thu Jul 8 16:20:03 PDT 2010


Author: dgregor
Date: Thu Jul  8 18:20:03 2010
New Revision: 107929

URL: http://llvm.org/viewvc/llvm-project?rev=107929&view=rev
Log:
Introduce a new code-completion point prior to an identifier in the
selector of an Objective-C method declaration, e.g., given

  - (int)first:(int)x second:(int)y;

this code completion point triggers at the location of "second". It
will provide completions that fill out the method declaration for any
known method, anywhere in the translation unit.


Modified:
    cfe/trunk/include/clang/Parse/Action.h
    cfe/trunk/include/clang/Sema/CodeCompleteConsumer.h
    cfe/trunk/lib/Parse/ParseObjc.cpp
    cfe/trunk/lib/Sema/Sema.h
    cfe/trunk/lib/Sema/SemaCodeComplete.cpp
    cfe/trunk/test/Index/complete-method-decls.m

Modified: cfe/trunk/include/clang/Parse/Action.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Parse/Action.h?rev=107929&r1=107928&r2=107929&view=diff
==============================================================================
--- cfe/trunk/include/clang/Parse/Action.h (original)
+++ cfe/trunk/include/clang/Parse/Action.h Thu Jul  8 18:20:03 2010
@@ -3043,7 +3043,7 @@
   /// parsed.
   virtual void CodeCompleteObjCProtocolReferences(IdentifierLocPair *Protocols,
                                                   unsigned NumProtocols) { }
-
+  
   /// \brief Code completion for a protocol declaration or definition, after
   /// the @protocol but before any identifier.
   ///
@@ -3133,6 +3133,28 @@
                                           TypeTy *ReturnType,
                                           DeclPtrTy IDecl) {
   }
+  
+  /// \brief Code completion for a selector identifier within an Objective-C
+  /// method declaration.
+  ///
+  /// \param S The scope in which this code completion occurs.
+  ///
+  /// \param IsInstanceMethod Whether we are parsing an instance method (or, 
+  /// if false, a class method).
+  ///
+  /// \param ReturnType If non-NULL, the specified return type of the method
+  /// being declared or defined.
+  ///
+  /// \param SelIdents The identifiers that occurred in the selector for the
+  /// method declaration prior to the code completion point.
+  ///
+  /// \param NumSelIdents The number of identifiers provided by SelIdents.
+  virtual void CodeCompleteObjCMethodDeclSelector(Scope *S, 
+                                                  bool IsInstanceMethod,
+                                                  TypeTy *ReturnType,
+                                                  IdentifierInfo **SelIdents,
+                                                  unsigned NumSelIdents) { }
+  
   //@}
 };
 

Modified: cfe/trunk/include/clang/Sema/CodeCompleteConsumer.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Sema/CodeCompleteConsumer.h?rev=107929&r1=107928&r2=107929&view=diff
==============================================================================
--- cfe/trunk/include/clang/Sema/CodeCompleteConsumer.h (original)
+++ cfe/trunk/include/clang/Sema/CodeCompleteConsumer.h Thu Jul  8 18:20:03 2010
@@ -355,6 +355,10 @@
     /// method, etc.) should be considered "informative".
     bool AllParametersAreInformative : 1;
 
+    /// \brief Whether we're completing a declaration of the given entity,
+    /// rather than a use of that entity.
+    bool DeclaringEntity : 1;
+    
     /// \brief If the result should have a nested-name-specifier, this is it.
     /// When \c QualifierIsInformative, the nested-name-specifier is 
     /// informative rather than required.
@@ -368,7 +372,7 @@
         Priority(getPriorityFromDecl(Declaration)), StartParameter(0), 
         Hidden(false), QualifierIsInformative(QualifierIsInformative),
         StartsNestedNameSpecifier(false), AllParametersAreInformative(false),
-        Qualifier(Qualifier) { 
+        DeclaringEntity(false), Qualifier(Qualifier) { 
     }
     
     /// \brief Build a result that refers to a keyword or symbol.
@@ -376,21 +380,21 @@
       : Kind(RK_Keyword), Keyword(Keyword), Priority(Priority), 
         StartParameter(0), Hidden(false), QualifierIsInformative(0), 
         StartsNestedNameSpecifier(false), AllParametersAreInformative(false),
-        Qualifier(0) { }
+        DeclaringEntity(false), Qualifier(0) { }
     
     /// \brief Build a result that refers to a macro.
     Result(IdentifierInfo *Macro, unsigned Priority = CCP_Macro)
      : Kind(RK_Macro), Macro(Macro), Priority(Priority), StartParameter(0), 
        Hidden(false), QualifierIsInformative(0), 
        StartsNestedNameSpecifier(false), AllParametersAreInformative(false),
-       Qualifier(0) { }
+       DeclaringEntity(false), Qualifier(0) { }
 
     /// \brief Build a result that refers to a pattern.
     Result(CodeCompletionString *Pattern, unsigned Priority = CCP_CodePattern)
       : Kind(RK_Pattern), Pattern(Pattern), Priority(Priority), 
         StartParameter(0), Hidden(false), QualifierIsInformative(0), 
         StartsNestedNameSpecifier(false), AllParametersAreInformative(false),
-        Qualifier(0) { }
+        DeclaringEntity(false), Qualifier(0) { }
     
     /// \brief Retrieve the declaration stored in this result.
     NamedDecl *getDeclaration() const {

Modified: cfe/trunk/lib/Parse/ParseObjc.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Parse/ParseObjc.cpp?rev=107929&r1=107928&r2=107929&view=diff
==============================================================================
--- cfe/trunk/lib/Parse/ParseObjc.cpp (original)
+++ cfe/trunk/lib/Parse/ParseObjc.cpp Thu Jul  8 18:20:03 2010
@@ -868,6 +868,17 @@
     ArgInfos.push_back(ArgInfo);
     KeyIdents.push_back(SelIdent);
 
+    // Code completion for the next piece of the selector.
+    if (Tok.is(tok::code_completion)) {
+      ConsumeCodeCompletionToken();
+      Actions.CodeCompleteObjCMethodDeclSelector(getCurScope(), 
+                                                 mType == tok::minus,
+                                                 ReturnType,
+                                                 KeyIdents.data(), 
+                                                 KeyIdents.size());
+      break;
+    }
+    
     // Check for another keyword selector.
     SourceLocation Loc;
     SelIdent = ParseObjCSelectorPiece(Loc);

Modified: cfe/trunk/lib/Sema/Sema.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/Sema.h?rev=107929&r1=107928&r2=107929&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/Sema.h (original)
+++ cfe/trunk/lib/Sema/Sema.h Thu Jul  8 18:20:03 2010
@@ -4572,6 +4572,12 @@
                                           bool IsInstanceMethod,
                                           TypeTy *ReturnType,
                                           DeclPtrTy IDecl);
+  virtual void CodeCompleteObjCMethodDeclSelector(Scope *S, 
+                                                  bool IsInstanceMethod,
+                                                  TypeTy *ReturnType,
+                                                  IdentifierInfo **SelIdents,
+                                                  unsigned NumSelIdents);
+  
   //@}
 
   //===--------------------------------------------------------------------===//

Modified: cfe/trunk/lib/Sema/SemaCodeComplete.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaCodeComplete.cpp?rev=107929&r1=107928&r2=107929&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/SemaCodeComplete.cpp (original)
+++ cfe/trunk/lib/Sema/SemaCodeComplete.cpp Thu Jul  8 18:20:03 2010
@@ -130,6 +130,8 @@
     /// different levels of, e.g., the inheritance hierarchy.
     std::list<ShadowMap> ShadowMaps;
     
+    void AdjustResultPriorityForPreferredType(Result &R);
+
   public:
     explicit ResultBuilder(Sema &SemaRef, LookupFilter Filter = 0)
       : SemaRef(SemaRef), Filter(Filter), AllowNestedNameSpecifiers(false) { }
@@ -470,6 +472,134 @@
   return false;
 }
 
+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::AdjustResultPriorityForPreferredType(Result &R) {
+  QualType T = getDeclUsageType(SemaRef.Context, R.Declaration);
+  if (T.isNull())
+    return;
+  
+  CanQualType TC = SemaRef.Context.getCanonicalType(T);
+  // Check for exactly-matching types (modulo qualifiers).
+  if (SemaRef.Context.hasSameUnqualifiedType(PreferredType, TC))
+    R.Priority /= CCF_ExactTypeMatch;
+  // Check for nearly-matching types, based on classification of each.
+  else if ((getSimplifiedTypeClass(PreferredType)
+                                               == getSimplifiedTypeClass(TC)) &&
+           !(PreferredType->isEnumeralType() && TC->isEnumeralType()))
+    R.Priority /= CCF_SimilarTypeMatch;  
+}
+
 void ResultBuilder::MaybeAddResult(Result R, DeclContext *CurContext) {
   assert(!ShadowMaps.empty() && "Must enter into a results scope");
   
@@ -554,8 +684,9 @@
   if (AsNestedNameSpecifier) {
     R.StartsNestedNameSpecifier = true;
     R.Priority = CCP_NestedNameSpecifier;
-  }
-  
+  } else if (!PreferredType.isNull())
+      AdjustResultPriorityForPreferredType(R);
+
   // If this result is supposed to have an informative qualifier, add one.
   if (R.QualifierIsInformative && !R.Qualifier &&
       !R.StartsNestedNameSpecifier) {
@@ -575,118 +706,6 @@
   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) {
@@ -740,20 +759,8 @@
   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;
-    }
-  }
+  if (!PreferredType.isNull())
+    AdjustResultPriorityForPreferredType(R);
   
   // Insert this result into the set of results.
   Results.push_back(R);
@@ -1955,9 +1962,9 @@
         if (IdentifierInfo *II = Sel.getIdentifierInfoForSlot(Idx))
           Keyword += II->getName().str();
         Keyword += ":";
-        if (Idx < StartParameter || AllParametersAreInformative) {
+        if (Idx < StartParameter || AllParametersAreInformative)
           Result->AddInformativeChunk(Keyword);
-        } else if (Idx == StartParameter)
+        else if (Idx == StartParameter)
           Result->AddTypedTextChunk(Keyword);
         else
           Result->AddTextChunk(Keyword);
@@ -1972,14 +1979,18 @@
       Arg = "(" + Arg + ")";
       if (IdentifierInfo *II = (*P)->getIdentifier())
         Arg += II->getName().str();
-      if (AllParametersAreInformative)
+      if (DeclaringEntity)
+        Result->AddTextChunk(Arg);
+      else if (AllParametersAreInformative)
         Result->AddInformativeChunk(Arg);
       else
         Result->AddPlaceholderChunk(Arg);
     }
 
     if (Method->isVariadic()) {
-      if (AllParametersAreInformative)
+      if (DeclaringEntity)
+        Result->AddTextChunk(", ...");
+      else if (AllParametersAreInformative)
         Result->AddInformativeChunk(", ...");
       else
         Result->AddPlaceholderChunk(", ...");
@@ -4133,3 +4144,55 @@
   
   HandleCodeCompleteResults(this, CodeCompleter, Results.data(),Results.size());
 }
+
+void Sema::CodeCompleteObjCMethodDeclSelector(Scope *S, 
+                                              bool IsInstanceMethod,
+                                              TypeTy *ReturnTy,
+                                              IdentifierInfo **SelIdents,
+                                              unsigned NumSelIdents) {
+  llvm::DenseMap<Selector, ObjCMethodList> &Pool 
+    = IsInstanceMethod? InstanceMethodPool : FactoryMethodPool;
+  
+  // If we have an external source, load the entire class method
+  // pool from the PCH file.
+  if (ExternalSource) {
+    for (uint32_t I = 0, N = ExternalSource->GetNumExternalSelectors();
+         I != N; ++I) {
+      Selector Sel = ExternalSource->GetExternalSelector(I);
+      if (Sel.isNull() || InstanceMethodPool.count(Sel) ||
+          FactoryMethodPool.count(Sel))
+        continue;
+      
+      ReadMethodPool(Sel, IsInstanceMethod);
+    }
+  }
+
+  // Build the set of methods we can see.
+  typedef CodeCompleteConsumer::Result Result;
+  ResultBuilder Results(*this);
+  
+  if (ReturnTy)
+    Results.setPreferredType(GetTypeFromParser(ReturnTy).getNonReferenceType());
+  
+  Results.EnterNewScope();  
+  for (llvm::DenseMap<Selector, ObjCMethodList>::iterator M = Pool.begin(),
+                                                       MEnd = Pool.end();
+       M != MEnd;
+       ++M) {
+    for (ObjCMethodList *MethList = &M->second; MethList && MethList->Method; 
+         MethList = MethList->Next) {
+      if (!isAcceptableObjCMethod(MethList->Method, MK_Any, SelIdents, 
+                                  NumSelIdents))
+        continue;
+      
+      Result R(MethList->Method, 0);
+      R.StartParameter = NumSelIdents;
+      R.AllParametersAreInformative = false;
+      R.DeclaringEntity = true;
+      Results.MaybeAddResult(R, CurContext);
+    }
+  }
+  
+  Results.ExitScope();
+  HandleCodeCompleteResults(this, CodeCompleter, Results.data(),Results.size());
+}

Modified: cfe/trunk/test/Index/complete-method-decls.m
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Index/complete-method-decls.m?rev=107929&r1=107928&r2=107929&view=diff
==============================================================================
--- cfe/trunk/test/Index/complete-method-decls.m (original)
+++ cfe/trunk/test/Index/complete-method-decls.m Thu Jul  8 18:20:03 2010
@@ -42,6 +42,16 @@
 - (id)categoryFunction:(int)x { return self; }
 @end
 
+ at interface C
+- (int)first:(int)x second:(float)y third:(double)z;
+- (id)first:(int)x second2:(float)y third:(double)z;
+- (void*)first:(int)x second3:(float)y third:(double)z;
+ at end
+
+ at interface D
+- (int)first:(int)x second4:(float)y third:(double)z;
+ at end
+
 // RUN: c-index-test -code-completion-at=%s:17:3 %s | FileCheck -check-prefix=CHECK-CC1 %s
 // CHECK-CC1: NotImplemented:{LeftParen (}{Text id}{RightParen )}{TypedText abc}
 // CHECK-CC1: NotImplemented:{LeftParen (}{Text int}{RightParen )}{TypedText getInt}
@@ -79,4 +89,9 @@
 // CHECK-CC6: NotImplemented:{TypedText initWithTwoInts}{Colon :}{LeftParen (}{Text int}{RightParen )}{Text x}{HorizontalSpace  }{Text second}{Colon :}{LeftParen (}{Text int}{RightParen )}{Text y}{HorizontalSpace  }{LeftBrace {}{VerticalSpace 
 // RUN: c-index-test -code-completion-at=%s:42:3 -Xclang -code-completion-patterns %s | FileCheck -check-prefix=CHECK-CC7 %s
 // CHECK-CC7: NotImplemented:{LeftParen (}{Text id}{RightParen )}{TypedText categoryFunction}{Colon :}{LeftParen (}{Text int}{RightParen )}{Text x}{HorizontalSpace  }{LeftBrace {}{VerticalSpace 
+// RUN: c-index-test -code-completion-at=%s:52:21 -Xclang -code-completion-patterns %s | FileCheck -check-prefix=CHECK-CC8 %s
+// CHECK-CC8: ObjCInstanceMethodDecl:{ResultType id}{Informative first:}{TypedText second2:}{Text (float)y}{HorizontalSpace  }{Text third:}{Text (double)z} (20)
+// CHECK-CC8: ObjCInstanceMethodDecl:{ResultType void *}{Informative first:}{TypedText second3:}{Text (float)y}{HorizontalSpace  }{Text third:}{Text (double)z} (20)
+// CHECK-CC8: ObjCInstanceMethodDecl:{ResultType int}{Informative first:}{TypedText second:}{Text (float)y}{HorizontalSpace  }{Text third:}{Text (double)z} (5)
+
 





More information about the cfe-commits mailing list