Where to put exception spec source locations?

Hi,

Where in the AST would be a good home for exception specification source
locations? I store the thrown types in the Type hierarchy, but I
obviously can't do that for source locations.

If it was only functions, I could put them into the FunctionDecl:

void fn() throw(int);

However, what about this function pointer?

void (*fn)() throw(int);

It only has some kind of VarDecl. It would be very weird to extend
VarDecl with source locations for an exception spec, and it wouldn't
work anyway:

void (*fn)(void (*)() throw (int)) throw(int);

What we have here is a pointer to a function that could throw int, and
takes as its only parameter a pointer to a function that could throw
int. One VarDecl for the whole construct, and of course I could extend
it to as many parameters as Clang supports (2^20-1).

I need such source locations to accurately point to the types that are
mismatches. I also need them if I want to point to anything useful when
instantiating a type that has a template parameter in its throw list:

template <typename T> struct X {
  void fn() throw(T); // Obviously, this could just as well be a
function pointer.
};
X<void> x; // Oops, cannot have throw(void) in function type. But where
to point?

Any suggestions?

Sebastian

Where in the AST would be a good home for exception specification source
locations? I store the thrown types in the Type hierarchy, but I
obviously can't do that for source locations.

If it was only functions, I could put them into the FunctionDecl:

void fn() throw(int);

However, what about this function pointer?

void (*fn)() throw(int);

It only has some kind of VarDecl. It would be very weird to extend
VarDecl with source locations for an exception spec, and it wouldn't
work anyway:

void (*fn)(void (*)() throw (int)) throw(int);

What we have here is a pointer to a function that could throw int, and
takes as its only parameter a pointer to a function that could throw
int. One VarDecl for the whole construct, and of course I could extend
it to as many parameters as Clang supports (2^20-1).

Given these examples, I think that the only reasonable answer is to put some SourceLocations into the type system.

I need such source locations to accurately point to the types that are
mismatches. I also need them if I want to point to anything useful when
instantiating a type that has a template parameter in its throw list:

template <typename T> struct X {
void fn() throw(T); // Obviously, this could just as well be a
function pointer.
};
X<void> x; // Oops, cannot have throw(void) in function type. But where
to point?

Any suggestions?

I've actually been planning to add some new sugary Type nodes into the AST that contain SourceLocations, precisely for use in template instantiation. Right now, we provide sub-par location information in diagnostics relating to template instantiation, because we have no SourceLocations in the types. Caveat #1: canonical types should never have source locations. Caveat #2: we don't want to bloat the Type nodes in the common case, so we should only add SourceLocations where we need them to produce good diagnostics, e.g., in dependent types (for template instantiation) and in function types with exception specifications (for the reasons Sebastian mentioned above).

I don't expect to get to adding the new, SourceLocation-improved dependent type nodes for a few weeks, though.

  - Doug