forked from OSchip/llvm-project
Diagnose attempts to use C++ default arguments outside of a function declaration
llvm-svn: 50799
This commit is contained in:
parent
9930bd8c4f
commit
caa8acebe7
|
@ -662,6 +662,8 @@ DIAG(err_param_default_argument_references_param, ERROR,
|
||||||
"default argument references parameter '%0'")
|
"default argument references parameter '%0'")
|
||||||
DIAG(err_param_default_argument_references_local, ERROR,
|
DIAG(err_param_default_argument_references_local, ERROR,
|
||||||
"default argument references local variable '%0' of enclosing function")
|
"default argument references local variable '%0' of enclosing function")
|
||||||
|
DIAG(err_param_default_argument_nonfunc, ERROR,
|
||||||
|
"default arguments can only be specified for parameters in a function declaration")
|
||||||
DIAG(err_previous_definition, ERROR,
|
DIAG(err_previous_definition, ERROR,
|
||||||
"previous definition is here")
|
"previous definition is here")
|
||||||
DIAG(err_previous_use, ERROR,
|
DIAG(err_previous_use, ERROR,
|
||||||
|
|
|
@ -279,6 +279,7 @@ private:
|
||||||
ParmVarDecl *CreateImplicitParameter(Scope *S, IdentifierInfo *Id,
|
ParmVarDecl *CreateImplicitParameter(Scope *S, IdentifierInfo *Id,
|
||||||
SourceLocation IdLoc, QualType Type);
|
SourceLocation IdLoc, QualType Type);
|
||||||
void CheckCXXDefaultArguments(FunctionDecl *FD);
|
void CheckCXXDefaultArguments(FunctionDecl *FD);
|
||||||
|
void CheckExtraCXXDefaultArguments(Declarator &D);
|
||||||
|
|
||||||
/// More parsing and symbol table subroutines...
|
/// More parsing and symbol table subroutines...
|
||||||
Decl *LookupDecl(const IdentifierInfo *II, unsigned NSI, Scope *S,
|
Decl *LookupDecl(const IdentifierInfo *II, unsigned NSI, Scope *S,
|
||||||
|
|
|
@ -785,6 +785,10 @@ Sema::ActOnDeclarator(Scope *S, Declarator &D, DeclTy *lastDecl) {
|
||||||
assert(!R.isNull() && "GetTypeForDeclarator() returned null type");
|
assert(!R.isNull() && "GetTypeForDeclarator() returned null type");
|
||||||
|
|
||||||
if (D.getDeclSpec().getStorageClassSpec() == DeclSpec::SCS_typedef) {
|
if (D.getDeclSpec().getStorageClassSpec() == DeclSpec::SCS_typedef) {
|
||||||
|
// Check that there are no default arguments (C++ only).
|
||||||
|
if (getLangOptions().CPlusPlus)
|
||||||
|
CheckExtraCXXDefaultArguments(D);
|
||||||
|
|
||||||
TypedefDecl *NewTD = ParseTypedefDecl(S, D, R, LastDeclarator);
|
TypedefDecl *NewTD = ParseTypedefDecl(S, D, R, LastDeclarator);
|
||||||
if (!NewTD) return 0;
|
if (!NewTD) return 0;
|
||||||
|
|
||||||
|
@ -889,6 +893,10 @@ Sema::ActOnDeclarator(Scope *S, Declarator &D, DeclTy *lastDecl) {
|
||||||
if (getLangOptions().CPlusPlus)
|
if (getLangOptions().CPlusPlus)
|
||||||
CheckCXXDefaultArguments(NewFD);
|
CheckCXXDefaultArguments(NewFD);
|
||||||
} else {
|
} else {
|
||||||
|
// Check that there are no default arguments (C++ only).
|
||||||
|
if (getLangOptions().CPlusPlus)
|
||||||
|
CheckExtraCXXDefaultArguments(D);
|
||||||
|
|
||||||
if (R.getTypePtr()->isObjCInterfaceType()) {
|
if (R.getTypePtr()->isObjCInterfaceType()) {
|
||||||
Diag(D.getIdentifierLoc(), diag::err_statically_allocated_object,
|
Diag(D.getIdentifierLoc(), diag::err_statically_allocated_object,
|
||||||
D.getIdentifier()->getName());
|
D.getIdentifier()->getName());
|
||||||
|
@ -1108,7 +1116,11 @@ Sema::ActOnParamDeclarator(Scope *S, Declarator &D) {
|
||||||
DS.ClearStorageClassSpecs();
|
DS.ClearStorageClassSpecs();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Check that there are no default arguments inside the type of this
|
||||||
|
// parameter (C++ only).
|
||||||
|
if (getLangOptions().CPlusPlus)
|
||||||
|
CheckExtraCXXDefaultArguments(D);
|
||||||
|
|
||||||
// In this context, we *do not* check D.getInvalidType(). If the declarator
|
// In this context, we *do not* check D.getInvalidType(). If the declarator
|
||||||
// type was invalid, GetTypeForDeclarator() still returns a "valid" type,
|
// type was invalid, GetTypeForDeclarator() still returns a "valid" type,
|
||||||
// though it will not reflect the user specified type.
|
// though it will not reflect the user specified type.
|
||||||
|
|
|
@ -134,14 +134,6 @@ Sema::ActOnParamDefaultArgument(DeclTy *param, SourceLocation EqualLoc,
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// FIXME: C++ [dcl.fct.default]p3
|
|
||||||
// A default argument expression shall be specified only in the
|
|
||||||
// parameter-declaration-clause of a function declaration or in a
|
|
||||||
// template-parameter (14.1). It shall not be specified for a
|
|
||||||
// parameter pack. If it is specified in a
|
|
||||||
// parameter-declaration-clause, it shall not occur within a
|
|
||||||
// declarator or abstract-declarator of a parameter-declaration.
|
|
||||||
|
|
||||||
// Check that the default argument is well-formed
|
// Check that the default argument is well-formed
|
||||||
CheckDefaultArgumentVisitor DefaultArgChecker(DefaultArg.get(), this);
|
CheckDefaultArgumentVisitor DefaultArgChecker(DefaultArg.get(), this);
|
||||||
if (DefaultArgChecker.Visit(DefaultArg.get()))
|
if (DefaultArgChecker.Visit(DefaultArg.get()))
|
||||||
|
@ -151,6 +143,34 @@ Sema::ActOnParamDefaultArgument(DeclTy *param, SourceLocation EqualLoc,
|
||||||
Param->setDefaultArg(DefaultArg.take());
|
Param->setDefaultArg(DefaultArg.take());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// CheckExtraCXXDefaultArguments - Check for any extra default
|
||||||
|
/// arguments in the declarator, which is not a function declaration
|
||||||
|
/// or definition and therefore is not permitted to have default
|
||||||
|
/// arguments. This routine should be invoked for every declarator
|
||||||
|
/// that is not a function declaration or definition.
|
||||||
|
void Sema::CheckExtraCXXDefaultArguments(Declarator &D) {
|
||||||
|
// C++ [dcl.fct.default]p3
|
||||||
|
// A default argument expression shall be specified only in the
|
||||||
|
// parameter-declaration-clause of a function declaration or in a
|
||||||
|
// template-parameter (14.1). It shall not be specified for a
|
||||||
|
// parameter pack. If it is specified in a
|
||||||
|
// parameter-declaration-clause, it shall not occur within a
|
||||||
|
// declarator or abstract-declarator of a parameter-declaration.
|
||||||
|
for (unsigned i = 0; i < D.getNumTypeObjects(); ++i) {
|
||||||
|
DeclaratorChunk &chunk = D.getTypeObject(i);
|
||||||
|
if (chunk.Kind == DeclaratorChunk::Function) {
|
||||||
|
for (unsigned argIdx = 0; argIdx < chunk.Fun.NumArgs; ++argIdx) {
|
||||||
|
ParmVarDecl *Param = (ParmVarDecl *)chunk.Fun.ArgInfo[argIdx].Param;
|
||||||
|
if (Param->getDefaultArg()) {
|
||||||
|
Diag(Param->getLocation(), diag::err_param_default_argument_nonfunc,
|
||||||
|
Param->getDefaultArg()->getSourceRange());
|
||||||
|
Param->setDefaultArg(0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// MergeCXXFunctionDecl - Merge two declarations of the same C++
|
// MergeCXXFunctionDecl - Merge two declarations of the same C++
|
||||||
// function, once we already know that they have the same
|
// function, once we already know that they have the same
|
||||||
// type. Subroutine of MergeFunctionDecl.
|
// type. Subroutine of MergeFunctionDecl.
|
||||||
|
|
|
@ -501,6 +501,10 @@ Sema::TypeResult Sema::ActOnTypeName(Scope *S, Declarator &D) {
|
||||||
|
|
||||||
assert(!T.isNull() && "GetTypeForDeclarator() returned null type");
|
assert(!T.isNull() && "GetTypeForDeclarator() returned null type");
|
||||||
|
|
||||||
|
// Check that there are no default arguments (C++ only).
|
||||||
|
if (getLangOptions().CPlusPlus)
|
||||||
|
CheckExtraCXXDefaultArguments(D);
|
||||||
|
|
||||||
// In this context, we *do not* check D.getInvalidType(). If the declarator
|
// In this context, we *do not* check D.getInvalidType(). If the declarator
|
||||||
// type was invalid, GetTypeForDeclarator() still returns a "valid" type,
|
// type was invalid, GetTypeForDeclarator() still returns a "valid" type,
|
||||||
// though it will not reflect the user specified type.
|
// though it will not reflect the user specified type.
|
||||||
|
|
|
@ -1,7 +1,10 @@
|
||||||
// RUN: clang -fsyntax-only -verify %s
|
// RUN: clang -fsyntax-only -verify %s
|
||||||
void f(int i, int j, int k = 3);
|
void f(int i, int j, int k = 3);
|
||||||
|
void f(int i, int j, int k);
|
||||||
void f(int i, int j = 2, int k);
|
void f(int i, int j = 2, int k);
|
||||||
|
void f(int i, int j, int k);
|
||||||
void f(int i = 1, int j, int k);
|
void f(int i = 1, int j, int k);
|
||||||
|
void f(int i, int j, int k);
|
||||||
|
|
||||||
void i()
|
void i()
|
||||||
{
|
{
|
||||||
|
@ -27,3 +30,9 @@ void h()
|
||||||
}
|
}
|
||||||
|
|
||||||
void g2(int x, int y, int z = x + y); // expected-error {{default argument references parameter 'x'}} expected-error {{default argument references parameter 'y'}}
|
void g2(int x, int y, int z = x + y); // expected-error {{default argument references parameter 'x'}} expected-error {{default argument references parameter 'y'}}
|
||||||
|
|
||||||
|
void nondecl(int (*f)(int x = 5)) // {expected-error {{default arguments can only be specified}}}
|
||||||
|
{
|
||||||
|
void (*f2)(int = 17) // {expected-error {{default arguments can only be specified}}}
|
||||||
|
= (void (*)(int = 42))f; // {expected-error {{default arguments can only be specified}}}
|
||||||
|
}
|
||||||
|
|
Loading…
Reference in New Issue