Browse Source

Fix debug crash (#1894)

* 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
pull/1862/merge
Jelle 6 months ago committed by GitHub
parent
commit
c25c7dfadf
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
  1. 9
      .github/workflows/main.yml
  2. 186
      src/CppParser/Parser.cpp

9
.github/workflows/main.yml

@ -90,9 +90,12 @@ jobs:
shell: bash shell: bash
run: build/build.sh prepack -platform $PLATFORM run: build/build.sh prepack -platform $PLATFORM
- uses: actions/upload-artifact@v3 - name: Upload Artifacts
uses: actions/upload-artifact@v4
with: with:
name: intermediate name: intermediate
retention-days: 7
overwrite: true
path: | path: |
artifacts artifacts
include/**/*.h include/**/*.h
@ -116,7 +119,7 @@ jobs:
- name: Set version - name: Set version
run: nbgv cloud --all-vars run: nbgv cloud --all-vars
- uses: actions/download-artifact@v3 - uses: actions/download-artifact@v4
with: with:
name: intermediate name: intermediate
@ -129,7 +132,7 @@ jobs:
run: build/build.sh pack run: build/build.sh pack
- name: Upload package - name: Upload package
uses: actions/upload-artifact@v3 uses: actions/upload-artifact@v4
with: with:
name: CppSharp.nupkg name: CppSharp.nupkg
path: | path: |

186
src/CppParser/Parser.cpp

@ -71,13 +71,13 @@
#define _assertm(condition, message, call) \ #define _assertm(condition, message, call) \
do{ \ do{ \
if (!(condition)) { \ if (!(condition)) { \
std::cerr << "Assert at " \ std::cerr << "Assert at `" \
<< __FILE__ \ << __FILE__ \
<< ":" \ << ":" \
<< __LINE__ \ << __LINE__ \
<< " in " \ << "` in `" \
<< __FUNCTION__ \ << __FUNCTION__ \
<< "failed. " \ << "` failed. " \
<< message; \ << message; \
call; \ call; \
} \ } \
@ -89,38 +89,57 @@
if (!(condition)) { \ if (!(condition)) { \
const clang::SourceManager& _sm = sm; \ const clang::SourceManager& _sm = sm; \
clang::SourceLocation _loc = loc; \ clang::SourceLocation _loc = loc; \
std::cerr << "Assert at " \ std::cerr << "Assert at `" \
<< __FILE__ \ << __FILE__ \
<< ":" \ << ":" \
<< __LINE__ \ << __LINE__ \
<< " in " \ << "` in `" \
<< __FUNCTION__ \ << __FUNCTION__ \
<< "failed. " \ << "` failed. " \
<< message \ << message \
<< " Filename " \ << " Filename `" \
<< _sm.getFilename(_loc).str() \ << _sm.getFilename(_loc).str() \
<< ":" \ << ":" \
<< _sm.getSpellingLineNumber(_loc) \ << _sm.getSpellingLineNumber(_loc) \
<< "\n"; \ << "`\n"; \
call; \ call; \
} \ } \
}while(0) }while(0)
// Macros which output messages to console if parsing encounters oddity. // 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 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. // Macro assertml outputs a message and parsing file and line on given source manager and source line.
// //
// assertml adds newline ending. // assertml adds newline ending.
#if defined(_DEBUG) && !defined(DEBUG_NO_ABORT) #ifdef NDEBUG
#define assertm(condition, message) _assertm(condition, message, abort()) #define debug_break() ((void)0)
#define assertml(condition, message, sm, source) _assertml(condition, message, sm, source, abort()) #define debug_fail() ((void)0)
#else #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
#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; using namespace CppSharp::CppParser;
// We use this as a placeholder for pointer values that should be ignored. // We use this as a placeholder for pointer values that should be ignored.
@ -959,7 +978,14 @@ static clang::CXXRecordDecl* GetCXXRecordDeclFromBaseType(const clang::ASTContex
return GetCXXRecordDeclFromTemplateName(TST->getTemplateName()); return GetCXXRecordDeclFromTemplateName(TST->getTemplateName());
else if (auto Injected = Ty->getAs<clang::InjectedClassNameType>()) else if (auto Injected = Ty->getAs<clang::InjectedClassNameType>())
return Injected->getDecl(); 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()); assertml(0, "Could not get base CXX record from type. Unhandled type: ", context.getSourceManager(), base.getBeginLoc());
return nullptr; return nullptr;
@ -2695,41 +2721,59 @@ Type* Parser::WalkType(clang::QualType QualType, const clang::TypeLoc* TL,
auto TST = new TemplateSpecializationType(); auto TST = new TemplateSpecializationType();
TemplateName Name = TS->getTemplateName(); TemplateName Name = TS->getTemplateName();
TST->_template = static_cast<Template*>(WalkDeclaration( TST->_template = static_cast<Template*>(WalkDeclaration(Name.getAsTemplateDecl()));
Name.getAsTemplateDecl()));
if (TS->isSugared()) if (TS->isSugared())
TST->desugared = GetQualifiedType(TS->getCanonicalTypeInternal(), TL); 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(); TST->Arguments = WalkTemplateArgumentList(&TArgs, (TemplateSpecializationTypeLoc*)nullptr);
if (TypeLocClass == TypeLoc::Qualified) Ty = TST;
{ break;
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");
} }
TemplateSpecializationTypeLoc TSpecTL; TypeLoc UTL, ETL, ITL;
TemplateSpecializationTypeLoc *TSTL = 0; if (TL->getTypeLocClass() == TypeLoc::Qualified)
if (LocValid)
{ {
TSpecTL = TL->getAs<TemplateSpecializationTypeLoc>(); UTL = TL->getUnqualifiedLoc();
TSTL = &TSpecTL; TL = &UTL;
}
if (TL->getTypeLocClass() == TypeLoc::Elaborated)
{
ETL = TL->getAs<ElaboratedTypeLoc>();
ITL = ETL.getNextTypeLoc();
TL = &ITL;
} }
TemplateArgumentList TArgs(TemplateArgumentList::OnStack, TS->template_arguments()); switch (TL->getTypeLocClass()) {
TST->Arguments = WalkTemplateArgumentList(&TArgs, TSTL); 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; Ty = TST;
break; break;
@ -2741,38 +2785,52 @@ Type* Parser::WalkType(clang::QualType QualType, const clang::TypeLoc* TL,
if (TS->isSugared()) if (TS->isSugared())
TST->desugared = GetQualifiedType(TS->getCanonicalTypeInternal(), TL); 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(); TST->Arguments = WalkTemplateArgumentList(&TArgs, (DependentTemplateSpecializationTypeLoc*)nullptr);
if (TypeLocClass == TypeLoc::Qualified) Ty = TST;
{ break;
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());
} }
DependentTemplateSpecializationTypeLoc TSpecTL; TypeLoc UTL, ETL, ITL;
DependentTemplateSpecializationTypeLoc *TSTL = 0; if (TL->getTypeLocClass() == TypeLoc::Qualified)
if (LocValid)
{ {
TSpecTL = TL->getAs<DependentTemplateSpecializationTypeLoc>(); UTL = TL->getUnqualifiedLoc();
TSTL = &TSpecTL; TL = &UTL;
}
if (TL->getTypeLocClass() == TypeLoc::Elaborated)
{
ETL = TL->getAs<ElaboratedTypeLoc>();
ITL = ETL.getNextTypeLoc();
TL = &ITL;
} }
TemplateArgumentList TArgs(TemplateArgumentList::OnStack, TS->template_arguments()); switch (TL->getTypeLocClass()) {
TST->Arguments = WalkTemplateArgumentList(&TArgs, TSTL); 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; Ty = TST;
break; break;

Loading…
Cancel
Save