summaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorBrad King <brad.king@kitware.com>2016-08-16 15:26:17 (GMT)
committerBrad King <brad.king@kitware.com>2016-08-16 15:43:46 (GMT)
commita583b278626bfd7d5930a462ebda5caa5906461a (patch)
treee4737d7647c5769cbb812de5cd22bf8cf7180b37 /src
parentd5934bd08651dbda95a65ccadcc5f39637d7bc59 (diff)
downloadCastXML-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.cxx15
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;
}
}
}