Esempio n. 1
0
// Given declarations d1 and d2, a declaration error occurs when:
//
//    - d2 changes the meaning of the name declared by d1, or if not that, then
//      - d1 and d2 are both objects, or
//      - d1 and d2 are functions that cannot be overloaded, or
//      - d1 and d2 are types having different kinds.
//
// Note that d1 precedes d2 in lexical order.
//
// TODO: Would it make sense to poison the declaration so that it's not
// analyzed in subsequent passes? We could essentially replace the existing
// overload set with one containing a poisoned declaration. Any expression
// that uses that name would have an invalid type. We could then use this
// to list the places where the error affects use.
void
check_declarations(Context& cxt, Decl const& d1, Decl const& d2)
{
  struct fn
  {
    Context& cxt;
    Decl const& d2;
    void operator()(Decl const& d)           { lingo_unhandled(d); }
    void operator()(Object_decl const& d1)   { return check_declarations(cxt, d1, cast_as(d1, d2)); }
    void operator()(Function_decl const& d1) { return check_declarations(cxt, d1, cast_as(d1, d2)); }
    void operator()(Type_decl const& d1)     { return check_declarations(cxt, d1, cast_as(d1, d2)); }
  };
  if (typeid(d1) != typeid(d2)) {
    // TODO: Get the source location right.
    error(cxt, "declaration changes the meaning of '{}'", d1.name());
    note("'{}' previously declared as:", d1.name());
    
    // TODO: Don't print the definition. It's not germaine to
    // the error. If we have source locations, I wonder if we
    // can just point at the line.
    note("{}", d1);
    throw Declaration_error();
  }
  apply(d1, fn{cxt, d2});
}
Esempio n. 2
0
void
check_declarations(Context& cxt, Object_decl const& d1, Object_decl const& d2)
{
  struct fn
  {
    char const* operator()(Decl const& d)          { lingo_unhandled(d); }
    char const* operator()(Variable_decl const& d) { return "variable"; }
    char const* operator()(Field_decl const& d)    { return "member variable"; }
    char const* operator()(Object_parm const& d)   { return "parameter"; }
  };

  error(cxt, "redeclaration of {} with the same name", apply(d1, fn{}));
  throw Declaration_error();
}
Esempio n. 3
0
void
check_declarations(Context& cxt, Type_decl const& d1, Type_decl const& d2)
{
  Type const& t1 = d1.type();
  Type const& t2 = d2.type();
  if (is_different(t1, t2)) {
    // TODO: Get the source location right.
    error(cxt, "declaration of '{}' as a different kind of type", d1.name());
    note("'{}' previously declared as:", d1.name());
    
    // TODO: Don't print the definition. It's not germaine to
    // the error. If we have source locations, I wonder if we
    // can just point at the line.
    note("{}", d1);
    throw Declaration_error();
  }
}
Esempio n. 4
0
// FIXME: Verify this diagnostics.
void
check_declarations(Context& cxt, Type_decl const& d1, Type_decl const& d2)
{
    error(cxt, "declaration of '{}' as a different kind of type", d1.name());
    throw Declaration_error();
}