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:
parent
bc0278400c
commit
84a4df8c92
|
@ -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
|
||||
|
||||
|
|
|
@ -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.
|
||||
|
|
|
@ -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)) {
|
||||
|
|
|
@ -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();
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
|
|
Loading…
Reference in New Issue