summaryrefslogtreecommitdiff
path: root/cpp
diff options
context:
space:
mode:
Diffstat (limited to 'cpp')
-rw-r--r--cpp/include/Slice/Parser.h22
-rw-r--r--cpp/src/Slice/Grammar.y1
-rw-r--r--cpp/src/Slice/Parser.cpp140
-rw-r--r--cpp/src/Slice/Scanner.l35
-rw-r--r--cpp/test/Slice/errorDetection/CaseInsensitive.err17
-rw-r--r--cpp/test/Slice/errorDetection/CaseInsensitive.ice25
-rw-r--r--cpp/test/Slice/errorDetection/DerivedRedefinition.err2
-rw-r--r--cpp/test/Slice/errorDetection/IllegalMI.err42
8 files changed, 159 insertions, 125 deletions
diff --git a/cpp/include/Slice/Parser.h b/cpp/include/Slice/Parser.h
index 63f40f00909..98a1b7cf577 100644
--- a/cpp/include/Slice/Parser.h
+++ b/cpp/include/Slice/Parser.h
@@ -53,6 +53,7 @@ class Dictionary;
class Enum;
class Enumerator;
class Unit;
+class CICompare;
typedef ::IceUtil::Handle<GrammarBase> GrammarBasePtr;
typedef ::IceUtil::Handle<SyntaxTreeBase> SyntaxTreeBasePtr;
@@ -114,9 +115,6 @@ typedef std::list<ContainedPtr> ContainedList;
typedef std::list<ModulePtr> ModuleList;
typedef std::list<ConstructedPtr> ConstructedList;
typedef std::list<ClassDefPtr> ClassList;
-typedef std::list<ClassList> GraphPartitionList; // TODO: ML: Can't this be a private typedef for Container?
-typedef std::set<std::string> StringSet;
-typedef std::list<StringSet> StringSetList;
typedef std::list<ExceptionPtr> ExceptionList;
typedef std::list<StructPtr> StructList;
typedef std::list<SequencePtr> SequenceList;
@@ -331,12 +329,15 @@ protected:
private:
+ typedef std::list<ClassList> GraphPartitionList;
+ typedef std::list<StringList> StringPartitionList;
+
bool isInList(const GraphPartitionList&, const ClassDefPtr) const;
void addPartition(GraphPartitionList&,
GraphPartitionList::reverse_iterator,
const ClassDefPtr) const;
- StringSetList toStringSetList(const GraphPartitionList&) const;
- StringList unionOfAllPairIntersections(const StringSetList&) const;
+ StringPartitionList toStringPartitionList(const GraphPartitionList&) const;
+ void checkPairIntersections(const StringPartitionList&, const std::string&) const;
};
// ----------------------------------------------------------------------
@@ -732,6 +733,17 @@ private:
extern SLICE_API Unit* unit; // The current parser for bison/flex
+// ----------------------------------------------------------------------
+// CICompare -- function object to do case-insensitive string comparison.
+// ----------------------------------------------------------------------
+
+class CICompare : public std::binary_function<std::string, std::string, bool>
+{
+public:
+
+ bool operator()(const std::string&, const std::string&) const;
+};
+
}
#endif
diff --git a/cpp/src/Slice/Grammar.y b/cpp/src/Slice/Grammar.y
index a174999bff9..0a04428c39c 100644
--- a/cpp/src/Slice/Grammar.y
+++ b/cpp/src/Slice/Grammar.y
@@ -797,6 +797,7 @@ exception
// ML: Not sure if these should be treated as builtin by the
// parser. They have no meaning in a Slice definition, so why make
// them builtin, if they cannot be used anywhere in Slice?
+// MH: Agree -- I don't think anything needs doing here.
: scoped_name
{
StringTokPtr scoped = StringTokPtr::dynamicCast($1);
diff --git a/cpp/src/Slice/Parser.cpp b/cpp/src/Slice/Parser.cpp
index 838a56c338e..da052a6aa36 100644
--- a/cpp/src/Slice/Parser.cpp
+++ b/cpp/src/Slice/Parser.cpp
@@ -326,31 +326,14 @@ Slice::Container::createClassDef(const string& name, bool intf, const ClassList&
// set containing the names of operations and data members defined in
// the classes in each partition.
//
- StringSetList spl = toStringSetList(gpl);
+ StringPartitionList spl = toStringPartitionList(gpl);
//
// Multiple inheritance is legal if no two partitions contain a common
// name (that is, if the union of the intersections of all possible pairs
- // of partitions is empty.
- //
- StringList clashes = unionOfAllPairIntersections(spl);
-
- //
- // The strings in the clashes list are those operations or data members
- // that prevent the multiple inheritance hierarchies about to the
- // current class to be joined.
- //
- for(StringList::const_iterator q = clashes.begin(); q != clashes.end(); ++q)
- {
- string msg = "ambiguous multiple inheritance: `";
- msg += *q + "' is defined in two or more base classes";
- _unit->error(msg);
- }
- //
- // We do *not* return 0 here; otherwise, we get lots of spurious
- // "Parse error" messsages and end up with lots of follow-up errors
- // about this class not being defined.
+ // of partitions is empty).
//
+ checkPairIntersections(spl, name);
}
ClassDefPtr def = new ClassDef(this, name, intf, bases, local);
@@ -1347,28 +1330,23 @@ Slice::Container::addPartition(GraphPartitionList& gpl,
//
// Convert the list of partitions of class definitions into a
-// list of sets, with each set containing the operation and member
-// names defined by the classes in each partition.
+// list of lists, with each member list containing the operation
+// names defined by the interfaces in each partition.
//
-StringSetList
-Slice::Container::toStringSetList(const GraphPartitionList& gpl) const
+Slice::Container::StringPartitionList
+Slice::Container::toStringPartitionList(const GraphPartitionList& gpl) const
{
- StringSetList spl;
+ StringPartitionList spl;
for(GraphPartitionList::const_iterator i = gpl.begin(); i != gpl.end(); ++i)
{
- StringSet ss;
- spl.push_back(ss);
+ StringList sl;
+ spl.push_back(sl);
for(ClassList::const_iterator j = i->begin(); j != i->end(); ++j)
{
OperationList operations = (*j)->operations();
- DataMemberList members = (*j)->dataMembers();
for(OperationList::const_iterator l = operations.begin(); l != operations.end(); ++l)
{
- spl.rbegin()->insert((*l)->name());
- }
- for(DataMemberList::const_iterator m = members.begin(); m != members.end(); ++m)
- {
- spl.rbegin()->insert((*m)->name());
+ spl.rbegin()->push_back((*l)->name());
}
}
}
@@ -1376,24 +1354,44 @@ Slice::Container::toStringSetList(const GraphPartitionList& gpl) const
}
//
-// Return the union of the intersections of all possible pairs of sets of strings.
+// For all (unique) pairs of string lists, check whether an identifier in one list occurs
+// in the other and, if so, complain.
//
-StringList
-Slice::Container::unionOfAllPairIntersections(const StringSetList& l) const
+void
+Slice::Container::checkPairIntersections(const StringPartitionList& l, const string& name) const
{
- StringList result;
- for(StringSetList::const_iterator i = l.begin(); i != l.end(); ++i)
+ set<string> reported;
+ for(StringPartitionList::const_iterator i = l.begin(); i != l.end(); ++i)
{
- StringSetList::const_iterator cursor = i;
+ StringPartitionList::const_iterator cursor = i;
++cursor;
- for(StringSetList::const_iterator j = cursor; j != l.end(); ++j)
+ for(StringPartitionList::const_iterator j = cursor; j != l.end(); ++j)
{
- set_intersection(i->begin(), i->end(), j->begin(), j->end(), back_inserter(result));
+ for(StringList::const_iterator s1 = i->begin(); s1 != i->end(); ++s1)
+ {
+ for (StringList::const_iterator s2 = j->begin(); s2 != j->end(); ++s2)
+ {
+ if((*s1) == (*s2) && reported.find(*s1) == reported.end())
+ {
+ string msg = "ambiguous multiple inheritance: `" + name;
+ msg += "' inherits operation `" + *s1 + "' from two or more unrelated base interfaces";
+ _unit->error(msg);
+ reported.insert(*s1);
+ }
+ else if(!CICompare()(*s1, *s2) && !CICompare()(*s2, *s1) &&
+ reported.find(*s1) == reported.end() && reported.find(*s2) == reported.end())
+ {
+ string msg = "ambiguous multiple inheritance: `" + name;
+ msg += "' inherits operations `" + *s1 + "' and `" + *s2;
+ msg += "', which differ only in capitalization, from unrelated base interfaces";
+ _unit->error(msg);
+ reported.insert(*s1);
+ reported.insert(*s2);
+ }
+ }
+ }
}
}
- result.sort();
- result.unique();
- return result;
}
// ----------------------------------------------------------------------
@@ -1412,7 +1410,7 @@ Slice::Module::uses(const ContainedPtr&) const
return false;
}
-std::string
+string
Slice::Module::kindOf() const
{
return "module";
@@ -1501,7 +1499,7 @@ Slice::ClassDecl::uses(const ContainedPtr&) const
return false;
}
-std::string
+string
Slice::ClassDecl::kindOf() const
{
string s = _interface ? "interface" : "class";
@@ -1927,7 +1925,7 @@ Slice::ClassDef::uses(const ContainedPtr&) const
return false;
}
-std::string
+string
Slice::ClassDef::kindOf() const
{
string s;
@@ -2142,7 +2140,7 @@ Slice::Exception::uses(const ContainedPtr&) const
return false;
}
-std::string
+string
Slice::Exception::kindOf() const
{
return "exception";
@@ -2268,7 +2266,7 @@ Slice::Struct::uses(const ContainedPtr&) const
return false;
}
-std::string
+string
Slice::Struct::kindOf() const
{
return "struct";
@@ -2332,7 +2330,7 @@ Slice::Sequence::uses(const ContainedPtr& contained) const
return false;
}
-std::string
+string
Slice::Sequence::kindOf() const
{
return "sequence";
@@ -2408,7 +2406,7 @@ Slice::Dictionary::uses(const ContainedPtr& contained) const
return false;
}
-std::string
+string
Slice::Dictionary::kindOf() const
{
return "dictionary";
@@ -2481,7 +2479,7 @@ Slice::Enum::uses(const ContainedPtr&) const
return false;
}
-std::string
+string
Slice::Enum::kindOf() const
{
return "enumeration";
@@ -2523,7 +2521,7 @@ Slice::Enumerator::uses(const ContainedPtr&) const
return false;
}
-std::string
+string
Slice::Enumerator::kindOf() const
{
return "enumerator";
@@ -2614,7 +2612,7 @@ Slice::Operation::uses(const ContainedPtr& contained) const
return false;
}
-std::string
+string
Slice::Operation::kindOf() const
{
return "operation";
@@ -2666,7 +2664,7 @@ Slice::DataMember::uses(const ContainedPtr& contained) const
return false;
}
-std::string
+string
Slice::DataMember::kindOf() const
{
return "data member";
@@ -3151,3 +3149,35 @@ Slice::Unit::Unit(bool ignRedefs, bool all) :
{
_unit = this;
}
+
+// ----------------------------------------------------------------------
+// CICompare
+// ----------------------------------------------------------------------
+
+bool
+Slice::CICompare::operator()(const string& s1, const string& s2) const
+{
+ string::const_iterator p1 = s1.begin();
+ string::const_iterator p2 = s2.begin();
+ while(p1 != s1.end() && p2 != s2.end() && tolower(*p1) == tolower(*p2))
+ {
+ ++p1;
+ ++p2;
+ }
+ if(p1 == s1.end() && p2 == s2.end())
+ {
+ return false;
+ }
+ else if(p1 == s1.end())
+ {
+ return true;
+ }
+ else if(p2 == s2.end())
+ {
+ return false;
+ }
+ else
+ {
+ return tolower(*p1) < tolower(*p2);
+ }
+};
diff --git a/cpp/src/Slice/Scanner.l b/cpp/src/Slice/Scanner.l
index f37fbc5a00b..0e0b878b21a 100644
--- a/cpp/src/Slice/Scanner.l
+++ b/cpp/src/Slice/Scanner.l
@@ -20,42 +20,9 @@ namespace Slice
{
//
-// Function object to do case-insensitive string comparison.
-//
-struct CICompare : public std::binary_function<std::string, std::string, bool>
-{
- bool operator()(const std::string& s1, const std::string& s2) const
- {
- std::string::const_iterator p1 = s1.begin();
- std::string::const_iterator p2 = s2.begin();
- while(p1 != s1.end() && p2 != s2.end() && tolower(*p1) == tolower(*p2))
- {
- ++p1;
- ++p2;
- }
- if(p1 == s1.end() && p2 == s2.end())
- {
- return false;
- }
- else if(p1 == s1.end())
- {
- return true;
- }
- else if(p2 == s2.end())
- {
- return false;
- }
- else
- {
- return tolower(*p1) < tolower(*p2);
- }
- }
-};
-
-//
// Definitions for the case-insensitive keyword-token map.
//
-typedef std::map<std::string, int, CICompare> StringTokenMap;
+typedef std::map<std::string, int, Slice::CICompare> StringTokenMap;
static StringTokenMap keywordMap;
void Slice::initScanner();
diff --git a/cpp/test/Slice/errorDetection/CaseInsensitive.err b/cpp/test/Slice/errorDetection/CaseInsensitive.err
index 3ddfd52ac60..79b565554f1 100644
--- a/cpp/test/Slice/errorDetection/CaseInsensitive.err
+++ b/cpp/test/Slice/errorDetection/CaseInsensitive.err
@@ -44,10 +44,13 @@ CaseInsensitive.ice:157: redefinition of enumeration `en1' as enumerator
CaseInsensitive.ice:158: warning: enumerator `EN1' differs only in capitalization from enumeration `en1'
CaseInsensitive.ice:159: redefinition of module `m1' as enumerator
CaseInsensitive.ice:160: warning: enumerator `M1' differs only in capitalization from module `m1'
-CaseInsensitive.ice:170: warning: type name `base' is capitalized inconsistently with its previous name: `::xxx::xx::Base'
-CaseInsensitive.ice:170: redefinition of interface `Derived'
-CaseInsensitive.ice:174: warning: exception name `E1' is capitalized inconsistently with its previous name: `::xxx::xx::e1'
-CaseInsensitive.ice:178: warning: type name `S1' is capitalized inconsistently with its previous name: `::xxx::xx::s1'
-CaseInsensitive.ice:179: `xx::S1' is not defined
-CaseInsensitive.ice:180: warning: type name `XX::s1' is capitalized inconsistently with its previous name: `::xxx::xx::s1'
-CaseInsensitive.ice:185: warning: type name `derived' is capitalized inconsistently with its previous name: `::xxx::xx::Derived'
+CaseInsensitive.ice:172: warning: type name `base' is capitalized inconsistently with its previous name: `::xxx::xx::Base'
+CaseInsensitive.ice:172: redefinition of interface `Derived'
+CaseInsensitive.ice:176: warning: exception name `E1' is capitalized inconsistently with its previous name: `::xxx::xx::e1'
+CaseInsensitive.ice:180: warning: type name `S1' is capitalized inconsistently with its previous name: `::xxx::xx::s1'
+CaseInsensitive.ice:181: `xx::S1' is not defined
+CaseInsensitive.ice:182: warning: type name `XX::s1' is capitalized inconsistently with its previous name: `::xxx::xx::s1'
+CaseInsensitive.ice:187: warning: type name `derived' is capitalized inconsistently with its previous name: `::xxx::xx::Derived'
+CaseInsensitive.ice:195: warning: parameter `param' differs only in capitalization from parameter `Param'
+CaseInsensitive.ice:197: warning: exception name `E1' is capitalized inconsistently with its previous name: `::e1'
+CaseInsensitive.ice:210: ambiguous multiple inheritance: `derived' inherits operations `op' and `OP', which differ only in capitalization, from unrelated base interfaces
diff --git a/cpp/test/Slice/errorDetection/CaseInsensitive.ice b/cpp/test/Slice/errorDetection/CaseInsensitive.ice
index 7330da156ea..8647c3a6125 100644
--- a/cpp/test/Slice/errorDetection/CaseInsensitive.ice
+++ b/cpp/test/Slice/errorDetection/CaseInsensitive.ice
@@ -159,9 +159,11 @@ enum en3 { EN1 };
enum en4 { m1 };
enum en5 { M1 };
-module xxx {
+module xxx
+{
-module xx {
+module xx
+{
interface Base { void op(); };
@@ -188,3 +190,22 @@ struct s2 {
};
};
+
+interface Foo {
+ void op(long param, string Param);
+ void op2() throws e1;
+ void op3() throws E1;
+};
+
+module CI
+{
+ interface base1 {
+ void op();
+ };
+
+ interface base2 {
+ void OP();
+ };
+
+ interface derived extends base1, base2 {};
+};
diff --git a/cpp/test/Slice/errorDetection/DerivedRedefinition.err b/cpp/test/Slice/errorDetection/DerivedRedefinition.err
index 7d1ebbb7e61..3d0e0e7d1d4 100644
--- a/cpp/test/Slice/errorDetection/DerivedRedefinition.err
+++ b/cpp/test/Slice/errorDetection/DerivedRedefinition.err
@@ -1,6 +1,6 @@
DerivedRedefinition.ice:17: operation `op' is already defined as an operation in a base interface or class
DerivedRedefinition.ice:18: operation `op' is already defined as an operation in a base interface or class
DerivedRedefinition.ice:31: operation `op' is already defined as an operation in a base interface or class
-DerivedRedefinition.ice:34: ambiguous multiple inheritance: `op' is defined in two or more base classes
+DerivedRedefinition.ice:34: ambiguous multiple inheritance: `D3' inherits operation `op' from two or more unrelated base interfaces
DerivedRedefinition.ice:39: data member `l' is already defined as a data member in a base interface or class
DerivedRedefinition.ice:41: data member `l' is already defined as a data member in a base interface or class
diff --git a/cpp/test/Slice/errorDetection/IllegalMI.err b/cpp/test/Slice/errorDetection/IllegalMI.err
index 1dc9b23f572..c88c80811fd 100644
--- a/cpp/test/Slice/errorDetection/IllegalMI.err
+++ b/cpp/test/Slice/errorDetection/IllegalMI.err
@@ -1,26 +1,26 @@
-IllegalMI.ice:46: ambiguous multiple inheritance: `op' is defined in two or more base classes
+IllegalMI.ice:46: ambiguous multiple inheritance: `A3' inherits operation `op' from two or more unrelated base interfaces
IllegalMI.ice:69: operation `op' is already defined as an operation in a base interface or class
IllegalMI.ice:91: operation `op' is already defined as an operation in a base interface or class
IllegalMI.ice:113: operation `op' is already defined as an operation in a base interface or class
-IllegalMI.ice:154: ambiguous multiple inheritance: `op' is defined in two or more base classes
-IllegalMI.ice:176: ambiguous multiple inheritance: `op' is defined in two or more base classes
-IllegalMI.ice:198: ambiguous multiple inheritance: `op' is defined in two or more base classes
-IllegalMI.ice:221: ambiguous multiple inheritance: `op' is defined in two or more base classes
-IllegalMI.ice:271: ambiguous multiple inheritance: `op' is defined in two or more base classes
-IllegalMI.ice:297: ambiguous multiple inheritance: `op' is defined in two or more base classes
-IllegalMI.ice:323: ambiguous multiple inheritance: `op' is defined in two or more base classes
-IllegalMI.ice:349: ambiguous multiple inheritance: `op' is defined in two or more base classes
-IllegalMI.ice:375: ambiguous multiple inheritance: `op' is defined in two or more base classes
-IllegalMI.ice:401: ambiguous multiple inheritance: `op' is defined in two or more base classes
-IllegalMI.ice:428: ambiguous multiple inheritance: `op' is defined in two or more base classes
-IllegalMI.ice:455: ambiguous multiple inheritance: `op' is defined in two or more base classes
-IllegalMI.ice:482: ambiguous multiple inheritance: `op' is defined in two or more base classes
-IllegalMI.ice:509: ambiguous multiple inheritance: `op' is defined in two or more base classes
-IllegalMI.ice:537: ambiguous multiple inheritance: `op' is defined in two or more base classes
+IllegalMI.ice:154: ambiguous multiple inheritance: `A2' inherits operation `op' from two or more unrelated base interfaces
+IllegalMI.ice:176: ambiguous multiple inheritance: `A2' inherits operation `op' from two or more unrelated base interfaces
+IllegalMI.ice:198: ambiguous multiple inheritance: `A2' inherits operation `op' from two or more unrelated base interfaces
+IllegalMI.ice:221: ambiguous multiple inheritance: `A2' inherits operation `op' from two or more unrelated base interfaces
+IllegalMI.ice:271: ambiguous multiple inheritance: `A2' inherits operation `op' from two or more unrelated base interfaces
+IllegalMI.ice:297: ambiguous multiple inheritance: `A2' inherits operation `op' from two or more unrelated base interfaces
+IllegalMI.ice:323: ambiguous multiple inheritance: `A2' inherits operation `op' from two or more unrelated base interfaces
+IllegalMI.ice:349: ambiguous multiple inheritance: `A2' inherits operation `op' from two or more unrelated base interfaces
+IllegalMI.ice:375: ambiguous multiple inheritance: `A2' inherits operation `op' from two or more unrelated base interfaces
+IllegalMI.ice:401: ambiguous multiple inheritance: `A2' inherits operation `op' from two or more unrelated base interfaces
+IllegalMI.ice:428: ambiguous multiple inheritance: `A2' inherits operation `op' from two or more unrelated base interfaces
+IllegalMI.ice:455: ambiguous multiple inheritance: `A2' inherits operation `op' from two or more unrelated base interfaces
+IllegalMI.ice:482: ambiguous multiple inheritance: `A2' inherits operation `op' from two or more unrelated base interfaces
+IllegalMI.ice:509: ambiguous multiple inheritance: `A2' inherits operation `op' from two or more unrelated base interfaces
+IllegalMI.ice:537: ambiguous multiple inheritance: `A2' inherits operation `op' from two or more unrelated base interfaces
IllegalMI.ice:604: operation `op' is already defined as an operation in a base interface or class
IllegalMI.ice:638: operation `op' is already defined as an operation in a base interface or class
-IllegalMI.ice:759: ambiguous multiple inheritance: `op' is defined in two or more base classes
-IllegalMI.ice:820: ambiguous multiple inheritance: `op' is defined in two or more base classes
-IllegalMI.ice:881: ambiguous multiple inheritance: `op' is defined in two or more base classes
-IllegalMI.ice:940: ambiguous multiple inheritance: `op' is defined in two or more base classes
-IllegalMI.ice:999: ambiguous multiple inheritance: `op' is defined in two or more base classes
+IllegalMI.ice:759: ambiguous multiple inheritance: `A4' inherits operation `op' from two or more unrelated base interfaces
+IllegalMI.ice:820: ambiguous multiple inheritance: `A4' inherits operation `op' from two or more unrelated base interfaces
+IllegalMI.ice:881: ambiguous multiple inheritance: `A4' inherits operation `op' from two or more unrelated base interfaces
+IllegalMI.ice:940: ambiguous multiple inheritance: `A4' inherits operation `op' from two or more unrelated base interfaces
+IllegalMI.ice:999: ambiguous multiple inheritance: `A4' inherits operation `op' from two or more unrelated base interfaces