forked from OSchip/llvm-project
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. llvm-svn: 147642
This commit is contained in:
parent
5c5e3b7e84
commit
d069d2f6ac
|
@ -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<VexingParse>;
|
||||
def warn_empty_parens_are_function_decl : Warning<
|
||||
"empty parentheses interpreted as a function declaration">,
|
||||
InGroup<VexingParse>;
|
||||
def warn_dangling_else : Warning<
|
||||
"add explicit braces to avoid dangling else">,
|
||||
InGroup<DanglingElse>;
|
||||
|
|
|
@ -112,6 +112,9 @@ def warn_unused_exception_param : Warning<"unused exception parameter %0">,
|
|||
InGroup<UnusedExceptionParameter>, 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<VexingParse>;
|
||||
def warn_unused_function : Warning<"unused function %0">,
|
||||
InGroup<UnusedFunction>, DefaultIgnore;
|
||||
def warn_unused_member_function : Warning<"unused member function %0">,
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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<FunctionType>()->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
|
||||
|
|
|
@ -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}}
|
||||
}
|
||||
|
|
|
@ -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 <typename> 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 <typename> 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}}
|
||||
}
|
||||
};
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
|
|
Loading…
Reference in New Issue