[cfe-commits] r50799 - in /cfe/trunk: include/clang/Basic/DiagnosticKinds.def lib/Sema/Sema.h lib/Sema/SemaDecl.cpp lib/Sema/SemaDeclCXX.cpp lib/Sema/SemaType.cpp test/Sema/default2.cpp
Douglas Gregor
doug.gregor at gmail.com
Tue May 6 21:49:30 PDT 2008
Author: dgregor
Date: Tue May 6 23:49:29 2008
New Revision: 50799
URL: http://llvm.org/viewvc/llvm-project?rev=50799&view=rev
Log:
Diagnose attempts to use C++ default arguments outside of a function declaration
Modified:
cfe/trunk/include/clang/Basic/DiagnosticKinds.def
cfe/trunk/lib/Sema/Sema.h
cfe/trunk/lib/Sema/SemaDecl.cpp
cfe/trunk/lib/Sema/SemaDeclCXX.cpp
cfe/trunk/lib/Sema/SemaType.cpp
cfe/trunk/test/Sema/default2.cpp
Modified: cfe/trunk/include/clang/Basic/DiagnosticKinds.def
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Basic/DiagnosticKinds.def?rev=50799&r1=50798&r2=50799&view=diff
==============================================================================
--- cfe/trunk/include/clang/Basic/DiagnosticKinds.def (original)
+++ cfe/trunk/include/clang/Basic/DiagnosticKinds.def Tue May 6 23:49:29 2008
@@ -662,6 +662,8 @@
"default argument references parameter '%0'")
DIAG(err_param_default_argument_references_local, ERROR,
"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,
"previous definition is here")
DIAG(err_previous_use, ERROR,
Modified: cfe/trunk/lib/Sema/Sema.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/Sema.h?rev=50799&r1=50798&r2=50799&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/Sema.h (original)
+++ cfe/trunk/lib/Sema/Sema.h Tue May 6 23:49:29 2008
@@ -279,6 +279,7 @@
ParmVarDecl *CreateImplicitParameter(Scope *S, IdentifierInfo *Id,
SourceLocation IdLoc, QualType Type);
void CheckCXXDefaultArguments(FunctionDecl *FD);
+ void CheckExtraCXXDefaultArguments(Declarator &D);
/// More parsing and symbol table subroutines...
Decl *LookupDecl(const IdentifierInfo *II, unsigned NSI, Scope *S,
Modified: cfe/trunk/lib/Sema/SemaDecl.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaDecl.cpp?rev=50799&r1=50798&r2=50799&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/SemaDecl.cpp (original)
+++ cfe/trunk/lib/Sema/SemaDecl.cpp Tue May 6 23:49:29 2008
@@ -785,6 +785,10 @@
assert(!R.isNull() && "GetTypeForDeclarator() returned null type");
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);
if (!NewTD) return 0;
@@ -889,6 +893,10 @@
if (getLangOptions().CPlusPlus)
CheckCXXDefaultArguments(NewFD);
} else {
+ // Check that there are no default arguments (C++ only).
+ if (getLangOptions().CPlusPlus)
+ CheckExtraCXXDefaultArguments(D);
+
if (R.getTypePtr()->isObjCInterfaceType()) {
Diag(D.getIdentifierLoc(), diag::err_statically_allocated_object,
D.getIdentifier()->getName());
@@ -1108,7 +1116,11 @@
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
// type was invalid, GetTypeForDeclarator() still returns a "valid" type,
// though it will not reflect the user specified type.
Modified: cfe/trunk/lib/Sema/SemaDeclCXX.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaDeclCXX.cpp?rev=50799&r1=50798&r2=50799&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/SemaDeclCXX.cpp (original)
+++ cfe/trunk/lib/Sema/SemaDeclCXX.cpp Tue May 6 23:49:29 2008
@@ -134,14 +134,6 @@
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
CheckDefaultArgumentVisitor DefaultArgChecker(DefaultArg.get(), this);
if (DefaultArgChecker.Visit(DefaultArg.get()))
@@ -151,6 +143,34 @@
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++
// function, once we already know that they have the same
// type. Subroutine of MergeFunctionDecl.
Modified: cfe/trunk/lib/Sema/SemaType.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaType.cpp?rev=50799&r1=50798&r2=50799&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/SemaType.cpp (original)
+++ cfe/trunk/lib/Sema/SemaType.cpp Tue May 6 23:49:29 2008
@@ -501,6 +501,10 @@
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
// type was invalid, GetTypeForDeclarator() still returns a "valid" type,
// though it will not reflect the user specified type.
Modified: cfe/trunk/test/Sema/default2.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Sema/default2.cpp?rev=50799&r1=50798&r2=50799&view=diff
==============================================================================
--- cfe/trunk/test/Sema/default2.cpp (original)
+++ cfe/trunk/test/Sema/default2.cpp Tue May 6 23:49:29 2008
@@ -1,7 +1,10 @@
// RUN: clang -fsyntax-only -verify %s
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, int k);
void f(int i = 1, int j, int k);
+void f(int i, int j, int k);
void i()
{
@@ -27,3 +30,9 @@
}
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}}}
+}
More information about the cfe-commits
mailing list