diff options
| author | Brad King <brad.king@kitware.com> | 2016-08-16 15:26:17 (GMT) |
|---|---|---|
| committer | Brad King <brad.king@kitware.com> | 2016-08-16 15:43:46 (GMT) |
| commit | a583b278626bfd7d5930a462ebda5caa5906461a (patch) | |
| tree | e4737d7647c5769cbb812de5cd22bf8cf7180b37 /src | |
| parent | d5934bd08651dbda95a65ccadcc5f39637d7bc59 (diff) | |
| download | CastXML-a583b278626bfd7d5930a462ebda5caa5906461a.zip CastXML-a583b278626bfd7d5930a462ebda5caa5906461a.tar.gz CastXML-a583b278626bfd7d5930a462ebda5caa5906461a.tar.bz2 | |
Output: Desugar typedefs whose context is a template
In the code
template <typename> struct A {
struct B {
typedef int intermediate_type;
typedef intermediate_type type;
};
};
Clang represents `A<int>::B::type` as a typedef whose type is sugared to
`A<>::B::intermediate_type` where `A<>::B` is a non-template whose
context is an uninstantiated template `A<>` even though the original
typedef's context `A<int>::B` is a non-template whose context is an
instaniated template `A<int>`.
Since CastXML's gccxml output format does not support uninstantiated
templates we cannot represent the context of `intermediate_type` so we
must desugar it instead. Otherwise we end up with an `Unimplemented`
node or even a crash in Clang because we perform operations meant for
non-templates on the template context. We previously did this for
typedefs that appear directly in template contexts, but not for those
whose contexts are nominally non-template but contained in a template
context. Fix the logic to loop through all nested contexts to perform
this check.
Closes: #70
Diffstat (limited to 'src')
| -rw-r--r-- | src/Output.cxx | 15 |
1 files changed, 10 insertions, 5 deletions
diff --git a/src/Output.cxx b/src/Output.cxx index e16d9b9..1736397 100644 --- a/src/Output.cxx +++ b/src/Output.cxx @@ -681,11 +681,14 @@ ASTVisitor::DumpId ASTVisitor::AddTypeDumpNode(DumpType dt, bool complete, case clang::Type::Typedef: { clang::TypedefType const* tdt = t->getAs<clang::TypedefType>(); if(!tdt->isInstantiationDependentType() && tdt->isSugared()) { - if(clang::DeclContext const* tdc = tdt->getDecl()->getDeclContext()) { - if(clang::CXXRecordDecl const* tdx = - clang::dyn_cast<clang::CXXRecordDecl>(tdc)) { - if(tdx->getDescribedClassTemplate() || - clang::isa<clang::ClassTemplatePartialSpecializationDecl>(tdx) + // Make sure all containing contexts are not templates. + clang::Decl const* d = tdt->getDecl(); + while (clang::DeclContext const* tdc = d->getDeclContext()) { + if (clang::CXXRecordDecl const* tdx = + clang::dyn_cast<clang::CXXRecordDecl>(tdc)) { + d = tdx; + if (tdx->getDescribedClassTemplate() || + clang::isa<clang::ClassTemplatePartialSpecializationDecl>(tdx) ) { // This TypedefType refers to a non-dependent // TypedefDecl member of a class template. Since gccxml @@ -694,6 +697,8 @@ ASTVisitor::DumpId ASTVisitor::AddTypeDumpNode(DumpType dt, bool complete, // referencing a class template as context. return this->AddTypeDumpNode(tdt->desugar(), complete, dq); } + } else { + break; } } } |
