r176542 - PR15390: If a function returns a pointer to a function, that function type
Richard Smith
richard-llvm at metafoo.co.uk
Tue Mar 5 17:37:38 PST 2013
Author: rsmith
Date: Tue Mar 5 19:37:38 2013
New Revision: 176542
URL: http://llvm.org/viewvc/llvm-project?rev=176542&view=rev
Log:
PR15390: If a function returns a pointer to a function, that function type
can't have default arguments even though it's a parameter-declaration-clause in
a function declaration.
Modified:
cfe/trunk/include/clang/Sema/DeclSpec.h
cfe/trunk/lib/Sema/SemaDecl.cpp
cfe/trunk/lib/Sema/SemaDeclCXX.cpp
cfe/trunk/test/CXX/dcl.decl/dcl.meaning/dcl.fct.default/p3.cpp
Modified: cfe/trunk/include/clang/Sema/DeclSpec.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Sema/DeclSpec.h?rev=176542&r1=176541&r2=176542&view=diff
==============================================================================
--- cfe/trunk/include/clang/Sema/DeclSpec.h (original)
+++ cfe/trunk/include/clang/Sema/DeclSpec.h Tue Mar 5 19:37:38 2013
@@ -1799,8 +1799,7 @@ public:
return DeclTypeInfo[i];
}
- void DropFirstTypeObject()
- {
+ void DropFirstTypeObject() {
assert(!DeclTypeInfo.empty() && "No type chunks to drop.");
DeclTypeInfo.front().destroy();
DeclTypeInfo.erase(DeclTypeInfo.begin());
@@ -1891,17 +1890,13 @@ public:
/// isn't a function declarator, if the type specifier refers to a function
/// type. This routine checks for both cases.
bool isDeclarationOfFunction() const;
-
- /// \brief Return true if a function declarator at this position would be a
- /// function declaration.
- bool isFunctionDeclaratorAFunctionDeclaration() const {
+
+ /// \brief Return true if this declaration appears in a context where a
+ /// function declarator would be a function declaration.
+ bool isFunctionDeclarationContext() const {
if (getDeclSpec().getStorageClassSpec() == DeclSpec::SCS_typedef)
return false;
- for (unsigned I = 0, N = getNumTypeObjects(); I != N; ++I)
- if (getTypeObject(I).Kind != DeclaratorChunk::Paren)
- return false;
-
switch (Context) {
case FileContext:
case MemberContext:
@@ -1929,6 +1924,19 @@ public:
}
llvm_unreachable("unknown context kind!");
}
+
+ /// \brief Return true if a function declarator at this position would be a
+ /// function declaration.
+ bool isFunctionDeclaratorAFunctionDeclaration() const {
+ if (!isFunctionDeclarationContext())
+ return false;
+
+ for (unsigned I = 0, N = getNumTypeObjects(); I != N; ++I)
+ if (getTypeObject(I).Kind != DeclaratorChunk::Paren)
+ return false;
+
+ return true;
+ }
/// takeAttributes - Takes attributes from the given parsed-attributes
/// set and add them to this declarator.
Modified: cfe/trunk/lib/Sema/SemaDecl.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaDecl.cpp?rev=176542&r1=176541&r2=176542&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/SemaDecl.cpp (original)
+++ cfe/trunk/lib/Sema/SemaDecl.cpp Tue Mar 5 19:37:38 2013
@@ -4117,6 +4117,11 @@ NamedDecl *Sema::HandleDeclarator(Scope
D.getDeclSpec().getStorageClassSpec() != DeclSpec::SCS_typedef)
Previous.clear();
+ // Check that there are no default arguments other than in the parameters
+ // of a function declaration (C++ only).
+ if (getLangOpts().CPlusPlus)
+ CheckExtraCXXDefaultArguments(D);
+
NamedDecl *New;
bool AddToScope = true;
@@ -4356,11 +4361,6 @@ Sema::ActOnTypedefDeclarator(Scope* S, D
Previous.clear();
}
- if (getLangOpts().CPlusPlus) {
- // Check that there are no default arguments (C++ only).
- CheckExtraCXXDefaultArguments(D);
- }
-
DiagnoseFunctionSpecifiers(D);
if (D.getDeclSpec().isThreadSpecified())
@@ -4591,10 +4591,6 @@ Sema::ActOnVariableDeclarator(Scope *S,
QualType R = TInfo->getType();
DeclarationName Name = GetNameForDeclarator(D).getName();
- // Check that there are no default arguments (C++ only).
- if (getLangOpts().CPlusPlus)
- CheckExtraCXXDefaultArguments(D);
-
DeclSpec::SCS SCSpec = D.getDeclSpec().getStorageClassSpec();
assert(SCSpec != DeclSpec::SCS_typedef &&
"Parser allowed 'typedef' as storage class VarDecl.");
Modified: cfe/trunk/lib/Sema/SemaDeclCXX.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaDeclCXX.cpp?rev=176542&r1=176541&r2=176542&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/SemaDeclCXX.cpp (original)
+++ cfe/trunk/lib/Sema/SemaDeclCXX.cpp Tue Mar 5 19:37:38 2013
@@ -352,16 +352,25 @@ void Sema::CheckExtraCXXDefaultArguments
// 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.
+ bool MightBeFunction = D.isFunctionDeclarationContext();
for (unsigned i = 0, e = D.getNumTypeObjects(); i != e; ++i) {
DeclaratorChunk &chunk = D.getTypeObject(i);
if (chunk.Kind == DeclaratorChunk::Function) {
+ if (MightBeFunction) {
+ // This is a function declaration. It can have default arguments, but
+ // keep looking in case its return type is a function type with default
+ // arguments.
+ MightBeFunction = false;
+ continue;
+ }
for (unsigned argIdx = 0, e = chunk.Fun.NumArgs; argIdx != e; ++argIdx) {
ParmVarDecl *Param =
cast<ParmVarDecl>(chunk.Fun.ArgInfo[argIdx].Param);
if (Param->hasUnparsedDefaultArg()) {
CachedTokens *Toks = chunk.Fun.ArgInfo[argIdx].DefaultArgTokens;
Diag(Param->getLocation(), diag::err_param_default_argument_nonfunc)
- << SourceRange((*Toks)[1].getLocation(), Toks->back().getLocation());
+ << SourceRange((*Toks)[1].getLocation(),
+ Toks->back().getLocation());
delete Toks;
chunk.Fun.ArgInfo[argIdx].DefaultArgTokens = 0;
} else if (Param->getDefaultArg()) {
@@ -370,6 +379,8 @@ void Sema::CheckExtraCXXDefaultArguments
Param->setDefaultArg(0);
}
}
+ } else if (chunk.Kind != DeclaratorChunk::Paren) {
+ MightBeFunction = false;
}
}
}
Modified: cfe/trunk/test/CXX/dcl.decl/dcl.meaning/dcl.fct.default/p3.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CXX/dcl.decl/dcl.meaning/dcl.fct.default/p3.cpp?rev=176542&r1=176541&r2=176542&view=diff
==============================================================================
--- cfe/trunk/test/CXX/dcl.decl/dcl.meaning/dcl.fct.default/p3.cpp (original)
+++ cfe/trunk/test/CXX/dcl.decl/dcl.meaning/dcl.fct.default/p3.cpp Tue Mar 5 19:37:38 2013
@@ -1,4 +1,4 @@
-// RUN: %clang_cc1 -fsyntax-only -verify %s
+// RUN: %clang_cc1 -std=c++11 -fsyntax-only -verify %s
void nondecl(int (*f)(int x = 5)) // expected-error {{default arguments can only be specified}}
{
@@ -8,6 +8,9 @@ void nondecl(int (*f)(int x = 5)) // exp
struct X0 {
int (*f)(int = 17); // expected-error{{default arguments can only be specified for parameters in a function declaration}}
+ void (*g())(int = 22); // expected-error{{default arguments can only be specified for parameters in a function declaration}}
+ void (*h(int = 49))(int);
+ auto i(int) -> void (*)(int = 9); // expected-error{{default arguments can only be specified for parameters in a function declaration}}
void mem8(int (*fp)(int) = (int (*)(int = 17))0); // expected-error{{default arguments can only be specified for parameters in a function declaration}}
};
More information about the cfe-commits
mailing list