[PATCH] Fix parsing comma in default arguments.

Richard Smith richard at metafoo.co.uk
Wed Jun 12 14:39:04 PDT 2013


I've had a look at this before. Here are some testcases for you:

Index: test/Parser/cxx-ambig-init-templ.cpp
===================================================================
--- test/Parser/cxx-ambig-init-templ.cpp        (revision 0)
+++ test/Parser/cxx-ambig-init-templ.cpp        (revision 0)
@@ -0,0 +1,57 @@
+// RUN: %clang_cc1 -std=c++11 -verify %s
+
+template<int> struct c { c(int) = delete; typedef void val; };
+
+int val;
+struct S {
+  int k1 = a < b < c, d > ::val, e1;
+  int k2 = a < b, c < d > ::val, e2;
+  int k3 = b < a < c, d > ::val, e3;
+  int k4 = b < c, x, y = d > ::val, e4;
+  int k5 = T1 < b, &S::operator=(int); // expected-warning {{qualification}}
+  int k6 = T2 < b, &S::operator= >::val;
+  int k7 = T1 < b, &S::operator>(int); // expected-warning {{qualification}}
+  int k8 = T2 < b, &S::operator> >::val;
+  int k9 = T3 < a < b, c >> (d), e5 = 1 > (e4);
+
+  void f(
+    int k1 = a < b < c, d > ::val,
+    int k3 = b < a < c, d > ::val,
+    int k4 = b < c, int x = 0 > ::val,
+    int k5 = a < b, T3 < int > >(),
+    int k6 = c < b, T3 < int > x,
+
+    int k2 = a < b, c < d > ::val, // 'a' must be a template
(otherwise we're missing a default arg)
+    int k7 = a < b, c < d > (n) // 'a' must be a template (otherwise
we're missing a default arg)
+  );
+
+  template<int, int=0> struct a { static const int val = 0; };
+  static const int b = 0, c = 1, d = 2;
+
+  static const int T1 = 4;
+  template<int, int &(S::*)(int)> struct T2 { static const int val = 0; };
+
+  template<typename> struct T3 { T3(int); operator int(); };
+};
+
+namespace CWG325 {
+
+  template <int A, typename B> struct T { static int i; operator int(); };
+  class C {
+    int Foo (int i = T<1, int>::i);
+  };
+
+  class D {
+    int Foo (int i = T<1, int>::i);
+    template <int A, typename B> struct T {static int i;};
+  };
+
+  const int a = 0;
+  typedef int b;
+  T<a,b> c;
+  struct E {
+    int n = T<a,b>(c);
+  };
+
+}

I don't see any handling of "operator<", "operator>", "operator,",
"operator=" in your patch, so I assume it doesn't handle those cases
properly. (That should be straightforward to fix.)

Essentially, there are two different tricks we need in order to fully
disambiguate these cases with no name lookup:

1) For an in-class function declaration, if we are in a default
argument, every parameter after the current parameter must also have a
default argument, and a template argument cannot contain a top-level
'='. So if we see a '=', we know we're back to a parameter, and can
back up to the comma at the start of that parameter.

2) For an in-class default initializer for a data member, any '=' must
be part of a new data member, and otherwise any '<' or '>' must be
part of the same initializer (because a declarator cannot contain a
'<' or '>').

On Sun, May 19, 2013 at 2:45 AM, Olivier Goffart <ogoffart at kde.org> wrote:
> Hi,
>
> I attached a patch to the bug http://llvm.org/bugs/show_bug.cgi?id=14486
> The problem is that a comma can be both the separation between template
> parameter, or the separation between function arguments.
>
> GCC tries to fully parse the part after the comma to see if it can be the
> separation between function argument:
> http://code.woboq.org/gcc/gcc/cp/parser.c.html#23442
>
> But I was too lazy to do the same (because the function like
> TryParseParameterDeclarationClause or TryParseDeclarationSpecifier are not good
> enough and stop too early.)
> So Instead I used some heuristics in the existence of a '=' before the
> possible closing '>' as further argument need to find a comma.
>
> I am not 100% sure that this cover all the cases, but i could not find an
> example that breaks.
>
> --
> Olivier
> _______________________________________________
> cfe-commits mailing list
> cfe-commits at cs.uiuc.edu
> http://lists.cs.uiuc.edu/mailman/listinfo/cfe-commits
>



More information about the cfe-commits mailing list