summaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorBrad King <brad.king@kitware.com>2015-04-28 13:45:35 (GMT)
committerBrad King <brad.king@kitware.com>2015-04-28 17:15:00 (GMT)
commitf0c00cb8bd3c5e6c38c6ee47370c15630e7446eb (patch)
tree2889095a7ca034ba79e9485052836c96d56bf3c0 /src
parentbafe43d6438fa5ce0ef778d5d713cd7f594370b9 (diff)
downloadCastXML-f0c00cb8bd3c5e6c38c6ee47370c15630e7446eb.zip
CastXML-f0c00cb8bd3c5e6c38c6ee47370c15630e7446eb.tar.gz
CastXML-f0c00cb8bd3c5e6c38c6ee47370c15630e7446eb.tar.bz2
Output: Refactor generation of CvQualifiedType elements
Previously our handling of cv-qualified types did not account for multiple locally cv-qualified types encountered through multiple levels of desugaring. This could lead to CvQualifiedType elements that reference elements that are generated with a different id. Refactor our internal representation of dump nodes to keep cv-qualifiers in the node ids. Teach AddTypeDumpNode to collect cv-qualifiers from each level of desugaring and compute their union. Once the desugared unqualified type is found, generate one CvQualifiedType element for the qualified type, if any. Update the expected test output to account for the new ordering of nodes. Mark the Class-template-constructor-template test case as no longer broken because this approach fixes it. Add test cases covering cv-qualifiers added at different layers of desugaring (via "T const" where T is already a "const" type in a template instantiation). GitHub-Issue: 10
Diffstat (limited to 'src')
-rw-r--r--src/Output.cxx385
1 files changed, 229 insertions, 156 deletions
diff --git a/src/Output.cxx b/src/Output.cxx
index 72c72b6..431f57e 100644
--- a/src/Output.cxx
+++ b/src/Output.cxx
@@ -49,12 +49,69 @@ protected:
clang::ASTContext const& ctx,
llvm::raw_ostream& os): CI(ci), CTX(ctx), OS(os) {}
+ // Represent cv qualifier state of one dump node.
+ struct DumpQual {
+ bool IsConst = false;
+ bool IsVolatile = false;
+ bool IsRestrict = false;
+ explicit operator bool() const {
+ return this->IsConst || this->IsVolatile || this->IsRestrict;
+ }
+ friend bool operator < (DumpQual const& l, DumpQual const& r) {
+ if (!l.IsConst && r.IsConst) {
+ return true;
+ } else if (l.IsConst && !r.IsConst) {
+ return false;
+ } else if (!l.IsVolatile && r.IsVolatile) {
+ return true;
+ } else if (l.IsVolatile && !r.IsVolatile) {
+ return false;
+ } else if (!l.IsRestrict && r.IsRestrict) {
+ return true;
+ } else if (l.IsRestrict && !r.IsRestrict) {
+ return false;
+ } else {
+ return false;
+ }
+ }
+ friend llvm::raw_ostream& operator << (llvm::raw_ostream& os,
+ DumpQual const& dq) {
+ return os << (dq.IsConst? "c":"")
+ << (dq.IsVolatile? "v":"")
+ << (dq.IsRestrict? "r":"");
+ }
+ };
+
+ // Represent id of one dump node.
+ struct DumpId {
+ unsigned int Id = 0;
+ DumpQual Qual;
+ DumpId() {}
+ DumpId(unsigned int id, DumpQual dq): Id(id), Qual(dq) {}
+ explicit operator bool() const {
+ return this->Id != 0;
+ }
+ friend bool operator < (DumpId const& l, DumpId const& r) {
+ if (l.Id < r.Id) {
+ return true;
+ } else if (l.Id > r.Id) {
+ return false;
+ } else {
+ return l.Qual < r.Qual;
+ }
+ }
+ friend llvm::raw_ostream& operator << (llvm::raw_ostream& os,
+ DumpId const& id) {
+ return os << id.Id << id.Qual;
+ }
+ };
+
// Record status of one AST node to be dumped.
struct DumpNode {
- DumpNode(): Index(0), Complete(false) {}
+ DumpNode(): Index(), Complete(false) {}
// Index in nodes ordered by first encounter.
- unsigned int Index;
+ DumpId Index;
// Whether the node is to be traversed completely.
bool Complete;
@@ -119,14 +176,17 @@ class ASTVisitor: public ASTVisitorBase
struct QueueEntry {
// Available node kinds.
enum Kinds {
+ KindQual,
KindDecl,
KindType
};
+ QueueEntry(DumpNode const* dn):
+ Kind(KindQual), Decl(nullptr), Type(), DN(dn) {}
QueueEntry(clang::Decl const* d, DumpNode const* dn):
- Kind(KindDecl), Decl(d), DN(dn) {}
+ Kind(KindDecl), Decl(d), Type(), DN(dn) {}
QueueEntry(DumpType t, DumpNode const* dn):
- Kind(KindType), Decl(0), Type(t), DN(dn) {}
+ Kind(KindType), Decl(nullptr), Type(t), DN(dn) {}
// Kind of node at this entry.
Kinds Kind;
@@ -155,30 +215,39 @@ class ASTVisitor: public ASTVisitorBase
return &this->TypeNodes[t];
}
+ /** Get the dump status node for a qualified DumpId. */
+ DumpNode* GetDumpNode(DumpId id) {
+ assert(id.Qual);
+ return &this->QualNodes[id];
+ }
+
/** Allocate a dump node for a Clang declaration. */
- unsigned int AddDeclDumpNode(clang::Decl const* d, bool complete);
+ DumpId AddDeclDumpNode(clang::Decl const* d, bool complete);
+ DumpId AddDeclDumpNode(clang::Decl const* d, bool complete, DumpQual dq);
/** Allocate a dump node for a Clang type. */
- unsigned int AddTypeDumpNode(DumpType dt, bool complete,
- clang::QualType* pt = 0);
+ DumpId AddTypeDumpNode(DumpType dt, bool complete, DumpQual dq = DumpQual());
+
+ /** Allocate a dump node for a qualified DumpId. */
+ DumpId AddQualDumpNode(DumpId id);
/** Helper common to AddDeclDumpNode and AddTypeDumpNode. */
- template <typename K> unsigned int AddDumpNodeImpl(K k, bool complete);
+ template <typename K> DumpId AddDumpNodeImpl(K k, bool complete);
/** Allocate a dump node for a source file entry. */
unsigned int AddDumpFile(clang::FileEntry const* f);
/** Add class template specializations and instantiations for output. */
void AddClassTemplateDecl(clang::ClassTemplateDecl const* d,
- std::set<unsigned int>* emitted = 0);
+ std::set<DumpId>* emitted = 0);
/** Add function template specializations and instantiations for output. */
void AddFunctionTemplateDecl(clang::FunctionTemplateDecl const* d,
- std::set<unsigned int>* emitted = 0);
+ std::set<DumpId>* emitted = 0);
/** Add declaration context members for output. */
void AddDeclContextMembers(clang::DeclContext const* dc,
- std::set<unsigned int>& emitted);
+ std::set<DumpId>& emitted);
/** Add a starting declaration for output. */
void AddStartDecl(clang::Decl const* d);
@@ -196,25 +265,17 @@ class ASTVisitor: public ASTVisitorBase
/** Dispatch output of a qualified or unqualified type. */
void OutputType(DumpType dt, DumpNode const* dn);
- /** Output a qualified type and queue its unqualified type. */
- void OutputCvQualifiedType(clang::QualType t, DumpNode const* dn);
+ /** Output a qualified type. */
+ void OutputCvQualifiedType(DumpNode const* dn);
/** Get the XML IDREF for the element defining the given
declaration context (namespace, class, etc.). */
- unsigned int GetContextIdRef(clang::DeclContext const* dc);
+ DumpId GetContextIdRef(clang::DeclContext const* dc);
/** Return the unqualified name of the declaration context
(class, struct, union) of the given method. */
std::string GetContextName(clang::CXXMethodDecl const* d);
- /** Get the XML IDREF for the element defining the given
- (possibly cv-qualified) type. The qc,qv,qr booleans are
- set to whether the IDREF should include the const,
- volatile, or restrict qualifier, respectively. Also
- queues the given type for later output. */
- unsigned int GetTypeIdRef(clang::QualType t, bool complete,
- bool& qc, bool& qv, bool& qr);
-
/** Print the XML IDREF value referencing the given type.
If the type has top-level cv-qualifiers, they are
appended to the numeric id as single characters (c=const,
@@ -259,7 +320,7 @@ class ASTVisitor: public ASTVisitorBase
members of the given declaration context. Also queues the
context members for later output. */
void PrintMembersAttribute(clang::DeclContext const* dc);
- void PrintMembersAttribute(std::set<unsigned int> const& emitted);
+ void PrintMembersAttribute(std::set<DumpId> const& emitted);
/** Print a bases="..." attribute listing the XML IDREFs for
bases of the given class type. Also queues the base classes
@@ -387,6 +448,10 @@ private:
typedef std::map<DumpType, DumpNode> TypeNodesMap;
TypeNodesMap TypeNodes;
+ // Map from qualified DumpId to our dump status node.
+ typedef std::map<DumpId, DumpNode> QualNodesMap;
+ QualNodesMap QualNodes;
+
// Map from clang file entry to our source file index.
typedef std::map<clang::FileEntry const*, unsigned int> FileNodesMap;
FileNodesMap FileNodes;
@@ -414,8 +479,8 @@ public:
};
//----------------------------------------------------------------------------
-unsigned int ASTVisitor::AddDeclDumpNode(clang::Decl const* d,
- bool complete) {
+ASTVisitor::DumpId ASTVisitor::AddDeclDumpNode(clang::Decl const* d,
+ bool complete) {
// Select the definition or canonical declaration.
d = d->getCanonicalDecl();
if(clang::RecordDecl const* rd = clang::dyn_cast<clang::RecordDecl>(d)) {
@@ -442,7 +507,7 @@ unsigned int ASTVisitor::AddDeclDumpNode(clang::Decl const* d,
// Skip invalid declarations.
if(d->isInvalidDecl()) {
- return 0;
+ return DumpId();
}
// Skip C++11 declarations gccxml does not support.
@@ -450,19 +515,19 @@ unsigned int ASTVisitor::AddDeclDumpNode(clang::Decl const* d,
if (clang::FunctionDecl const* fd =
clang::dyn_cast<clang::FunctionDecl>(d)) {
if (fd->isDeleted()) {
- return 0;
+ return DumpId();
}
if (clang::FunctionProtoType const* fpt =
fd->getType()->getAs<clang::FunctionProtoType>()) {
if (fpt->getReturnType()->isRValueReferenceType()) {
- return 0;
+ return DumpId();
}
for (clang::FunctionProtoType::param_type_iterator
i = fpt->param_type_begin(), e = fpt->param_type_end();
i != e; ++i) {
if((*i)->isRValueReferenceType()) {
- return 0;
+ return DumpId();
}
}
}
@@ -473,89 +538,129 @@ unsigned int ASTVisitor::AddDeclDumpNode(clang::Decl const* d,
}
//----------------------------------------------------------------------------
-unsigned int ASTVisitor::AddTypeDumpNode(DumpType dt, bool complete,
- clang::QualType* pt) {
+ASTVisitor::DumpId ASTVisitor::AddDeclDumpNode(clang::Decl const* d,
+ bool complete, DumpQual dq) {
+ // Get the id for the canonical decl.
+ DumpId id = this->AddDeclDumpNode(d, complete);
+
+ // If any qualifiers were collected through layers of desugaring
+ // then get the id of the qualified type referencing this decl.
+ if (id && dq) {
+ id = this->AddQualDumpNode(DumpId(id.Id, dq));
+ }
+
+ return id;
+}
+
+//----------------------------------------------------------------------------
+ASTVisitor::DumpId ASTVisitor::AddTypeDumpNode(DumpType dt, bool complete,
+ DumpQual dq) {
clang::QualType t = dt.Type;
clang::Type const* c = dt.Class;
+ // Extract local qualifiers and recurse with locally unqualified type.
+ if(t.hasLocalQualifiers()) {
+ dq.IsConst = dq.IsConst || t.isLocalConstQualified();
+ dq.IsVolatile = dq.IsVolatile || t.isLocalVolatileQualified();
+ dq.IsRestrict = dq.IsRestrict || t.isLocalRestrictQualified();
+ return this->AddTypeDumpNode(DumpType(t.getLocalUnqualifiedType(), c),
+ complete, dq);
+ }
+
// Replace some types with their decls.
- if(!t.hasLocalQualifiers()) {
- switch (t->getTypeClass()) {
- case clang::Type::Adjusted:
- return this->AddTypeDumpNode(DumpType(
- t->getAs<clang::AdjustedType>()->getAdjustedType(), c),
- complete, pt);
- case clang::Type::Attributed:
- return this->AddTypeDumpNode(DumpType(
- t->getAs<clang::AttributedType>()->getEquivalentType(), c),
- complete, pt);
- case clang::Type::Decayed:
- return this->AddTypeDumpNode(DumpType(
- t->getAs<clang::DecayedType>()->getDecayedType(), c),
- complete, pt);
- case clang::Type::Elaborated:
- return this->AddTypeDumpNode(DumpType(
- t->getAs<clang::ElaboratedType>()->getNamedType(), c),
- complete, pt);
- case clang::Type::Enum:
- return this->AddDeclDumpNode(t->getAs<clang::EnumType>()->getDecl(),
- complete);
- case clang::Type::Paren:
- return this->AddTypeDumpNode(DumpType(
- t->getAs<clang::ParenType>()->getInnerType(), c),
- complete, pt);
- case clang::Type::Record:
- return this->AddDeclDumpNode(t->getAs<clang::RecordType>()->getDecl(),
- complete);
- case clang::Type::SubstTemplateTypeParm:
- return this->AddTypeDumpNode(DumpType(
- t->getAs<clang::SubstTemplateTypeParmType>()->getReplacementType(), c),
- complete, pt);
- case clang::Type::TemplateSpecialization: {
- clang::TemplateSpecializationType const* tst =
- t->getAs<clang::TemplateSpecializationType>();
- if(tst->isSugared()) {
- return this->AddTypeDumpNode(DumpType(tst->desugar(), c),
- complete, pt);
- }
- } break;
- 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)
- ) {
- // This TypedefType refers to a non-dependent
- // TypedefDecl member of a class template. Since gccxml
- // format does not include uninstantiated templates we
- // must use the desugared type so that we do not end up
- // referencing a class template as context.
- return this->AddTypeDumpNode(tdt->desugar(), complete, pt);
- }
+ switch (t->getTypeClass()) {
+ case clang::Type::Adjusted:
+ return this->AddTypeDumpNode(DumpType(
+ t->getAs<clang::AdjustedType>()->getAdjustedType(), c),
+ complete, dq);
+ case clang::Type::Attributed:
+ return this->AddTypeDumpNode(DumpType(
+ t->getAs<clang::AttributedType>()->getEquivalentType(), c),
+ complete, dq);
+ case clang::Type::Decayed:
+ return this->AddTypeDumpNode(DumpType(
+ t->getAs<clang::DecayedType>()->getDecayedType(), c),
+ complete, dq);
+ case clang::Type::Elaborated:
+ return this->AddTypeDumpNode(DumpType(
+ t->getAs<clang::ElaboratedType>()->getNamedType(), c),
+ complete, dq);
+ case clang::Type::Enum:
+ return this->AddDeclDumpNode(t->getAs<clang::EnumType>()->getDecl(),
+ complete, dq);
+ case clang::Type::Paren:
+ return this->AddTypeDumpNode(DumpType(
+ t->getAs<clang::ParenType>()->getInnerType(), c),
+ complete, dq);
+ case clang::Type::Record:
+ return this->AddDeclDumpNode(t->getAs<clang::RecordType>()->getDecl(),
+ complete, dq);
+ case clang::Type::SubstTemplateTypeParm:
+ return this->AddTypeDumpNode(DumpType(
+ t->getAs<clang::SubstTemplateTypeParmType>()->getReplacementType(), c),
+ complete, dq);
+ case clang::Type::TemplateSpecialization: {
+ clang::TemplateSpecializationType const* tst =
+ t->getAs<clang::TemplateSpecializationType>();
+ if(tst->isSugared()) {
+ return this->AddTypeDumpNode(DumpType(tst->desugar(), c),
+ complete, dq);
+ }
+ } break;
+ 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)
+ ) {
+ // This TypedefType refers to a non-dependent
+ // TypedefDecl member of a class template. Since gccxml
+ // format does not include uninstantiated templates we
+ // must use the desugared type so that we do not end up
+ // referencing a class template as context.
+ return this->AddTypeDumpNode(tdt->desugar(), complete, dq);
}
}
}
- return this->AddDeclDumpNode(tdt->getDecl(), complete);
- } break;
- default:
- break;
}
+ return this->AddDeclDumpNode(tdt->getDecl(), complete, dq);
+ } break;
+ default:
+ break;
}
- // Report to caller the type we actually will dump.
- if (pt) {
- *pt = t;
+ // Get the id for the fully desugared, unqualified type.
+ DumpId id = this->AddDumpNodeImpl(dt, complete);
+
+ // If any qualifiers were collected through layers of desugaring
+ // then get the id of the qualified type.
+ if (id && dq) {
+ id = this->AddQualDumpNode(DumpId(id.Id, dq));
}
- return this->AddDumpNodeImpl(dt, complete);
+ return id;
+}
+
+//----------------------------------------------------------------------------
+ASTVisitor::DumpId ASTVisitor::AddQualDumpNode(DumpId id) {
+ DumpNode* dn = this->GetDumpNode(id);
+ if (!dn->Index) {
+ // Consume a node index for temporary compatibility.
+ ++this->NodeCount;
+ dn->Index = id;
+ // Always treat CvQualifiedType nodes as complete.
+ dn->Complete = true;
+ this->Queue.insert(QueueEntry(dn));
+ }
+ return dn->Index;
}
//----------------------------------------------------------------------------
template <typename K>
-unsigned int ASTVisitor::AddDumpNodeImpl(K k, bool complete)
+ASTVisitor::DumpId ASTVisitor::AddDumpNodeImpl(K k, bool complete)
{
// Update an existing node or add one.
DumpNode* dn = this->GetDumpNode(k);
@@ -568,7 +673,7 @@ unsigned int ASTVisitor::AddDumpNodeImpl(K k, bool complete)
}
} else {
// This is a new node. Assign it an index.
- dn->Index = ++this->NodeCount;
+ dn->Index.Id = ++this->NodeCount;
dn->Complete = complete;
if(complete || !this->RequireComplete) {
// Node is complete. Queue it.
@@ -592,13 +697,13 @@ unsigned int ASTVisitor::AddDumpFile(clang::FileEntry const* f)
//----------------------------------------------------------------------------
void ASTVisitor::AddClassTemplateDecl(clang::ClassTemplateDecl const* d,
- std::set<unsigned int>* emitted)
+ std::set<DumpId>* emitted)
{
// Queue all the instantiations of this class template.
for(clang::ClassTemplateDecl::spec_iterator i = d->spec_begin(),
e = d->spec_end(); i != e; ++i) {
clang::CXXRecordDecl const* rd = *i;
- unsigned int id = this->AddDeclDumpNode(rd, true);
+ DumpId id = this->AddDeclDumpNode(rd, true);
if(id && emitted) {
emitted->insert(id);
}
@@ -607,13 +712,13 @@ void ASTVisitor::AddClassTemplateDecl(clang::ClassTemplateDecl const* d,
//----------------------------------------------------------------------------
void ASTVisitor::AddFunctionTemplateDecl(clang::FunctionTemplateDecl const* d,
- std::set<unsigned int>* emitted)
+ std::set<DumpId>* emitted)
{
// Queue all the instantiations of this function template.
for(clang::FunctionTemplateDecl::spec_iterator i = d->spec_begin(),
e = d->spec_end(); i != e; ++i) {
clang::FunctionDecl const* fd = *i;
- unsigned int id = this->AddDeclDumpNode(fd, true);
+ DumpId id = this->AddDeclDumpNode(fd, true);
if(id && emitted) {
emitted->insert(id);
}
@@ -622,7 +727,7 @@ void ASTVisitor::AddFunctionTemplateDecl(clang::FunctionTemplateDecl const* d,
//----------------------------------------------------------------------------
void ASTVisitor::AddDeclContextMembers(clang::DeclContext const* dc,
- std::set<unsigned int>& emitted)
+ std::set<DumpId>& emitted)
{
for(clang::DeclContext::decl_iterator i = dc->decls_begin(),
e = dc->decls_end(); i != e; ++i) {
@@ -678,7 +783,7 @@ void ASTVisitor::AddDeclContextMembers(clang::DeclContext const* dc,
}
// Queue this decl and print its id.
- if(unsigned int id = this->AddDeclDumpNode(d, true)) {
+ if(DumpId id = this->AddDeclDumpNode(d, true)) {
emitted.insert(id);
}
}
@@ -737,6 +842,9 @@ void ASTVisitor::ProcessQueue()
QueueEntry qe = *this->Queue.begin();
this->Queue.erase(this->Queue.begin());
switch(qe.Kind) {
+ case QueueEntry::KindQual:
+ this->OutputCvQualifiedType(qe.DN);
+ break;
case QueueEntry::KindDecl:
this->OutputDecl(qe.Decl, qe.DN);
break;
@@ -791,10 +899,6 @@ void ASTVisitor::OutputType(DumpType dt, DumpNode const* dn)
if(c) {
// Output the method type.
this->OutputMethodType(t->getAs<clang::FunctionProtoType>(), c, dn);
- } else if(t.hasLocalQualifiers()) {
- // Output the qualified type. This will queue
- // the unqualified type if necessary.
- this->OutputCvQualifiedType(t, dn);
} else {
// Dispatch output of the unqualified type.
switch (t->getTypeClass()) {
@@ -810,41 +914,37 @@ void ASTVisitor::OutputType(DumpType dt, DumpNode const* dn)
}
//----------------------------------------------------------------------------
-void ASTVisitor::OutputCvQualifiedType(clang::QualType t, DumpNode const* dn)
+void ASTVisitor::OutputCvQualifiedType(DumpNode const* dn)
{
- bool qc, qv, qr;
- unsigned int id = this->GetTypeIdRef(t, dn->Complete, qc, qv, qr);
- const char* c = qc? "c" : "";
- const char* v = qv? "v" : "";
- const char* r = qr? "r" : "";
+ DumpId id = dn->Index;
// Create a special CvQualifiedType element to hold top-level
// cv-qualifiers for a real type node.
- this->OS << " <CvQualifiedType id=\"_" << id << c << v << r << "\"";
+ this->OS << " <CvQualifiedType id=\"_" << id << "\"";
// Refer to the unqualified type.
- this->OS << " type=\"_" << id << "\"";
+ this->OS << " type=\"_" << id.Id << "\"";
// Add the cv-qualification attributes.
- if (qc) {
+ if (id.Qual.IsConst) {
this->OS << " const=\"1\"";
}
- if (qv) {
+ if (id.Qual.IsVolatile) {
this->OS << " volatile=\"1\"";
}
- if (qr) {
+ if (id.Qual.IsRestrict) {
this->OS << " restrict=\"1\"";
}
this->OS << "/>\n";
}
//----------------------------------------------------------------------------
-unsigned int ASTVisitor::GetContextIdRef(clang::DeclContext const* dc)
+ASTVisitor::DumpId ASTVisitor::GetContextIdRef(clang::DeclContext const* dc)
{
if(clang::Decl const* d = clang::dyn_cast<clang::Decl>(dc)) {
return this->AddDeclDumpNode(d, false);
} else {
- return 0;
+ return DumpId();
}
}
@@ -859,40 +959,13 @@ std::string ASTVisitor::GetContextName(clang::CXXMethodDecl const* d)
}
//----------------------------------------------------------------------------
-unsigned int ASTVisitor::GetTypeIdRef(clang::QualType t, bool complete,
- bool& qc, bool& qv, bool& qr)
-{
- // Add the type node.
- unsigned int id = this->AddTypeDumpNode(t, complete, &t);
-
- // Check for qualifiers.
- qc = t.isLocalConstQualified();
- qv = t.isLocalVolatileQualified();
- qr = t.isLocalRestrictQualified();
-
- // If the type has qualifiers, add the unqualified type and use its id.
- if(t.hasLocalQualifiers()) {
- id = this->AddTypeDumpNode(t.getLocalUnqualifiedType(), complete);
- }
-
- // Return the dump node id of the unqualified type.
- return id;
-}
-
-//----------------------------------------------------------------------------
void ASTVisitor::PrintTypeIdRef(clang::QualType t, bool complete)
{
// Add the type node.
- bool qc, qv, qr;
- unsigned int id = this->GetTypeIdRef(t, complete, qc, qv, qr);
-
- // Check cv-qualificiation.
- const char* c = qc? "c" : "";
- const char* v = qv? "v" : "";
- const char* r = qr? "r" : "";
+ DumpId id = this->AddTypeDumpNode(t, complete);
// Print the reference.
- this->OS << "_" << id << c << v << r;
+ this->OS << "_" << id;
}
//----------------------------------------------------------------------------
@@ -1003,7 +1076,7 @@ void ASTVisitor::PrintAccessAttribute(clang::AccessSpecifier as)
void ASTVisitor::PrintContextAttribute(clang::Decl const* d)
{
clang::DeclContext const* dc = d->getDeclContext();
- if(unsigned int id = this->GetContextIdRef(dc)) {
+ if(DumpId id = this->GetContextIdRef(dc)) {
this->OS << " context=\"_" << id << "\"";
if (dc->isRecord()) {
this->PrintAccessAttribute(d->getAccess());
@@ -1014,18 +1087,18 @@ void ASTVisitor::PrintContextAttribute(clang::Decl const* d)
//----------------------------------------------------------------------------
void ASTVisitor::PrintMembersAttribute(clang::DeclContext const* dc)
{
- std::set<unsigned int> emitted;
+ std::set<DumpId> emitted;
this->AddDeclContextMembers(dc, emitted);
this->PrintMembersAttribute(emitted);
}
//----------------------------------------------------------------------------
-void ASTVisitor::PrintMembersAttribute(std::set<unsigned int> const& emitted)
+void ASTVisitor::PrintMembersAttribute(std::set<DumpId> const& emitted)
{
if(!emitted.empty()) {
this->OS << " members=\"";
const char* sep = "";
- for(std::set<unsigned int>::const_iterator i = emitted.begin(),
+ for(std::set<DumpId>::const_iterator i = emitted.begin(),
e = emitted.end(); i != e; ++i) {
this->OS << sep << "_" << *i;
sep = " ";
@@ -1106,7 +1179,7 @@ void ASTVisitor::PrintBefriendingAttribute(clang::CXXRecordDecl const* dx)
continue;
}
- if(unsigned int id = this->AddDeclDumpNode(nd, false)) {
+ if(DumpId id = this->AddDeclDumpNode(nd, false)) {
this->OS << sep << "_" << id;
sep = " ";
}
@@ -1275,7 +1348,7 @@ void ASTVisitor::OutputNamespaceDecl(
this->PrintNameAttribute(d->getName().str());
this->PrintContextAttribute(d);
if(dn->Complete) {
- std::set<unsigned int> emitted;
+ std::set<DumpId> emitted;
for (clang::NamespaceDecl const* r: d->redecls()) {
this->AddDeclContextMembers(r, emitted);
}
@@ -1638,7 +1711,7 @@ void ASTVisitor::OutputMemberPointerType(clang::MemberPointerType const* t,
} else {
this->OS << " <PointerType";
this->PrintIdAttribute(dn);
- unsigned int id = this->AddTypeDumpNode(
+ DumpId id = this->AddTypeDumpNode(
DumpType(t->getPointeeType(), t->getClass()), false);
this->OS << " type=\"_" << id << "\"";
this->OS << "/>\n";