From: Douglas Gregor Date: Thu, 15 Jul 2010 21:05:01 +0000 (+0000) Subject: When we're performing tentative parsing to determine whether the X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=06b7080b04ba799379469c03471558e4222921ce;p=clang When we're performing tentative parsing to determine whether the parser is looking at a declaration or an expression, use a '=' to conclude that we are parsing a declaration. This is wrong. However, our previous approach of finding a comma after the '=' is also wrong, because the ',' could be part of a template-argument-list. So, for now we're going to use the same wrong heuristic as GCC and Visual C++, because less real-world code is likely to be broken this way. I've opened PR7655 to keep track of our wrongness; note also the XFAIL'd test. Fixes . git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@108459 91177308-0d34-0410-b5e6-96231b3b80d8 --- diff --git a/lib/Parse/ParseTentative.cpp b/lib/Parse/ParseTentative.cpp index 5e64e6162b..dfd866ff84 100644 --- a/lib/Parse/ParseTentative.cpp +++ b/lib/Parse/ParseTentative.cpp @@ -172,14 +172,6 @@ Parser::TPResult Parser::TryParseSimpleDeclaration() { /// '{' '}' /// Parser::TPResult Parser::TryParseInitDeclaratorList() { - // GCC only examines the first declarator for disambiguation: - // i.e: - // int(x), ++x; // GCC regards it as ill-formed declaration. - // - // Comeau and MSVC will regard the above statement as correct expression. - // Clang examines all of the declarators and also regards the above statement - // as correct expression. - while (1) { // declarator TPResult TPR = TryParseDeclarator(false/*mayBeAbstract*/); @@ -197,14 +189,15 @@ Parser::TPResult Parser::TryParseInitDeclaratorList() { if (!SkipUntil(tok::r_paren)) return TPResult::Error(); } else if (Tok.is(tok::equal)) { - // MSVC won't examine the rest of declarators if '=' is encountered, it - // will conclude that it is a declaration. - // Comeau and Clang will examine the rest of declarators. - // Note that "int(x) = {0}, ++x;" will be interpreted as ill-formed - // expression. + // MSVC and g++ won't examine the rest of declarators if '=' is + // encountered; they just conclude that we have a declaration. + // EDG parses the initializer completely, which is the proper behavior + // for this case. // - // Parse through the initializer-clause. - SkipUntil(tok::comma, true/*StopAtSemi*/, true/*DontConsume*/); + // At present, Clang follows MSVC and g++, since the parser does not have + // the ability to parse an expression fully without recording the + // results of that parse. + return TPResult::True(); } if (Tok.isNot(tok::comma)) diff --git a/test/Parser/cxx-ambig-decl-expr-xfail.cpp b/test/Parser/cxx-ambig-decl-expr-xfail.cpp new file mode 100644 index 0000000000..ac4accb2ac --- /dev/null +++ b/test/Parser/cxx-ambig-decl-expr-xfail.cpp @@ -0,0 +1,16 @@ +// RUN: %clang_cc1 -fsyntax-only -verify %s +// XFAIL: * +struct X { + template X(T); + X(int, int); + + X operator()(int, int) const; +}; + +template struct Y { }; + +X *x; +void f() { + int y = 0; + X (*x)(int(y), int(y)) = Y(), ++y; +} diff --git a/test/Parser/cxx-ambig-decl-expr.cpp b/test/Parser/cxx-ambig-decl-expr.cpp new file mode 100644 index 0000000000..b5ff728b47 --- /dev/null +++ b/test/Parser/cxx-ambig-decl-expr.cpp @@ -0,0 +1,10 @@ +// RUN: %clang_cc1 -fsyntax-only -verify %s + +struct X { + template + static void f(int, int); +}; + +void f() { + void (*ptr)(int, int) = &X::f; +}