Issue a warning when there's an ambiguous function declarator (that could be a direct initializer for a variable defition).

Idea originated from here: http://thread.gmane.org/gmane.comp.gcc.devel/101524

llvm-svn: 57609
This commit is contained in:
Argyrios Kyrtzidis 2008-10-15 23:21:32 +00:00
parent bc0278400c
commit 84a4df8c92
5 changed files with 21 additions and 8 deletions

View File

@ -557,6 +557,8 @@ DIAG(err_expected_equal_after_declarator, ERROR,
"expected '=' after declarator")
DIAG(warn_statement_disambiguation, WARNING,
"statement was disambiguated as %0")
DIAG(warn_parens_disambiguated_as_function_decl, WARNING,
"parentheses were disambiguated as a function declarator")
// Language specific pragmas

View File

@ -615,10 +615,11 @@ private:
/// isCXXFunctionDeclarator - Disambiguates between a function declarator or
/// a constructor-style initializer, when parsing declaration statements.
/// Returns true for function declarator and false for constructor-style
/// initializer.
/// initializer. If 'diagIfAmbiguous' is true a warning will be emitted to
/// indicate that the parens were disambiguated as function declarator.
/// If during the disambiguation process a parsing error is encountered,
/// the function returns true to let the declaration parsing code handle it.
bool isCXXFunctionDeclarator();
bool isCXXFunctionDeclarator(bool diagIfAmbiguous);
/// isCXXConditionDeclaration - Disambiguates between a declaration or an
/// expression for a condition of a if/switch/while/for statement.

View File

@ -1226,11 +1226,14 @@ void Parser::ParseDirectDeclarator(Declarator &D) {
while (1) {
if (Tok.is(tok::l_paren)) {
// When not in file scope, warn for ambiguous function declarators, just
// in case the author intended it as a variable definition.
bool diagIfAmbiguous = D.getContext() != Declarator::FileContext;
// The paren may be part of a C++ direct initializer, eg. "int x(1);".
// In such a case, check if we actually have a function declarator; if it
// is not, the declarator has been fully parsed.
if (getLang().CPlusPlus && D.mayBeFollowedByCXXDirectInit() &&
!isCXXFunctionDeclarator())
!isCXXFunctionDeclarator(diagIfAmbiguous))
break;
ParseFunctionDeclarator(ConsumeParen(), D);
} else if (Tok.is(tok::l_square)) {

View File

@ -453,7 +453,7 @@ Parser::TPResult Parser::TryParseDeclarator(bool mayBeAbstract,
// initializer that follows the declarator. Note that ctor-style
// initializers are not possible in contexts where abstract declarators
// are allowed.
if (!mayBeAbstract && !isCXXFunctionDeclarator())
if (!mayBeAbstract && !isCXXFunctionDeclarator(false/*diagIfAmbiguous*/))
break;
// direct-declarator '(' parameter-declaration-clause ')'
@ -722,7 +722,7 @@ Parser::TPResult Parser::TryParseDeclarationSpecifier() {
/// '(' parameter-declaration-clause ')' cv-qualifier-seq[opt]
/// exception-specification[opt]
///
bool Parser::isCXXFunctionDeclarator() {
bool Parser::isCXXFunctionDeclarator(bool diagIfAmbiguous) {
// C++ 8.2p1:
// The ambiguity arising from the similarity between a function-style cast and
@ -740,15 +740,21 @@ bool Parser::isCXXFunctionDeclarator() {
if (TPR == TPResult::Ambiguous() && Tok.isNot(tok::r_paren))
TPR = TPResult::False();
SourceLocation TPLoc = Tok.getLocation();
PA.Revert();
// In case of an error, let the declaration parsing code handle it.
if (TPR == TPResult::Error())
return true;
// Function declarator has precedence over constructor-style initializer.
if (TPR == TPResult::Ambiguous())
if (TPR == TPResult::Ambiguous()) {
// Function declarator has precedence over constructor-style initializer.
// Emit a warning just in case the author intended a variable definition.
if (diagIfAmbiguous)
Diag(Tok.getLocation(), diag::warn_parens_disambiguated_as_function_decl,
SourceRange(Tok.getLocation(), TPLoc));
return true;
}
return TPR == TPResult::True();
}

View File

@ -22,7 +22,8 @@ void f() {
(int())1; // expected-error {{used type 'int ()' where arithmetic or pointer type is required}}
// Declarations.
T(*d)(int(p)); // expected-warning {{statement was disambiguated as declaration}} expected-error {{previous definition is here}}
int fd(T(a)); // expected-warning {{parentheses were disambiguated as a function declarator}}
T(*d)(int(p)); // expected-warning {{parentheses were disambiguated as a function declarator}} expected-warning {{statement was disambiguated as declaration}} expected-error {{previous definition is here}}
T(d)[5]; // expected-warning {{statement was disambiguated as declaration}} expected-error {{redefinition of 'd'}}
typeof(int[])(f) = { 1, 2 }; // expected-warning {{statement was disambiguated as declaration}}
void(b)(int);