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 <rdar://problem/8193163>.

llvm-svn: 108459
This commit is contained in:
Douglas Gregor 2010-07-15 21:05:01 +00:00
parent cedf95623b
commit dc9361876c
3 changed files with 34 additions and 15 deletions

View File

@ -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))

View File

@ -0,0 +1,16 @@
// RUN: %clang_cc1 -fsyntax-only -verify %s
// XFAIL: *
struct X {
template<typename T> X(T);
X(int, int);
X operator()(int, int) const;
};
template<typename T, typename U> struct Y { };
X *x;
void f() {
int y = 0;
X (*x)(int(y), int(y)) = Y<int, float>(), ++y;
}

View File

@ -0,0 +1,10 @@
// RUN: %clang_cc1 -fsyntax-only -verify %s
struct X {
template<typename T, typename U>
static void f(int, int);
};
void f() {
void (*ptr)(int, int) = &X::f<int, int>;
}