From: Richard Smith Date: Fri, 6 Jan 2012 01:31:20 +0000 (+0000) Subject: Tweak to r147599 for PR10828: Move the check from the parser into sema, and use X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=1d7bcf4b35f8bc0a0a40f4ea7b06b55c63725108;p=clang Tweak to r147599 for PR10828: Move the check from the parser into sema, and use the Semantic Powers to only warn on class types (or dependent types), where the constructor or destructor could do something interesting. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@147642 91177308-0d34-0410-b5e6-96231b3b80d8 --- diff --git a/include/clang/Basic/DiagnosticParseKinds.td b/include/clang/Basic/DiagnosticParseKinds.td index bd30f486b7..919d105a51 100644 --- a/include/clang/Basic/DiagnosticParseKinds.td +++ b/include/clang/Basic/DiagnosticParseKinds.td @@ -389,9 +389,6 @@ def err_expected_equal_after_declarator : Error< def warn_parens_disambiguated_as_function_decl : Warning< "parentheses were disambiguated as a function declarator">, InGroup; -def warn_empty_parens_are_function_decl : Warning< - "empty parentheses interpreted as a function declaration">, - InGroup; def warn_dangling_else : Warning< "add explicit braces to avoid dangling else">, InGroup; diff --git a/include/clang/Basic/DiagnosticSemaKinds.td b/include/clang/Basic/DiagnosticSemaKinds.td index 3a11d14b22..e15352bcd5 100644 --- a/include/clang/Basic/DiagnosticSemaKinds.td +++ b/include/clang/Basic/DiagnosticSemaKinds.td @@ -112,6 +112,9 @@ def warn_unused_exception_param : Warning<"unused exception parameter %0">, InGroup, DefaultIgnore; def warn_decl_in_param_list : Warning< "declaration of %0 will not be visible outside of this function">; +def warn_empty_parens_are_function_decl : Warning< + "empty parentheses interpreted as a function declaration">, + InGroup; def warn_unused_function : Warning<"unused function %0">, InGroup, DefaultIgnore; def warn_unused_member_function : Warning<"unused member function %0">, diff --git a/lib/Parse/ParseDecl.cpp b/lib/Parse/ParseDecl.cpp index d3c8211372..ee4a51e184 100644 --- a/lib/Parse/ParseDecl.cpp +++ b/lib/Parse/ParseDecl.cpp @@ -1111,21 +1111,6 @@ Parser::DeclGroupPtrTy Parser::ParseDeclGroup(ParsingDeclSpec &DS, if (FirstDecl) DeclsInGroup.push_back(FirstDecl); - // In C++, "T var();" at block scope is probably an attempt to initialize a - // variable, not a function declaration. We don't catch this case earlier, - // since there is no ambiguity here. - if (getLang().CPlusPlus && Context != Declarator::FileContext && - D.getNumTypeObjects() == 1 && D.isFunctionDeclarator() && - D.getDeclSpec().getStorageClassSpecAsWritten() - == DeclSpec::SCS_unspecified && - D.getDeclSpec().getTypeSpecType() != DeclSpec::TST_void) { - DeclaratorChunk &C = D.getTypeObject(0); - if (C.Fun.NumArgs == 0 && !C.Fun.isVariadic && !C.Fun.TrailingReturnType && - C.Fun.getExceptionSpecType() == EST_None) - Diag(C.Loc, diag::warn_empty_parens_are_function_decl) - << SourceRange(C.Loc, C.EndLoc); - } - bool ExpectSemi = Context != Declarator::ForContext; // If we don't have a comma, it is either the end of the list (a ';') or an diff --git a/lib/Sema/SemaDecl.cpp b/lib/Sema/SemaDecl.cpp index 8353c087d5..3e9e66d55d 100644 --- a/lib/Sema/SemaDecl.cpp +++ b/lib/Sema/SemaDecl.cpp @@ -4904,6 +4904,25 @@ Sema::ActOnFunctionDeclarator(Scope *S, Declarator &D, DeclContext *DC, FunctionTemplate->setInvalidDecl(); } + // If we see "T var();" at block scope, where T is a class type, it is + // probably an attempt to initialize a variable, not a function declaration. + // We don't catch this case earlier, since there is no ambiguity here. + if (!FunctionTemplate && D.getFunctionDefinitionKind() == FDK_Declaration && + CurContext->isFunctionOrMethod() && + D.getNumTypeObjects() == 1 && D.isFunctionDeclarator() && + D.getDeclSpec().getStorageClassSpecAsWritten() + == DeclSpec::SCS_unspecified) { + QualType T = R->getAs()->getResultType(); + DeclaratorChunk &C = D.getTypeObject(0); + if ((T->isDependentType() || T->isRecordType()) && + C.Fun.NumArgs == 0 && !C.Fun.isVariadic && + !C.Fun.TrailingReturnType && + C.Fun.getExceptionSpecType() == EST_None) { + Diag(C.Loc, diag::warn_empty_parens_are_function_decl) + << SourceRange(C.Loc, C.EndLoc); + } + } + // C++ [dcl.fct.spec]p5: // The virtual specifier shall only be used in declarations of // nonstatic class member functions that appear within a diff --git a/test/CXX/basic/basic.link/p9.cpp b/test/CXX/basic/basic.link/p9.cpp index c895253c68..d8969ba1ba 100644 --- a/test/CXX/basic/basic.link/p9.cpp +++ b/test/CXX/basic/basic.link/p9.cpp @@ -6,5 +6,5 @@ namespace N { } // expected-note{{here}} // First bullet: two names with external linkage that refer to // different kinds of entities. void f() { - int N(); // expected-error{{redefinition}} expected-warning{{interpreted as a function declaration}} + int N(); // expected-error{{redefinition}} } diff --git a/test/CXX/dcl.dcl/basic.namespace/namespace.udecl/p11.cpp b/test/CXX/dcl.dcl/basic.namespace/namespace.udecl/p11.cpp index b1dcf4d015..303df8d230 100644 --- a/test/CXX/dcl.dcl/basic.namespace/namespace.udecl/p11.cpp +++ b/test/CXX/dcl.dcl/basic.namespace/namespace.udecl/p11.cpp @@ -25,13 +25,13 @@ namespace test1 { namespace test2 { namespace ns { void foo(); } // expected-note 2 {{target of using declaration}} void test0() { - int foo(); // expected-note {{conflicting declaration}} expected-warning{{function declaration}} + int foo(); // expected-note {{conflicting declaration}} using ns::foo; // expected-error {{target of using declaration conflicts with declaration already in scope}} } void test1() { using ns::foo; //expected-note {{using declaration}} - int foo(); // expected-error {{declaration conflicts with target of using declaration already in scope}} expected-warning{{function declaration}} + int foo(); // expected-error {{declaration conflicts with target of using declaration already in scope}} } } @@ -39,7 +39,7 @@ namespace test3 { namespace ns { void foo(); } // expected-note 2 {{target of using declaration}} class Test0 { void test() { - int foo(); // expected-note {{conflicting declaration}} expected-warning{{function declaration}} + int foo(); // expected-note {{conflicting declaration}} using ns::foo; // expected-error {{target of using declaration conflicts with declaration already in scope}} } }; @@ -47,7 +47,7 @@ namespace test3 { class Test1 { void test() { using ns::foo; //expected-note {{using declaration}} - int foo(); // expected-error {{declaration conflicts with target of using declaration already in scope}} expected-warning{{function declaration}} + int foo(); // expected-error {{declaration conflicts with target of using declaration already in scope}} } }; } @@ -56,7 +56,7 @@ namespace test4 { namespace ns { void foo(); } // expected-note 2 {{target of using declaration}} template class Test0 { void test() { - int foo(); // expected-note {{conflicting declaration}} expected-warning{{function declaration}} + int foo(); // expected-note {{conflicting declaration}} using ns::foo; // expected-error {{target of using declaration conflicts with declaration already in scope}} } }; @@ -64,7 +64,7 @@ namespace test4 { template class Test1 { void test() { using ns::foo; //expected-note {{using declaration}} - int foo(); // expected-error {{declaration conflicts with target of using declaration already in scope}} expected-warning{{function declaration}} + int foo(); // expected-error {{declaration conflicts with target of using declaration already in scope}} } }; } diff --git a/test/SemaCXX/decl-expr-ambiguity.cpp b/test/SemaCXX/decl-expr-ambiguity.cpp index 555e89ca7d..4a93b9ae71 100644 --- a/test/SemaCXX/decl-expr-ambiguity.cpp +++ b/test/SemaCXX/decl-expr-ambiguity.cpp @@ -26,9 +26,13 @@ void f() { T(*d)(int(p)); // expected-warning {{parentheses were disambiguated as a function declarator}} expected-note {{previous definition is here}} typedef T(*td)(int(p)); extern T(*tp)(int(p)); - T d3(); // expected-warning {{empty parentheses interpreted as a function declaration}} - typedef T d3t(); - extern T f3(); + S d3(); // expected-warning {{empty parentheses interpreted as a function declaration}} + S d3v(void); + typedef S d3t(); + extern S f3(); + __typeof(*T()) f4(); // expected-warning {{empty parentheses interpreted as a function declaration}} + S multi1, + multi2(); // expected-warning {{empty parentheses interpreted as a function declaration}} T(d)[5]; // expected-error {{redefinition of 'd'}} typeof(int[])(f) = { 1, 2 }; // expected-error {{extension used}} void(b)(int);