@@ -2066,34 +2066,91 @@ clang::CXXMethodDecl *SwiftDeclSynthesizer::synthesizeCXXForwardingMethod(
20662066
20672067 // Create a new method in the derived class that calls the base method.
20682068 clang::DeclarationName name = method->getNameInfo ().getName ();
2069+ std::string newName;
2070+ llvm::raw_string_ostream os (newName);
2071+ bool useExistingName = false ;
20692072 if (name.isIdentifier ()) {
2070- std::string newName;
2071- llvm::raw_string_ostream os (newName);
20722073 os << (forwardingMethodKind == ForwardingMethodKind::Virtual
20732074 ? " __synthesizedVirtualCall_"
20742075 : " __synthesizedBaseCall_" )
20752076 << name.getAsIdentifierInfo ()->getName ();
2076- name = clang::DeclarationName (
2077- &ImporterImpl.getClangPreprocessor ().getIdentifierTable ().get (
2078- os.str ()));
2079- } else if (name.getCXXOverloadedOperator () == clang::OO_Subscript) {
2080- name = clang::DeclarationName (
2081- &ImporterImpl.getClangPreprocessor ().getIdentifierTable ().get (
2082- (forwardingMethodKind == ForwardingMethodKind::Virtual
2077+ } else {
2078+ switch (auto op = name.getCXXOverloadedOperator ()) {
2079+ case clang::OO_Subscript:
2080+ os << (forwardingMethodKind == ForwardingMethodKind::Virtual
20832081 ? " __synthesizedVirtualCall_operatorSubscript"
2084- : " __synthesizedBaseCall_operatorSubscript" )));
2085- } else if (name.getCXXOverloadedOperator () == clang::OO_Star) {
2086- name = clang::DeclarationName (
2087- &ImporterImpl.getClangPreprocessor ().getIdentifierTable ().get (
2088- (forwardingMethodKind == ForwardingMethodKind::Virtual
2082+ : " __synthesizedBaseCall_operatorSubscript" );
2083+ if (forceConstQualifier)
2084+ os << " C" ;
2085+ break ;
2086+
2087+ case clang::OO_Star:
2088+ os << (forwardingMethodKind == ForwardingMethodKind::Virtual
20892089 ? " __synthesizedVirtualCall_operatorStar"
2090- : " __synthesizedBaseCall_operatorStar" )));
2091- } else if (name.getCXXOverloadedOperator () == clang::OO_Call) {
2092- assert (forwardingMethodKind != ForwardingMethodKind::Virtual);
2090+ : " __synthesizedBaseCall_operatorStar" );
2091+ if (forceConstQualifier)
2092+ os << " C" ;
2093+ break ;
2094+
2095+ case clang::OO_Call:
2096+ assert (forwardingMethodKind != ForwardingMethodKind::Virtual);
2097+ os << " __synthesizedBaseCall_operatorCall" ;
2098+ if (forceConstQualifier)
2099+ os << " C" ;
2100+ break ;
2101+
2102+ case clang::OO_Plus:
2103+ case clang::OO_Minus:
2104+ case clang::OO_Slash:
2105+ case clang::OO_PlusEqual:
2106+ case clang::OO_MinusEqual:
2107+ case clang::OO_StarEqual:
2108+ case clang::OO_SlashEqual:
2109+ case clang::OO_Percent:
2110+ case clang::OO_Caret:
2111+ case clang::OO_Amp:
2112+ case clang::OO_Pipe:
2113+ case clang::OO_Tilde:
2114+ case clang::OO_Exclaim:
2115+ case clang::OO_Less:
2116+ case clang::OO_Greater:
2117+ case clang::OO_LessLess:
2118+ case clang::OO_GreaterGreater:
2119+ case clang::OO_EqualEqual:
2120+ case clang::OO_PlusPlus:
2121+ case clang::OO_ExclaimEqual:
2122+ case clang::OO_LessEqual:
2123+ case clang::OO_GreaterEqual:
2124+ case clang::OO_AmpAmp:
2125+ case clang::OO_PipePipe:
2126+ os << importer::getOperatorName (ImporterImpl.SwiftContext , op).str ();
2127+ break ;
2128+
2129+ default :
2130+ useExistingName = true ;
2131+ break ;
2132+ }
2133+ }
2134+
2135+ if (!useExistingName) {
2136+ // The created method is inside the derived class already. If that's
2137+ // different from the base class, also include the base class in the
2138+ // mangling to keep this separate from other similar functions cloned from
2139+ // other base classes.
2140+ if (derivedClass != baseClass) {
2141+ os << " _" ;
2142+ std::unique_ptr<clang::ItaniumMangleContext> mangler{
2143+ clang::ItaniumMangleContext::create (clangCtx, clangCtx.getDiagnostics ())};
2144+ auto derivedType = clangCtx.getTypeDeclType (baseClass)
2145+ .getCanonicalType ();
2146+ mangler->mangleCanonicalTypeName (derivedType, os);
2147+ }
2148+
20932149 name = clang::DeclarationName (
20942150 &ImporterImpl.getClangPreprocessor ().getIdentifierTable ().get (
2095- " __synthesizedBaseCall_operatorCall " ));
2151+ os. str () ));
20962152 }
2153+
20972154 auto methodType = method->getType ();
20982155 // Check if we need to drop the reference from the return type
20992156 // of the new method. This is needed when a synthesized `operator []`
0 commit comments