"a %select{function|block}0 declaration without a prototype is deprecated "
"%select{in all versions of C|}0">, InGroup<StrictPrototypes>;
def warn_non_prototype_changes_behavior : Warning<
- "a function declaration without a prototype is deprecated in all versions of "
- "C and is not supported in C2x">, InGroup<DeprecatedNonPrototype>;
-def note_func_decl_changes_behavior : Note<
- "a function declaration without a prototype is not supported in C2x">;
+ "a function %select{declaration|definition}0 without a prototype is "
+ "deprecated in all versions of C %select{and is not supported in C2x|and is "
+ "treated as a zero-parameter prototype in C2x, conflicting with a "
+ "%select{previous|subsequent}2 %select{declaration|definition}3}1">,
+ InGroup<DeprecatedNonPrototype>;
+def note_conflicting_prototype : Note<"conflicting prototype is here">;
def warn_missing_variable_declarations : Warning<
"no previous extern declaration for non-static variable %0">,
InGroup<DiagGroup<"missing-variable-declarations">>, DefaultIgnore;
}
if (WithProto->getNumParams() != 0) {
- // The function definition has parameters, so this will change
- // behavior in C2x.
- //
- // If we already warned about about the function without a prototype
- // being deprecated, add a note that it also changes behavior. If we
- // didn't warn about it being deprecated (because the diagnostic is
- // not enabled), warn now that it is deprecated and changes behavior.
- bool AddNote = false;
- if (Diags.isIgnored(diag::warn_strict_prototypes,
- WithoutProto->getLocation())) {
- if (WithoutProto->getBuiltinID() == 0 &&
- !WithoutProto->isImplicit() &&
- SourceMgr.isBeforeInTranslationUnit(WithoutProto->getLocation(),
- WithProto->getLocation())) {
- PartialDiagnostic PD =
- PDiag(diag::warn_non_prototype_changes_behavior);
- if (TypeSourceInfo *TSI = WithoutProto->getTypeSourceInfo()) {
- if (auto FTL = TSI->getTypeLoc().getAs<FunctionNoProtoTypeLoc>())
- PD << FixItHint::CreateInsertion(FTL.getRParenLoc(), "void");
- }
- Diag(WithoutProto->getLocation(), PD);
- }
- } else {
- AddNote = true;
- }
-
- // Because the function with a prototype has parameters but a previous
- // declaration had none, the function with the prototype will also
- // change behavior in C2x.
- if (WithProto->getBuiltinID() == 0 && !WithProto->isImplicit()) {
- if (SourceMgr.isBeforeInTranslationUnit(
- WithProto->getLocation(), WithoutProto->getLocation())) {
- // If the function with the prototype comes before the function
- // without the prototype, we only want to diagnose the one without
- // the prototype.
- Diag(WithoutProto->getLocation(),
- diag::warn_non_prototype_changes_behavior);
- } else {
- // Otherwise, diagnose the one with the prototype, and potentially
- // attach a note to the one without a prototype if needed.
- Diag(WithProto->getLocation(),
- diag::warn_non_prototype_changes_behavior);
- if (AddNote && WithoutProto->getBuiltinID() == 0)
- Diag(WithoutProto->getLocation(),
- diag::note_func_decl_changes_behavior);
- }
- } else if (AddNote && WithoutProto->getBuiltinID() == 0 &&
- !WithoutProto->isImplicit()) {
- // If we were supposed to add a note but the function with a
- // prototype is a builtin or was implicitly declared, which means we
- // have nothing to attach the note to, so we issue a warning instead.
+ if (WithoutProto->getBuiltinID() == 0 && !WithoutProto->isImplicit()) {
+ // The one without the prototype will be changing behavior in C2x, so
+ // warn about that one so long as it's a user-visible declaration.
+ bool IsWithoutProtoADef = false, IsWithProtoADef = false;
+ if (WithoutProto == New)
+ IsWithoutProtoADef = NewDeclIsDefn;
+ else
+ IsWithProtoADef = NewDeclIsDefn;
Diag(WithoutProto->getLocation(),
- diag::warn_non_prototype_changes_behavior);
+ diag::warn_non_prototype_changes_behavior)
+ << IsWithoutProtoADef << (WithoutProto->getNumParams() ? 0 : 1)
+ << (WithoutProto == Old) << IsWithProtoADef;
+
+ // The reason the one without the prototype will be changing behavior
+ // is because of the one with the prototype, so note that so long as
+ // it's a user-visible declaration. There is one exception to this:
+ // when the new declaration is a definition without a prototype, the
+ // old declaration with a prototype is not the cause of the issue,
+ // and that does not need to be noted because the one with a
+ // prototype will not change behavior in C2x.
+ if (WithProto->getBuiltinID() == 0 && !WithProto->isImplicit() &&
+ !IsWithoutProtoADef)
+ Diag(WithProto->getLocation(), diag::note_conflicting_prototype);
}
}
}
// deprecated, add a note that it also changes behavior. If we didn't
// warn about it being deprecated (because the diagnostic is not
// enabled), warn now that it is deprecated and changes behavior.
- bool AddNote = false;
- if (PossiblePrototype) {
- if (Diags.isIgnored(diag::warn_strict_prototypes,
- PossiblePrototype->getLocation())) {
-
- PartialDiagnostic PD =
- PDiag(diag::warn_non_prototype_changes_behavior);
- if (TypeSourceInfo *TSI = PossiblePrototype->getTypeSourceInfo()) {
- if (auto FTL = TSI->getTypeLoc().getAs<FunctionNoProtoTypeLoc>())
- PD << FixItHint::CreateInsertion(FTL.getRParenLoc(), "void");
- }
- Diag(PossiblePrototype->getLocation(), PD);
- } else {
- AddNote = true;
- }
- }
- // Because this function definition has no prototype and it has
- // parameters, it will definitely change behavior in C2x.
- Diag(FD->getLocation(), diag::warn_non_prototype_changes_behavior);
- if (AddNote)
+ // This K&R C function definition definitely changes behavior in C2x,
+ // so diagnose it.
+ Diag(FD->getLocation(), diag::warn_non_prototype_changes_behavior)
+ << /*definition*/ 1 << /* not supported in C2x */ 0;
+
+ // If we have a possible prototype for the function which is a user-
+ // visible declaration, we already tested that it has no prototype.
+ // This will change behavior in C2x. This gets a warning rather than a
+ // note because it's the same behavior-changing problem as with the
+ // definition.
+ if (PossiblePrototype)
Diag(PossiblePrototype->getLocation(),
- diag::note_func_decl_changes_behavior);
+ diag::warn_non_prototype_changes_behavior)
+ << /*declaration*/ 0 << /* conflicting */ 1 << /*subsequent*/ 1
+ << /*definition*/ 1;
}
// Warn on CPUDispatch with an actual body.
/* WG14 DR035: partial
* Questions about definition of functions without a prototype
*/
-void dr035_1(a, b) /* expected-warning {{a function declaration without a prototype is deprecated in all versions of C and is not supported in C2x}} */
+void dr035_1(a, b) /* expected-warning {{a function definition without a prototype is deprecated in all versions of C and is not supported in C2x}} */
int a(enum b {x, y}); /* expected-warning {{declaration of 'enum b' will not be visible outside of this function}} */
int b; {
int test = x; /* expected-error {{use of undeclared identifier 'x'}} */
}
-void dr035_2(c) /* expected-warning {{a function declaration without a prototype is deprecated in all versions of C and is not supported in C2x}} */
+void dr035_2(c) /* expected-warning {{a function definition without a prototype is deprecated in all versions of C and is not supported in C2x}} */
enum m{q, r} c; { /* expected-warning {{declaration of 'enum m' will not be visible outside of this function}} */
/* FIXME: This should be accepted because the scope of m, q, and r ends at
* the closing brace of the function per C89 6.1.2.1.
* a prototype causes implicit conversions rather than relying on default
* argument promotion and warm thoughts.
*/
-void dr070_1(c) /* expected-warning {{a function declaration without a prototype is deprecated in all versions of C and is not supported in C2x}} */
+void dr070_1(c) /* expected-warning {{a function definition without a prototype is deprecated in all versions of C and is not supported in C2x}} */
int c; {
}
int (*func)();
};
-static int func(f) // expected-warning {{a function declaration without a prototype is deprecated in all versions of C and is not supported in C2x}}
+static int func(f) // expected-warning {{a function definition without a prototype is deprecated in all versions of C and is not supported in C2x}}
void *f;
{
return 0;
}
typedef int atype;
-void test3(x, /* expected-warning {{a function declaration without a prototype is deprecated in all versions of C and is not supported in C2x}} */
+void test3(x, /* expected-warning {{a function definition without a prototype is deprecated in all versions of C and is not supported in C2x}} */
atype /* expected-error {{unexpected type name 'atype': expected identifier}} */
) int x, atype; {}
void test4(x, x) int x; {} // expected-error {{redefinition of parameter 'x'}} \
- // expected-warning {{a function declaration without a prototype is deprecated in all versions of C and is not supported in C2x}}
+ // expected-warning {{a function definition without a prototype is deprecated in all versions of C and is not supported in C2x}}
// PR3031
long struct X { int x; } test15(void); // expected-error {{'long struct' is invalid}}
void test16(i) int i j; { } // expected-error {{expected ';' at end of declaration}} \
- // expected-warning {{a function declaration without a prototype is deprecated in all versions of C and is not supported in C2x}}
+ // expected-warning {{a function definition without a prototype is deprecated in all versions of C and is not supported in C2x}}
void test17(i, j) int i, j k; { } // expected-error {{expected ';' at end of declaration}} \
- // expected-warning {{a function declaration without a prototype is deprecated in all versions of C and is not supported in C2x}}
+ // expected-warning {{a function definition without a prototype is deprecated in all versions of C and is not supported in C2x}}
void knrNoSemi(i) int i { } // expected-error {{expected ';' at end of declaration}} \
- // expected-warning {{a function declaration without a prototype is deprecated in all versions of C and is not supported in C2x}}
+ // expected-warning {{a function definition without a prototype is deprecated in all versions of C and is not supported in C2x}}
// PR12595
void test18(void) {
// RUN: %clang_cc1 -fsyntax-only -verify %s -std=c99
-int f3(y, x, // expected-warning {{a function declaration without a prototype is deprecated in all versions of C and is not supported in C2x}}
+int f3(y, x, // expected-warning {{a function definition without a prototype is deprecated in all versions of C and is not supported in C2x}}
x) // expected-error {{redefinition of parameter}}
int y,
x, // expected-note {{previous declaration is here}}
// RUN: %clang_cc1 -triple i386-pc-unknown -Wconversion -Wliteral-conversion -fsyntax-only -verify %s
// C DR #316, PR 3626.
-void f0(a, b, c, d) int a,b,c,d; {} // expected-warning {{a function declaration without a prototype is deprecated in all versions of C and is not supported in C2x}}
+void f0(a, b, c, d) int a,b,c,d; {} // expected-warning {{a function definition without a prototype is deprecated in all versions of C and is not supported in C2x}}
void t0(void) {
f0(1); // expected-warning{{too few arguments}}
}
-void f1(a, b) int a, b; {} // expected-warning {{a function declaration without a prototype is deprecated in all versions of C and is not supported in C2x}}
+void f1(a, b) int a, b; {} // expected-warning {{a function definition without a prototype is deprecated in all versions of C and is not supported in C2x}}
void t1(void) {
f1(1, 2, 3); // expected-warning{{too many arguments}}
}
void f2(float); // expected-note{{previous declaration is here}}
void f2(x) float x; { } // expected-warning{{promoted type 'double' of K&R function parameter is not compatible with the parameter type 'float' declared in a previous prototype}} \
- expected-warning {{a function declaration without a prototype is deprecated in all versions of C and is not supported in C2x}}
+ expected-warning {{a function definition without a prototype is deprecated in all versions of C and is not supported in C2x}}
typedef void (*f3)(void);
f3 t3(int b) { return b? f0 : f1; } // okay
// PR8314
void proto(int);
-void proto(x) // expected-warning {{a function declaration without a prototype is deprecated in all versions of C and is not supported in C2x}}
+void proto(x) // expected-warning {{a function definition without a prototype is deprecated in all versions of C and is not supported in C2x}}
int x;
{
}
// PR31020
void func(short d) __attribute__((cdecl)); // expected-note{{previous declaration is here}}
-void __attribute__((cdecl)) func(d) // expected-warning {{a function declaration without a prototype is deprecated in all versions of C and is not supported in C2x}}
+void __attribute__((cdecl)) func(d) // expected-warning {{a function definition without a prototype is deprecated in all versions of C and is not supported in C2x}}
short d; // expected-warning{{promoted type 'int' of K&R function parameter is not compatible with the parameter type 'short' declared in a previous prototype}}
{}
char *foo = "test";
int test(char*,...);
-int test(fmt) // expected-warning {{a function declaration without a prototype is deprecated in all versions of C and is not supported in C2x}}
+int test(fmt) // expected-warning {{a function definition without a prototype is deprecated in all versions of C and is not supported in C2x}}
char*fmt;
{
va_list ap;
void exit(); // expected-warning {{a function declaration without a prototype is deprecated in all versions of C}}
-int main(argc,argv) // expected-warning {{a function declaration without a prototype is deprecated in all versions of C and is not supported in C2x}}
+int main(argc,argv) // expected-warning {{a function definition without a prototype is deprecated in all versions of C and is not supported in C2x}}
int argc;char**argv;
{
exit(test("",foo));
void again() {} // strict-warning {{a function declaration without a prototype is deprecated in all versions of C}}
// On by default warnings
-void func(); // expected-warning {{a function declaration without a prototype is deprecated in all versions of C and is not supported in C2x}} \
- strict-warning {{a function declaration without a prototype is deprecated in all versions of C}} \
- strict-note {{a function declaration without a prototype is not supported in C2x}}
-void func(a, b) int a, b; {} // both-warning {{a function declaration without a prototype is deprecated in all versions of C and is not supported in C2x}}
+void func(); // both-warning {{a function declaration without a prototype is deprecated in all versions of C and is treated as a zero-parameter prototype in C2x, conflicting with a subsequent definition}} \
+ strict-warning {{a function declaration without a prototype is deprecated in all versions of C}}
+void func(a, b) int a, b; {} // both-warning {{a function definition without a prototype is deprecated in all versions of C and is not supported in C2x}}
-void one_more(a, b) int a, b; {} // both-warning {{a function declaration without a prototype is deprecated in all versions of C and is not supported in C2x}}
+void one_more(a, b) int a, b; {} // both-warning {{a function definition without a prototype is deprecated in all versions of C and is not supported in C2x}}
void sheesh(int a);
-void sheesh(a) int a; {} // both-warning {{a function declaration without a prototype is deprecated in all versions of C and is not supported in C2x}}
+void sheesh(a) int a; {} // both-warning {{a function definition without a prototype is deprecated in all versions of C and is not supported in C2x}}
void another(); // strict-warning {{a function declaration without a prototype is deprecated in all versions of C}}
another(1, 2); // both-warning {{passing arguments to 'another' without a prototype is deprecated in all versions of C and is not supported in C2x}}
}
-void order1(); // expected-warning {{a function declaration without a prototype is deprecated in all versions of C and is not supported in C2x}} \
- strict-warning {{a function declaration without a prototype is deprecated in all versions of C}} \
- strict-note {{a function declaration without a prototype is not supported in C2x}}
-void order1(int i); // both-warning {{a function declaration without a prototype is deprecated in all versions of C and is not supported in C2x}}
+void order1(); // both-warning {{a function declaration without a prototype is deprecated in all versions of C and is treated as a zero-parameter prototype in C2x, conflicting with a subsequent declaration}} \
+ strict-warning {{a function declaration without a prototype is deprecated in all versions of C}}
+void order1(int i); // both-note {{conflicting prototype is here}}
-void order2(int i);
-void order2(); // both-warning {{a function declaration without a prototype is deprecated in all versions of C and is not supported in C2x}} \
+void order2(int i); // both-note {{conflicting prototype is here}}
+void order2(); // both-warning {{a function declaration without a prototype is deprecated in all versions of C and is treated as a zero-parameter prototype in C2x, conflicting with a previous declaration}} \
strict-warning {{a function declaration without a prototype is deprecated in all versions of C}}
-void order3(); // expected-warning {{a function declaration without a prototype is deprecated in all versions of C and is not supported in C2x}} \
- strict-warning {{a function declaration without a prototype is deprecated in all versions of C}} \
- strict-note {{a function declaration without a prototype is not supported in C2x}}
-void order3(int i) {} // both-warning {{a function declaration without a prototype is deprecated in all versions of C and is not supported in C2x}}
+void order3(); // both-warning {{a function declaration without a prototype is deprecated in all versions of C and is treated as a zero-parameter prototype in C2x, conflicting with a subsequent definition}} \
+ strict-warning {{a function declaration without a prototype is deprecated in all versions of C}}
+void order3(int i) {} // both-note {{conflicting prototype is here}}
// Just because the prototype is variadic doesn't mean we shouldn't warn on the
// K&R C function definition; this still changes behavior in C2x.
void test(char*,...);
-void test(fmt) // both-warning {{a function declaration without a prototype is deprecated in all versions of C and is not supported in C2x}}
+void test(fmt) // both-warning {{a function definition without a prototype is deprecated in all versions of C and is not supported in C2x}}
char*fmt;
{
}
-// FIXME: we get two diagnostics here when running in pedantic mode. The first
-// comes when forming the function type for the definition, and the second
-// comes from merging the function declarations together. The second is the
-// point at which we know the behavior has changed (because we can see the
-// previous declaration at that point), but we've already issued the type
-// error by that point. It's not ideal to be this chatty, but this situation
-// should be pretty rare.
void blapp(int); // both-note {{previous declaration is here}}
void blapp() { } // both-error {{conflicting types for 'blapp'}} \
// strict-warning {{a function declaration without a prototype is deprecated in all versions of C}}
}
// K&R function definition not preceded by full prototype
-int foo9(a, b) // expected-warning {{a function declaration without a prototype is deprecated in all versions of C and is not supported in C2x}}
+int foo9(a, b) // expected-warning {{a function definition without a prototype is deprecated in all versions of C and is not supported in C2x}}
int a, b;
{
return a + b;
// Function declaration with no types
void foo10(); // expected-warning {{a function declaration without a prototype is deprecated in all versions of C}} \
- expected-note {{a function declaration without a prototype is not supported in C2x}}
+ expected-warning {{a function declaration without a prototype is deprecated in all versions of C and is treated as a zero-parameter prototype in C2x, conflicting with a subsequent definition}}
// CHECK: fix-it:"{{.*}}":{[[@LINE-2]]:12-[[@LINE-2]]:12}:"void"
// K&R function definition with incomplete param list declared
-void foo10(p, p2) void *p; {} // expected-warning {{a function declaration without a prototype is deprecated in all versions of C and is not supported in C2x}} \
+void foo10(p, p2) void *p; {} // expected-warning {{a function definition without a prototype is deprecated in all versions of C and is not supported in C2x}} \
expected-warning {{parameter 'p2' was not declared, defaults to 'int'; ISO C99 and later do not support implicit int}}
void foo11(int p, int p2);
-void foo11(p, p2) int p; int p2; {} // expected-warning {{a function declaration without a prototype is deprecated in all versions of C and is not supported in C2x}}
+void foo11(p, p2) int p; int p2; {} // expected-warning {{a function definition without a prototype is deprecated in all versions of C and is not supported in C2x}}
// PR31020
-void __attribute__((cdecl)) foo12(d) // expected-warning {{a function declaration without a prototype is deprecated in all versions of C and is not supported in C2x}}
+void __attribute__((cdecl)) foo12(d) // expected-warning {{a function definition without a prototype is deprecated in all versions of C and is not supported in C2x}}
short d;
{}