Skip to content

Commit

Permalink
Fix debug crash (#1894)
Browse files Browse the repository at this point in the history
* Trigger debug break on assert

* Fix crashes in debug builds causing CI to fail

Implementation is based on #1819.

* Update to actions/<upload/download>-artifact@v4
  • Loading branch information
duckdoom5 authored Jan 23, 2025
1 parent b9685f0 commit c25c7df
Show file tree
Hide file tree
Showing 2 changed files with 128 additions and 67 deletions.
9 changes: 6 additions & 3 deletions .github/workflows/main.yml
Original file line number Diff line number Diff line change
Expand Up @@ -90,9 +90,12 @@ jobs:
shell: bash
run: build/build.sh prepack -platform $PLATFORM

- uses: actions/upload-artifact@v3
- name: Upload Artifacts
uses: actions/upload-artifact@v4
with:
name: intermediate
retention-days: 7
overwrite: true
path: |
artifacts
include/**/*.h
Expand All @@ -116,7 +119,7 @@ jobs:
- name: Set version
run: nbgv cloud --all-vars

- uses: actions/download-artifact@v3
- uses: actions/download-artifact@v4
with:
name: intermediate

Expand All @@ -129,7 +132,7 @@ jobs:
run: build/build.sh pack

- name: Upload package
uses: actions/upload-artifact@v3
uses: actions/upload-artifact@v4
with:
name: CppSharp.nupkg
path: |
Expand Down
186 changes: 122 additions & 64 deletions src/CppParser/Parser.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -71,13 +71,13 @@
#define _assertm(condition, message, call) \
do{ \
if (!(condition)) { \
std::cerr << "Assert at " \
std::cerr << "Assert at `" \
<< __FILE__ \
<< ":" \
<< __LINE__ \
<< " in " \
<< "` in `" \
<< __FUNCTION__ \
<< "failed. " \
<< "` failed. " \
<< message; \
call; \
} \
Expand All @@ -89,38 +89,57 @@
if (!(condition)) { \
const clang::SourceManager& _sm = sm; \
clang::SourceLocation _loc = loc; \
std::cerr << "Assert at " \
std::cerr << "Assert at `" \
<< __FILE__ \
<< ":" \
<< __LINE__ \
<< " in " \
<< "` in `" \
<< __FUNCTION__ \
<< "failed. " \
<< "` failed. " \
<< message \
<< " Filename " \
<< " Filename `" \
<< _sm.getFilename(_loc).str() \
<< ":" \
<< _sm.getSpellingLineNumber(_loc) \
<< "\n"; \
<< "`\n"; \
call; \
} \
}while(0)

// Macros which output messages to console if parsing encounters oddity.
// If _DEBUG is defined but DEBUG_NO_ABORT is not macros abort.
// In debug builds, macros abort unless DEBUG_NO_ABORT is defined.
//
// Macro assertm outputs a message if condition is false.
// Macro assertml outputs a message and parsing file and line on given source manager and source line.
//
// assertml adds newline ending.
#if defined(_DEBUG) && !defined(DEBUG_NO_ABORT)
#define assertm(condition, message) _assertm(condition, message, abort())
#define assertml(condition, message, sm, source) _assertml(condition, message, sm, source, abort())
#ifdef NDEBUG
#define debug_break() ((void)0)
#define debug_fail() ((void)0)
#else
#define assertm(condition, message) _assertm(condition, message, )
#define assertml(condition, message, sm, source) _assertml(condition, message, sm, source, )

#if __GNUC__
#define debug_break() \
__builtin_trap()
#elif _MSC_VER
#define debug_break() \
__debugbreak()
#else
#define debug_break(c) \
*reinterpret_cast<volatile int*>(0) = 47283;
#endif

#ifdef DEBUG_NO_ABORT
#define debug_fail() debug_break()
#else
#define debug_fail() debug_break(); abort()
#endif

#endif

#define assertm(condition, message) _assertm(condition, message, debug_fail())
#define assertml(condition, message, sm, source) _assertml(condition, message, sm, source, debug_fail())

using namespace CppSharp::CppParser;

// We use this as a placeholder for pointer values that should be ignored.
Expand Down Expand Up @@ -959,7 +978,14 @@ static clang::CXXRecordDecl* GetCXXRecordDeclFromBaseType(const clang::ASTContex
return GetCXXRecordDeclFromTemplateName(TST->getTemplateName());
else if (auto Injected = Ty->getAs<clang::InjectedClassNameType>())
return Injected->getDecl();
else if (auto TTPT = Ty->getAs<clang::TemplateTypeParmType>()) {
return nullptr;
}
else if (auto DNT = Ty->getAs<clang::DependentNameType>()) {
return nullptr;
}

Ty->dump();
assertml(0, "Could not get base CXX record from type. Unhandled type: ", context.getSourceManager(), base.getBeginLoc());

return nullptr;
Expand Down Expand Up @@ -2695,41 +2721,59 @@ Type* Parser::WalkType(clang::QualType QualType, const clang::TypeLoc* TL,
auto TST = new TemplateSpecializationType();

TemplateName Name = TS->getTemplateName();
TST->_template = static_cast<Template*>(WalkDeclaration(
Name.getAsTemplateDecl()));
TST->_template = static_cast<Template*>(WalkDeclaration(Name.getAsTemplateDecl()));

if (TS->isSugared())
TST->desugared = GetQualifiedType(TS->getCanonicalTypeInternal(), TL);

TypeLoc UTL, ETL, ITL;
TemplateArgumentList TArgs(TemplateArgumentList::OnStack, TS->template_arguments());

if (LocValid)
if (!LocValid)
{
auto TypeLocClass = TL->getTypeLocClass();
if (TypeLocClass == TypeLoc::Qualified)
{
UTL = TL->getUnqualifiedLoc();
TL = &UTL;
}
else if (TypeLocClass == TypeLoc::Elaborated)
{
ETL = TL->getAs<ElaboratedTypeLoc>();
ITL = ETL.getNextTypeLoc();
TL = &ITL;
}

assertm(TL->getTypeLocClass() == TypeLoc::TemplateSpecialization, "Only Template specialization accepted!\n");
TST->Arguments = WalkTemplateArgumentList(&TArgs, (TemplateSpecializationTypeLoc*)nullptr);
Ty = TST;
break;
}

TemplateSpecializationTypeLoc TSpecTL;
TemplateSpecializationTypeLoc *TSTL = 0;
if (LocValid)
TypeLoc UTL, ETL, ITL;
if (TL->getTypeLocClass() == TypeLoc::Qualified)
{
TSpecTL = TL->getAs<TemplateSpecializationTypeLoc>();
TSTL = &TSpecTL;
UTL = TL->getUnqualifiedLoc();
TL = &UTL;
}

if (TL->getTypeLocClass() == TypeLoc::Elaborated)
{
ETL = TL->getAs<ElaboratedTypeLoc>();
ITL = ETL.getNextTypeLoc();
TL = &ITL;
}

TemplateArgumentList TArgs(TemplateArgumentList::OnStack, TS->template_arguments());
TST->Arguments = WalkTemplateArgumentList(&TArgs, TSTL);
switch (TL->getTypeLocClass()) {
case TypeLoc::DependentTemplateSpecialization:
{
DependentTemplateSpecializationTypeLoc TSpecTL = TL->getAs<DependentTemplateSpecializationTypeLoc>();
TST->Arguments = WalkTemplateArgumentList(&TArgs, &TSpecTL);
Ty = TST;
break;
}
case TypeLoc::TemplateSpecialization:
{
TemplateSpecializationTypeLoc TSpecTL = TL->getAs<TemplateSpecializationTypeLoc>();
TST->Arguments = WalkTemplateArgumentList(&TArgs, &TSpecTL);
Ty = TST;
break;
}
case TypeLoc::TemplateTypeParm:
{
TemplateTypeParmTypeLoc TTPTL = TL->getAs<TemplateTypeParmTypeLoc>();
TST->Arguments = WalkTemplateArgumentList(&TArgs, (TemplateSpecializationTypeLoc*)nullptr);
break;
}
default:
assertml(0, "Unhandled TemplateSpecializationTypeLoc!\n", c->getSourceManager(), TL->getBeginLoc());
break;
}

Ty = TST;
break;
Expand All @@ -2741,38 +2785,52 @@ Type* Parser::WalkType(clang::QualType QualType, const clang::TypeLoc* TL,

if (TS->isSugared())
TST->desugared = GetQualifiedType(TS->getCanonicalTypeInternal(), TL);

TemplateArgumentList TArgs(TemplateArgumentList::OnStack, TS->template_arguments());

TypeLoc UTL, ETL, ITL;

if (LocValid)
if (!LocValid)
{
auto TypeLocClass = TL->getTypeLocClass();
if (TypeLocClass == TypeLoc::Qualified)
{
UTL = TL->getUnqualifiedLoc();
TL = &UTL;
}
else if (TypeLocClass == TypeLoc::Elaborated)
{
ETL = TL->getAs<ElaboratedTypeLoc>();
ITL = ETL.getNextTypeLoc();
TL = &ITL;
}
assertml(TL->getTypeLocClass() == TypeLoc::DependentTemplateSpecialization,
"Dependent template only accepted!",
c->getSourceManager(), TL->getBeginLoc());
TST->Arguments = WalkTemplateArgumentList(&TArgs, (DependentTemplateSpecializationTypeLoc*)nullptr);
Ty = TST;
break;
}

DependentTemplateSpecializationTypeLoc TSpecTL;
DependentTemplateSpecializationTypeLoc *TSTL = 0;
if (LocValid)
TypeLoc UTL, ETL, ITL;
if (TL->getTypeLocClass() == TypeLoc::Qualified)
{
TSpecTL = TL->getAs<DependentTemplateSpecializationTypeLoc>();
TSTL = &TSpecTL;
UTL = TL->getUnqualifiedLoc();
TL = &UTL;
}

if (TL->getTypeLocClass() == TypeLoc::Elaborated)
{
ETL = TL->getAs<ElaboratedTypeLoc>();
ITL = ETL.getNextTypeLoc();
TL = &ITL;
}

TemplateArgumentList TArgs(TemplateArgumentList::OnStack, TS->template_arguments());
TST->Arguments = WalkTemplateArgumentList(&TArgs, TSTL);
switch (TL->getTypeLocClass()) {
case TypeLoc::DependentTemplateSpecialization:
{
DependentTemplateSpecializationTypeLoc TSpecTL = TL->getAs<DependentTemplateSpecializationTypeLoc>();
TST->Arguments = WalkTemplateArgumentList(&TArgs, &TSpecTL);
break;
}
case TypeLoc::TemplateSpecialization:
{
TemplateSpecializationTypeLoc TSpecTL = TL->getAs<TemplateSpecializationTypeLoc>();
TST->Arguments = WalkTemplateArgumentList(&TArgs, &TSpecTL);
break;
}
case TypeLoc::TemplateTypeParm:
{
TST->Arguments = WalkTemplateArgumentList(&TArgs, (DependentTemplateSpecializationTypeLoc*)nullptr);
break;
}
default:
assertml(0, "Unhandled DependentTemplateSpecializationTypeLoc!\n", c->getSourceManager(), TL->getBeginLoc());
break;
}

Ty = TST;
break;
Expand Down

0 comments on commit c25c7df

Please sign in to comment.