Index: clang/include/clang/Basic/DiagnosticSemaKinds.td =================================================================== --- clang/include/clang/Basic/DiagnosticSemaKinds.td +++ clang/include/clang/Basic/DiagnosticSemaKinds.td @@ -5589,8 +5589,10 @@ 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; -def note_func_decl_changes_behavior : Note< - "a function declaration without a prototype is not supported in C2x">; +def warn_prototype_changes_behavior : Warning< + "this function %select{declaration|definition}0 with a prototype will change " + "behavior in C2x because of a previous declaration with no prototype">, + InGroup; def warn_missing_variable_declarations : Warning< "no previous extern declaration for non-static variable %0">, InGroup>, DefaultIgnore; Index: clang/lib/Sema/SemaDecl.cpp =================================================================== --- clang/lib/Sema/SemaDecl.cpp +++ clang/lib/Sema/SemaDecl.cpp @@ -3941,11 +3941,8 @@ // 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 we didn't warn about it being deprecated (because the diagnostic + // is not enabled), warn now that it is deprecated and changes behavior. if (Diags.isIgnored(diag::warn_strict_prototypes, WithoutProto->getLocation())) { if (WithoutProto->getBuiltinID() == 0 && @@ -3960,8 +3957,6 @@ } Diag(WithoutProto->getLocation(), PD); } - } else { - AddNote = true; } // Because the function with a prototype has parameters but a previous @@ -3977,20 +3972,18 @@ 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. + // attach a note to the one without a prototype if needed. If the + // declaration with the prototype is going to be a definition, warn + // about the definition changing behavior rather than the + // declaration. + bool WarnAboutDefn = false; + if (New == WithProto) + WarnAboutDefn = NewDeclIsDefn; + Diag(WithProto->getLocation(), - diag::warn_non_prototype_changes_behavior); - if (AddNote && WithoutProto->getBuiltinID() == 0) - Diag(WithoutProto->getLocation(), - diag::note_func_decl_changes_behavior); + diag::warn_prototype_changes_behavior) + << WarnAboutDefn; } - } 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); } } } @@ -15039,11 +15032,9 @@ // 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; + // -Wstrict-prototypes is enabled. If we didn't warn about it being + // deprecated (because the diagnostic is not enabled), warn now that it + // is deprecated and changes behavior. if (PossiblePrototype) { if (Diags.isIgnored(diag::warn_strict_prototypes, PossiblePrototype->getLocation())) { @@ -15055,17 +15046,12 @@ 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. Index: clang/test/Sema/warn-deprecated-non-prototype.c =================================================================== --- clang/test/Sema/warn-deprecated-non-prototype.c +++ clang/test/Sema/warn-deprecated-non-prototype.c @@ -24,8 +24,7 @@ // 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}} + strict-warning {{a function declaration without a prototype is deprecated in all versions of C}} void func(a, b) int a, b; {} // both-warning {{a function 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}} @@ -40,18 +39,16 @@ } 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}} + strict-warning {{a function declaration without a prototype is deprecated in all versions of C}} +void order1(int i); // both-warning {{this function declaration with a prototype will change behavior in C2x because of a previous declaration with no prototype}} 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}} + strict-warning {{a function declaration without a prototype is deprecated in all versions of C}} +void order3(int i) {} // both-warning {{this function definition with a prototype will change behavior in C2x because of a previous declaration with no prototype}} // 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. Index: clang/test/Sema/warn-strict-prototypes.c =================================================================== --- clang/test/Sema/warn-strict-prototypes.c +++ clang/test/Sema/warn-strict-prototypes.c @@ -55,9 +55,8 @@ } // Function declaration with no types -void foo10(); // expected-warning {{a function declaration without a prototype is deprecated in all versions of C}} \ - expected-note {{a function declaration without a prototype is not supported in C2x}} - // CHECK: fix-it:"{{.*}}":{[[@LINE-2]]:12-[[@LINE-2]]:12}:"void" +void foo10(); // expected-warning {{a function declaration without a prototype is deprecated in all versions of C}} + // CHECK: fix-it:"{{.*}}":{[[@LINE-1]]:12-[[@LINE-1]]:12}:"void" // K&R function definition with incomplete param list declared void foo10(p, p2) void *p; {} // expected-warning {{a function declaration without a prototype is deprecated in all versions of C and is not supported in C2x}} \ expected-warning {{parameter 'p2' was not declared, defaults to 'int'; ISO C99 and later do not support implicit int}}