[cfe-commits] r72689 - in /cfe/trunk: lib/Sema/SemaDecl.cpp lib/Sema/SemaExpr.cpp test/Sema/knr-variadic-def.c
Eli Friedman
eli.friedman at gmail.com
Mon Jun 1 02:25:06 PDT 2009
Author: efriedma
Date: Mon Jun 1 04:24:59 2009
New Revision: 72689
URL: http://llvm.org/viewvc/llvm-project?rev=72689&view=rev
Log:
PR4287: allow a variadic prototype to make a subsequent K&R style
definition variadic. I'm not completely sure it's legal, but the
standard can be interpreted as making it legal, and gcc seems to think
it's legal, so I didn't add an extension warning.
Added:
cfe/trunk/test/Sema/knr-variadic-def.c
Modified:
cfe/trunk/lib/Sema/SemaDecl.cpp
cfe/trunk/lib/Sema/SemaExpr.cpp
Modified: cfe/trunk/lib/Sema/SemaDecl.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaDecl.cpp?rev=72689&r1=72688&r2=72689&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/SemaDecl.cpp (original)
+++ cfe/trunk/lib/Sema/SemaDecl.cpp Mon Jun 1 04:24:59 2009
@@ -765,6 +765,11 @@
// promoted types of the parameters from the K&R definition differ
// from the types in the prototype. GCC then keeps the types from
// the prototype.
+ //
+ // If a variadic prototype is followed by a non-variadic K&R definition,
+ // the K&R definition becomes variadic. This is sort of an edge case, but
+ // it's legal per the standard depending on how you read C99 6.7.5.3p15 and
+ // C99 6.9.1p8.
if (!getLangOptions().CPlusPlus &&
Old->hasPrototype() && !New->hasPrototype() &&
New->getType()->getAsFunctionProtoType() &&
@@ -777,12 +782,11 @@
= New->getType()->getAsFunctionProtoType();
// Determine whether this is the GNU C extension.
- bool GNUCompatible =
- Context.typesAreCompatible(OldProto->getResultType(),
- NewProto->getResultType()) &&
- (OldProto->isVariadic() == NewProto->isVariadic());
+ QualType MergedReturn = Context.mergeTypes(OldProto->getResultType(),
+ NewProto->getResultType());
+ bool LooseCompatible = !MergedReturn.isNull();
for (unsigned Idx = 0, End = Old->getNumParams();
- GNUCompatible && Idx != End; ++Idx) {
+ LooseCompatible && Idx != End; ++Idx) {
ParmVarDecl *OldParm = Old->getParamDecl(Idx);
ParmVarDecl *NewParm = New->getParamDecl(Idx);
if (Context.typesAreCompatible(OldParm->getType(),
@@ -795,10 +799,10 @@
Warnings.push_back(Warn);
ArgTypes.push_back(NewParm->getType());
} else
- GNUCompatible = false;
+ LooseCompatible = false;
}
- if (GNUCompatible) {
+ if (LooseCompatible) {
for (unsigned Warn = 0; Warn < Warnings.size(); ++Warn) {
Diag(Warnings[Warn].NewParm->getLocation(),
diag::ext_param_promoted_not_compatible_with_prototype)
@@ -808,10 +812,9 @@
diag::note_previous_declaration);
}
- New->setType(Context.getFunctionType(NewProto->getResultType(),
- &ArgTypes[0], ArgTypes.size(),
- NewProto->isVariadic(),
- NewProto->getTypeQuals()));
+ New->setType(Context.getFunctionType(MergedReturn, &ArgTypes[0],
+ ArgTypes.size(),
+ OldProto->isVariadic(), 0));
return MergeCompatibleFunctionDecls(New, Old);
}
Modified: cfe/trunk/lib/Sema/SemaExpr.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaExpr.cpp?rev=72689&r1=72688&r2=72689&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/SemaExpr.cpp (original)
+++ cfe/trunk/lib/Sema/SemaExpr.cpp Mon Jun 1 04:24:59 2009
@@ -2670,9 +2670,14 @@
// Check if we have too few/too many template arguments, based
// on our knowledge of the function definition.
const FunctionDecl *Def = 0;
- if (FDecl->getBody(Context, Def) && NumArgs != Def->param_size())
- Diag(RParenLoc, diag::warn_call_wrong_number_of_arguments)
- << (NumArgs > Def->param_size()) << FDecl << Fn->getSourceRange();
+ if (FDecl->getBody(Context, Def) && NumArgs != Def->param_size()) {
+ const FunctionProtoType *Proto =
+ Def->getType()->getAsFunctionProtoType();
+ if (!Proto || !(Proto->isVariadic() && NumArgs >= Def->param_size())) {
+ Diag(RParenLoc, diag::warn_call_wrong_number_of_arguments)
+ << (NumArgs > Def->param_size()) << FDecl << Fn->getSourceRange();
+ }
+ }
}
// Promote the arguments (C99 6.5.2.2p6).
Added: cfe/trunk/test/Sema/knr-variadic-def.c
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Sema/knr-variadic-def.c?rev=72689&view=auto
==============================================================================
--- cfe/trunk/test/Sema/knr-variadic-def.c (added)
+++ cfe/trunk/test/Sema/knr-variadic-def.c Mon Jun 1 04:24:59 2009
@@ -0,0 +1,29 @@
+// RUN: clang-cc -fsyntax-only -verify -pedantic %s
+// PR4287
+
+#include <stdarg.h>
+char *foo = "test";
+int test(char*,...);
+
+int test(fmt)
+ char*fmt;
+{
+ va_list ap;
+ char*a;
+ int x;
+
+ va_start(ap,fmt);
+ a=va_arg(ap,char*);
+ x=(a!=foo);
+ va_end(ap);
+ return x;
+}
+
+void exit();
+
+int main(argc,argv)
+ int argc;char**argv;
+{
+ exit(test("",foo));
+}
+
More information about the cfe-commits
mailing list