aboutsummaryrefslogtreecommitdiff
path: root/lib
diff options
context:
space:
mode:
authorDouglas Gregor <dgregor@apple.com>2009-02-18 07:07:28 +0000
committerDouglas Gregor <dgregor@apple.com>2009-02-18 07:07:28 +0000
commit965acbb321e94e36aa5365126eee46b97745fdbb (patch)
treeb90c16f0aedbfca9146e07251c896cd22d9fd9c6 /lib
parentc6c16af963eddc3e9b75b5d2614d069e1162fe27 (diff)
Allow "overloadable" functions in C to be declared as variadic without
any named parameters, e.g., this is accepted in C: void f(...) __attribute__((overloadable)); although this would be rejected: void f(...); To do this, moved the checking of the "ellipsis without any named arguments" condition from the parser into Sema (where it belongs anyway). git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@64902 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'lib')
-rw-r--r--lib/Parse/DeclSpec.cpp2
-rw-r--r--lib/Parse/ParseDecl.cpp15
-rw-r--r--lib/Parse/ParseExpr.cpp3
-rw-r--r--lib/Sema/SemaDecl.cpp3
-rw-r--r--lib/Sema/SemaType.cpp16
5 files changed, 27 insertions, 12 deletions
diff --git a/lib/Parse/DeclSpec.cpp b/lib/Parse/DeclSpec.cpp
index 4f1ef2490a..28c8149639 100644
--- a/lib/Parse/DeclSpec.cpp
+++ b/lib/Parse/DeclSpec.cpp
@@ -27,6 +27,7 @@ static DiagnosticBuilder Diag(Diagnostic &D, SourceLocation Loc,
/// DeclaratorChunk::getFunction - Return a DeclaratorChunk for a function.
/// "TheDeclarator" is the declarator that this will be added to.
DeclaratorChunk DeclaratorChunk::getFunction(bool hasProto, bool isVariadic,
+ SourceLocation EllipsisLoc,
ParamInfo *ArgInfo,
unsigned NumArgs,
unsigned TypeQuals,
@@ -37,6 +38,7 @@ DeclaratorChunk DeclaratorChunk::getFunction(bool hasProto, bool isVariadic,
I.Loc = Loc;
I.Fun.hasPrototype = hasProto;
I.Fun.isVariadic = isVariadic;
+ I.Fun.EllipsisLoc = EllipsisLoc.getRawEncoding();
I.Fun.DeleteArgInfo = false;
I.Fun.TypeQuals = TypeQuals;
I.Fun.NumArgs = NumArgs;
diff --git a/lib/Parse/ParseDecl.cpp b/lib/Parse/ParseDecl.cpp
index 953b552562..9974aea005 100644
--- a/lib/Parse/ParseDecl.cpp
+++ b/lib/Parse/ParseDecl.cpp
@@ -2036,6 +2036,7 @@ void Parser::ParseFunctionDeclarator(SourceLocation LParenLoc, Declarator &D,
// int() -> no prototype, no '...'.
D.AddTypeInfo(DeclaratorChunk::getFunction(/*prototype*/getLang().CPlusPlus,
/*variadic*/ false,
+ SourceLocation(),
/*arglist*/ 0, 0,
DS.getTypeQualifiers(),
LParenLoc, D),
@@ -2069,19 +2070,11 @@ void Parser::ParseFunctionDeclarator(SourceLocation LParenLoc, Declarator &D,
ParseScope PrototypeScope(this, Scope::FunctionPrototypeScope|Scope::DeclScope);
bool IsVariadic = false;
+ SourceLocation EllipsisLoc;
while (1) {
if (Tok.is(tok::ellipsis)) {
IsVariadic = true;
-
- // Check to see if this is "void(...)" which is not allowed.
- if (!getLang().CPlusPlus && ParamInfo.empty()) {
- // Otherwise, parse parameter type list. If it starts with an
- // ellipsis, diagnose the malformed function.
- Diag(Tok, diag::err_ellipsis_first_arg);
- IsVariadic = false; // Treat this like 'void()'.
- }
-
- ConsumeToken(); // Consume the ellipsis.
+ EllipsisLoc = ConsumeToken(); // Consume the ellipsis.
break;
}
@@ -2201,6 +2194,7 @@ void Parser::ParseFunctionDeclarator(SourceLocation LParenLoc, Declarator &D,
// Remember that we parsed a function type, and remember the attributes.
D.AddTypeInfo(DeclaratorChunk::getFunction(/*proto*/true, IsVariadic,
+ EllipsisLoc,
&ParamInfo[0], ParamInfo.size(),
DS.getTypeQualifiers(),
LParenLoc, D),
@@ -2273,6 +2267,7 @@ void Parser::ParseFunctionDeclaratorIdentifierList(SourceLocation LParenLoc,
// function type is always a K&R style function type, which is not varargs and
// has no prototype.
D.AddTypeInfo(DeclaratorChunk::getFunction(/*proto*/false, /*varargs*/false,
+ SourceLocation(),
&ParamInfo[0], ParamInfo.size(),
/*TypeQuals*/0, LParenLoc, D),
RLoc);
diff --git a/lib/Parse/ParseExpr.cpp b/lib/Parse/ParseExpr.cpp
index f7eeef7556..d2e59ece35 100644
--- a/lib/Parse/ParseExpr.cpp
+++ b/lib/Parse/ParseExpr.cpp
@@ -1296,7 +1296,8 @@ Parser::OwningExprResult Parser::ParseBlockLiteralExpression() {
ParseBlockId();
} else {
// Otherwise, pretend we saw (void).
- ParamInfo.AddTypeInfo(DeclaratorChunk::getFunction(true, false,
+ ParamInfo.AddTypeInfo(DeclaratorChunk::getFunction(true, false,
+ SourceLocation(),
0, 0, 0, CaretLoc,
ParamInfo),
CaretLoc);
diff --git a/lib/Sema/SemaDecl.cpp b/lib/Sema/SemaDecl.cpp
index 0543b0adc6..92f167dcf2 100644
--- a/lib/Sema/SemaDecl.cpp
+++ b/lib/Sema/SemaDecl.cpp
@@ -2928,7 +2928,8 @@ NamedDecl *Sema::ImplicitlyDefineFunction(SourceLocation Loc,
Error = Error; // Silence warning.
assert(!Error && "Error setting up implicit decl!");
Declarator D(DS, Declarator::BlockContext);
- D.AddTypeInfo(DeclaratorChunk::getFunction(false, false, 0, 0, 0, Loc, D),
+ D.AddTypeInfo(DeclaratorChunk::getFunction(false, false, SourceLocation(),
+ 0, 0, 0, Loc, D),
SourceLocation());
D.SetIdentifier(&II, Loc);
diff --git a/lib/Sema/SemaType.cpp b/lib/Sema/SemaType.cpp
index e6aafdab08..a385a13f4c 100644
--- a/lib/Sema/SemaType.cpp
+++ b/lib/Sema/SemaType.cpp
@@ -474,6 +474,22 @@ QualType Sema::GetTypeForDeclarator(Declarator &D, Scope *S, unsigned Skip) {
// C++ 8.3.5p2: If the parameter-declaration-clause is empty, the
// function takes no arguments.
T = Context.getFunctionType(T, NULL, 0, FTI.isVariadic,FTI.TypeQuals);
+ } else if (FTI.isVariadic) {
+ // We allow a zero-parameter variadic function in C if the
+ // function is marked with the "overloadable"
+ // attribute. Scan for this attribute now.
+ bool Overloadable = false;
+ for (const AttributeList *Attrs = D.getAttributes();
+ Attrs; Attrs = Attrs->getNext()) {
+ if (Attrs->getKind() == AttributeList::AT_overloadable) {
+ Overloadable = true;
+ break;
+ }
+ }
+
+ if (!Overloadable)
+ Diag(FTI.getEllipsisLoc(), diag::err_ellipsis_first_arg);
+ T = Context.getFunctionType(T, NULL, 0, FTI.isVariadic, 0);
} else {
// Simple void foo(), where the incoming T is the result type.
T = Context.getFunctionTypeNoProto(T);