From f0c00cb8bd3c5e6c38c6ee47370c15630e7446eb Mon Sep 17 00:00:00 2001 From: Brad King Date: Tue, 28 Apr 2015 09:45:35 -0400 Subject: 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 --- src/Output.cxx | 385 ++++++++++++--------- test/CMakeLists.txt | 4 +- test/expect/gccxml.any.Class-abstract.xml.txt | 2 +- test/expect/gccxml.any.Class-base-typedef.xml.txt | 4 +- test/expect/gccxml.any.Class-forward.xml.txt | 2 +- test/expect/gccxml.any.Class-friends.xml.txt | 2 +- ...ny.Class-implicit-member-access-mutable.xml.txt | 2 +- ...gccxml.any.Class-implicit-member-access.xml.txt | 2 +- .../gccxml.any.Class-implicit-member-array.xml.txt | 2 +- ...cxml.any.Class-implicit-member-bad-base.xml.txt | 10 +- .../gccxml.any.Class-implicit-member-const.xml.txt | 8 +- ...xml.any.Class-implicit-member-reference.xml.txt | 2 +- .../gccxml.any.Class-implicit-members.xml.txt | 6 +- .../gccxml.any.Class-member-template.xml.txt | 2 +- ...y.Class-partial-template-member-Typedef.xml.txt | 2 +- ...ny.Class-template-Method-Argument-const.xml.txt | 24 ++ ....Class-template-Method-Argument-default.xml.txt | 2 +- ....any.Class-template-Method-return-const.xml.txt | 20 ++ ...any.Class-template-constructor-template.xml.txt | 20 ++ .../gccxml.any.Class-template-friends.xml.txt | 2 +- ...any.Class-template-member-Typedef-const.xml.txt | 10 +- ...ccxml.any.Class-template-member-Typedef.xml.txt | 2 +- ...cxml.any.Class-template-member-template.xml.txt | 2 +- test/expect/gccxml.any.Class-template.xml.txt | 4 +- test/expect/gccxml.any.Class.xml.txt | 2 +- test/expect/gccxml.any.CvQualifiedType.xml.txt | 6 +- test/expect/gccxml.any.Field.xml.txt | 2 +- .../gccxml.any.Function-Argument-default.xml.txt | 6 +- test/expect/gccxml.any.GNU-float128.xml.txt | 2 +- test/expect/gccxml.any.Method.xml.txt | 2 +- test/expect/gccxml.any.MethodType-cv.xml.txt | 6 +- .../gccxml.any.Namespace-Class-members.xml.txt | 2 +- test/expect/gccxml.any.OffsetType-cv.xml.txt | 10 +- test/expect/gccxml.any.OperatorMethod.xml.txt | 2 +- test/expect/gccxml.any.Variable-in-Class.xml.txt | 2 +- test/expect/gccxml.any.Variable-init.xml.txt | 6 +- .../gccxml.any.using-declaration-class.xml.txt | 4 +- ...any.Class-template-constructor-template.xml.txt | 21 -- test/expect/gccxml.c++11.Class-bases.xml.txt | 8 +- .../gccxml.c++11.Class-template-bases.xml.txt | 6 +- test/expect/gccxml.c++98.Class-bases.xml.txt | 8 +- .../gccxml.c++98.Class-template-bases.xml.txt | 6 +- .../input/Class-template-Method-Argument-const.cxx | 4 + test/input/Class-template-Method-return-const.cxx | 4 + 44 files changed, 378 insertions(+), 252 deletions(-) create mode 100644 test/expect/gccxml.any.Class-template-Method-Argument-const.xml.txt create mode 100644 test/expect/gccxml.any.Class-template-Method-return-const.xml.txt create mode 100644 test/expect/gccxml.any.Class-template-constructor-template.xml.txt delete mode 100644 test/expect/gccxml.broken.any.Class-template-constructor-template.xml.txt create mode 100644 test/input/Class-template-Method-Argument-const.cxx create mode 100644 test/input/Class-template-Method-return-const.cxx 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 unsigned int AddDumpNodeImpl(K k, bool complete); + template 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* emitted = 0); + std::set* emitted = 0); /** Add function template specializations and instantiations for output. */ void AddFunctionTemplateDecl(clang::FunctionTemplateDecl const* d, - std::set* emitted = 0); + std::set* emitted = 0); /** Add declaration context members for output. */ void AddDeclContextMembers(clang::DeclContext const* dc, - std::set& emitted); + std::set& 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 const& emitted); + void PrintMembersAttribute(std::set 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 TypeNodesMap; TypeNodesMap TypeNodes; + // Map from qualified DumpId to our dump status node. + typedef std::map QualNodesMap; + QualNodesMap QualNodes; + // Map from clang file entry to our source file index. typedef std::map 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(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(d)) { if (fd->isDeleted()) { - return 0; + return DumpId(); } if (clang::FunctionProtoType const* fpt = fd->getType()->getAs()) { 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()->getAdjustedType(), c), - complete, pt); - case clang::Type::Attributed: - return this->AddTypeDumpNode(DumpType( - t->getAs()->getEquivalentType(), c), - complete, pt); - case clang::Type::Decayed: - return this->AddTypeDumpNode(DumpType( - t->getAs()->getDecayedType(), c), - complete, pt); - case clang::Type::Elaborated: - return this->AddTypeDumpNode(DumpType( - t->getAs()->getNamedType(), c), - complete, pt); - case clang::Type::Enum: - return this->AddDeclDumpNode(t->getAs()->getDecl(), - complete); - case clang::Type::Paren: - return this->AddTypeDumpNode(DumpType( - t->getAs()->getInnerType(), c), - complete, pt); - case clang::Type::Record: - return this->AddDeclDumpNode(t->getAs()->getDecl(), - complete); - case clang::Type::SubstTemplateTypeParm: - return this->AddTypeDumpNode(DumpType( - t->getAs()->getReplacementType(), c), - complete, pt); - case clang::Type::TemplateSpecialization: { - clang::TemplateSpecializationType const* tst = - t->getAs(); - if(tst->isSugared()) { - return this->AddTypeDumpNode(DumpType(tst->desugar(), c), - complete, pt); - } - } break; - case clang::Type::Typedef: { - clang::TypedefType const* tdt = t->getAs(); - if(!tdt->isInstantiationDependentType() && tdt->isSugared()) { - if(clang::DeclContext const* tdc = tdt->getDecl()->getDeclContext()) { - if(clang::CXXRecordDecl const* tdx = - clang::dyn_cast(tdc)) { - if(tdx->getDescribedClassTemplate() || - clang::isa(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()->getAdjustedType(), c), + complete, dq); + case clang::Type::Attributed: + return this->AddTypeDumpNode(DumpType( + t->getAs()->getEquivalentType(), c), + complete, dq); + case clang::Type::Decayed: + return this->AddTypeDumpNode(DumpType( + t->getAs()->getDecayedType(), c), + complete, dq); + case clang::Type::Elaborated: + return this->AddTypeDumpNode(DumpType( + t->getAs()->getNamedType(), c), + complete, dq); + case clang::Type::Enum: + return this->AddDeclDumpNode(t->getAs()->getDecl(), + complete, dq); + case clang::Type::Paren: + return this->AddTypeDumpNode(DumpType( + t->getAs()->getInnerType(), c), + complete, dq); + case clang::Type::Record: + return this->AddDeclDumpNode(t->getAs()->getDecl(), + complete, dq); + case clang::Type::SubstTemplateTypeParm: + return this->AddTypeDumpNode(DumpType( + t->getAs()->getReplacementType(), c), + complete, dq); + case clang::Type::TemplateSpecialization: { + clang::TemplateSpecializationType const* tst = + t->getAs(); + if(tst->isSugared()) { + return this->AddTypeDumpNode(DumpType(tst->desugar(), c), + complete, dq); + } + } break; + case clang::Type::Typedef: { + clang::TypedefType const* tdt = t->getAs(); + if(!tdt->isInstantiationDependentType() && tdt->isSugared()) { + if(clang::DeclContext const* tdc = tdt->getDecl()->getDeclContext()) { + if(clang::CXXRecordDecl const* tdx = + clang::dyn_cast(tdc)) { + if(tdx->getDescribedClassTemplate() || + clang::isa(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 -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* emitted) + std::set* 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* emitted) + std::set* 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& emitted) + std::set& 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(), 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 << " OS << " 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(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 emitted; + std::set emitted; this->AddDeclContextMembers(dc, emitted); this->PrintMembersAttribute(emitted); } //---------------------------------------------------------------------------- -void ASTVisitor::PrintMembersAttribute(std::set const& emitted) +void ASTVisitor::PrintMembersAttribute(std::set const& emitted) { if(!emitted.empty()) { this->OS << " members=\""; const char* sep = ""; - for(std::set::const_iterator i = emitted.begin(), + for(std::set::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 emitted; + std::set 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 << " PrintIdAttribute(dn); - unsigned int id = this->AddTypeDumpNode( + DumpId id = this->AddTypeDumpNode( DumpType(t->getPointeeType(), t->getClass()), false); this->OS << " type=\"_" << id << "\""; this->OS << "/>\n"; diff --git a/test/CMakeLists.txt b/test/CMakeLists.txt index 9006016..76ccf23 100644 --- a/test/CMakeLists.txt +++ b/test/CMakeLists.txt @@ -159,8 +159,11 @@ castxml_test_gccxml(Class-incomplete-twice) castxml_test_gccxml(Class-member-template) castxml_test_gccxml(Class-partial-template-member-Typedef) castxml_test_gccxml(Class-template) +castxml_test_gccxml(Class-template-Method-Argument-const) castxml_test_gccxml(Class-template-Method-Argument-default) +castxml_test_gccxml(Class-template-Method-return-const) castxml_test_gccxml(Class-template-bases) +castxml_test_gccxml(Class-template-constructor-template) castxml_test_gccxml(Class-template-friends) castxml_test_gccxml(Class-template-member-Typedef) castxml_test_gccxml(Class-template-member-Typedef-const) @@ -231,7 +234,6 @@ castxml_test_gccxml_c(Typedef-called-class) castxml_test_gccxml_c(invalid) -castxml_test_gccxml_broken(Class-template-constructor-template) castxml_test_gccxml_broken(ReferenceType-to-Class-template) #----------------------------------------------------------------------------- diff --git a/test/expect/gccxml.any.Class-abstract.xml.txt b/test/expect/gccxml.any.Class-abstract.xml.txt index 47b4971..336e014 100644 --- a/test/expect/gccxml.any.Class-abstract.xml.txt +++ b/test/expect/gccxml.any.Class-abstract.xml.txt @@ -16,7 +16,7 @@ - + $ diff --git a/test/expect/gccxml.any.Class-base-typedef.xml.txt b/test/expect/gccxml.any.Class-base-typedef.xml.txt index 49f2a64..44f11d9 100644 --- a/test/expect/gccxml.any.Class-base-typedef.xml.txt +++ b/test/expect/gccxml.any.Class-base-typedef.xml.txt @@ -13,6 +13,7 @@ + @@ -23,9 +24,8 @@ + - - $ diff --git a/test/expect/gccxml.any.Class-forward.xml.txt b/test/expect/gccxml.any.Class-forward.xml.txt index b4d9d8e..1b7be75 100644 --- a/test/expect/gccxml.any.Class-forward.xml.txt +++ b/test/expect/gccxml.any.Class-forward.xml.txt @@ -10,8 +10,8 @@ + - $ diff --git a/test/expect/gccxml.any.Class-friends.xml.txt b/test/expect/gccxml.any.Class-friends.xml.txt index 042028c..8143e8f 100644 --- a/test/expect/gccxml.any.Class-friends.xml.txt +++ b/test/expect/gccxml.any.Class-friends.xml.txt @@ -10,11 +10,11 @@ + - $ diff --git a/test/expect/gccxml.any.Class-implicit-member-access-mutable.xml.txt b/test/expect/gccxml.any.Class-implicit-member-access-mutable.xml.txt index e7b0225..9b98f75 100644 --- a/test/expect/gccxml.any.Class-implicit-member-access-mutable.xml.txt +++ b/test/expect/gccxml.any.Class-implicit-member-access-mutable.xml.txt @@ -16,9 +16,9 @@ + - $ diff --git a/test/expect/gccxml.any.Class-implicit-member-access.xml.txt b/test/expect/gccxml.any.Class-implicit-member-access.xml.txt index 7dd63c2..6483804 100644 --- a/test/expect/gccxml.any.Class-implicit-member-access.xml.txt +++ b/test/expect/gccxml.any.Class-implicit-member-access.xml.txt @@ -15,8 +15,8 @@ + - $ diff --git a/test/expect/gccxml.any.Class-implicit-member-array.xml.txt b/test/expect/gccxml.any.Class-implicit-member-array.xml.txt index 421df50..1310ad6 100644 --- a/test/expect/gccxml.any.Class-implicit-member-array.xml.txt +++ b/test/expect/gccxml.any.Class-implicit-member-array.xml.txt @@ -12,9 +12,9 @@ + - $ diff --git a/test/expect/gccxml.any.Class-implicit-member-bad-base.xml.txt b/test/expect/gccxml.any.Class-implicit-member-bad-base.xml.txt index 14a5495..2bf091b 100644 --- a/test/expect/gccxml.any.Class-implicit-member-bad-base.xml.txt +++ b/test/expect/gccxml.any.Class-implicit-member-bad-base.xml.txt @@ -10,17 +10,17 @@ - + + - - + + - - + $ diff --git a/test/expect/gccxml.any.Class-implicit-member-const.xml.txt b/test/expect/gccxml.any.Class-implicit-member-const.xml.txt index d240fdf..99d41d8 100644 --- a/test/expect/gccxml.any.Class-implicit-member-const.xml.txt +++ b/test/expect/gccxml.any.Class-implicit-member-const.xml.txt @@ -1,16 +1,16 @@ ^<\?xml version="1.0"\?> ]*> - + - - + + - + $ diff --git a/test/expect/gccxml.any.Class-implicit-member-reference.xml.txt b/test/expect/gccxml.any.Class-implicit-member-reference.xml.txt index 325c063..e9d21a0 100644 --- a/test/expect/gccxml.any.Class-implicit-member-reference.xml.txt +++ b/test/expect/gccxml.any.Class-implicit-member-reference.xml.txt @@ -9,8 +9,8 @@ + - $ diff --git a/test/expect/gccxml.any.Class-implicit-members.xml.txt b/test/expect/gccxml.any.Class-implicit-members.xml.txt index 4c077e4..6a2115f 100644 --- a/test/expect/gccxml.any.Class-implicit-members.xml.txt +++ b/test/expect/gccxml.any.Class-implicit-members.xml.txt @@ -5,16 +5,16 @@ - + - + + - $ diff --git a/test/expect/gccxml.any.Class-member-template.xml.txt b/test/expect/gccxml.any.Class-member-template.xml.txt index dcc4bf9..01bf425 100644 --- a/test/expect/gccxml.any.Class-member-template.xml.txt +++ b/test/expect/gccxml.any.Class-member-template.xml.txt @@ -14,8 +14,8 @@ + - $ diff --git a/test/expect/gccxml.any.Class-partial-template-member-Typedef.xml.txt b/test/expect/gccxml.any.Class-partial-template-member-Typedef.xml.txt index 7c7fcf5..a3d8c18 100644 --- a/test/expect/gccxml.any.Class-partial-template-member-Typedef.xml.txt +++ b/test/expect/gccxml.any.Class-partial-template-member-Typedef.xml.txt @@ -15,8 +15,8 @@ + - $ diff --git a/test/expect/gccxml.any.Class-template-Method-Argument-const.xml.txt b/test/expect/gccxml.any.Class-template-Method-Argument-const.xml.txt new file mode 100644 index 0000000..c4e288c --- /dev/null +++ b/test/expect/gccxml.any.Class-template-Method-Argument-const.xml.txt @@ -0,0 +1,24 @@ +^<\?xml version="1.0"\?> +]*> + + + + + + + + + + + + + + + + + + + + + +$ diff --git a/test/expect/gccxml.any.Class-template-Method-Argument-default.xml.txt b/test/expect/gccxml.any.Class-template-Method-Argument-default.xml.txt index 033e39d..b5dd76c 100644 --- a/test/expect/gccxml.any.Class-template-Method-Argument-default.xml.txt +++ b/test/expect/gccxml.any.Class-template-Method-Argument-default.xml.txt @@ -14,8 +14,8 @@ + - $ diff --git a/test/expect/gccxml.any.Class-template-Method-return-const.xml.txt b/test/expect/gccxml.any.Class-template-Method-return-const.xml.txt new file mode 100644 index 0000000..5bf29e2 --- /dev/null +++ b/test/expect/gccxml.any.Class-template-Method-return-const.xml.txt @@ -0,0 +1,20 @@ +^<\?xml version="1.0"\?> +]*> + + + + + + + + + + + + + + + + + +$ diff --git a/test/expect/gccxml.any.Class-template-constructor-template.xml.txt b/test/expect/gccxml.any.Class-template-constructor-template.xml.txt new file mode 100644 index 0000000..b9a8e1f --- /dev/null +++ b/test/expect/gccxml.any.Class-template-constructor-template.xml.txt @@ -0,0 +1,20 @@ +^<\?xml version="1.0"\?> +]*> + + + + + + + + + + + + + + + + + +$ diff --git a/test/expect/gccxml.any.Class-template-friends.xml.txt b/test/expect/gccxml.any.Class-template-friends.xml.txt index ae87767..061a913 100644 --- a/test/expect/gccxml.any.Class-template-friends.xml.txt +++ b/test/expect/gccxml.any.Class-template-friends.xml.txt @@ -10,13 +10,13 @@ + - $ diff --git a/test/expect/gccxml.any.Class-template-member-Typedef-const.xml.txt b/test/expect/gccxml.any.Class-template-member-Typedef-const.xml.txt index a31207f..3348184 100644 --- a/test/expect/gccxml.any.Class-template-member-Typedef-const.xml.txt +++ b/test/expect/gccxml.any.Class-template-member-Typedef-const.xml.txt @@ -1,8 +1,8 @@ ^<\?xml version="1.0"\?> ]*> - - + + @@ -13,11 +13,11 @@ - - + + + - $ diff --git a/test/expect/gccxml.any.Class-template-member-Typedef.xml.txt b/test/expect/gccxml.any.Class-template-member-Typedef.xml.txt index 7aea3ff..d687249 100644 --- a/test/expect/gccxml.any.Class-template-member-Typedef.xml.txt +++ b/test/expect/gccxml.any.Class-template-member-Typedef.xml.txt @@ -15,8 +15,8 @@ + - $ diff --git a/test/expect/gccxml.any.Class-template-member-template.xml.txt b/test/expect/gccxml.any.Class-template-member-template.xml.txt index 93f59a5..b7f565e 100644 --- a/test/expect/gccxml.any.Class-template-member-template.xml.txt +++ b/test/expect/gccxml.any.Class-template-member-template.xml.txt @@ -15,8 +15,8 @@ + - $ diff --git a/test/expect/gccxml.any.Class-template.xml.txt b/test/expect/gccxml.any.Class-template.xml.txt index f8d5446..ccec63f 100644 --- a/test/expect/gccxml.any.Class-template.xml.txt +++ b/test/expect/gccxml.any.Class-template.xml.txt @@ -20,11 +20,11 @@ + + - - $ diff --git a/test/expect/gccxml.any.Class.xml.txt b/test/expect/gccxml.any.Class.xml.txt index 9dea0cc..6c87c6f 100644 --- a/test/expect/gccxml.any.Class.xml.txt +++ b/test/expect/gccxml.any.Class.xml.txt @@ -10,8 +10,8 @@ + - $ diff --git a/test/expect/gccxml.any.CvQualifiedType.xml.txt b/test/expect/gccxml.any.CvQualifiedType.xml.txt index a6b0ec8..a360ee6 100644 --- a/test/expect/gccxml.any.CvQualifiedType.xml.txt +++ b/test/expect/gccxml.any.CvQualifiedType.xml.txt @@ -1,8 +1,8 @@ ^<\?xml version="1.0"\?> ]*> - - - + + + $ diff --git a/test/expect/gccxml.any.Field.xml.txt b/test/expect/gccxml.any.Field.xml.txt index 269929c..c967c77 100644 --- a/test/expect/gccxml.any.Field.xml.txt +++ b/test/expect/gccxml.any.Field.xml.txt @@ -15,8 +15,8 @@ + - $ diff --git a/test/expect/gccxml.any.Function-Argument-default.xml.txt b/test/expect/gccxml.any.Function-Argument-default.xml.txt index d9ffd40..ce29f8d 100644 --- a/test/expect/gccxml.any.Function-Argument-default.xml.txt +++ b/test/expect/gccxml.any.Function-Argument-default.xml.txt @@ -6,9 +6,9 @@ - + + - - + $ diff --git a/test/expect/gccxml.any.GNU-float128.xml.txt b/test/expect/gccxml.any.GNU-float128.xml.txt index 43b5411..d21678f 100644 --- a/test/expect/gccxml.any.GNU-float128.xml.txt +++ b/test/expect/gccxml.any.GNU-float128.xml.txt @@ -16,10 +16,10 @@ + - $ diff --git a/test/expect/gccxml.any.Method.xml.txt b/test/expect/gccxml.any.Method.xml.txt index 5821218..ca938e8 100644 --- a/test/expect/gccxml.any.Method.xml.txt +++ b/test/expect/gccxml.any.Method.xml.txt @@ -14,8 +14,8 @@ + - $ diff --git a/test/expect/gccxml.any.MethodType-cv.xml.txt b/test/expect/gccxml.any.MethodType-cv.xml.txt index 5c43a24..a2f11bd 100644 --- a/test/expect/gccxml.any.MethodType-cv.xml.txt +++ b/test/expect/gccxml.any.MethodType-cv.xml.txt @@ -1,8 +1,8 @@ ^<\?xml version="1.0"\?> ]*> - - - + + + diff --git a/test/expect/gccxml.any.Namespace-Class-members.xml.txt b/test/expect/gccxml.any.Namespace-Class-members.xml.txt index 9f38370..bda8d84 100644 --- a/test/expect/gccxml.any.Namespace-Class-members.xml.txt +++ b/test/expect/gccxml.any.Namespace-Class-members.xml.txt @@ -13,8 +13,8 @@ + - $ diff --git a/test/expect/gccxml.any.OffsetType-cv.xml.txt b/test/expect/gccxml.any.OffsetType-cv.xml.txt index 15c35ac..16e70a5 100644 --- a/test/expect/gccxml.any.OffsetType-cv.xml.txt +++ b/test/expect/gccxml.any.OffsetType-cv.xml.txt @@ -1,11 +1,11 @@ ^<\?xml version="1.0"\?> ]*> - - - + + + - - + + $ diff --git a/test/expect/gccxml.any.OperatorMethod.xml.txt b/test/expect/gccxml.any.OperatorMethod.xml.txt index b04b30a..b72b2cd 100644 --- a/test/expect/gccxml.any.OperatorMethod.xml.txt +++ b/test/expect/gccxml.any.OperatorMethod.xml.txt @@ -15,7 +15,7 @@ - + $ diff --git a/test/expect/gccxml.any.Variable-in-Class.xml.txt b/test/expect/gccxml.any.Variable-in-Class.xml.txt index e89800d..12e8056 100644 --- a/test/expect/gccxml.any.Variable-in-Class.xml.txt +++ b/test/expect/gccxml.any.Variable-in-Class.xml.txt @@ -12,8 +12,8 @@ + - $ diff --git a/test/expect/gccxml.any.Variable-init.xml.txt b/test/expect/gccxml.any.Variable-init.xml.txt index 6659b64..6061dc1 100644 --- a/test/expect/gccxml.any.Variable-init.xml.txt +++ b/test/expect/gccxml.any.Variable-init.xml.txt @@ -4,9 +4,9 @@ - + + - - + $ diff --git a/test/expect/gccxml.any.using-declaration-class.xml.txt b/test/expect/gccxml.any.using-declaration-class.xml.txt index abcc136..9669b01 100644 --- a/test/expect/gccxml.any.using-declaration-class.xml.txt +++ b/test/expect/gccxml.any.using-declaration-class.xml.txt @@ -21,6 +21,7 @@ + @@ -31,9 +32,8 @@ + - - $ diff --git a/test/expect/gccxml.broken.any.Class-template-constructor-template.xml.txt b/test/expect/gccxml.broken.any.Class-template-constructor-template.xml.txt deleted file mode 100644 index 3fa83ec..0000000 --- a/test/expect/gccxml.broken.any.Class-template-constructor-template.xml.txt +++ /dev/null @@ -1,21 +0,0 @@ -^<\?xml version="1.0"\?> -]*> - - - - - - - - - - - - - (broken: duplicate ReferenceType)? - - - - - -$ diff --git a/test/expect/gccxml.c++11.Class-bases.xml.txt b/test/expect/gccxml.c++11.Class-bases.xml.txt index db478dd..69666f0 100644 --- a/test/expect/gccxml.c++11.Class-bases.xml.txt +++ b/test/expect/gccxml.c++11.Class-bases.xml.txt @@ -18,6 +18,7 @@ + @@ -44,14 +45,13 @@ + + - - - - + $ diff --git a/test/expect/gccxml.c++11.Class-template-bases.xml.txt b/test/expect/gccxml.c++11.Class-template-bases.xml.txt index 1a7a047..aaf6a75 100644 --- a/test/expect/gccxml.c++11.Class-template-bases.xml.txt +++ b/test/expect/gccxml.c++11.Class-template-bases.xml.txt @@ -15,6 +15,7 @@ + @@ -33,12 +34,11 @@ + + - - - $ diff --git a/test/expect/gccxml.c++98.Class-bases.xml.txt b/test/expect/gccxml.c++98.Class-bases.xml.txt index 1ec7843..852b1c1 100644 --- a/test/expect/gccxml.c++98.Class-bases.xml.txt +++ b/test/expect/gccxml.c++98.Class-bases.xml.txt @@ -18,6 +18,7 @@ + @@ -43,15 +44,14 @@ + + + - - - - $ diff --git a/test/expect/gccxml.c++98.Class-template-bases.xml.txt b/test/expect/gccxml.c++98.Class-template-bases.xml.txt index 1ad68ab..a683164 100644 --- a/test/expect/gccxml.c++98.Class-template-bases.xml.txt +++ b/test/expect/gccxml.c++98.Class-template-bases.xml.txt @@ -15,6 +15,7 @@ + @@ -33,12 +34,11 @@ + + - - - $ diff --git a/test/input/Class-template-Method-Argument-const.cxx b/test/input/Class-template-Method-Argument-const.cxx new file mode 100644 index 0000000..76c6c4b --- /dev/null +++ b/test/input/Class-template-Method-Argument-const.cxx @@ -0,0 +1,4 @@ +template class start { + void method(T const&); +}; +template class start; // instantiation diff --git a/test/input/Class-template-Method-return-const.cxx b/test/input/Class-template-Method-return-const.cxx new file mode 100644 index 0000000..28063b4 --- /dev/null +++ b/test/input/Class-template-Method-return-const.cxx @@ -0,0 +1,4 @@ +template class start { + T const method(); +}; +template class start; // instantiation -- cgit v0.12