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:
parent
cedf95623b
commit
dc9361876c
|
@ -172,14 +172,6 @@ Parser::TPResult Parser::TryParseSimpleDeclaration() {
|
||||||
/// '{' '}'
|
/// '{' '}'
|
||||||
///
|
///
|
||||||
Parser::TPResult Parser::TryParseInitDeclaratorList() {
|
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) {
|
while (1) {
|
||||||
// declarator
|
// declarator
|
||||||
TPResult TPR = TryParseDeclarator(false/*mayBeAbstract*/);
|
TPResult TPR = TryParseDeclarator(false/*mayBeAbstract*/);
|
||||||
|
@ -197,14 +189,15 @@ Parser::TPResult Parser::TryParseInitDeclaratorList() {
|
||||||
if (!SkipUntil(tok::r_paren))
|
if (!SkipUntil(tok::r_paren))
|
||||||
return TPResult::Error();
|
return TPResult::Error();
|
||||||
} else if (Tok.is(tok::equal)) {
|
} else if (Tok.is(tok::equal)) {
|
||||||
// MSVC won't examine the rest of declarators if '=' is encountered, it
|
// MSVC and g++ won't examine the rest of declarators if '=' is
|
||||||
// will conclude that it is a declaration.
|
// encountered; they just conclude that we have a declaration.
|
||||||
// Comeau and Clang will examine the rest of declarators.
|
// EDG parses the initializer completely, which is the proper behavior
|
||||||
// Note that "int(x) = {0}, ++x;" will be interpreted as ill-formed
|
// for this case.
|
||||||
// expression.
|
|
||||||
//
|
//
|
||||||
// Parse through the initializer-clause.
|
// At present, Clang follows MSVC and g++, since the parser does not have
|
||||||
SkipUntil(tok::comma, true/*StopAtSemi*/, true/*DontConsume*/);
|
// the ability to parse an expression fully without recording the
|
||||||
|
// results of that parse.
|
||||||
|
return TPResult::True();
|
||||||
}
|
}
|
||||||
|
|
||||||
if (Tok.isNot(tok::comma))
|
if (Tok.isNot(tok::comma))
|
||||||
|
|
|
@ -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;
|
||||||
|
}
|
|
@ -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>;
|
||||||
|
}
|
Loading…
Reference in New Issue