- ``-Wunused-variable`` no longer warn for references extending the lifetime
of temporaries with side effects. This fixes `Issue 54489
<https://github.com/llvm/llvm-project/issues/54489>`_.
+- Modified the behavior of ``-Wstrict-prototypes`` and added a new, related
+ diagnostic ``-Wdeprecated-non-prototype``. The strict prototypes warning will
+ now only diagnose deprecated declarations and definitions of functions
+ without a prototype where the behavior in C2x will remain correct. This
+ diagnostic remains off by default but is now enabled via ``-pedantic`` due to
+ it being a deprecation warning. ``-Wdeprecated-non-prototype`` will diagnose
+ cases where the deprecated declarations or definitions of a function without
+ a prototype will change behavior in C2x. This diagnostic is grouped under the
+ ``-Wstrict-prototypes`` warning group, but is enabled by default.
Non-comprehensive list of changes in this release
-------------------------------------------------
def InvalidNoreturn : DiagGroup<"invalid-noreturn">;
def InvalidSourceEncoding : DiagGroup<"invalid-source-encoding">;
def KNRPromotedParameter : DiagGroup<"knr-promoted-parameter">;
+def DeprecatedNonPrototype : DiagGroup<"deprecated-non-prototype">;
+def StrictPrototypes : DiagGroup<"strict-prototypes", [DeprecatedNonPrototype]>;
def : DiagGroup<"init-self">;
def : DiagGroup<"inline">;
def : DiagGroup<"invalid-pch">;
def note_declaration_not_a_prototype : Note<
"this declaration is not a prototype; add %select{'void'|parameter declarations}0 "
"to make it %select{a prototype for a zero-parameter function|one}0">;
-def warn_strict_prototypes : Warning<
- "this %select{function declaration is not|block declaration is not|"
- "old-style function definition is not preceded by}0 a prototype">,
- InGroup<DiagGroup<"strict-prototypes">>, DefaultIgnore;
+// This is not actually an extension, but we only want it to be enabled in
+// -pedantic mode and this is the most direct way of accomplishing that.
+def warn_strict_prototypes : Extension<
+ "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">;
def warn_missing_variable_declarations : Warning<
"no previous extern declaration for non-static variable %0">,
InGroup<DiagGroup<"missing-variable-declarations">>, DefaultIgnore;
// C: Function types need to be compatible, not identical. This handles
// duplicate function decls like "void f(int); void f(enum X);" properly.
- if (!getLangOpts().CPlusPlus &&
- Context.typesAreCompatible(OldQType, NewQType)) {
- const FunctionType *OldFuncType = OldQType->getAs<FunctionType>();
- const FunctionType *NewFuncType = NewQType->getAs<FunctionType>();
- const FunctionProtoType *OldProto = nullptr;
- if (MergeTypeWithOld && isa<FunctionNoProtoType>(NewFuncType) &&
- (OldProto = dyn_cast<FunctionProtoType>(OldFuncType))) {
- // The old declaration provided a function prototype, but the
- // new declaration does not. Merge in the prototype.
- assert(!OldProto->hasExceptionSpec() && "Exception spec in C");
- SmallVector<QualType, 16> ParamTypes(OldProto->param_types());
- NewQType =
- Context.getFunctionType(NewFuncType->getReturnType(), ParamTypes,
- OldProto->getExtProtoInfo());
- New->setType(NewQType);
- New->setHasInheritedPrototype();
-
- // Synthesize parameters with the same types.
- SmallVector<ParmVarDecl*, 16> Params;
- for (const auto &ParamType : OldProto->param_types()) {
- ParmVarDecl *Param = ParmVarDecl::Create(Context, New, SourceLocation(),
- SourceLocation(), nullptr,
- ParamType, /*TInfo=*/nullptr,
- SC_None, nullptr);
- Param->setScopeInfo(0, Params.size());
- Param->setImplicit();
- Params.push_back(Param);
+ if (!getLangOpts().CPlusPlus) {
+ // If we are merging two functions where only one of them has a prototype,
+ // we may have enough information to decide to issue a diagnostic that the
+ // function without a protoype will change behavior in C2x. This handles
+ // cases like:
+ // void i(); void i(int j);
+ // void i(int j); void i();
+ // void i(); void i(int j) {}
+ // See ActOnFinishFunctionBody() for other cases of the behavior change
+ // diagnostic. See GetFullTypeForDeclarator() for handling of a function
+ // type without a prototype.
+ if (New->hasWrittenPrototype() != Old->hasWrittenPrototype() &&
+ !New->isImplicit() && !Old->isImplicit()) {
+ const FunctionDecl *WithProto, *WithoutProto;
+ if (New->hasWrittenPrototype()) {
+ WithProto = New;
+ WithoutProto = Old;
+ } else {
+ WithProto = Old;
+ WithoutProto = New;
}
- New->setParams(Params);
+ 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.
+ Diag(WithoutProto->getLocation(),
+ diag::warn_non_prototype_changes_behavior);
+ }
+ }
}
- return MergeCompatibleFunctionDecls(New, Old, S, MergeTypeWithOld);
+ if (Context.typesAreCompatible(OldQType, NewQType)) {
+ const FunctionType *OldFuncType = OldQType->getAs<FunctionType>();
+ const FunctionType *NewFuncType = NewQType->getAs<FunctionType>();
+ const FunctionProtoType *OldProto = nullptr;
+ if (MergeTypeWithOld && isa<FunctionNoProtoType>(NewFuncType) &&
+ (OldProto = dyn_cast<FunctionProtoType>(OldFuncType))) {
+ // The old declaration provided a function prototype, but the
+ // new declaration does not. Merge in the prototype.
+ assert(!OldProto->hasExceptionSpec() && "Exception spec in C");
+ SmallVector<QualType, 16> ParamTypes(OldProto->param_types());
+ NewQType =
+ Context.getFunctionType(NewFuncType->getReturnType(), ParamTypes,
+ OldProto->getExtProtoInfo());
+ New->setType(NewQType);
+ New->setHasInheritedPrototype();
+
+ // Synthesize parameters with the same types.
+ SmallVector<ParmVarDecl *, 16> Params;
+ for (const auto &ParamType : OldProto->param_types()) {
+ ParmVarDecl *Param = ParmVarDecl::Create(
+ Context, New, SourceLocation(), SourceLocation(), nullptr,
+ ParamType, /*TInfo=*/nullptr, SC_None, nullptr);
+ Param->setScopeInfo(0, Params.size());
+ Param->setImplicit();
+ Params.push_back(Param);
+ }
+
+ New->setParams(Params);
+ }
+
+ return MergeCompatibleFunctionDecls(New, Old, S, MergeTypeWithOld);
+ }
}
// Check if the function types are compatible when pointer size address
? FixItHint::CreateInsertion(findBeginLoc(), "static ")
: FixItHint{});
}
+ }
- // GNU warning -Wstrict-prototypes
- // Warn if K&R function is defined without a previous declaration.
- // This warning is issued only if the definition itself does not
- // provide a prototype. Only K&R definitions do not provide a
- // prototype.
- if (!FD->hasWrittenPrototype()) {
- TypeSourceInfo *TI = FD->getTypeSourceInfo();
- TypeLoc TL = TI->getTypeLoc();
- FunctionTypeLoc FTL = TL.getAsAdjusted<FunctionTypeLoc>();
- Diag(FTL.getLParenLoc(), diag::warn_strict_prototypes) << 2;
+ // If the function being defined does not have a prototype, then we may
+ // need to diagnose it as changing behavior in C2x because we now know
+ // whether the function accepts arguments or not. This only handles the
+ // case where the definition has no prototype but does have parameters
+ // and either there is no previous potential prototype, or the previous
+ // potential prototype also has no actual prototype. This handles cases
+ // like:
+ // void f(); void f(a) int a; {}
+ // void g(a) int a; {}
+ // See MergeFunctionDecl() for other cases of the behavior change
+ // diagnostic. See GetFullTypeForDeclarator() for handling of a function
+ // type without a prototype.
+ if (!FD->hasWrittenPrototype() && FD->getNumParams() != 0 &&
+ (!PossiblePrototype || (!PossiblePrototype->hasWrittenPrototype() &&
+ !PossiblePrototype->isImplicit()))) {
+ // The function definition has parameters, so this will change behavior
+ // in C2x. If there is a possible prototype, it comes before the
+ // function definition.
+ // FIXME: The declaration may have already been diagnosed as being
+ // deprecated in GetFullTypeForDeclarator() if it had no arguments, but
+ // there's no way to test for the "changes behavior" condition in
+ // SemaType.cpp when forming the declaration's function type. So, we do
+ // this awkward dance instead.
+ //
+ // If we have a possible prototype and it declares a function with a
+ // prototype, we don't want to diagnose it; if we have a possible
+ // prototype and it has no prototype, it may have already been
+ // diagnosed in SemaType.cpp as deprecated depending on whether
+ // -Wstrict-prototypes is enabled. If we already warned about it 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 (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)
+ Diag(PossiblePrototype->getLocation(),
+ diag::note_func_decl_changes_behavior);
}
// Warn on CPUDispatch with an actual body.
diag::warn_noderef_on_non_pointer_or_array);
// GNU warning -Wstrict-prototypes
- // Warn if a function declaration is without a prototype.
+ // Warn if a function declaration or definition is without a prototype.
// This warning is issued for all kinds of unprototyped function
// declarations (i.e. function type typedef, function pointer etc.)
// C99 6.7.5.3p14:
// The empty list in a function declarator that is not part of a definition
// of that function specifies that no information about the number or types
// of the parameters is supplied.
- if (!LangOpts.CPlusPlus &&
- D.getFunctionDefinitionKind() == FunctionDefinitionKind::Declaration) {
+ // See ActOnFinishFunctionBody() and MergeFunctionDecl() for handling of
+ // function declarations whose behavior changes in C2x.
+ if (!LangOpts.CPlusPlus) {
bool IsBlock = false;
for (const DeclaratorChunk &DeclType : D.type_objects()) {
switch (DeclType.Kind) {
-// RUN: %clang_cc1 %s -o %t -emit-llvm -verify
-// expected-no-diagnostics
+// RUN: %clang_cc1 %s -o %t -emit-llvm -verify -std=c89
// PR4289
struct funcptr {
int (*func)();
};
-static int func(f)
+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}}
void *f;
{
return 0;
-// RUN: %clang_cc1 -pedantic -Wunused-label -verify -x c %s
+// RUN: %clang_cc1 -pedantic -Wunused-label -Wno-deprecated-non-prototype -verify -x c %s
// RUN: cp %s %t
// RUN: not %clang_cc1 -pedantic -Wunused-label -fixit -x c %t
-// RUN: %clang_cc1 -pedantic -Wunused-label -Werror -x c %t
+// RUN: %clang_cc1 -pedantic -Wunused-label -Wno-deprecated-non-prototype -Werror -x c %t
// RUN: grep -v CHECK %t | FileCheck %t
/* This is a test of the various code modification hints that are
-// RUN: %clang_cc1 %s -fsyntax-only -verify -pedantic
+// RUN: %clang_cc1 %s -fsyntax-only -verify -pedantic -std=c99
extern int a1[];
-void f0();
+void f0(); /* expected-warning {{a function declaration without a prototype is deprecated in all versions of C}} */
void f1(int [*]);
void f2(int [const *]);
void f3(int [volatile const*]);
}
typedef int atype;
-void test3(x,
+void test3(x, /* expected-warning {{a function declaration 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'}} */
+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}}
// PR3031
foo_t *d; // expected-error {{unknown type name 'foo_t'}}
foo_t a; // expected-error {{unknown type name 'foo_t'}}
-int test6() { return a; } // a should be declared.
+int test6() { /* expected-warning {{a function declaration without a prototype is deprecated in all versions of C}} */
+ return a; // a should be declared.
+}
// Use of tagged type without tag. rdar://6783347
struct xyz { int y; };
xyz b; // expected-error {{must use 'struct' tag to refer to type 'xyz'}}
myenum c; // expected-error {{must use 'enum' tag to refer to type 'myenum'}}
-float *test7() {
+float *test7(void) {
// We should recover 'b' by parsing it with a valid type of "struct xyz", which
// allows us to diagnose other bad things done with y, such as this.
return &b.y; // expected-warning {{incompatible pointer types returning 'int *' from a function with result type 'float *'}}
}
-struct xyz test8() { return a; } // a should be be marked invalid, no diag.
+struct xyz test8(void) { return a; } // a should be be marked invalid, no diag.
// Verify that implicit int still works.
struct test11 { int a; } const test11x;
// PR6216
-void test12() {
+void test12(void) {
(void)__builtin_offsetof(struct { char c; int i; }, i);
}
// PR7617 - error recovery on missing ;.
-void test14() // expected-error {{expected ';' after top level declarator}}
+void test14(void) // expected-error {{expected ';' after top level declarator}}
-void test14a();
+void test14a(void);
void *test14b = (void*)test14a; // Make sure test14a didn't get skipped.
// rdar://problem/8358508
-long struct X { int x; } test15(); // expected-error {{'long struct' is invalid}}
-
-void test16(i) int i j; { } // expected-error {{expected ';' at end of declaration}}
-void test17(i, j) int i, j k; { } // expected-error {{expected ';' at end of declaration}}
-void knrNoSemi(i) int i { } // expected-error {{expected ';' at end of declaration}}
+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}}
+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}}
+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}}
// PR12595
-void test18() {
+void test18(void) {
int x = 4+(5-12)); // expected-error {{extraneous ')' before ';'}}
}
-// RUN: %clang_cc1 -fsyntax-only -W -Wall -Werror -verify %s
+// RUN: %clang_cc1 -fsyntax-only -W -Wall -Wno-deprecated-non-prototype -Werror -verify %s -std=c99
// expected-no-diagnostics
int f(int i __attribute__((__unused__)))
// RUN: %clang_cc1 %s -verify -pedantic -fsyntax-only
-// expected-no-diagnostics
-__kernel void test()
+__kernel void test() // expected-warning {{a function declaration without a prototype is deprecated in all versions of C}}
{
}
-kernel void test1()
+kernel void test1() // expected-warning {{a function declaration without a prototype is deprecated in all versions of C}}
{
}
-// RUN: %clang_cc1 -fsyntax-only %s -verify
+// RUN: %clang_cc1 -fsyntax-only %s -verify -Wno-deprecated-non-prototype -std=c99
int x(a) int a; {return a;}
int y(b) int b; {return a;} // expected-error {{use of undeclared identifier}}
-// RUN: %clang_cc1 -fsyntax-only -verify %s
+// RUN: %clang_cc1 -fsyntax-only -verify %s -std=c99
-int f3(y, x,
+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}}
x) // expected-error {{redefinition of parameter}}
int y,
x, // expected-note {{previous declaration is here}}
int (*funcptr3[5])(long);
int sz8 = sizeof(^int (*[5])(long) {return funcptr3;}); // expected-error {{block cannot return array type}} expected-warning {{incompatible pointer to integer conversion}}
int sz9 = sizeof(^int(*())()[3]{ }); // expected-error {{function cannot return array type}}
+ // expected-warning@-1 2 {{a function declaration without a prototype is deprecated in all versions of C}}
void foo6(void) {
int (^b)(int) __attribute__((noreturn));
// 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; {}
+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 t0(void) {
f0(1); // expected-warning{{too few arguments}}
}
-void f1(a, b) int a, b; {}
+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 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}}
+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}}
typedef void (*f3)(void);
f3 t3(int b) { return b? f0 : f1; } // okay
char *rindex();
}
+// FIXME: we should diagnose this case, but when merging function declarations,
+// we don't diagnose it because the function is a builtin.
char *rindex(s, c)
register char *s, c; // expected-warning{{promoted type 'char *' of K&R function parameter is not compatible with the parameter type 'const char *' declared in a previous prototype}}
{
// PR8314
void proto(int);
-void proto(x)
+void proto(x) // expected-warning {{a function declaration 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)
+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}}
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}}
{}
-// RUN: %clang_cc1 -fsyntax-only -verify -pedantic %s
-// expected-no-diagnostics
+// RUN: %clang_cc1 -fsyntax-only -verify -pedantic %s -std=c99
// PR4287
#include <stdarg.h>
char *foo = "test";
int test(char*,...);
-int test(fmt)
+int test(fmt) // expected-warning {{a function declaration without a prototype is deprecated in all versions of C and is not supported in C2x}}
char*fmt;
{
va_list ap;
return x;
}
-void exit();
+void exit(); // expected-warning {{a function declaration without a prototype is deprecated in all versions of C}}
-int main(argc,argv)
+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 argc;char**argv;
{
exit(test("",foo));
-// RUN: %clang_cc1 %s -fsyntax-only -pedantic -verify
-// RUN: %clang_cc1 %s -fsyntax-only -pedantic -verify -DPREDECLARE
+// RUN: %clang_cc1 %s -fsyntax-only -pedantic -verify -std=c99
+// RUN: %clang_cc1 %s -fsyntax-only -pedantic -verify -DPREDECLARE -std=c99
#ifdef PREDECLARE
// PR16344
// PR4290
// The following declaration is compatible with vfprintf, so we shouldn't
// reject.
-int vfprintf();
+int vfprintf(); // expected-warning {{a function declaration without a prototype is deprecated in all versions of C}}
#ifndef PREDECLARE
// expected-warning@-2 {{requires inclusion of the header <stdio.h>}}
#endif
--- /dev/null
+// RUN: %clang_cc1 -fsyntax-only -verify=both,expected %s
+// RUN: %clang_cc1 -fsyntax-only -Wstrict-prototypes -verify=both,strict %s
+
+// Test both with and without -Wstrict-prototypes because there are complicated
+// interactions between it and -Wdeprecated-non-prototype.
+
+// Off by default warnings, enabled by -pedantic or -Wstrict-prototypes
+void other_func(); // strict-warning {{a function declaration without a prototype is deprecated in all versions of C}}
+void other_func() {} // strict-warning {{a function declaration without a prototype is deprecated in all versions of C}}
+
+void never_defined(); // strict-warning {{a function declaration without a prototype is deprecated in all versions of C}}
+
+typedef void (*fp)(); // strict-warning {{a function declaration without a prototype is deprecated in all versions of C}}
+
+void blerp(
+ void (*func_ptr)() // strict-warning {{a function declaration without a prototype is deprecated in all versions of C}}
+);
+
+void whatever(void) {
+ extern void hoo_boy(); // strict-warning {{a function declaration without a prototype is deprecated in all versions of C}}
+}
+
+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 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 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 another(); // strict-warning {{a function declaration without a prototype is deprecated in all versions of C}}
+
+int main(void) {
+ another(1, 2); // OK for now
+}
+
+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 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}} \
+ 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}}
+
+// 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}}
+ 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
+// warning by that point. It's not ideal to be this chatty, but this situation
+// should be pretty rare.
+void blapp(int);
+void blapp() { } // both-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}}
-// RUN: %clang_cc1 -fsyntax-only -Wdocumentation -Wmissing-prototypes -verify %s
-// RUN: %clang_cc1 -fsyntax-only -Wdocumentation -Wmissing-prototypes -fdiagnostics-parseable-fixits %s 2>&1 | FileCheck %s
+// RUN: %clang_cc1 -fsyntax-only -Wdocumentation -Wmissing-prototypes -Wno-deprecated-non-prototype -verify %s
+// RUN: %clang_cc1 -fsyntax-only -Wdocumentation -Wmissing-prototypes -Wno-deprecated-non-prototype -fdiagnostics-parseable-fixits %s 2>&1 | FileCheck %s
int f(); // expected-note{{this declaration is not a prototype; add parameter declarations to make it one}}
// CHECK-NOT: fix-it:"{{.*}}":{[[@LINE-1]]:{{.*}}-[[@LINE-1]]:{{.*}}}:"{{.*}}"
// RUN: %clang_cc1 -triple i386-pc-unknown -fsyntax-only -Wstrict-prototypes -fdiagnostics-parseable-fixits %s 2>&1 | FileCheck %s
// function definition with 0 params, no prototype, no preceding declaration.
-void foo0() {} // expected-warning {{this old-style function definition is not preceded by a prototype}}
+void foo0() {} // expected-warning {{a function declaration without a prototype is deprecated in all versions of C}}
// function declaration with unspecified params
-void foo1(); // expected-warning {{this function declaration is not a prototype}}
+void foo1(); // expected-warning {{a function declaration without a prototype is deprecated in all versions of C}}
// CHECK: fix-it:"{{.*}}":{[[@LINE-1]]:11-[[@LINE-1]]:11}:"void"
// function declaration with 0 params
void foo2(void);
// function definition with 0 params, no prototype.
-void foo1() {} // expected-warning {{this old-style function definition is not preceded by a prototype}}
+void foo1() {} // expected-warning {{a function declaration without a prototype is deprecated in all versions of C}}
// function definition with 0 params, prototype.
void foo2(void) {}
// function type typedef unspecified params
-typedef void foo3(); // expected-warning {{this function declaration is not a prototype}}
+typedef void foo3(); // expected-warning {{a function declaration without a prototype is deprecated in all versions of C}}
// CHECK: fix-it:"{{.*}}":{[[@LINE-1]]:19-[[@LINE-1]]:19}:"void"
// global fp unspecified params
-void (*foo4)(); // expected-warning {{this function declaration is not a prototype}}
+void (*foo4)(); // expected-warning {{a function declaration without a prototype is deprecated in all versions of C}}
// CHECK: fix-it:"{{.*}}":{[[@LINE-1]]:14-[[@LINE-1]]:14}:"void"
// struct member fp unspecified params
-struct { void (*foo5)(); } s; // expected-warning {{this function declaration is not a prototype}}
+struct { void (*foo5)(); } s; // expected-warning {{a function declaration without a prototype is deprecated in all versions of C}}
// CHECK: fix-it:"{{.*}}":{[[@LINE-1]]:23-[[@LINE-1]]:23}:"void"
// param fp unspecified params
-void bar2(void (*foo6)()) { // expected-warning {{this function declaration is not a prototype}}
+void bar2(void (*foo6)()) { // expected-warning {{a function declaration without a prototype is deprecated in all versions of C}}
// CHECK: fix-it:"{{.*}}":{[[@LINE-1]]:24-[[@LINE-1]]:24}:"void"
// local fp unspecified params
- void (*foo7)() = 0; // expected-warning {{this function declaration is not a prototype}}
+ void (*foo7)() = 0; // expected-warning {{a function declaration without a prototype is deprecated in all versions of C}}
// CHECK: fix-it:"{{.*}}":{[[@LINE-1]]:16-[[@LINE-1]]:16}:"void"
// array fp unspecified params
- void (*foo8[2])() = {0}; // expected-warning {{this function declaration is not a prototype}}
+ void (*foo8[2])() = {0}; // expected-warning {{a function declaration without a prototype is deprecated in all versions of C}}
// CHECK: fix-it:"{{.*}}":{[[@LINE-1]]:19-[[@LINE-1]]:19}:"void"
}
// function type cast using using an anonymous function declaration
void bar3(void) {
// casting function w/out prototype to unspecified params function type
- (void)(void(*)()) foo1; // expected-warning {{this function declaration is not a prototype}}
+ (void)(void(*)()) foo1; // expected-warning {{a function declaration without a prototype is deprecated in all versions of C}}
// CHECK: fix-it:"{{.*}}":{[[@LINE-1]]:18-[[@LINE-1]]:18}:"void"
// .. specified params
(void)(void(*)(void)) foo1;
}
// K&R function definition not preceded by full prototype
-int foo9(a, b) // expected-warning {{old-style function definition is not preceded by a 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 a, b;
{
return a + b;
}
// Function declaration with no types
-void foo10(); // expected-warning {{this function declaration is not a prototype}}
- // CHECK: fix-it:"{{.*}}":{[[@LINE-1]]:12-[[@LINE-1]]:12}:"void"
+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}}
+ // 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 {{old-style function definition is not preceded by a prototype}}
+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}}
-// K&R function definition with previous prototype declared is not diagnosed.
void foo11(int p, int p2);
-void foo11(p, p2) 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}}
// PR31020
-void __attribute__((cdecl)) foo12(d) // expected-warning {{this old-style function definition is not preceded by a prototype}}
+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}}
short d;
{}
@interface Foo
-@property (nonatomic, copy) void (^noProtoBlock)(); // expected-warning {{this block declaration is not a prototype}}
+@property (nonatomic, copy) void (^noProtoBlock)(); // expected-warning {{a block declaration without a prototype is deprecated}}
@property (nonatomic, copy) void (^block)(void); // no warning
-- doStuff:(void (^)()) completionHandler; // expected-warning {{this block declaration is not a prototype}}
+- doStuff:(void (^)()) completionHandler; // expected-warning {{a block declaration without a prototype is deprecated}}
- doOtherStuff:(void (^)(void)) completionHandler; // no warning
@end
-void foo() { // expected-warning {{this old-style function definition is not preceded by a prototype}}
- void (^block)() = // expected-warning {{this block declaration is not a prototype}}
+void foo() { // expected-warning {{a function declaration without a prototype is deprecated in all versions of C}}
+ void (^block)() = // expected-warning {{a block declaration without a prototype is deprecated}}
^void(int arg) { // no warning
};
- void (^block2)(void) = ^void() { // no warning
+ // FIXME: this should say "a block declaration" instead, but block literal
+ // expressions do not track their full declarator information, so we don't
+ // know it's a block when diagnosing.
+ void (^block2)(void) = ^void() { // expected-warning {{a function declaration without a prototype is deprecated in all versions of C}}
};
void (^block3)(void) = ^ { // no warning
};
}
-void (*(^(*(^block4)()) // expected-warning {{this block declaration is not a prototype}}
- ()) // expected-warning {{this function declaration is not a prototype}}
- ()) // expected-warning {{this block declaration is not a prototype}}
- (); // expected-warning {{this function declaration is not a prototype}}
+void (*(^(*(^block4)()) // expected-warning {{a block declaration without a prototype is deprecated}}
+ ()) // expected-warning {{a function declaration without a prototype is deprecated in all versions of C}}
+ ()) // expected-warning {{a block declaration without a prototype is deprecated}}
+ (); // expected-warning {{a function declaration without a prototype is deprecated in all versions of C}}
// RUN: %clang_cc1 -fblocks -fsyntax-only -verify -Wno-objc-root-class %s
// REQUIRES: LP64
-
@class NSObject;
NONNULL_ATTR
extern void func4 (void (^block1)(), void (^block2)()) __attribute__((nonnull(1)))
__attribute__((nonnull(2)));
-void func6();
+void func6(); // expected-warning {{a function declaration without a prototype is deprecated in all versions of C and is not supported in C2x}}
void func7();
void
__attribute__((nonnull))
void _dispatch_queue_push_list(dispatch_object_t _head); // no warning
-void func6(dispatch_object_t _head) {
+void func6(dispatch_object_t _head) { // expected-warning {{a function declaration without a prototype is deprecated in all versions of C and is not supported in C2x}}
_dispatch_queue_push_list(0); // expected-warning {{null passed to a callee that requires a non-null argument}}
_dispatch_queue_push_list(_head._do); // no warning
}
-// RUN: %clang_cc1 %s -verify -pedantic -fsyntax-only
-// RUN: %clang_cc1 %s -cl-std=CL2.0 -verify -pedantic -fsyntax-only
-// RUN: %clang_cc1 %s -cl-std=CL3.0 -cl-ext=+__opencl_c_generic_address_space -verify -pedantic -fsyntax-only
+// RUN: %clang_cc1 %s -verify=expected,c -pedantic -fsyntax-only
+// RUN: %clang_cc1 %s -cl-std=CL2.0 -verify=expected,c -pedantic -fsyntax-only
+// RUN: %clang_cc1 %s -cl-std=CL3.0 -cl-ext=+__opencl_c_generic_address_space -verify=expected,c -pedantic -fsyntax-only
// RUN: %clang_cc1 %s -cl-std=clc++1.0 -verify -pedantic -fsyntax-only
// RUN: %clang_cc1 %s -cl-std=clc++2021 -cl-ext=+__opencl_c_generic_address_space -verify -pedantic -fsyntax-only
void func_with_array_param(const unsigned data[16]);
-__kernel void k() {
+__kernel void k() { // c-warning {{a function declaration without a prototype is deprecated in all versions of C}}
unsigned data[16];
func_with_array_param(data);
}
typedef struct {int a;} ndrange_t;
// Diagnostic tests for different overloads of enqueue_kernel from Table 6.13.17.1 of OpenCL 2.0 Spec.
-kernel void enqueue_kernel_tests() {
+kernel void enqueue_kernel_tests(void) {
queue_t default_queue;
unsigned flags = 0;
QUALS ndrange_t ndrange;
}
// Diagnostic tests for get_kernel_work_group_size and allowed block parameter types in dynamic parallelism.
-kernel void work_group_size_tests() {
+kernel void work_group_size_tests(void) {
void (^const block_A)(void) = ^{
return;
};
kernel void foo(global unsigned int *buf)
{
ndrange_t n;
- buf[0] = get_kernel_max_sub_group_size_for_ndrange(n, ^(){});
+ // FIXME: this should be diagnosed as a block instead of a function, but
+ // block literals don't track the ^ as part of their declarator.
+ buf[0] = get_kernel_max_sub_group_size_for_ndrange(n, ^(){}); // expected-warning {{a function declaration without a prototype is deprecated in all versions of C}}
buf[0] = get_kernel_max_sub_group_size_for_ndrange(0, ^(){}); // expected-error{{illegal call to 'get_kernel_max_sub_group_size_for_ndrange', expected 'ndrange_t' argument type}}
+ // expected-warning@-1 {{a function declaration without a prototype is deprecated in all versions of C}}
buf[0] = get_kernel_max_sub_group_size_for_ndrange(n, 1); // expected-error{{illegal call to 'get_kernel_max_sub_group_size_for_ndrange', expected block argument type}}
}
kernel void bar(global unsigned int *buf)
{
__private ndrange_t n;
- buf[0] = get_kernel_sub_group_count_for_ndrange(n, ^(){});
+ // FIXME: this should be diagnosed as a block instead of a function, but
+ // block literals don't track the ^ as part of their declarator.
+ buf[0] = get_kernel_sub_group_count_for_ndrange(n, ^(){}); // expected-warning {{a function declaration without a prototype is deprecated in all versions of C}}
buf[0] = get_kernel_sub_group_count_for_ndrange(0, ^(){}); // expected-error{{illegal call to 'get_kernel_sub_group_count_for_ndrange', expected 'ndrange_t' argument type}}
+ // expected-warning@-1 {{a function declaration without a prototype is deprecated in all versions of C}}
buf[0] = get_kernel_sub_group_count_for_ndrange(n, 1); // expected-error{{illegal call to 'get_kernel_sub_group_count_for_ndrange', expected block argument type}}
}
kernel void foo1(global unsigned int *buf)
{
ndrange_t n;
+ // FIXME: this should be diagnosed as a block instead of a function, but
+ // block literals don't track the ^ as part of their declarator.
buf[0] = get_kernel_max_sub_group_size_for_ndrange(n, ^(){}); // expected-error {{use of declaration 'get_kernel_max_sub_group_size_for_ndrange' requires cl_khr_subgroups or __opencl_c_subgroups support}}
+ // expected-warning@-1 {{a function declaration without a prototype is deprecated in all versions of C}}
}
kernel void bar1(global unsigned int *buf)
{
ndrange_t n;
+ // FIXME: this should be diagnosed as a block instead of a function, but
+ // block literals don't track the ^ as part of their declarator.
buf[0] = get_kernel_sub_group_count_for_ndrange(n, ^(){}); // expected-error {{use of declaration 'get_kernel_sub_group_count_for_ndrange' requires cl_khr_subgroups or __opencl_c_subgroups support}}
+ // expected-warning@-1 {{a function declaration without a prototype is deprecated in all versions of C}}
}
#endif // ifdef cl_khr_subgroups
#endif
// Expect no diagnostics for an empty parameter list.
-void bar();
+void bar(); // expected-warning {{a function declaration without a prototype is deprecated in all versions of C}}
-void bar()
+void bar() // expected-warning {{a function declaration without a prototype is deprecated in all versions of C}}
{
// declaring a function pointer is an error
void (*fptr)(int);