]> granicus.if.org Git - clang/commitdiff
Issue a warning when there's an ambiguous function declarator (that could be a direct...
authorArgyrios Kyrtzidis <akyrtzi@gmail.com>
Wed, 15 Oct 2008 23:21:32 +0000 (23:21 +0000)
committerArgyrios Kyrtzidis <akyrtzi@gmail.com>
Wed, 15 Oct 2008 23:21:32 +0000 (23:21 +0000)
Idea originated from here: http://thread.gmane.org/gmane.comp.gcc.devel/101524

git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@57609 91177308-0d34-0410-b5e6-96231b3b80d8

include/clang/Basic/DiagnosticKinds.def
include/clang/Parse/Parser.h
lib/Parse/ParseDecl.cpp
lib/Parse/ParseTentative.cpp
test/SemaCXX/decl-expr-ambiguity.cpp

index fc2b7f6088ef1f96e13754f1311fc5b265058406..98e760145b884265ee9c34784e830d8b35610cc5 100644 (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
 
index c1259c69654fa6a990ee7a7724fcb2af6de9bc6f..de12549d7f0848c108b16ab85a5ea0c20150d85a 100644 (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.
index c541a1336f4d9e2a9112ccc6739c1bf74edcd9d4..142347687e21389685899462cec5c214bf34e8ae 100644 (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)) {
index 5dbc327b7134dcf877649294c3c42f886f77f1b1..1666e39ee1aa81853f4f8501fa5be5939f53a1ec 100644 (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();
 }
index 3459d771ab1ede862a755d6054dfad1df4ed8aec..72948e6c75536c9235c4ca82bee426251557456f 100644 (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);