Skip to content

Commit

Permalink
Revert "[Clang] [AST] Fix placeholder return type name mangling for M…
Browse files Browse the repository at this point in the history
…SVC 1920+ / VS2019+ (#102848)"

It cause builds to start failing with

  Invalid type expected
  UNREACHABLE executed at clang/lib/AST/MicrosoftMangle.cpp:2551!

see comments on the PR.

> Partial fix for #92204.
> This PR just fixes VS2019+ since that is the suite of compilers that I
> require link compatibility with at the moment.
> I still intend to fix VS2017 and to update llvm-undname in future PRs.
> Once those are also finished and merged I'll close out
> #92204.
> I am hoping to get the llvm-undname PR up in a couple of weeks to be
> able to demangle the VS2019+ name mangling.
>
> MSVC 1920+ mangles placeholder return types for non-templated functions
> with "@".
> For example `auto foo() { return 0; }` is mangled as `?foo@@ya@XZ`.
>
> MSVC 1920+ mangles placeholder return types for templated functions as
> the qualifiers of the AutoType followed by "_P" for `auto` and "_T" for
> `decltype(auto)`.
> For example `template<class T> auto foo() { return 0; }` is mangled as
> `??$foo@H@@ya?A_PXZ` when `foo` is instantiated as follows `foo<int>()`.
>
> Lambdas with placeholder return types are still mangled with clang's
> custom mangling since MSVC lambda mangling hasn't been deciphered yet.
> Similarly any pointers in the return type with an address space are
> mangled with clang's custom mangling since that is a clang extension.
>
> We cannot augment `mangleType` to support this mangling scheme as the
> mangling schemes for variables and functions differ.
> auto variables are encoded with the fully deduced type where auto return
> types are not.
> The following two functions with a static variable are mangled the same
> ```
> template<class T>
> int test()
> {
>     static int i = 0; // "?i@?1???$test@H@@yahxz@4HA"
>     return i;
> }
>
> template<class T>
> int test()
> {
>     static auto i = 0; // "?i@?1???$test@H@@yahxz@4HA"
>     return i;
> }
> ```
> Inside `mangleType` once we get to mangling the `AutoType` we have no
> context if we are from a variable encoding or some other encoding.
> Therefore it was easier to handle any special casing for `AutoType`
> return types with a separate function instead of using the `mangleType`
> infrastructure.

This reverts commit e0d173d
and the wollow-up fa343be.
  • Loading branch information
zmodem committed Aug 15, 2024
1 parent 5e95571 commit 05f6630
Show file tree
Hide file tree
Showing 6 changed files with 19 additions and 534 deletions.
2 changes: 0 additions & 2 deletions clang/docs/ReleaseNotes.rst
Original file line number Diff line number Diff line change
Expand Up @@ -77,8 +77,6 @@ C++ Specific Potentially Breaking Changes
ABI Changes in This Version
---------------------------

- Fixed Microsoft name mangling of placeholder, auto and decltype(auto), return types for MSVC 1920+. This change resolves incompatibilities with code compiled by MSVC 1920+ but will introduce incompatibilities with code compiled by earlier versions of Clang unless such code is built with the compiler option -fms-compatibility-version=19.14 to imitate the MSVC 1914 mangling behavior.

AST Dumping Potentially Breaking Changes
----------------------------------------

Expand Down
162 changes: 9 additions & 153 deletions clang/lib/AST/MicrosoftMangle.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -408,8 +408,6 @@ class MicrosoftCXXNameMangler {
void mangleSourceName(StringRef Name);
void mangleNestedName(GlobalDecl GD);

void mangleAutoReturnType(QualType T, QualifierMangleMode QMM);

private:
bool isStructorDecl(const NamedDecl *ND) const {
return ND == Structor || getStructor(ND) == Structor;
Expand Down Expand Up @@ -479,11 +477,6 @@ class MicrosoftCXXNameMangler {
SourceRange Range);
void mangleObjCKindOfType(const ObjCObjectType *T, Qualifiers Quals,
SourceRange Range);

void mangleAutoReturnType(const MemberPointerType *T, Qualifiers Quals);
void mangleAutoReturnType(const PointerType *T, Qualifiers Quals);
void mangleAutoReturnType(const LValueReferenceType *T, Qualifiers Quals);
void mangleAutoReturnType(const RValueReferenceType *T, Qualifiers Quals);
};
}

Expand Down Expand Up @@ -2501,57 +2494,6 @@ void MicrosoftCXXNameMangler::mangleAddressSpaceType(QualType T,
mangleArtificialTagType(TagTypeKind::Struct, ASMangling, {"__clang"});
}

void MicrosoftCXXNameMangler::mangleAutoReturnType(QualType T,
QualifierMangleMode QMM) {
assert(getASTContext().getLangOpts().isCompatibleWithMSVC(
LangOptions::MSVC2019) &&
"Cannot mangle MSVC 2017 auto return types!");

if (isa<AutoType>(T)) {
const auto *AT = T->getContainedAutoType();
Qualifiers Quals = T.getLocalQualifiers();

if (QMM == QMM_Result)
Out << '?';
if (QMM != QMM_Drop)
mangleQualifiers(Quals, false);
Out << (AT->isDecltypeAuto() ? "_T" : "_P");
return;
}

T = T.getDesugaredType(getASTContext());
Qualifiers Quals = T.getLocalQualifiers();

switch (QMM) {
case QMM_Drop:
case QMM_Result:
break;
case QMM_Mangle:
mangleQualifiers(Quals, false);
break;
default:
llvm_unreachable("QMM_Escape unexpected");
}

const Type *ty = T.getTypePtr();
switch (ty->getTypeClass()) {
case Type::MemberPointer:
mangleAutoReturnType(cast<MemberPointerType>(ty), Quals);
break;
case Type::Pointer:
mangleAutoReturnType(cast<PointerType>(ty), Quals);
break;
case Type::LValueReference:
mangleAutoReturnType(cast<LValueReferenceType>(ty), Quals);
break;
case Type::RValueReference:
mangleAutoReturnType(cast<RValueReferenceType>(ty), Quals);
break;
default:
llvm_unreachable("Invalid type expected");
}
}

void MicrosoftCXXNameMangler::mangleType(QualType T, SourceRange Range,
QualifierMangleMode QMM) {
// Don't use the canonical types. MSVC includes things like 'const' on
Expand Down Expand Up @@ -2965,52 +2907,17 @@ void MicrosoftCXXNameMangler::mangleFunctionType(const FunctionType *T,
// can differ by their calling convention and are typically deduced. So
// we make sure that this type gets mangled properly.
mangleType(ResultType, Range, QMM_Result);
} else if (IsInLambda) {
if (const auto *AT = ResultType->getContainedAutoType()) {
assert(AT->getKeyword() == AutoTypeKeyword::Auto &&
"should only need to mangle auto!");
(void)AT;
Out << '?';
mangleQualifiers(ResultType.getLocalQualifiers(), /*IsMember=*/false);
Out << '?';
mangleSourceName("<auto>");
Out << '@';
} else {
Out << '@';
}
} else if (const auto *AT = ResultType->getContainedAutoType()) {
} else if (const auto *AT = dyn_cast_or_null<AutoType>(
ResultType->getContainedAutoType())) {
Out << '?';
mangleQualifiers(ResultType.getLocalQualifiers(), /*IsMember=*/false);
Out << '?';
assert(AT->getKeyword() != AutoTypeKeyword::GNUAutoType &&
"shouldn't need to mangle __auto_type!");

// If we have any pointer types with the clang address space extension
// then defer to the custom clang mangling to keep backwards
// compatibility. See `mangleType(const PointerType *T, Qualifiers Quals,
// SourceRange Range)` for details.
auto UseClangMangling = [](QualType ResultType) {
QualType T = ResultType;
while (isa<PointerType>(T.getTypePtr())) {
T = T->getPointeeType();
if (T.getQualifiers().hasAddressSpace())
return true;
}
return false;
};

if (getASTContext().getLangOpts().isCompatibleWithMSVC(
LangOptions::MSVC2019) &&
!UseClangMangling(ResultType)) {
if (D && !D->getPrimaryTemplate()) {
Out << '@';
} else {
mangleAutoReturnType(ResultType, QMM_Result);
}
} else {
Out << '?';
mangleQualifiers(ResultType.getLocalQualifiers(), /*IsMember=*/false);
Out << '?';
mangleSourceName(AT->isDecltypeAuto() ? "<decltype-auto>" : "<auto>");
Out << '@';
}
mangleSourceName(AT->isDecltypeAuto() ? "<decltype-auto>" : "<auto>");
Out << '@';
} else if (IsInLambda) {
Out << '@';
} else {
if (ResultType->isVoidType())
ResultType = ResultType.getUnqualifiedType();
Expand Down Expand Up @@ -4313,57 +4220,6 @@ void MicrosoftMangleContextImpl::mangleStringLiteral(const StringLiteral *SL,
Mangler.getStream() << '@';
}

void MicrosoftCXXNameMangler::mangleAutoReturnType(const MemberPointerType *T,
Qualifiers Quals) {
QualType PointeeType = T->getPointeeType();
manglePointerCVQualifiers(Quals);
manglePointerExtQualifiers(Quals, PointeeType);
if (const FunctionProtoType *FPT = PointeeType->getAs<FunctionProtoType>()) {
Out << '8';
mangleName(T->getClass()->castAs<RecordType>()->getDecl());
mangleFunctionType(FPT, nullptr, true);
} else {
mangleQualifiers(PointeeType.getQualifiers(), true);
mangleName(T->getClass()->castAs<RecordType>()->getDecl());
mangleAutoReturnType(PointeeType, QMM_Drop);
}
}

void MicrosoftCXXNameMangler::mangleAutoReturnType(const PointerType *T,
Qualifiers Quals) {
QualType PointeeType = T->getPointeeType();
assert(!PointeeType.getQualifiers().hasAddressSpace() &&
"Unexpected address space mangling required");

manglePointerCVQualifiers(Quals);
manglePointerExtQualifiers(Quals, PointeeType);

if (const FunctionProtoType *FPT = PointeeType->getAs<FunctionProtoType>()) {
Out << '6';
mangleFunctionType(FPT);
} else {
mangleAutoReturnType(PointeeType, QMM_Mangle);
}
}

void MicrosoftCXXNameMangler::mangleAutoReturnType(const LValueReferenceType *T,
Qualifiers Quals) {
QualType PointeeType = T->getPointeeType();
assert(!Quals.hasConst() && !Quals.hasVolatile() && "unexpected qualifier!");
Out << 'A';
manglePointerExtQualifiers(Quals, PointeeType);
mangleAutoReturnType(PointeeType, QMM_Mangle);
}

void MicrosoftCXXNameMangler::mangleAutoReturnType(const RValueReferenceType *T,
Qualifiers Quals) {
QualType PointeeType = T->getPointeeType();
assert(!Quals.hasConst() && !Quals.hasVolatile() && "unexpected qualifier!");
Out << "$$Q";
manglePointerExtQualifiers(Quals, PointeeType);
mangleAutoReturnType(PointeeType, QMM_Mangle);
}

MicrosoftMangleContext *MicrosoftMangleContext::create(ASTContext &Context,
DiagnosticsEngine &Diags,
bool IsAux) {
Expand Down
Loading

0 comments on commit 05f6630

Please sign in to comment.