public virtual bool VisitCXXMemberCallExpr(CXXMemberCallExpr stmt) { if (!VisitCallExpr(stmt)) { return(false); } return(true); }
public bool VisitCXXMemberCallExpr(CXXMemberCallExpr stmt) { throw new NotImplementedException(); }
protected override void VisitMemberCallExpr(CXXMemberCallExpr memberCallExpression) { // TODO: This is frail and breaks if a line has nested emplace_back (we push out signatures for all types constructed by emplace_back) // Only process emplace(_back) calls on the requested line and within the requested span memberCallExpression.Location.GetFileLocation(out var file, out var line, out _, out _); if (file.Name.CString != _filePath || line - 1 != _line) { return; } // Check if this is a method call expression. var methodReference = memberCallExpression.CursorChildren.FirstOrDefault(child => child.CursorKind == CXCursorKind.CXCursor_MemberRefExpr); if (methodReference == default) { return; } // Needs to be emplace or emplace_back if (methodReference.Spelling != "emplace" && methodReference.Spelling != "emplace_back") { return; } // Find the object instance on which the function is called var objectInstance = methodReference.CursorChildren.OfType <DeclRefExpr>().FirstOrDefault(); if (objectInstance == default) { return; } // Find the actual object type (not the instanciated specialization) var objectType = objectInstance.Decl.CursorChildren .FirstOrDefault(child => child.CursorKind == CXCursorKind.CXCursor_TemplateRef) .As <Ref>()?.Referenced as ClassTemplateDecl; if (objectType == default) { return; } // From the resolved type, find the 'value_type" typedef. var valueType = objectType.ResolveTypeAlias(typedef => typedef.Spelling == "value_type"); if (valueType == default) { return; } // Retrieve the index of the actual type in the pack declaration //! Not a .OfType<TemplateTypeParmDecl>() because of non-type template parameters. var elementTypeIndex = objectType.TemplateParameters.IndexOf(param => param is TemplateTypeParmDecl typeParam && typeParam.TypeForDecl == valueType); if (elementTypeIndex == -1) { return; } // Retrieve the instanciated specialization var instanceType = objectInstance.Type.GetTemplateSpecializationType()? .CanonicalType.As <RecordType>()? .Decl.As <ClassTemplateSpecializationDecl>(); if (instanceType == null) { return; } // Find the argument type. If not a record type, exit out. var resolvedElementType = instanceType.TemplateArgs[elementTypeIndex].CanonicalType.As <RecordType>()?.Decl; if (resolvedElementType == default) { return; } switch (resolvedElementType) { case CXXRecordDecl recordDecl: { foreach (var constructor in recordDecl.Ctors) { TryNotifyConstructorFound(instanceType, constructor); } // Also search for function template ctors foreach (var functionTemplate in recordDecl.CursorChildren.OfType <FunctionTemplateDecl>()) { // Only keep template ctors if (functionTemplate.Spelling != resolvedElementType.Spelling) { continue; } TryNotifyConstructorFound(instanceType, functionTemplate); } break; } default: // Could be a builtin Debug.WriteLine($"> Found an emplace call to a container with an unhandled {resolvedElementType.CursorKindSpelling}."); break; } }