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>;
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">,
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
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
// 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}}
}
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}}
}
}
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}}
}
};
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}}
}
};
}
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}}
}
};
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}}
}
};
}
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);