diff options
author | Brad King <brad.king@kitware.com> | 2016-04-12 14:34:35 (GMT) |
---|---|---|
committer | Brad King <brad.king@kitware.com> | 2016-04-12 17:26:10 (GMT) |
commit | b367e2db71910f088856849fd2990207cf5841c4 (patch) | |
tree | 0b172f39eb4ff94fe6c789a94e17518d52ffe645 /src | |
parent | cea9ba63e1efedb4052a50b4f5dda13b664ffff6 (diff) | |
download | CastXML-b367e2db71910f088856849fd2990207cf5841c4.zip CastXML-b367e2db71910f088856849fd2990207cf5841c4.tar.gz CastXML-b367e2db71910f088856849fd2990207cf5841c4.tar.bz2 |
Output: Fix access specifier of class template instantiations
In code like
class foo {
template <typename> class bar {};
};
the instantiations of `foo::bar<>` should have the same access as the
original template. Clang generates access `AS_none` for member template
instantiations because they have no meaningful access of their own.
Previously we have misinterpreted this as `AS_public` because it is not
`AS_private` or `AS_protected`. Instead we must detect when a class is
a template instantiation and get the access specifier from its original
template.
GitHub-Issue: CastXML/CastXML#56
Diffstat (limited to 'src')
-rw-r--r-- | src/Output.cxx | 35 |
1 files changed, 28 insertions, 7 deletions
diff --git a/src/Output.cxx b/src/Output.cxx index 25d147a..2ec5d79 100644 --- a/src/Output.cxx +++ b/src/Output.cxx @@ -421,7 +421,8 @@ class ASTVisitor: public ASTVisitorBase the containing declaration context (namespace, class, etc.). Also prints access="..." attribute for class members to indicate public, protected, or private membership. */ - void PrintContextAttribute(clang::Decl const* d); + void PrintContextAttribute(clang::Decl const* d, + clang::AccessSpecifier alt = clang::AS_none); void PrintFloat128Type(DumpNode const* dn); @@ -1236,23 +1237,31 @@ bool ASTVisitor::PrintHelpStmt(clang::Stmt const* s, llvm::raw_ostream& os) //---------------------------------------------------------------------------- void ASTVisitor::PrintAccessAttribute(clang::AccessSpecifier as) { - if (as == clang::AS_private) { + switch (as) { + case clang::AS_private: this->OS << " access=\"private\""; - } else if (as == clang::AS_protected) { + break; + case clang::AS_protected: this->OS << " access=\"protected\""; - } else { + break; + case clang::AS_public: this->OS << " access=\"public\""; + break; + case clang::AS_none: + break; } } //---------------------------------------------------------------------------- -void ASTVisitor::PrintContextAttribute(clang::Decl const* d) +void ASTVisitor::PrintContextAttribute(clang::Decl const* d, + clang::AccessSpecifier alt) { clang::DeclContext const* dc = d->getDeclContext(); if(DumpId id = this->GetContextIdRef(dc)) { this->OS << " context=\"_" << id << "\""; if (dc->isRecord()) { - this->PrintAccessAttribute(d->getAccess()); + clang::AccessSpecifier as = d->getAccess(); + this->PrintAccessAttribute(as != clang::AS_none? as : alt); } } } @@ -1637,7 +1646,19 @@ void ASTVisitor::OutputRecordDecl(clang::RecordDecl const* d, d->getNameForDiagnostic(rso, this->PrintingPolicy, false); this->PrintNameAttribute(rso.str()); } - this->PrintContextAttribute(d); + clang::AccessSpecifier access = clang::AS_none; + if (dx) { + // If this is a template instantiation then get the access of the original + // template. Access of the instantiation itself has no meaning. + if (clang::CXXRecordDecl const* dxp = + dx->getTemplateInstantiationPattern()) { + if (clang::ClassTemplateDecl const* dxpt = + dxp->getDescribedClassTemplate()) { + access = dxpt->getAccess(); + } + } + } + this->PrintContextAttribute(d, access); this->PrintLocationAttribute(d); if(d->getDefinition()) { if(dx && dx->isAbstract()) { |