[cfe-dev] C++ default arguments patch, rework Parse-Sema interaction for function parameters

Doug Gregor doug.gregor at gmail.com
Sun Apr 6 10:24:45 PDT 2008


The attached patch implements support for C++ default arguments, e.g.,

  void g(int x, int y, int z = 0);

The patch does the following:
  - Allows the definition of default arguments for function parameters
(C++ only, of course)
  - Checks that the default arguments are well-formed w.r.t their
parameter type
  - Handles merging of default arguments when merging function declarations
  - Handles calls to functions that use default arguments
  - Introduces parameter names into the "prototype scope" when they
are parsed, rather than waiting for the function definition.

All but the last are relatively straightforward. Up until now,
ParseFunctionDeclarator had a simple notion of a function prototype
scope, but it was never actually used because parameters were never
put into that scope. For example, when parsing

  void f(int x, int y);

the parameters 'x' and 'y' would never be put into the scope of that
function prototype. Parameters were only introduced into the function
scope at definition time, e.g.,

  void f(int x, int y) { /* x and y introduced into scope for the
definition */ }

For default arguments, we need to put these parameters into prototype
scope as soon as we see them, to get the right name-lookup behavior:

  void f(int x, int y = x); // name lookup of 'x' in default argument
of 'y' should refer to the parameter x.

Among other things, this problem means that some ill-formed code will
not be diagnosed because name lookup is wrong, e.g.,

  int x;
  void f(int x, int y = x); // currently, Clang finds ::x.

Interestingly, without support for default arguments, we can still use
C extensions to get different behavior than we'd expect:

  struct S { } s;
  void f(int s, typeof(s) t);

  void g() {  f(1, 2); }

GCC compiles this, because the 's' in typeof(s) refers to the
parameter 's', so the parameter 't' is an int.
Clang currently rejects this, because name lookup of 's' finds the
global struct 's', which isn't compatible with an int.
With this patch, Clang does what GCC does, because we always put
parameters into prototype scope.

Changes to look out for in this patch:
  - Action::ActOnParamDeclaratorType has been replaced with
Action::ActOnParamDeclarator; the latter actually introduces the
parameter into the current scope
  - Action::ActOnParamDefaultArgument handles default arguments; the
C++-specific code for Semi is in the new SemaDeclCXX.cpp
  - The Objective-C Sema code for creating ParmVarDecls has not be
changed to use Sema::ActOnParamDeclarator, because my understanding of
Objective-C is far too weak.

You'll see a few new FIXMEs in this code that I haven't attacked yet.
The most annoying one (for me) is that

  void f(int x, int y = x);

doesn't actually produce an error. We do name lookup of 'x' in the
default argument of 'y' properly, but I don't have a feel for how we
should check that parameter names shall not be used in the default
argument. It could be done "quickly" by adding a flag in the parser
(DontAllowParamIdentifiers) or could be separated from the main flow
by passing over the AST for the default arguments within
Sema::ActOnParamDefaultArgument.

I ran "make test" within the Clang directory, and there were no
regressions on x86 Linux. I'm not sure what else I'm supposed to test
before submitting patches.

Comments welcome :)

  - Doug
-------------- next part --------------
A non-text attachment was scrubbed...
Name: clang-default-arg-try2.patch
Type: text/x-patch
Size: 49247 bytes
Desc: not available
URL: <http://lists.llvm.org/pipermail/cfe-dev/attachments/20080406/c76b6d46/attachment.bin>


More information about the cfe-dev mailing list