From 3bf42ed8ccc93a3ff5fdabb9153b887018075acc Mon Sep 17 00:00:00 2001 From: Boris Kolpackov Date: Tue, 19 Jan 2010 11:44:48 +0200 Subject: Add support for selective polymorphic in C++/Tree New options: --polymorphic-type, --polymorphic-type-all. --- xsd/cxx/tree/cli.hxx | 4 + xsd/cxx/tree/elements.cxx | 79 +-- xsd/cxx/tree/elements.hxx | 41 +- xsd/cxx/tree/generator.cxx | 23 + xsd/cxx/tree/parser-source.cxx | 8 +- xsd/cxx/tree/polymorphism-processor.cxx | 791 ++++++++++++++++++++++++++++++ xsd/cxx/tree/polymorphism-processor.hxx | 35 ++ xsd/cxx/tree/serialization-source.cxx | 41 +- xsd/cxx/tree/stream-extraction-source.cxx | 19 +- xsd/cxx/tree/stream-insertion-source.cxx | 26 +- xsd/cxx/tree/stream-source.cxx | 26 +- xsd/cxx/tree/tree-header.cxx | 49 +- xsd/cxx/tree/tree-source.cxx | 95 ++-- xsd/cxx/tree/validator.cxx | 3 + xsd/makefile | 1 + 15 files changed, 1034 insertions(+), 207 deletions(-) create mode 100644 xsd/cxx/tree/polymorphism-processor.cxx create mode 100644 xsd/cxx/tree/polymorphism-processor.hxx (limited to 'xsd') diff --git a/xsd/cxx/tree/cli.hxx b/xsd/cxx/tree/cli.hxx index 538c10b..c4294b6 100644 --- a/xsd/cxx/tree/cli.hxx +++ b/xsd/cxx/tree/cli.hxx @@ -27,6 +27,8 @@ namespace CXX extern Key char_encoding; extern Key output_dir; extern Key generate_polymorphic; + extern Key polymorphic_type; + extern Key polymorphic_type_all; extern Key generate_serialization; extern Key generate_inline; extern Key generate_ostream; @@ -123,6 +125,8 @@ namespace CXX char_encoding, NarrowString, output_dir, NarrowString, generate_polymorphic, Boolean, + polymorphic_type, Cult::Containers::Vector, + polymorphic_type_all, Boolean, generate_serialization, Boolean, generate_inline, Boolean, generate_ostream, Boolean, diff --git a/xsd/cxx/tree/elements.cxx b/xsd/cxx/tree/elements.cxx index 31e0c08..0072e07 100644 --- a/xsd/cxx/tree/elements.cxx +++ b/xsd/cxx/tree/elements.cxx @@ -85,6 +85,7 @@ namespace CXX generate_xml_schema (generate_xml_schema_), doxygen (doxygen_), polymorphic (ops.value ()), + polymorphic_all (ops.value ()), fwd_expr (fe), hxx_expr (he), ixx_expr (ie), @@ -322,6 +323,7 @@ namespace CXX generate_xml_schema (c.generate_xml_schema), doxygen (c.doxygen), polymorphic (c.polymorphic), + polymorphic_all (c.polymorphic_all), fwd_expr (c.fwd_expr), hxx_expr (c.hxx_expr), ixx_expr (c.ixx_expr), @@ -361,6 +363,7 @@ namespace CXX generate_xml_schema (c.generate_xml_schema), doxygen (c.doxygen), polymorphic (c.polymorphic), + polymorphic_all (c.polymorphic_all), fwd_expr (c.fwd_expr), hxx_expr (c.hxx_expr), ixx_expr (c.ixx_expr), @@ -595,6 +598,20 @@ namespace CXX } } + Boolean Context:: + polymorphic_p (SemanticGraph::Type& t) + { + if (polymorphic_all) + { + Boolean fund (false); + IsFundamentalType test (fund); + test.dispatch (t); + return !fund; + } + else + return t.context ().get ("polymorphic"); + } + // GenerateDefautCtor // GenerateDefaultCtor:: @@ -710,15 +727,15 @@ namespace CXX // HasComplexNonOptArgs // - HasComplexNonFundNonOptArgs:: - HasComplexNonFundNonOptArgs (Context& c, - Boolean base, - Boolean& complex, - Boolean& non_fund, - Boolean& clash) + HasComplexPolyNonOptArgs:: + HasComplexPolyNonOptArgs (Context& c, + Boolean base, + Boolean& complex, + Boolean& poly, + Boolean& clash) : Context (c), complex_ (complex), - non_fund_ (non_fund), + poly_ (poly), clash_ (clash) { if (base) @@ -727,7 +744,7 @@ namespace CXX *this >> names_ >> *this; } - Void HasComplexNonFundNonOptArgs:: + Void HasComplexPolyNonOptArgs:: traverse (SemanticGraph::Complex& c) { // No optimizations: need to check every arg for clashes. @@ -736,28 +753,25 @@ namespace CXX names (c, names_); } - Void HasComplexNonFundNonOptArgs:: + Void HasComplexPolyNonOptArgs:: traverse (SemanticGraph::Element& e) { if (!skip (e) && min (e) == 1 && max (e) == 1) { - Boolean fund (false); - IsFundamentalType t (fund); + Boolean poly (polymorphic && polymorphic_p (e.type ())); + + Boolean simple (true); + IsSimpleType t (simple); t.dispatch (e.type ()); - if (!fund) - { - non_fund_ = true; + if (poly) + poly_ = true; - Boolean simple (true); - IsSimpleType t (simple); - t.dispatch (e.type ()); + if (!simple) + complex_ = true; - if (!simple) - complex_ = true; - else - clash_ = false; - } + if (poly && simple) + clash_ = false; } } @@ -811,12 +825,9 @@ namespace CXX auto_ptr = !simple; break; } - case arg_non_fund_auto_ptr: + case arg_poly_auto_ptr: { - Boolean fund (false); - IsFundamentalType t (fund); - t.dispatch (e.type ()); - auto_ptr = !fund; + auto_ptr = polymorphic && polymorphic_p (e.type ()); break; } case arg_type: @@ -947,12 +958,9 @@ namespace CXX auto_ptr = !simple; break; } - case arg_non_fund_auto_ptr: + case arg_poly_auto_ptr: { - Boolean fund (false); - IsFundamentalType t (fund); - t.dispatch (e.type ()); - auto_ptr = !fund; + auto_ptr = polymorphic && polymorphic_p (e.type ()); break; } case arg_type: @@ -1039,12 +1047,9 @@ namespace CXX auto_ptr = !simple; break; } - case arg_non_fund_auto_ptr: + case arg_poly_auto_ptr: { - Boolean fund (false); - IsFundamentalType t (fund); - t.dispatch (e.type ()); - auto_ptr = !fund; + auto_ptr = polymorphic && polymorphic_p (e.type ()); break; } case arg_type: diff --git a/xsd/cxx/tree/elements.hxx b/xsd/cxx/tree/elements.hxx index 1caf378..2160baf 100644 --- a/xsd/cxx/tree/elements.hxx +++ b/xsd/cxx/tree/elements.hxx @@ -158,6 +158,18 @@ namespace CXX Void write_annotation (SemanticGraph::Annotation&); + // + // + public: + Boolean + polymorphic_p (SemanticGraph::Type&); + + Boolean + anonymous_p (SemanticGraph::Type const& t) + { + return t.context ().count ("anonymous"); + } + // Escaped names. // public: @@ -400,6 +412,7 @@ namespace CXX Boolean& generate_xml_schema; Boolean& doxygen; Boolean polymorphic; + Boolean polymorphic_all; Regex const* fwd_expr; Regex const* hxx_expr; @@ -1437,20 +1450,20 @@ namespace CXX }; // Test whether the type has any non-optional element of complex - // (has attributes/elements) and non-fundamental types. + // (has attributes/elements) and polymorpjic types. // - struct HasComplexNonFundNonOptArgs: Traversal::Complex, - Traversal::Element, - Context + struct HasComplexPolyNonOptArgs: Traversal::Complex, + Traversal::Element, + Context { - // complex and non_fund should initially be false. clash + // complex and poly should initially be false. clash // should initially be true. // - HasComplexNonFundNonOptArgs (Context& c, - Boolean including_base, - Boolean& complex, - Boolean& non_fund, - Boolean& clash); + HasComplexPolyNonOptArgs (Context& c, + Boolean including_base, + Boolean& complex, + Boolean& poly, + Boolean& clash); virtual Void traverse (SemanticGraph::Complex&); @@ -1460,7 +1473,7 @@ namespace CXX private: Boolean& complex_; - Boolean& non_fund_; + Boolean& poly_; Boolean& clash_; Traversal::Inherits inherits_; @@ -1479,7 +1492,7 @@ namespace CXX { arg_type, arg_complex_auto_ptr, - arg_non_fund_auto_ptr + arg_poly_auto_ptr }; FromBaseCtorArg (Context& c, ArgType, Boolean arg); @@ -1513,7 +1526,7 @@ namespace CXX { arg_type, arg_complex_auto_ptr, - arg_non_fund_auto_ptr + arg_poly_auto_ptr }; // The second version outputs the argument name and stores @@ -1680,7 +1693,7 @@ namespace CXX { arg_type, arg_complex_auto_ptr, - arg_non_fund_auto_ptr + arg_poly_auto_ptr }; CtorArgsWithoutBase (Context& c, ArgType, Boolean arg, Boolean first); diff --git a/xsd/cxx/tree/generator.cxx b/xsd/cxx/tree/generator.cxx index 012a1fd..a70214c 100644 --- a/xsd/cxx/tree/generator.cxx +++ b/xsd/cxx/tree/generator.cxx @@ -10,6 +10,7 @@ #include #include #include +#include #include #include @@ -119,6 +120,8 @@ namespace CXX extern Key char_encoding = "char-encoding"; extern Key output_dir = "output-dir"; extern Key generate_polymorphic = "generate-polymorphic"; + extern Key polymorphic_type = "polymorphic-type"; + extern Key polymorphic_type_all = "polymorphic-type-all"; extern Key generate_serialization = "generate-serialization"; extern Key generate_inline = "generate-inline"; extern Key generate_ostream = "generate-ostream"; @@ -239,6 +242,16 @@ namespace CXX << " option if you use substitution groups or xsi:type." << endl; + e << "--polymorphic-type " << endl + << " Indicate that is a root of a polymorphic\n" + << " type hierarchy." + << endl; + + e << "--polymorphic-type-all" << endl + << " Indicate that all types should be treated as\n" + << " polymorphic." + << endl; + e << "--generate-serialization" << endl << " Generate serialization functions. They convert an\n" << " in-memory representation back to XML." @@ -878,6 +891,16 @@ namespace CXX throw Failed (); } + // Process polymorphic types. + // + if (ops.value () && + !ops.value ()) + { + PolymorphismProcessor proc; + if (!proc.process (ops, schema, file_path, disabled_warnings)) + throw Failed (); + } + // Parts. // UnsignedLong parts (ops.value ()); diff --git a/xsd/cxx/tree/parser-source.cxx b/xsd/cxx/tree/parser-source.cxx index 66abf96..94d0b91 100644 --- a/xsd/cxx/tree/parser-source.cxx +++ b/xsd/cxx/tree/parser-source.cxx @@ -295,18 +295,16 @@ namespace CXX // Boolean fund (false); - { IsFundamentalType test (fund); test.dispatch (t); } // Check if we need to handle xsi:type and substitution groups. - // If this element's type is anonymous or mapped to a fundamental - // C++ type then we don't need to do anything. + // If this element's type is anonymous then we don't need to do + // anything. // - Boolean poly (!fund && polymorphic && - !t.context ().count ("anonymous")); + Boolean poly (polymorphic && polymorphic_p (t) && !anonymous_p (t)); // const DOMDocument& // diff --git a/xsd/cxx/tree/polymorphism-processor.cxx b/xsd/cxx/tree/polymorphism-processor.cxx new file mode 100644 index 0000000..2d12a75 --- /dev/null +++ b/xsd/cxx/tree/polymorphism-processor.cxx @@ -0,0 +1,791 @@ +// file : xsde/cxx/tree/polymorphism-processor.cxx +// author : Boris Kolpackov +// copyright : Copyright (c) 2006-2010 Code Synthesis Tools CC +// license : GNU GPL v2 + exceptions; see accompanying LICENSE file + +#include +#include + +#include +#include + +#include + +#include + +using std::wcerr; + +namespace CXX +{ + namespace Tree + { + namespace + { + struct TypeSet + { + template + TypeSet (I begin, I end) + { + for (; begin != end; ++begin) + insert (*begin); + } + + Void + insert (String const& name) + { + Size p (name.rfind ('#')); + + if (p == String::npos) + unames_.insert (name); + else + qnames_.insert (name); + } + + Boolean + find (SemanticGraph::Type& t) + { + if (!unames_.empty ()) + { + if (unames_.find (t.name ()) != unames_.end ()) + return true; + } + + if (!qnames_.empty ()) + { + if (qnames_.find (t.scope ().name () + L"#" + t.name ()) != + qnames_.end ()) + return true; + } + + return false; + } + + private: + typedef Cult::Containers::Set StringSet; + + StringSet unames_; + StringSet qnames_; + }; + + + // + // + struct Type: Traversal::Type, + Traversal::Complex + { + Type (TypeSet& poly_types) + : poly_types_ (poly_types) + { + } + + virtual Void + traverse (SemanticGraph::Type& t) + { + SemanticGraph::Context& ctx (t.context ()); + + if (!ctx.count ("polymorphic")) + ctx.set ("polymorphic", poly_types_.find (t)); + } + + virtual Void + traverse (SemanticGraph::Complex& c) + { + SemanticGraph::Context& ctx (c.context ()); + + if (!ctx.count ("polymorphic")) + { + // First check our base. + // + Boolean pb (false); + if (c.inherits_p ()) + { + SemanticGraph::Type& b (c.inherits ().base ()); + + if (!b.context ().count ("polymorphic")) + dispatch (b); + + pb = b.context ().get ("polymorphic"); + } + + ctx.set ("polymorphic", pb || poly_types_.find (c)); + } + } + + private: + TypeSet& poly_types_; + }; + + struct FundType: Traversal::AnyType, + Traversal::AnySimpleType, + + Traversal::Fundamental::Byte, + Traversal::Fundamental::UnsignedByte, + Traversal::Fundamental::Short, + Traversal::Fundamental::UnsignedShort, + Traversal::Fundamental::Int, + Traversal::Fundamental::UnsignedInt, + Traversal::Fundamental::Long, + Traversal::Fundamental::UnsignedLong, + Traversal::Fundamental::Integer, + Traversal::Fundamental::NonPositiveInteger, + Traversal::Fundamental::NonNegativeInteger, + Traversal::Fundamental::PositiveInteger, + Traversal::Fundamental::NegativeInteger, + + Traversal::Fundamental::Boolean, + + Traversal::Fundamental::Float, + Traversal::Fundamental::Double, + Traversal::Fundamental::Decimal, + + Traversal::Fundamental::String, + Traversal::Fundamental::NormalizedString, + Traversal::Fundamental::Token, + Traversal::Fundamental::Name, + Traversal::Fundamental::NameToken, + Traversal::Fundamental::NameTokens, + Traversal::Fundamental::NCName, + Traversal::Fundamental::Language, + + Traversal::Fundamental::QName, + + Traversal::Fundamental::Id, + Traversal::Fundamental::IdRef, + Traversal::Fundamental::IdRefs, + + Traversal::Fundamental::AnyURI, + + Traversal::Fundamental::Base64Binary, + Traversal::Fundamental::HexBinary, + + Traversal::Fundamental::Date, + Traversal::Fundamental::DateTime, + Traversal::Fundamental::Duration, + Traversal::Fundamental::Day, + Traversal::Fundamental::Month, + Traversal::Fundamental::MonthDay, + Traversal::Fundamental::Year, + Traversal::Fundamental::YearMonth, + Traversal::Fundamental::Time, + + Traversal::Fundamental::Entity, + Traversal::Fundamental::Entities + { + FundType (TypeSet& poly_types, Boolean& valid) + : poly_types_ (poly_types), valid_ (valid) + { + } + + Void + check (SemanticGraph::Type& t, Boolean fund) + { + SemanticGraph::Context& ctx (t.context ()); + + if (poly_types_.find (t)) + { + if (!fund) + ctx.set ("polymorphic", true); + else + { + wcerr << "error: built-in type '" << t.name () << "' cannot " + << "be polymorphic because it is mapped to a fundamental " + << "C++ type" + << endl; + + valid_ = false; + } + } + else + ctx.set ("polymorphic", false); + } + + // anyType & anySimpleType. + // + virtual Void + traverse (SemanticGraph::AnyType& t) + { + check (t, true); + } + + virtual Void + traverse (SemanticGraph::AnySimpleType& t) + { + check (t, true); + } + + // Boolean. + // + virtual Void + traverse (SemanticGraph::Fundamental::Boolean& t) + { + check (t, false); + } + + // Integral types. + // + virtual Void + traverse (SemanticGraph::Fundamental::Byte& t) + { + check (t, false); + } + + virtual Void + traverse (SemanticGraph::Fundamental::UnsignedByte& t) + { + check (t, false); + } + + virtual Void + traverse (SemanticGraph::Fundamental::Short& t) + { + check (t, false); + } + + virtual Void + traverse (SemanticGraph::Fundamental::UnsignedShort& t) + { + check (t, false); + } + + virtual Void + traverse (SemanticGraph::Fundamental::Int& t) + { + check (t, false); + } + + virtual Void + traverse (SemanticGraph::Fundamental::UnsignedInt& t) + { + check (t, false); + } + + virtual Void + traverse (SemanticGraph::Fundamental::Long& t) + { + check (t, false); + } + + virtual Void + traverse (SemanticGraph::Fundamental::UnsignedLong& t) + { + check (t, false); + } + + virtual Void + traverse (SemanticGraph::Fundamental::Integer& t) + { + check (t, false); + } + + virtual Void + traverse (SemanticGraph::Fundamental::NonPositiveInteger& t) + { + check (t, false); + } + + virtual Void + traverse (SemanticGraph::Fundamental::NonNegativeInteger& t) + { + check (t, false); + } + + virtual Void + traverse (SemanticGraph::Fundamental::PositiveInteger& t) + { + check (t, false); + } + + virtual Void + traverse (SemanticGraph::Fundamental::NegativeInteger& t) + { + check (t, false); + } + + // Floats. + // + virtual Void + traverse (SemanticGraph::Fundamental::Float& t) + { + check (t, false); + } + + virtual Void + traverse (SemanticGraph::Fundamental::Double& t) + { + check (t, false); + } + + virtual Void + traverse (SemanticGraph::Fundamental::Decimal& t) + { + check (t, false); + } + + // Strings. + // + virtual Void + traverse (SemanticGraph::Fundamental::String& t) + { + check (t, true); + } + + virtual Void + traverse (SemanticGraph::Fundamental::NormalizedString& t) + { + check (t, true); + } + + virtual Void + traverse (SemanticGraph::Fundamental::Token& t) + { + check (t, true); + } + + virtual Void + traverse (SemanticGraph::Fundamental::NameToken& t) + { + check (t, true); + } + + virtual Void + traverse (SemanticGraph::Fundamental::NameTokens& t) + { + check (t, true); + } + + virtual Void + traverse (SemanticGraph::Fundamental::Name& t) + { + check (t, true); + } + + virtual Void + traverse (SemanticGraph::Fundamental::NCName& t) + { + check (t, true); + } + + virtual Void + traverse (SemanticGraph::Fundamental::Language& t) + { + check (t, true); + } + + + // Qualified name. + // + virtual Void + traverse (SemanticGraph::Fundamental::QName& t) + { + check (t, true); + } + + + // ID/IDREF. + // + virtual Void + traverse (SemanticGraph::Fundamental::Id& t) + { + check (t, true); + } + + virtual Void + traverse (SemanticGraph::Fundamental::IdRef& t) + { + check (t, true); + } + + virtual Void + traverse (SemanticGraph::Fundamental::IdRefs& t) + { + check (t, true); + } + + // URI. + // + virtual Void + traverse (SemanticGraph::Fundamental::AnyURI& t) + { + check (t, true); + } + + // Binary. + // + virtual Void + traverse (SemanticGraph::Fundamental::Base64Binary& t) + { + check (t, true); + } + + virtual Void + traverse (SemanticGraph::Fundamental::HexBinary& t) + { + check (t, true); + } + + + // Date/time. + // + virtual Void + traverse (SemanticGraph::Fundamental::Date& t) + { + check (t, true); + } + + virtual Void + traverse (SemanticGraph::Fundamental::DateTime& t) + { + check (t, true); + } + + virtual Void + traverse (SemanticGraph::Fundamental::Duration& t) + { + check (t, true); + } + + virtual Void + traverse (SemanticGraph::Fundamental::Day& t) + { + check (t, true); + } + + virtual Void + traverse (SemanticGraph::Fundamental::Month& t) + { + check (t, true); + } + + virtual Void + traverse (SemanticGraph::Fundamental::MonthDay& t) + { + check (t, true); + } + + virtual Void + traverse (SemanticGraph::Fundamental::Year& t) + { + check (t, true); + } + + virtual Void + traverse (SemanticGraph::Fundamental::YearMonth& t) + { + check (t, true); + } + + virtual Void + traverse (SemanticGraph::Fundamental::Time& t) + { + check (t, true); + } + + // Entity. + // + virtual Void + traverse (SemanticGraph::Fundamental::Entity& t) + { + check (t, true); + } + + virtual Void + traverse (SemanticGraph::Fundamental::Entities& t) + { + check (t, true); + } + + private: + TypeSet& poly_types_; + Boolean& valid_; + }; + + struct GlobalElement: Traversal::Element + { + GlobalElement (TypeSet& poly_types, + Boolean& valid, + const WarningSet& disabled_warnings) + : poly_types_ (poly_types), valid_ (valid), warning_ (true) + { + if (disabled_warnings.find ("all") != disabled_warnings.end () || + disabled_warnings.find ("T005") != disabled_warnings.end ()) + warning_ = false; + } + + virtual Void + traverse (Type& e) + { + using SemanticGraph::Schema; + + if (!e.substitutes_p ()) + return; + + // If we are a substitution for some element, then mark + // that element's type as polymorphic. + // + Type& r (e.substitutes ().root ()); + SemanticGraph::Type& rt (r.type ()); + SemanticGraph::Context& ctx (rt.context ()); + + // We may need to override the previous value. + // + if (ctx.count ("polymorphic") && ctx.get ("polymorphic")) + return; + + // Built-in types that are mapped to fundamental types cannot + // be declared polymorphic. + // + Boolean fund (false); + IsFundamentalType test (fund); + test.dispatch (rt); + + if (fund) + { + wcerr << r.file () << ":" << r.line () << ":" << r.column () + << ": error: built-in type '" << rt.name () << "' " + << "is mapped to a fundamental C++ type and is expected " + << "to be polymorphic" << endl; + + wcerr << e.file () << ":" << e.line () << ":" << e.column () + << ": info: because type '" << rt.name () << "' is " + << "used in a substitution group declared here" << endl; + + valid_ = false; + return; + } + + ctx.set ("polymorphic", true); + + if (!warning_) + return; + + Schema& es (dynamic_cast (e.scope ().scope ())); + Schema& rts (dynamic_cast (rt.scope ().scope ())); + + // If the root type and this element are in different schemas + // and the root type is not explicitly marked as polymorphic, + // then issue a warning. + // + if (&es != &rts && !sources_p (es, rts) && !poly_types_.find (rt)) + { + wcerr << rt.file () << ":" << rt.line () << ":" << rt.column () + << ": warning T005: assuming type '" << rt.name () << "' " + << "is polymorphic" << endl; + + wcerr << e.file () << ":" << e.line () << ":" << e.column () + << ": info: because type '" << rt.name () << "' is " + << "used in a substitution group declared here" << endl; + + wcerr << rt.file () << ":" << rt.line () << ":" << rt.column () + << ": info: use --polymorphic-type to indicate this type " + << "is polymorphic when compiling schemas that " + << "reference it" << endl; + } + } + + private: + // Return true if root sources s. + // + Boolean + sources_p (SemanticGraph::Schema& root, SemanticGraph::Schema& s) + { + using SemanticGraph::Schema; + using SemanticGraph::Sources; + + for (Schema::UsesIterator i (root.uses_begin ()); + i != root.uses_end (); ++i) + { + if (i->is_a ()) + { + if (&i->schema () == &s || sources_p (i->schema (), s)) + return true; + } + } + + return false; + } + + private: + TypeSet& poly_types_; + Boolean& valid_; + Boolean warning_; + }; + + // Go into sourced/included/imported schemas while making sure + // we don't process the same stuff more than once. + // + struct Uses: Traversal::Sources, + Traversal::Includes, + Traversal::Imports + { + Uses (Char const* seen_key) + : seen_key_ (seen_key) + { + } + + virtual Void + traverse (SemanticGraph::Sources& sr) + { + SemanticGraph::Schema& s (sr.schema ()); + + if (!s.context ().count (seen_key_)) + { + s.context ().set (seen_key_, true); + Traversal::Sources::traverse (sr); + } + } + + virtual Void + traverse (SemanticGraph::Includes& i) + { + SemanticGraph::Schema& s (i.schema ()); + + if (!s.context ().count (seen_key_)) + { + s.context ().set (seen_key_, true); + Traversal::Includes::traverse (i); + } + } + + virtual Void + traverse (SemanticGraph::Imports& i) + { + SemanticGraph::Schema& s (i.schema ()); + + if (!s.context ().count (seen_key_)) + { + s.context ().set (seen_key_, true); + Traversal::Imports::traverse (i); + } + } + + private: + Char const* seen_key_; + }; + + Char const* pass_one_key = "cxx-tree-polymorphism-processor-seen-one"; + Char const* pass_two_key = "cxx-tree-polymorphism-processor-seen-two"; + + Boolean + process_impl (CLI::Options const& ops, + SemanticGraph::Schema& tu, + SemanticGraph::Path const&, + const WarningSet& disabled_warnings) + { + Boolean valid (true); + + // Prepare a set of polymorphic types. + // + + TypeSet poly_types (ops.value ().begin (), + ops.value ().end ()); + + // Root schema in the file-per-type mode is just a bunch + // of includes without a namespace. + // + SemanticGraph::Schema::NamesIterator i (tu.names_begin ()); + + if (i != tu.names_end () && + i->named ().name () == L"http://www.w3.org/2001/XMLSchema") + { + // XML Schema namespace. + // + Traversal::Schema schema; + + Traversal::Names schema_names; + Traversal::Namespace ns; + Traversal::Names ns_names; + FundType fund_type (poly_types, valid); + + schema >> schema_names >> ns >> ns_names >> fund_type; + + schema.dispatch (tu); + } + else + { + // First handle fundamental types. + // + { + Traversal::Schema schema; + Traversal::Implies implies; + Traversal::Schema xs_schema; + + schema >> implies >> xs_schema; + + Traversal::Names xs_schema_names; + Traversal::Namespace ns; + Traversal::Names ns_names; + FundType fund_type (poly_types, valid); + + xs_schema >> xs_schema_names >> ns >> ns_names >> fund_type; + + schema.dispatch (tu); + } + + // Note that we check first if this schema has already been + // processed which may happen in the file-per-type compilation + // mode. + // + if (!tu.context ().count (pass_two_key)) + { + // Pass one - check substitution groups. + // + if (valid) + { + Traversal::Schema schema; + Uses uses (pass_one_key); + + schema >> uses >> schema; + + Traversal::Names schema_names; + Traversal::Namespace ns; + Traversal::Names ns_names; + GlobalElement element (poly_types, valid, disabled_warnings); + + schema >> schema_names >> ns >> ns_names >> element; + + // Some twisted schemas do recusive self-inclusion. + // + tu.context ().set (pass_one_key, true); + + schema.dispatch (tu); + } + + // Pass two - process types. + // + if (valid) + { + Traversal::Schema schema; + Uses uses (pass_two_key); + + schema >> uses >> schema; + + Traversal::Names schema_names; + Traversal::Namespace ns; + Traversal::Names ns_names; + Type type (poly_types); + + schema >> schema_names >> ns >> ns_names >> type; + + // Some twisted schemas do recusive self-inclusion. + // + tu.context ().set (pass_two_key, true); + + schema.dispatch (tu); + } + } + } + + return valid; + } + } + + Boolean PolymorphismProcessor:: + process (CLI::Options const& ops, + SemanticGraph::Schema& tu, + SemanticGraph::Path const& file, + const WarningSet& disabled_warnings) + { + return process_impl (ops, tu, file, disabled_warnings); + } + } +} diff --git a/xsd/cxx/tree/polymorphism-processor.hxx b/xsd/cxx/tree/polymorphism-processor.hxx new file mode 100644 index 0000000..3fbeca8 --- /dev/null +++ b/xsd/cxx/tree/polymorphism-processor.hxx @@ -0,0 +1,35 @@ +// file : xsde/cxx/tree/polymorphism-processor.hxx +// author : Boris Kolpackov +// copyright : Copyright (c) 2006-2010 Code Synthesis Tools CC +// license : GNU GPL v2 + exceptions; see accompanying LICENSE file + +#ifndef CXX_TREE_POLYMORPHISM_PROCESSOR_HXX +#define CXX_TREE_POLYMORPHISM_PROCESSOR_HXX + +#include + +#include + +#include + +#include + +namespace CXX +{ + namespace Tree + { + using namespace Cult::Types; + + class PolymorphismProcessor + { + public: + Boolean + process (CLI::Options const& options, + XSDFrontend::SemanticGraph::Schema&, + XSDFrontend::SemanticGraph::Path const& file, + const WarningSet& disabled_warnings); + }; + } +} + +#endif // CXX_TREE_POLYMORPHISM_PROCESSOR_HXX diff --git a/xsd/cxx/tree/serialization-source.cxx b/xsd/cxx/tree/serialization-source.cxx index 69f66c0..410b59a 100644 --- a/xsd/cxx/tree/serialization-source.cxx +++ b/xsd/cxx/tree/serialization-source.cxx @@ -93,7 +93,7 @@ namespace CXX // Register with type factory map. // - if (polymorphic && !l.context ().count ("anonymous")) + if (polymorphic && polymorphic_p (l) && !anonymous_p (l)) { // Note that we are using the original type name. // @@ -173,7 +173,7 @@ namespace CXX // Register with type factory map. // - if (polymorphic && !u.context ().count ("anonymous")) + if (polymorphic && polymorphic_p (u) && !anonymous_p (u)) { // Note that we are using the original type name. // @@ -255,7 +255,7 @@ namespace CXX // Register with type factory map. // - if (polymorphic && !e.context ().count ("anonymous")) + if (polymorphic && polymorphic_p (e) && !anonymous_p (e)) { // Note that we are using the original type name. // @@ -295,21 +295,13 @@ namespace CXX String type (scope + L"::" + etype (e)); // Check if we need to handle xsi:type and substitution groups. - // If this element's type is anonymous or mapped to a fundamental - // C++ type then we don't need to do anything. Note that if the - // type is anonymous then it can't be derived from which makes it - // impossible to substitute or dynamically-type with xsi:type. + // If this element's type is anonymous then we don't need to do + // anything. Note that if the type is anonymous then it can't be + // derived from which makes it impossible to substitute or + // dynamically-type with xsi:type. // SemanticGraph::Type& t (e.type ()); - Boolean poly (polymorphic && !t.context ().count ("anonymous")); - - if (poly) - { - Boolean fund (false); - IsFundamentalType traverser (fund); - traverser.dispatch (t); - poly = !fund; - } + Boolean poly (polymorphic && polymorphic_p (t) && !anonymous_p (t)); os << "// " << comment (e.name ()) << endl << "//" << endl; @@ -815,7 +807,7 @@ namespace CXX // Register with type factory map. // - if (polymorphic && !c.context ().count ("anonymous")) + if (polymorphic && polymorphic_p (c) && !anonymous_p (c)) { // Note that we are using the original type name. // @@ -958,18 +950,13 @@ namespace CXX // confused if the name is 'type'. (see tests/schema/anonymous) // - Boolean fund (false); - { - IsFundamentalType t (fund); - t.dispatch (type); - } - // Check if we need to handle xsi:type and substitution groups. - // If this element's type is anonymous or mapped to a fundamental - // C++ type then we don't need to do anything. + // If this element's type is anonymous then we don't need to do + // anything. // - Boolean poly (!fund && polymorphic && - !type.context ().count ("anonymous")); + Boolean poly (polymorphic && + polymorphic_p (type) && + !anonymous_p (type)); // To std::ostream. // diff --git a/xsd/cxx/tree/stream-extraction-source.cxx b/xsd/cxx/tree/stream-extraction-source.cxx index c777f30..fe9e31f 100644 --- a/xsd/cxx/tree/stream-extraction-source.cxx +++ b/xsd/cxx/tree/stream-extraction-source.cxx @@ -61,7 +61,7 @@ namespace CXX // Register with type map. // - if (polymorphic && !l.context ().count ("anonymous")) + if (polymorphic && polymorphic_p (l) && !anonymous_p (l)) { // Note that we are using the original type name. // @@ -129,7 +129,7 @@ namespace CXX // Register with type map. // - if (polymorphic && !u.context ().count ("anonymous")) + if (polymorphic && polymorphic_p (u) && !anonymous_p (u)) { // Note that we are using the original type name. // @@ -198,7 +198,7 @@ namespace CXX // Register with type map. // - if (polymorphic && !e.context ().count ("anonymous")) + if (polymorphic && polymorphic_p (e) && !anonymous_p (e)) { // Note that we are using the original type name. // @@ -299,13 +299,12 @@ namespace CXX } // Figure out if we need to generate polymorphic code. If this - // elemen's type is anonymous or mapped to a fundamental C++ - // type then we don't need to do anything. Note that if the type - // is anonymous then it can't be derived from which makes it - // impossible to substitute or dynamically-type with xsi:type. + // elemen's type is anonymous then we don't need to do anything. + // Note that if the type is anonymous then it can't be derived + // from which makes it impossible to substitute or dynamically- + // type with xsi:type. // - Boolean poly (!fund && polymorphic && - !t.context ().count ("anonymous")); + Boolean poly (polymorphic && polymorphic_p (t) && !anonymous_p (t)); if (max (e) != 1) { @@ -632,7 +631,7 @@ namespace CXX // Register with type map. // - if (polymorphic && !c.context ().count ("anonymous")) + if (polymorphic && polymorphic_p (c) && !anonymous_p (c)) { // Note that we are using the original type name. // diff --git a/xsd/cxx/tree/stream-insertion-source.cxx b/xsd/cxx/tree/stream-insertion-source.cxx index d7e721d..ae58dcc 100644 --- a/xsd/cxx/tree/stream-insertion-source.cxx +++ b/xsd/cxx/tree/stream-insertion-source.cxx @@ -60,7 +60,7 @@ namespace CXX // Register with type map. // - if (polymorphic && !l.context ().count ("anonymous")) + if (polymorphic && polymorphic_p (l) && !anonymous_p (l)) { // Note that we are using the original type name. // @@ -128,7 +128,7 @@ namespace CXX // Register with type map. // - if (polymorphic && !u.context ().count ("anonymous")) + if (polymorphic && polymorphic_p (u) && !anonymous_p (u)) { // Note that we are using the original type name. // @@ -187,7 +187,7 @@ namespace CXX // Register with type map. // - if (polymorphic && !e.context ().count ("anonymous")) + if (polymorphic && polymorphic_p (e) && !anonymous_p (e)) { // Note that we are using the original type name. // @@ -228,20 +228,12 @@ namespace CXX String type (scope + L"::" + etype (e)); // Figure out if we need to generate polymorphic code. If this - // elemen's type is anonymous or mapped to a fundamental C++ - // type then we don't need to do anything. Note that if the type - // is anonymous then it can't be derived from which makes it - // impossible to substitute or dynamically-type with xsi:type. + // elemen's type is anonymous then we don't need to do anything. + // Note that if the type is anonymous then it can't be derived + // from which makes it impossible to substitute or dynamically- + // type with xsi:type. // - Boolean poly (polymorphic && !t.context ().count ("anonymous")); - - if (poly) - { - Boolean fund (false); - IsFundamentalType traverser (fund); - traverser.dispatch (t); - poly = !fund; - } + Boolean poly (polymorphic && polymorphic_p (t) && !anonymous_p (t)); if (max (e) != 1) { @@ -416,7 +408,7 @@ namespace CXX // Register with type map. // - if (polymorphic && !c.context ().count ("anonymous")) + if (polymorphic && polymorphic_p (c) && !anonymous_p (c)) { // Note that we are using the original type name. // diff --git a/xsd/cxx/tree/stream-source.cxx b/xsd/cxx/tree/stream-source.cxx index a93d49e..c663158 100644 --- a/xsd/cxx/tree/stream-source.cxx +++ b/xsd/cxx/tree/stream-source.cxx @@ -52,7 +52,7 @@ namespace CXX // Register with ostream map. // - if (polymorphic && !l.context ().count ("anonymous")) + if (polymorphic && polymorphic_p (l) && !anonymous_p (l)) { // Note that we are using the original type name. // @@ -107,7 +107,7 @@ namespace CXX // Register with ostream map. // - if (polymorphic && !u.context ().count ("anonymous")) + if (polymorphic && polymorphic_p (u) && !anonymous_p (u)) { // Note that we are using the original type name. // @@ -185,7 +185,7 @@ namespace CXX // Register with ostream map. // - if (polymorphic && !e.context ().count ("anonymous")) + if (polymorphic && polymorphic_p (e) && !anonymous_p (e)) { // Note that we are using the original type name. // @@ -220,21 +220,13 @@ namespace CXX String const& aname (eaname (e)); // Check if we need to handle xsi:type and substitution groups. - // If this element's type is anonymous or mapped to a fundamental - // C++ type then we don't need to do anything. Note that if the - // type is anonymous then it can't be derived from which makes it - // impossible to substitute or dynamically-type with xsi:type. + // If this element's type is anonymous then we don't need to do + // anything. Note that if the type is anonymous then it can't be + // derived from which makes it impossible to substitute or + // dynamically-type with xsi:type. // SemanticGraph::Type& t (e.type ()); - Boolean poly (polymorphic && !t.context ().count ("anonymous")); - - if (poly) - { - Boolean fund (false); - IsFundamentalType traverser (fund); - traverser.dispatch (t); - poly = !fund; - } + Boolean poly (polymorphic && polymorphic_p (t) && !anonymous_p (t)); // aCC cannot handle an inline call to std_ostream_map_instance. // @@ -388,7 +380,7 @@ namespace CXX // Register with ostream map. // - if (polymorphic && !c.context ().count ("anonymous")) + if (polymorphic && polymorphic_p (c) && !anonymous_p (c)) { // Note that we are using the original type name. // diff --git a/xsd/cxx/tree/tree-header.cxx b/xsd/cxx/tree/tree-header.cxx index fa5820d..7e884c8 100644 --- a/xsd/cxx/tree/tree-header.cxx +++ b/xsd/cxx/tree/tree-header.cxx @@ -2389,13 +2389,13 @@ namespace CXX } Boolean has_complex_non_op_args (false); - Boolean has_non_fund_non_op_args (false); - Boolean complex_non_fund_args_clash (true); + Boolean has_poly_non_op_args (false); + Boolean complex_poly_args_clash (true); { - HasComplexNonFundNonOptArgs t (*this, true, - has_complex_non_op_args, - has_non_fund_non_op_args, - complex_non_fund_args_clash); + HasComplexPolyNonOptArgs t (*this, true, + has_complex_non_op_args, + has_poly_non_op_args, + complex_poly_args_clash); t.traverse (c); } @@ -2450,13 +2450,13 @@ namespace CXX if (generate) { Boolean has_complex_non_op_args (false); - Boolean has_non_fund_non_op_args (false); - Boolean complex_non_fund_args_clash (true); + Boolean has_poly_non_op_args (false); + Boolean complex_poly_args_clash (true); { - HasComplexNonFundNonOptArgs t (*this, false, - has_complex_non_op_args, - has_non_fund_non_op_args, - complex_non_fund_args_clash); + HasComplexPolyNonOptArgs t (*this, false, + has_complex_non_op_args, + has_poly_non_op_args, + complex_poly_args_clash); t.traverse (c); } @@ -2517,10 +2517,10 @@ namespace CXX } // If we are generating polymorphic code then we also need to - // provide auto_ptr version for every non-fundamental type. + // provide auto_ptr version for every polymorphic type. // if (polymorphic && - has_non_fund_non_op_args && !complex_non_fund_args_clash) + has_poly_non_op_args && !complex_poly_args_clash) { if (doxygen) { @@ -2542,7 +2542,7 @@ namespace CXX os << "&"; { FromBaseCtorArg args ( - *this, FromBaseCtorArg::arg_non_fund_auto_ptr, false); + *this, FromBaseCtorArg::arg_poly_auto_ptr, false); Traversal::Names args_names (args); names (c, args_names); } @@ -2605,10 +2605,10 @@ namespace CXX } // If we are generating polymorphic code then we also need to - // provide auto_ptr version for every non-fundamental type. + // provide auto_ptr version for every polymorphic type. // if (polymorphic && - has_non_fund_non_op_args && !complex_non_fund_args_clash) + has_poly_non_op_args && !complex_poly_args_clash) { if (doxygen) { @@ -2626,7 +2626,7 @@ namespace CXX os << name << " ("; { CtorArgsWithoutBase ctor_args ( - *this, CtorArgsWithoutBase::arg_non_fund_auto_ptr, false, true); + *this, CtorArgsWithoutBase::arg_poly_auto_ptr, false, true); ctor_args.dispatch (c); } os << ");" @@ -2763,10 +2763,9 @@ namespace CXX } // If we are generating polymorphic code then we also need to - // provide auto_ptr version for every non-fundamental type. + // provide auto_ptr version for every polymorphic type. // - if (polymorphic && - has_non_fund_non_op_args && !complex_non_fund_args_clash) + if (polymorphic && has_poly_non_op_args && !complex_poly_args_clash) { if (doxygen) { @@ -2786,7 +2785,7 @@ namespace CXX os << name << " ("; { - CtorArgs ctor_args (*this, CtorArgs::arg_non_fund_auto_ptr); + CtorArgs ctor_args (*this, CtorArgs::arg_poly_auto_ptr); ctor_args.dispatch (c); } @@ -3341,11 +3340,9 @@ namespace CXX // If the element value is a complex type (has elements, // attributes, or wildcards) then also generate the auto_ptr // version. If we are generating polymorphic code then we - // also need to provide auto_ptr version for simple, non- - // fundamental values. + // also need to provide auto_ptr version for simple types. // - // - if (!simple || (polymorphic && !fund)) + if (!simple || (polymorphic && polymorphic_p (t))) { if (doxygen) { diff --git a/xsd/cxx/tree/tree-source.cxx b/xsd/cxx/tree/tree-source.cxx index 8c70f23..3f902e7 100644 --- a/xsd/cxx/tree/tree-source.cxx +++ b/xsd/cxx/tree/tree-source.cxx @@ -105,7 +105,7 @@ namespace CXX // Register with type factory map. // - if (polymorphic && !l.context ().count ("anonymous")) + if (polymorphic && polymorphic_p (l) && !anonymous_p (l)) { // Note that we are using the original type name. // @@ -212,7 +212,7 @@ namespace CXX // Register with type factory map. // - if (polymorphic && !u.context ().count ("anonymous")) + if (polymorphic && polymorphic_p (u) && !anonymous_p (u)) { // Note that we are using the original type name. // @@ -504,7 +504,7 @@ namespace CXX // Register with type factory map. // - if (polymorphic && !e.context ().count ("anonymous")) + if (polymorphic && polymorphic_p (e) && !anonymous_p (e)) { // Note that we are using the original type name. // @@ -672,23 +672,21 @@ namespace CXX String tr (etraits (e)); // traits type name String type (etype (e)); - // Check if we need to handle xsi:type and substitution groups. - // If this element's type is anonymous or mapped to a fundamental - // C++ type then we don't need to do anything. Note that if the - // type is anonymous then it can't be derived from which makes it - // impossible to substitute or dynamically-type with xsi:type. - // SemanticGraph::Type& t (e.type ()); - Boolean fund (false); { IsFundamentalType traverser (fund); traverser.dispatch (t); } - Boolean poly ( - !fund && polymorphic && !t.context ().count ("anonymous")); + // Check if we need to handle xsi:type and substitution groups. + // If this element's type is anonymous then we don't need to do + // anything. Note that if the type is anonymous then it can't be + // derived from which makes it impossible to substitute or + // dynamically-type with xsi:type. + // + Boolean poly (polymorphic && polymorphic_p (t) && !anonymous_p (t)); os << "// " << comment (e.name ()) << endl << "//" << endl; @@ -1802,21 +1800,13 @@ namespace CXX String const& aname (eaname (e)); // Check if we need to handle xsi:type and substitution groups. - // If this element's type is anonymous or mapped to a fundamental - // C++ type then we don't need to do anything. Note that if the - // type is anonymous then it can't be derived from which makes it - // impossible to substitute or dynamically-type with xsi:type. + // If this element's type is anonymous then we don't need to do + // anything. Note that if the type is anonymous then it can't be + // derived from which makes it impossible to substitute or + // dynamically-type with xsi:type. // SemanticGraph::Type& t (e.type ()); - Boolean poly (polymorphic && !t.context ().count ("anonymous")); - - if (poly) - { - Boolean fund (false); - IsFundamentalType traverser (fund); - traverser.dispatch (t); - poly = !fund; - } + Boolean poly (polymorphic && polymorphic_p (t) && !anonymous_p (t)); if (!poly) { @@ -2221,13 +2211,13 @@ namespace CXX } Boolean has_complex_non_op_args (false); - Boolean has_non_fund_non_op_args (false); - Boolean complex_non_fund_args_clash (true); + Boolean has_poly_non_op_args (false); + Boolean complex_poly_args_clash (true); { - HasComplexNonFundNonOptArgs t (*this, true, - has_complex_non_op_args, - has_non_fund_non_op_args, - complex_non_fund_args_clash); + HasComplexPolyNonOptArgs t (*this, true, + has_complex_non_op_args, + has_poly_non_op_args, + complex_poly_args_clash); t.traverse (c); } @@ -2277,13 +2267,13 @@ namespace CXX if (generate) { Boolean has_complex_non_op_args (false); - Boolean has_non_fund_non_op_args (false); - Boolean complex_non_fund_args_clash (true); + Boolean has_poly_non_op_args (false); + Boolean complex_poly_args_clash (true); { - HasComplexNonFundNonOptArgs t (*this, false, - has_complex_non_op_args, - has_non_fund_non_op_args, - complex_non_fund_args_clash); + HasComplexPolyNonOptArgs t (*this, false, + has_complex_non_op_args, + has_poly_non_op_args, + complex_poly_args_clash); t.traverse (c); } @@ -2352,11 +2342,10 @@ namespace CXX } // If we are generating polymorphic code then we also need to - // provide auto_ptr version for every non-fundamental type. + // provide auto_ptr version for every polymorphic type. // - if (has_non_fund_non_op_args && - !complex_non_fund_args_clash && - polymorphic) + if (polymorphic && + has_poly_non_op_args && !complex_poly_args_clash) { os << name << "::" << endl << name << " (const "; @@ -2364,7 +2353,7 @@ namespace CXX os << "& " << base_arg; { FromBaseCtorArg args ( - *this, FromBaseCtorArg::arg_non_fund_auto_ptr, true); + *this, FromBaseCtorArg::arg_poly_auto_ptr, true); Traversal::Names args_names (args); names (c, args_names); } @@ -2465,17 +2454,16 @@ namespace CXX } // If we are generating polymorphic code then we also need to - // provide auto_ptr version for every non-fundamental type. + // provide auto_ptr version for every polymorphic type. // - if (has_non_fund_non_op_args && - !complex_non_fund_args_clash && - polymorphic) + if (polymorphic && + has_poly_non_op_args && !complex_poly_args_clash) { os << name << "::" << endl << name << " ("; { CtorArgsWithoutBase ctor_args ( - *this, CtorArgsWithoutBase::arg_non_fund_auto_ptr, true, true); + *this, CtorArgsWithoutBase::arg_poly_auto_ptr, true, true); ctor_args.dispatch (c); } os << ")" << endl @@ -2716,11 +2704,10 @@ namespace CXX } // If we are generating polymorphic code then we also need to - // provide auto_ptr version for every non-fundamental type. + // provide auto_ptr version for every polymorphic type. // - if (has_non_fund_non_op_args && - !complex_non_fund_args_clash && - polymorphic) + if (polymorphic && + has_poly_non_op_args && !complex_poly_args_clash) { os << name << "::" << endl << name << " ("; @@ -2729,7 +2716,7 @@ namespace CXX { CtorArgs ctor_args ( - *this, CtorArgs::arg_non_fund_auto_ptr, base_arg); + *this, CtorArgs::arg_poly_auto_ptr, base_arg); ctor_args.dispatch (c); } @@ -3001,7 +2988,7 @@ namespace CXX // Register with type factory map. // - if (polymorphic && !c.context ().count ("anonymous")) + if (polymorphic && polymorphic_p (c) && !anonymous_p (c)) { // Note that we are using the original type name. // @@ -3201,7 +3188,7 @@ namespace CXX // c-tor (auto_ptr) // - if (!simple || (polymorphic && !fund)) + if (!simple || (polymorphic && polymorphic_p (t))) { os << name << "::" << endl << name << " (::std::auto_ptr< " << type << " > p)" << endl diff --git a/xsd/cxx/tree/validator.cxx b/xsd/cxx/tree/validator.cxx index 1f05e65..32dee69 100644 --- a/xsd/cxx/tree/validator.cxx +++ b/xsd/cxx/tree/validator.cxx @@ -672,6 +672,9 @@ namespace CXX } return valid; + + // T005 is used in polymorphism-processor.cxx. + // } } } diff --git a/xsd/makefile b/xsd/makefile index 8ff41ed..cc04568 100644 --- a/xsd/makefile +++ b/xsd/makefile @@ -31,6 +31,7 @@ cxx_tun += cxx/tree/elements.cxx \ cxx/tree/validator.cxx \ cxx/tree/counter.cxx \ cxx/tree/name-processor.cxx \ + cxx/tree/polymorphism-processor.cxx \ cxx/tree/default-value.cxx \ cxx/tree/generator.cxx \ cxx/tree/tree-forward.cxx \ -- cgit v1.1