[cfe-commits] r64902 - in /cfe/trunk: docs/LanguageExtensions.html include/clang/Basic/DiagnosticParseKinds.def include/clang/Basic/DiagnosticSemaKinds.def include/clang/Parse/DeclSpec.h lib/Parse/DeclSpec.cpp lib/Parse/ParseDecl.cpp lib/Parse/ParseExpr.cpp lib/Sema/SemaDecl.cpp lib/Sema/SemaType.cpp test/Sema/overloadable.c
Douglas Gregor
dgregor at apple.com
Tue Feb 17 23:07:28 PST 2009
Author: dgregor
Date: Wed Feb 18 01:07:28 2009
New Revision: 64902
URL: http://llvm.org/viewvc/llvm-project?rev=64902&view=rev
Log:
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).
Modified:
cfe/trunk/docs/LanguageExtensions.html
cfe/trunk/include/clang/Basic/DiagnosticParseKinds.def
cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.def
cfe/trunk/include/clang/Parse/DeclSpec.h
cfe/trunk/lib/Parse/DeclSpec.cpp
cfe/trunk/lib/Parse/ParseDecl.cpp
cfe/trunk/lib/Parse/ParseExpr.cpp
cfe/trunk/lib/Sema/SemaDecl.cpp
cfe/trunk/lib/Sema/SemaType.cpp
cfe/trunk/test/Sema/overloadable.c
Modified: cfe/trunk/docs/LanguageExtensions.html
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/docs/LanguageExtensions.html?rev=64902&r1=64901&r2=64902&view=diff
==============================================================================
--- cfe/trunk/docs/LanguageExtensions.html (original)
+++ cfe/trunk/docs/LanguageExtensions.html Wed Feb 18 01:07:28 2009
@@ -112,6 +112,24 @@
</pre>
</blockquote>
+<p>Functions marked <tt>overloadable</tt> must have
+prototypes. Therefore, the following code is ill-formed:</p>
+
+<blockquote>
+<pre>
+int h() __attribute__((overloadable)); <i>// error: h does not have a prototype</i>
+</pre>
+</blockquote>
+
+<p>However, <tt>overloadable</tt> functions are allowed to use a
+ellipsis even if there are no named parameters (as is permitted in C++). This feature is particularly useful when combined with the <tt>unavailable</tt> attribute:</p>
+
+<blockquote>
+<pre>
+void honeypot(..) __attribute__((overloadable, unavailable)); <i>// calling me is an error</i>
+</pre>
+</blockquote>
+
<p>Functions declared with the <tt>overloadable</tt> attribute have
their names mangled according to the same rules as C++ function
names. For example, the three <tt>tgsin</tt> functions in our
Modified: cfe/trunk/include/clang/Basic/DiagnosticParseKinds.def
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Basic/DiagnosticParseKinds.def?rev=64902&r1=64901&r2=64902&view=diff
==============================================================================
--- cfe/trunk/include/clang/Basic/DiagnosticParseKinds.def (original)
+++ cfe/trunk/include/clang/Basic/DiagnosticParseKinds.def Wed Feb 18 01:07:28 2009
@@ -162,8 +162,6 @@
"%0 declared as a reference to a reference")
DIAG(err_argument_required_after_attribute, ERROR,
"argument required after attribute")
-DIAG(err_ellipsis_first_arg, ERROR,
- "ISO C requires a named argument before '...'")
DIAG(err_missing_param, ERROR,
"expected parameter declarator")
DIAG(err_unexpected_typedef_ident, ERROR,
Modified: cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.def
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.def?rev=64902&r1=64901&r2=64902&view=diff
==============================================================================
--- cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.def (original)
+++ cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.def Wed Feb 18 01:07:28 2009
@@ -78,7 +78,8 @@
"declaration of %0 will not be visible outside of this function")
DIAG(warn_implicit_function_decl, WARNING,
"implicit declaration of function %0")
-
+DIAG(err_ellipsis_first_arg, ERROR,
+ "ISO C requires a named argument before '...'")
DIAG(err_declarator_need_ident, ERROR,
"declarator requires an identifier")
DIAG(err_bad_language, ERROR,
Modified: cfe/trunk/include/clang/Parse/DeclSpec.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Parse/DeclSpec.h?rev=64902&r1=64901&r2=64902&view=diff
==============================================================================
--- cfe/trunk/include/clang/Parse/DeclSpec.h (original)
+++ cfe/trunk/include/clang/Parse/DeclSpec.h Wed Feb 18 01:07:28 2009
@@ -503,10 +503,14 @@
/// and is treated as a K&R-style function.
bool hasPrototype : 1;
- /// isVariadic - If this function has a prototype, and if that proto ends
- /// with ',...)', this is true.
+ /// isVariadic - If this function has a prototype, and if that
+ /// proto ends with ',...)', this is true. When true, EllipsisLoc
+ /// contains the location of the ellipsis.
bool isVariadic : 1;
+ /// When isVariadic is true, the location of the ellipsis in the source.
+ unsigned EllipsisLoc;
+
/// The type qualifiers: const/volatile/restrict.
/// The qualifier bitmask values are the same as in QualType.
unsigned TypeQuals : 3;
@@ -537,6 +541,10 @@
if (DeleteArgInfo)
delete[] ArgInfo;
}
+
+ SourceLocation getEllipsisLoc() const {
+ return SourceLocation::getFromRawEncoding(EllipsisLoc);
+ }
};
struct BlockPointerTypeInfo {
@@ -646,6 +654,7 @@
/// DeclaratorChunk::getFunction - Return a DeclaratorChunk for a function.
/// "TheDeclarator" is the declarator that this will be added to.
static DeclaratorChunk getFunction(bool hasProto, bool isVariadic,
+ SourceLocation EllipsisLoc,
ParamInfo *ArgInfo, unsigned NumArgs,
unsigned TypeQuals, SourceLocation Loc,
Declarator &TheDeclarator);
Modified: cfe/trunk/lib/Parse/DeclSpec.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Parse/DeclSpec.cpp?rev=64902&r1=64901&r2=64902&view=diff
==============================================================================
--- cfe/trunk/lib/Parse/DeclSpec.cpp (original)
+++ cfe/trunk/lib/Parse/DeclSpec.cpp Wed Feb 18 01:07:28 2009
@@ -27,6 +27,7 @@
/// 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 @@
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;
Modified: cfe/trunk/lib/Parse/ParseDecl.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Parse/ParseDecl.cpp?rev=64902&r1=64901&r2=64902&view=diff
==============================================================================
--- cfe/trunk/lib/Parse/ParseDecl.cpp (original)
+++ cfe/trunk/lib/Parse/ParseDecl.cpp Wed Feb 18 01:07:28 2009
@@ -2036,6 +2036,7 @@
// 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 @@
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 @@
// 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 @@
// 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);
Modified: cfe/trunk/lib/Parse/ParseExpr.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Parse/ParseExpr.cpp?rev=64902&r1=64901&r2=64902&view=diff
==============================================================================
--- cfe/trunk/lib/Parse/ParseExpr.cpp (original)
+++ cfe/trunk/lib/Parse/ParseExpr.cpp Wed Feb 18 01:07:28 2009
@@ -1296,7 +1296,8 @@
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);
Modified: cfe/trunk/lib/Sema/SemaDecl.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaDecl.cpp?rev=64902&r1=64901&r2=64902&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/SemaDecl.cpp (original)
+++ cfe/trunk/lib/Sema/SemaDecl.cpp Wed Feb 18 01:07:28 2009
@@ -2928,7 +2928,8 @@
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);
Modified: cfe/trunk/lib/Sema/SemaType.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaType.cpp?rev=64902&r1=64901&r2=64902&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/SemaType.cpp (original)
+++ cfe/trunk/lib/Sema/SemaType.cpp Wed Feb 18 01:07:28 2009
@@ -474,6 +474,22 @@
// 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);
Modified: cfe/trunk/test/Sema/overloadable.c
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Sema/overloadable.c?rev=64902&r1=64901&r2=64902&view=diff
==============================================================================
--- cfe/trunk/test/Sema/overloadable.c (original)
+++ cfe/trunk/test/Sema/overloadable.c Wed Feb 18 01:07:28 2009
@@ -42,9 +42,12 @@
long double promote(long double) __attribute__((__overloadable__));
void promote() __attribute__((__overloadable__)); // expected-error{{'overloadable' function 'promote' must have a prototype}}
+void promote(...) __attribute__((__overloadable__, __unavailable__)); // \
+ // expected-note{{unavailable function is declared here}}
void test_promote(short* sp) {
promote(1.0);
+ promote(sp); // expected-error{{call to function 'promote' that has been intentionally made unavailable}}
}
More information about the cfe-commits
mailing list