Browse Source

Fix crashing name mangler (#1910)

* Fix broken name mangler

* Remove llvm backend mangeling
pull/1900/head
Jelle 5 months ago committed by GitHub
parent
commit
4250c0e318
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
  1. 125
      src/CppParser/ASTNameMangler.cpp
  2. 50
      src/CppParser/ASTNameMangler.h
  3. 82
      src/CppParser/Parser.cpp
  4. 6
      src/CppParser/Parser.h

125
src/CppParser/ASTNameMangler.cpp

@ -0,0 +1,125 @@ @@ -0,0 +1,125 @@
/************************************************************************
*
* CppSharp
* Licensed under the simplified BSD license. All rights reserved.
*
************************************************************************/
#include "ASTNameMangler.h"
#include <clang/AST/GlobalDecl.h>
#include <clang/AST/Mangle.h>
#include <clang/AST/VTableBuilder.h>
#include <clang/Basic/TargetInfo.h>
#include <llvm/IR/Mangler.h>
using namespace clang;
using namespace CppSharp::CppParser;
namespace {
enum ObjCKind {
ObjCClass,
ObjCMetaclass,
};
StringRef getClassSymbolPrefix(ObjCKind Kind, const ASTContext& Context) {
if (Context.getLangOpts().ObjCRuntime.isGNUFamily())
return Kind == ObjCMetaclass ? "_OBJC_METACLASS_" : "_OBJC_CLASS_";
return Kind == ObjCMetaclass ? "OBJC_METACLASS_$_" : "OBJC_CLASS_$_";
}
void WriteObjCClassName(const ObjCInterfaceDecl* D, raw_ostream& OS) {
OS << getClassSymbolPrefix(ObjCClass, D->getASTContext());
OS << D->getObjCRuntimeNameAsString();
}
}
ASTNameMangler::ASTNameMangler(ASTContext& Ctx)
: DL(Ctx.getTargetInfo().getDataLayoutString())
, MC(Ctx.createMangleContext())
{
}
std::string ASTNameMangler::GetName(const Decl* D) {
std::string Name;
{
llvm::raw_string_ostream OS(Name);
WriteName(D, OS);
}
return Name;
}
bool ASTNameMangler::WriteName(const Decl* D, raw_ostream& OS) {
// First apply frontend mangling.
if (auto* FD = dyn_cast<FunctionDecl>(D)) {
if (FD->isDependentContext())
return true;
if (WriteFuncOrVarName(FD, OS))
return true;
}
else if (auto* VD = dyn_cast<VarDecl>(D)) {
if (WriteFuncOrVarName(VD, OS))
return true;
}
else if (auto* MD = dyn_cast<ObjCMethodDecl>(D)) {
MC->mangleObjCMethodName(MD, OS, /*includePrefixByte=*/false,
/*includeCategoryNamespace=*/true);
return false;
}
else if (auto* ID = dyn_cast<ObjCInterfaceDecl>(D)) {
WriteObjCClassName(ID, OS);
}
else {
return true;
}
return false;
}
std::string ASTNameMangler::GetMangledStructor(const NamedDecl* ND, unsigned StructorType) {
std::string FrontendBuf;
llvm::raw_string_ostream FOS(FrontendBuf);
GlobalDecl GD;
if (const auto* CD = dyn_cast_or_null<CXXConstructorDecl>(ND))
GD = GlobalDecl(CD, static_cast<CXXCtorType>(StructorType));
else if (const auto* DD = dyn_cast_or_null<CXXDestructorDecl>(ND))
GD = GlobalDecl(DD, static_cast<CXXDtorType>(StructorType));
MC->mangleName(GD, FOS);
return FrontendBuf;
}
std::string ASTNameMangler::GetMangledThunk(const CXXMethodDecl* MD, const ThunkInfo& T, bool /*ElideOverrideInfo*/) {
std::string FrontendBuf;
llvm::raw_string_ostream FOS(FrontendBuf);
// TODO: Enable `ElideOverrideInfo` param if clang is updated to 19
MC->mangleThunk(MD, T, /*ElideOverrideInfo,*/ FOS);
return FrontendBuf;
}
bool ASTNameMangler::WriteFuncOrVarName(const NamedDecl* D, raw_ostream& OS) const
{
if (!MC->shouldMangleDeclName(D)) {
const IdentifierInfo* II = D->getIdentifier();
if (!II)
return true;
OS << II->getName();
return false;
}
GlobalDecl GD;
if (const auto* CtorD = dyn_cast<CXXConstructorDecl>(D))
GD = GlobalDecl(CtorD, Ctor_Base);
else if (const auto* DtorD = dyn_cast<CXXDestructorDecl>(D))
GD = GlobalDecl(DtorD, Dtor_Base);
else if (D->hasAttr<CUDAGlobalAttr>())
GD = GlobalDecl(cast<FunctionDecl>(D));
else
GD = GlobalDecl(D);
MC->mangleName(GD, OS);
return false;
}

50
src/CppParser/ASTNameMangler.h

@ -0,0 +1,50 @@ @@ -0,0 +1,50 @@
/************************************************************************
*
* CppSharp
* Licensed under the simplified BSD license. All rights reserved.
*
************************************************************************/
#pragma once
#include <clang/AST/ASTFwd.h>
#include <llvm/IR/DataLayout.h>
#include <string>
namespace clang
{
class ASTContext;
class MangleContext;
struct ThunkInfo;
}
namespace llvm
{
class raw_ostream;
}
namespace CppSharp::CppParser {
/// <summary>
/// Helper class for getting the mangled name of a declaration
/// </summary>
/// <remarks>Source adapted from https://clang.llvm.org/doxygen/Mangle_8cpp_source.html#l00394</remarks>
class ASTNameMangler
{
public:
explicit ASTNameMangler(clang::ASTContext& Ctx);
std::string GetName(const clang::Decl* D);
bool WriteName(const clang::Decl* D, llvm::raw_ostream& OS);
private:
std::string GetMangledStructor(const clang::NamedDecl* ND, unsigned StructorType);
std::string GetMangledThunk(const clang::CXXMethodDecl* MD, const clang::ThunkInfo& T, bool ElideOverrideInfo);
bool WriteFuncOrVarName(const clang::NamedDecl* D, llvm::raw_ostream& OS) const;
llvm::DataLayout DL;
std::unique_ptr<clang::MangleContext> MC;
};
}

82
src/CppParser/Parser.cpp

@ -58,6 +58,8 @@ @@ -58,6 +58,8 @@
#include <Driver/ToolChains/Linux.h>
#include <Driver/ToolChains/MSVC.h>
#include "ASTNameMangler.h"
#if defined(__APPLE__) || defined(__linux__)
#ifndef _GNU_SOURCE
#define _GNU_SOURCE
@ -468,69 +470,55 @@ void Parser::Setup(bool Compile) @@ -468,69 +470,55 @@ void Parser::Setup(bool Compile)
PP.getLangOpts());
c->createASTContext();
NameMangler.reset(new ASTNameMangler(c->getASTContext()));
}
//-----------------------------------//
std::string Parser::GetDeclMangledName(const clang::Decl* D)
std::string Parser::GetDeclMangledName(const clang::Decl* D) const
{
using namespace clang;
// Source adapted from https://clang.llvm.org/doxygen/JSONNodeDumper_8cpp_source.html#l00845
if(!D || !isa<NamedDecl>(D))
return "";
bool CanMangle = isa<FunctionDecl>(D) || isa<VarDecl>(D)
|| isa<CXXConstructorDecl>(D) || isa<CXXDestructorDecl>(D);
using namespace clang;
if (!CanMangle) return "";
auto ND = dyn_cast_or_null<NamedDecl>(D);
if (!ND || !ND->getDeclName())
return {};
auto ND = cast<NamedDecl>(D);
std::unique_ptr<MangleContext> MC;
// If the declaration is dependent or is in a dependent context, then the
// mangling is unlikely to be meaningful (and in some cases may cause
// "don't know how to mangle this" assertion failures.)
if (ND->isTemplated())
return {};
auto& AST = c->getASTContext();
auto targetABI = c->getTarget().getCXXABI().getKind();
switch(targetABI)
{
default:
MC.reset(ItaniumMangleContext::create(AST, AST.getDiagnostics()));
break;
case TargetCXXABI::Microsoft:
MC.reset(MicrosoftMangleContext::create(AST, AST.getDiagnostics()));
break;
}
if (!MC)
llvm_unreachable("Unknown mangling ABI");
std::string Mangled;
llvm::raw_string_ostream Out(Mangled);
/*bool CanMangle = isa<FunctionDecl>(D) || isa<VarDecl>(D)
|| isa<CXXConstructorDecl>(D) || isa<CXXDestructorDecl>(D);
bool IsDependent = false;
if (const ValueDecl *VD = dyn_cast<ValueDecl>(ND))
IsDependent |= VD->getType()->isDependentType();
if (!CanMangle)
return {};*/
if (!IsDependent)
IsDependent |= ND->getDeclContext()->isDependentContext();
// FIXME: There are likely other contexts in which it makes no sense to ask
// for a mangled name.
if (isa<RequiresExprBodyDecl>(ND->getDeclContext()))
return {};
if (!MC->shouldMangleDeclName(ND) || IsDependent)
return ND->getDeclName().getAsString();
// Do not mangle template deduction guides.
if (isa<CXXDeductionGuideDecl>(ND))
return {};
GlobalDecl GD;
if (const CXXConstructorDecl *CD = dyn_cast<CXXConstructorDecl>(ND))
GD = GlobalDecl(CD, Ctor_Base);
else if (const CXXDestructorDecl *DD = dyn_cast<CXXDestructorDecl>(ND))
GD = GlobalDecl(DD, Dtor_Base);
else
GD = GlobalDecl(ND);
MC->mangleName(GD, Out);
// Mangled names are not meaningful for locals, and may not be well-defined
// in the case of VLAs.
auto* VD = dyn_cast<VarDecl>(ND);
if (VD && VD->hasLocalStorage())
return {};
Out.flush();
std::string MangledName = NameMangler->GetName(ND);
// Strip away LLVM name marker.
if(!Mangled.empty() && Mangled[0] == '\01')
Mangled = Mangled.substr(1);
if (!MangledName.empty() && MangledName[0] == '\01')
MangledName = MangledName.substr(1);
return Mangled;
return MangledName;
}
//-----------------------------------//
@ -632,7 +620,7 @@ static clang::SourceLocation GetDeclStartLocation(clang::CompilerInstance* C, @@ -632,7 +620,7 @@ static clang::SourceLocation GetDeclStartLocation(clang::CompilerInstance* C,
return GetDeclStartLocation(C, prevDecl);
}
std::string Parser::GetTypeName(const clang::Type* Type)
std::string Parser::GetTypeName(const clang::Type* Type) const
{
using namespace clang;

6
src/CppParser/Parser.h

@ -47,6 +47,7 @@ namespace clang { @@ -47,6 +47,7 @@ namespace clang {
#define Debug printf
namespace CppSharp { namespace CppParser {
class ASTNameMangler;
class Parser
{
@ -133,8 +134,8 @@ private: @@ -133,8 +134,8 @@ private:
// Clang helpers
SourceLocationKind GetLocationKind(const clang::SourceLocation& Loc);
bool IsValidDeclaration(const clang::SourceLocation& Loc);
std::string GetDeclMangledName(const clang::Decl* D);
std::string GetTypeName(const clang::Type* Type);
std::string GetDeclMangledName(const clang::Decl* D) const;
std::string GetTypeName(const clang::Type* Type) const;
bool CanCheckCodeGenInfo(const clang::Type* Ty);
void CompleteIfSpecializationType(const clang::QualType& QualType);
Parameter* WalkParameter(const clang::ParmVarDecl* PVD,
@ -181,6 +182,7 @@ private: @@ -181,6 +182,7 @@ private:
int index;
std::unique_ptr<clang::CompilerInstance> c;
llvm::LLVMContext LLVMCtx;
std::unique_ptr<ASTNameMangler> NameMangler;
std::unique_ptr<llvm::Module> LLVMModule;
std::unique_ptr<clang::CodeGen::CodeGenModule> CGM;
std::unique_ptr<clang::CodeGen::CodeGenTypes> codeGenTypes;

Loading…
Cancel
Save