Skip to content

Possibly incorrect or missing back reference registration for Microsoft name mangling #85423

@tahonermann

Description

@tahonermann

The Microsoft name mangling issue tracked by #83616 was due to a missing back reference registration that caused incorrectly resolved back reference indices to appear in mangled names resulting in ABI incompatibilities due to mismatched mangled names relative to those generated by MSVC. Producing a fix for that issue involved determining whether the back reference registration should or should not include the $ character that preceded the implicit TSS<discriminator> name used for the corresponding symbol. Testing clarified that the $ character should be included in the registration; though the implicitly generated name is registered as a back reference target, user-defined names written in source code should never be resolved to it. This was demonstrated in the following test:

namespace NS {
// The name "TSS0" for the name of the class below has been specifically
// chosen to ensure that back reference lookup does not match against the
// implicitly generated "$TSS0" name of the thread safe static initialization
// variable.
struct __declspec(dllexport) TSS0 {
  static TSS0& get();
  __forceinline static TSS0& singleton() {
    static TSS0& lsv = get();
    return lsv;
  }
};
}

Following the fix in #85300, both MSVC and Clang generate the following mangled name for the synthesized guard variable.

  • ?$TSS0@?1??singleton@ TSS0@ NS@@SAAAU23@XZ@4HA

Had the TSS0 name of the class been resolved to the registered back reference, the following (incorrect) mangled name would be generated:

  • ?$TSS0@?1??singleton@ 0 NS@@SAAAU02@XZ@4HA

This is a subtle issue that will only cause problems in unusual edge cases.

As part of preparing the fix in #85300, a brief audit of clang/lib/AST/MicrosoftMangle.cpp was performed to look for cases where a $ is included in the mangled name, but not included as part of the name passed to mangleSourceName() to register a back reference candidate. These are all cases that require further analysis to determine if changes are needed. Ideally, tests would be added to exercise name mangling for each case.

  • mangleObjCProtocol()
    2021   Stream << "?$";
    2022   Extra.mangleSourceName("Protocol");
    
  • mangleObjCLifetime()
    2035   Stream << "?$";
    2036   switch (Quals.getObjCLifetime()) {
    ....
    2040   case Qualifiers::OCL_Autoreleasing:
    2041     Extra.mangleSourceName("Autoreleasing");
    2042     break;
    2043   case Qualifiers::OCL_Strong:
    2044     Extra.mangleSourceName("Strong");
    2045     break;
    2046   case Qualifiers::OCL_Weak:
    2047     Extra.mangleSourceName("Weak");
    2048     break;
    2049   }
    
  • mangleObjCKindOfType()
    2064   Stream << "?$";
    2065   Extra.mangleSourceName("KindOf");
    
  • mangleAddressSpaceType()
    2304   Stream << "?$";
    ....
    2307   if (Context.getASTContext().addressSpaceMapManglingFor(AS)) {
    ....
    2309     Extra.mangleSourceName("_AS");
    ....
    2311   } else {
    2312     switch (AS) {
    ....
    2315     case LangAS::opencl_global:
    2316       Extra.mangleSourceName("_ASCLglobal");
    2317       break;
    2318     case LangAS::opencl_global_device:
    2319       Extra.mangleSourceName("_ASCLdevice");
    2320       break;
    2321     case LangAS::opencl_global_host:
    2322       Extra.mangleSourceName("_ASCLhost");
    2323       break;
    2324     case LangAS::opencl_local:
    2325       Extra.mangleSourceName("_ASCLlocal");
    2326       break;
    2327     case LangAS::opencl_constant:
    2328       Extra.mangleSourceName("_ASCLconstant");
    2329       break;
    2330     case LangAS::opencl_private:
    2331       Extra.mangleSourceName("_ASCLprivate");
    2332       break;
    2333     case LangAS::opencl_generic:
    2334       Extra.mangleSourceName("_ASCLgeneric");
    2335       break;
    2336     case LangAS::cuda_device:
    2337       Extra.mangleSourceName("_ASCUdevice");
    2338       break;
    2339     case LangAS::cuda_constant:
    2340       Extra.mangleSourceName("_ASCUconstant");
    2341       break;
    2342     case LangAS::cuda_shared:
    2343       Extra.mangleSourceName("_ASCUshared");
    2344       break;
    
  • mangleType(const ComplexType *, ...)
    3185   Stream << "?$";
    3186   Extra.mangleSourceName("_Complex");
    
  • mangleType(const VectorType *, ...)
    3250     Stream << "?$";
    3251     Extra.mangleSourceName("__vector");
    
  • mangleType(const ObjCObjectType *, ...)
    3334   Out << "?$";
    3335   if (T->isObjCId())
    3336     mangleSourceName("objc_object");
    3337   else if (T->isObjCClass())
    3338     mangleSourceName("objc_class");
    3339   else
    3340     mangleSourceName(T->getInterface()->getName());
    
  • mangleType(const AtomicType *, ...)
    3482   Stream << "?$";
    3483   Extra.mangleSourceName("_Atomic");
    
  • mangleType(const PipeType *, ...)
    3496   Stream << "?$";
    3497   Extra.mangleSourceName("ocl_pipe");
    
  • mangleType(const BitIntType *, ...)
    3534   Stream << "?$";
    3535   if (T->isUnsigned())
    3536     Extra.mangleSourceName("_UBitInt");
    3537   else
    3538     Extra.mangleSourceName("_BitInt");
    

Many of the functions above also contain calls to mangleArtificialTagType() that pass a sequence of string literals that are then passed to mangleSourceName() without a preceding $ character. These names are not prefixed by a $ in the mangled name at all, but perhaps they should be.

Finally, the following function looks like it has the same issue that mangleThreadSafeStaticGuardVariable() did prior to the change in #85300. Perhaps $RT should be mangled via a call to mangleSourceName().

  • mangleReferenceTemporary()
    3914   Mangler.getStream() << "?$RT" << ManglingNumber << '@';
    

Of all of these, only the last (mangleReferenceTemporary()) looks likely to be relevant with regard to compatibility with MSVC. The rest involve languages that MSVC doesn't support (Objective-C), Clang extensions that MSVC doesn't support, or builtin types that are not yet implemented in MSVC (and thus it is not yet known what mangling should be used).

Metadata

Metadata

Assignees

No one assigned

    Labels

    clang:frontendLanguage frontend issues, e.g. anything involving "Sema"

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions