[clang] 11da1b5 - [C89/C2x] Improve diagnostics around strict prototypes in C

Aaron Ballman via cfe-commits cfe-commits at lists.llvm.org
Fri Apr 8 13:23:53 PDT 2022


Author: Aaron Ballman
Date: 2022-04-08T16:19:58-04:00
New Revision: 11da1b53d8cd3507959022cd790d5a7ad4573d94

URL: https://github.com/llvm/llvm-project/commit/11da1b53d8cd3507959022cd790d5a7ad4573d94
DIFF: https://github.com/llvm/llvm-project/commit/11da1b53d8cd3507959022cd790d5a7ad4573d94.diff

LOG: [C89/C2x] Improve diagnostics around strict prototypes in C

Functions without prototypes in C (also known as K&R C functions) were
introduced into C89 as a deprecated feature and C2x is now reclaiming
that syntax space with different semantics. However, Clang's
-Wstrict-prototypes diagnostic is off-by-default (even in pedantic
mode) and does not suffice to warn users about issues in their code.

This patch changes the behavior of -Wstrict-prototypes to only diagnose
declarations and definitions which are not going to change behavior in
C2x mode, and enables the diagnostic in -pedantic mode. The diagnostic
is now specifically about the fact that the feature is deprecated.

It also adds -Wdeprecated-non-prototype, which is grouped under
-Wstrict-prototypes and diagnoses declarations or definitions which
will change behavior in C2x mode. This diagnostic is enabled by default
because the risk is higher for the user to continue to use the
deprecated feature.

Differential Revision: https://reviews.llvm.org/D122895

Added: 
    clang/test/Sema/warn-deprecated-non-prototype.c

Modified: 
    clang/docs/ReleaseNotes.rst
    clang/include/clang/Basic/DiagnosticGroups.td
    clang/include/clang/Basic/DiagnosticSemaKinds.td
    clang/lib/Sema/SemaDecl.cpp
    clang/lib/Sema/SemaType.cpp
    clang/test/CodeGen/2009-06-01-addrofknr.c
    clang/test/FixIt/fixit.c
    clang/test/Parser/declarators.c
    clang/test/Parser/knr_parameter_attributes.c
    clang/test/Parser/opencl-kernel.cl
    clang/test/Parser/traditional_arg_scope.c
    clang/test/Sema/arg-duplicate.c
    clang/test/Sema/block-return.c
    clang/test/Sema/knr-def-call.c
    clang/test/Sema/knr-variadic-def.c
    clang/test/Sema/vfprintf-valid-redecl.c
    clang/test/Sema/warn-missing-prototypes.c
    clang/test/Sema/warn-strict-prototypes.c
    clang/test/Sema/warn-strict-prototypes.m
    clang/test/SemaObjC/nonnull.m
    clang/test/SemaOpenCL/address-spaces.cl
    clang/test/SemaOpenCL/cl20-device-side-enqueue.cl
    clang/test/SemaOpenCL/func.cl

Removed: 
    


################################################################################
diff  --git a/clang/docs/ReleaseNotes.rst b/clang/docs/ReleaseNotes.rst
index 2729213ffe70b..f4feaeabf3548 100644
--- a/clang/docs/ReleaseNotes.rst
+++ b/clang/docs/ReleaseNotes.rst
@@ -129,6 +129,15 @@ Improvements to Clang's diagnostics
 - ``-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
 -------------------------------------------------

diff  --git a/clang/include/clang/Basic/DiagnosticGroups.td b/clang/include/clang/Basic/DiagnosticGroups.td
index eb73732838667..ebcbb798eb941 100644
--- a/clang/include/clang/Basic/DiagnosticGroups.td
+++ b/clang/include/clang/Basic/DiagnosticGroups.td
@@ -444,6 +444,8 @@ def InlineNamespaceReopenedNoninline
 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">;

diff  --git a/clang/include/clang/Basic/DiagnosticSemaKinds.td b/clang/include/clang/Basic/DiagnosticSemaKinds.td
index a6516436ae54d..3213163ee7876 100644
--- a/clang/include/clang/Basic/DiagnosticSemaKinds.td
+++ b/clang/include/clang/Basic/DiagnosticSemaKinds.td
@@ -5560,10 +5560,16 @@ def warn_missing_prototype : Warning<
 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;

diff  --git a/clang/lib/Sema/SemaDecl.cpp b/clang/lib/Sema/SemaDecl.cpp
index ce1eb2e763052..a99b9833b3f53 100644
--- a/clang/lib/Sema/SemaDecl.cpp
+++ b/clang/lib/Sema/SemaDecl.cpp
@@ -3879,39 +3879,118 @@ bool Sema::MergeFunctionDecl(FunctionDecl *New, NamedDecl *&OldD,
 
   // 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
@@ -14838,18 +14917,63 @@ Decl *Sema::ActOnFinishFunctionBody(Decl *dcl, Stmt *Body,
                       ? 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.

diff  --git a/clang/lib/Sema/SemaType.cpp b/clang/lib/Sema/SemaType.cpp
index d9f7995a5ac3f..43ab9070aa9b9 100644
--- a/clang/lib/Sema/SemaType.cpp
+++ b/clang/lib/Sema/SemaType.cpp
@@ -5548,15 +5548,16 @@ static TypeSourceInfo *GetFullTypeForDeclarator(TypeProcessingState &state,
            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) {

diff  --git a/clang/test/CodeGen/2009-06-01-addrofknr.c b/clang/test/CodeGen/2009-06-01-addrofknr.c
index f987e3270c873..1c8c9430a9f08 100644
--- a/clang/test/CodeGen/2009-06-01-addrofknr.c
+++ b/clang/test/CodeGen/2009-06-01-addrofknr.c
@@ -1,12 +1,11 @@
-// 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;

diff  --git a/clang/test/FixIt/fixit.c b/clang/test/FixIt/fixit.c
index f94b1eff8a928..67bd94721d610 100644
--- a/clang/test/FixIt/fixit.c
+++ b/clang/test/FixIt/fixit.c
@@ -1,7 +1,7 @@
-// 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

diff  --git a/clang/test/Parser/declarators.c b/clang/test/Parser/declarators.c
index 48936d5922696..0faedca8d29b9 100644
--- a/clang/test/Parser/declarators.c
+++ b/clang/test/Parser/declarators.c
@@ -1,8 +1,8 @@
-// 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*]);
@@ -27,11 +27,12 @@ void test2(int *P, int A) {
 }
 
 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
@@ -43,7 +44,9 @@ int (test5), ;  // expected-error {{expected identifier or '('}}
 
 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; };
@@ -51,13 +54,13 @@ enum myenum { ASDFAS };
 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.
@@ -78,7 +81,7 @@ struct test10 { int a; } static test10x;
 struct test11 { int a; } const test11x;
 
 // PR6216
-void test12() {
+void test12(void) {
   (void)__builtin_offsetof(struct { char c; int i; }, i);
 }
 
@@ -91,21 +94,23 @@ struct X<foo::int> { }; // expected-error{{expected identifier or '('}}
 
 // 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 ';'}}
 }
 

diff  --git a/clang/test/Parser/knr_parameter_attributes.c b/clang/test/Parser/knr_parameter_attributes.c
index b11a75ed20753..93c866bfee4e1 100644
--- a/clang/test/Parser/knr_parameter_attributes.c
+++ b/clang/test/Parser/knr_parameter_attributes.c
@@ -1,4 +1,4 @@
-// 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__)))

diff  --git a/clang/test/Parser/opencl-kernel.cl b/clang/test/Parser/opencl-kernel.cl
index 01c7ed6b5ab69..e509ed59a9ea3 100644
--- a/clang/test/Parser/opencl-kernel.cl
+++ b/clang/test/Parser/opencl-kernel.cl
@@ -1,10 +1,9 @@
 // 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}}
 {
 }

diff  --git a/clang/test/Parser/traditional_arg_scope.c b/clang/test/Parser/traditional_arg_scope.c
index 3811d0d88cdea..ee2a011142477 100644
--- a/clang/test/Parser/traditional_arg_scope.c
+++ b/clang/test/Parser/traditional_arg_scope.c
@@ -1,4 +1,4 @@
-// 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}}

diff  --git a/clang/test/Sema/arg-duplicate.c b/clang/test/Sema/arg-duplicate.c
index feeb458a3f42b..70aab5f95b12f 100644
--- a/clang/test/Sema/arg-duplicate.c
+++ b/clang/test/Sema/arg-duplicate.c
@@ -1,6 +1,6 @@
-// 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}}

diff  --git a/clang/test/Sema/block-return.c b/clang/test/Sema/block-return.c
index 1ad76dcd672fc..a1aa63bd6bb46 100644
--- a/clang/test/Sema/block-return.c
+++ b/clang/test/Sema/block-return.c
@@ -99,6 +99,7 @@ bptr foo5(int j) {
 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 at -1 2 {{a function declaration without a prototype is deprecated in all versions of C}}
 
 void foo6(void) {
   int (^b)(int) __attribute__((noreturn));

diff  --git a/clang/test/Sema/knr-def-call.c b/clang/test/Sema/knr-def-call.c
index 2bd4a79fd0f81..36aeab358e37b 100644
--- a/clang/test/Sema/knr-def-call.c
+++ b/clang/test/Sema/knr-def-call.c
@@ -1,18 +1,19 @@
 // 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
@@ -22,6 +23,8 @@ void f4() {
     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}}
 {
@@ -30,7 +33,7 @@ char *rindex(s, c)
 
 // 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;
 {
 }
@@ -42,6 +45,6 @@ void use_proto() {
 
 // 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}}
 {}

diff  --git a/clang/test/Sema/knr-variadic-def.c b/clang/test/Sema/knr-variadic-def.c
index 934f32fd26b17..6daaa0a97a7eb 100644
--- a/clang/test/Sema/knr-variadic-def.c
+++ b/clang/test/Sema/knr-variadic-def.c
@@ -1,12 +1,11 @@
-// 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;
@@ -20,9 +19,9 @@ int test(fmt)
         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));

diff  --git a/clang/test/Sema/vfprintf-valid-redecl.c b/clang/test/Sema/vfprintf-valid-redecl.c
index eb5c4d3307181..7cd3cb7a00f19 100644
--- a/clang/test/Sema/vfprintf-valid-redecl.c
+++ b/clang/test/Sema/vfprintf-valid-redecl.c
@@ -1,5 +1,5 @@
-// 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
@@ -12,7 +12,7 @@ int vfprintf(void) { return 0; } // expected-warning {{requires inclusion of the
 // 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 at -2 {{requires inclusion of the header <stdio.h>}}
 #endif

diff  --git a/clang/test/Sema/warn-deprecated-non-prototype.c b/clang/test/Sema/warn-deprecated-non-prototype.c
new file mode 100644
index 0000000000000..57e03968e9fd7
--- /dev/null
+++ b/clang/test/Sema/warn-deprecated-non-prototype.c
@@ -0,0 +1,73 @@
+// 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}}

diff  --git a/clang/test/Sema/warn-missing-prototypes.c b/clang/test/Sema/warn-missing-prototypes.c
index 1830b3ff9e731..37176c66de4b6 100644
--- a/clang/test/Sema/warn-missing-prototypes.c
+++ b/clang/test/Sema/warn-missing-prototypes.c
@@ -1,5 +1,5 @@
-// 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]]:{{.*}}}:"{{.*}}"

diff  --git a/clang/test/Sema/warn-strict-prototypes.c b/clang/test/Sema/warn-strict-prototypes.c
index 50b0f7d060f2e..4dc7913cd33e7 100644
--- a/clang/test/Sema/warn-strict-prototypes.c
+++ b/clang/test/Sema/warn-strict-prototypes.c
@@ -2,70 +2,70 @@
 // 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;
 {}
 

diff  --git a/clang/test/Sema/warn-strict-prototypes.m b/clang/test/Sema/warn-strict-prototypes.m
index e2fde8ee38fc1..edb8bc6ea388b 100644
--- a/clang/test/Sema/warn-strict-prototypes.m
+++ b/clang/test/Sema/warn-strict-prototypes.m
@@ -2,25 +2,28 @@
 
 @interface Foo
 
- at property (nonatomic, copy) void (^noProtoBlock)(); // expected-warning {{this block declaration is not a prototype}}
+ at 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}}

diff  --git a/clang/test/SemaObjC/nonnull.m b/clang/test/SemaObjC/nonnull.m
index 48594327192fb..303a201f48618 100644
--- a/clang/test/SemaObjC/nonnull.m
+++ b/clang/test/SemaObjC/nonnull.m
@@ -2,7 +2,6 @@
 
 // RUN: %clang_cc1 -fblocks -fsyntax-only -verify -Wno-objc-root-class %s
 // REQUIRES: LP64
-
 @class NSObject;
 
 NONNULL_ATTR
@@ -23,7 +22,7 @@ extern void func3 (void (^block1)(), int, void (^block2)(), int)
 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
@@ -63,7 +62,7 @@ extern void func4 (void (^block1)(), void (^block2)()) __attribute__((nonnull(1)
 __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
 }

diff  --git a/clang/test/SemaOpenCL/address-spaces.cl b/clang/test/SemaOpenCL/address-spaces.cl
index 5fe79eadd7646..03f303575964b 100644
--- a/clang/test/SemaOpenCL/address-spaces.cl
+++ b/clang/test/SemaOpenCL/address-spaces.cl
@@ -1,6 +1,6 @@
-// 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
 
@@ -251,7 +251,7 @@ void func_multiple_addr(void) {
 
 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);
 }

diff  --git a/clang/test/SemaOpenCL/cl20-device-side-enqueue.cl b/clang/test/SemaOpenCL/cl20-device-side-enqueue.cl
index 344297ebbe0ca..7e3bcb5290f18 100644
--- a/clang/test/SemaOpenCL/cl20-device-side-enqueue.cl
+++ b/clang/test/SemaOpenCL/cl20-device-side-enqueue.cl
@@ -11,7 +11,7 @@
 
 typedef struct {int a;} ndrange_t;
 // Diagnostic tests for 
diff erent 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;
@@ -169,7 +169,7 @@ kernel void enqueue_kernel_tests() {
 }
 
 // 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;
   };
@@ -223,16 +223,22 @@ kernel void work_group_size_tests() {
 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 at -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 at -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}}
 }
 
@@ -241,12 +247,18 @@ kernel void bar(global unsigned int *buf)
 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 at -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 at -1 {{a function declaration without a prototype is deprecated in all versions of C}}
 }
 #endif // ifdef cl_khr_subgroups

diff  --git a/clang/test/SemaOpenCL/func.cl b/clang/test/SemaOpenCL/func.cl
index 233e82f244975..b11de505d73da 100644
--- a/clang/test/SemaOpenCL/func.cl
+++ b/clang/test/SemaOpenCL/func.cl
@@ -43,9 +43,9 @@ void foo(void*);
 #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);


        


More information about the cfe-commits mailing list