summaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorBrad King <brad.king@kitware.com>2016-04-12 14:34:35 (GMT)
committerBrad King <brad.king@kitware.com>2016-04-12 17:26:10 (GMT)
commitb367e2db71910f088856849fd2990207cf5841c4 (patch)
tree0b172f39eb4ff94fe6c789a94e17518d52ffe645 /src
parentcea9ba63e1efedb4052a50b4f5dda13b664ffff6 (diff)
downloadCastXML-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.cxx35
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()) {