Author: serge-sans-paille Date: 2022-07-08T22:36:05+02:00 New Revision: cc5b77273af3705b6f5cf574567b49d5158bb3a9
URL: https://github.com/llvm/llvm-project/commit/cc5b77273af3705b6f5cf574567b49d5158bb3a9 DIFF: https://github.com/llvm/llvm-project/commit/cc5b77273af3705b6f5cf574567b49d5158bb3a9.diff LOG: [clang] Introduce -Warray-parameter This warning exist in GCC[0] and warns about re-declarations of functions involving arguments of array or pointer types of inconsistent kinds or forms. This is not the exact same implementation as GCC's : there's no warning level and that flag has no effect on -Warray-bounds. [0] https://gcc.gnu.org/onlinedocs/gcc-12.1.0/gcc/Warning-Options.html#index-Wno-array-parameter Differential Revision: https://reviews.llvm.org/D128449 Added: clang/test/Sema/array-parameter.c clang/test/Sema/array-parameter.cpp Modified: clang/docs/ReleaseNotes.rst clang/include/clang/Basic/DiagnosticGroups.td clang/include/clang/Basic/DiagnosticSemaKinds.td clang/lib/Sema/SemaDecl.cpp clang/test/Misc/warning-wall.c Removed: ################################################################################ diff --git a/clang/docs/ReleaseNotes.rst b/clang/docs/ReleaseNotes.rst index 9d244ca5fbf0d..c6d36568099b4 100644 --- a/clang/docs/ReleaseNotes.rst +++ b/clang/docs/ReleaseNotes.rst @@ -321,6 +321,11 @@ New Compiler Flags removed in the future once clang supports all such operations. - Added the ``-print-diagnostic-options`` option, which prints a list of warnings the compiler supports. +- Added the ``-Warray-parameter`` warning. It diagnoses diff erences between + array parameters between function redeclarations (arrays of diff erent extents, + etc). This flag is related to the same flag in GCC, but is diff erent in that + it does not accept an explicitly- specified warning level and use of this flag + has no effect on ``-Warray-bounds``. Deprecated Compiler Flags ------------------------- diff --git a/clang/include/clang/Basic/DiagnosticGroups.td b/clang/include/clang/Basic/DiagnosticGroups.td index 10da02ecbf7e8..0c9646e525e50 100644 --- a/clang/include/clang/Basic/DiagnosticGroups.td +++ b/clang/include/clang/Basic/DiagnosticGroups.td @@ -31,6 +31,7 @@ def GNUAnonymousStruct : DiagGroup<"gnu-anonymous-struct">; def GNUAutoType : DiagGroup<"gnu-auto-type">; def ArrayBounds : DiagGroup<"array-bounds">; def ArrayBoundsPointerArithmetic : DiagGroup<"array-bounds-pointer-arithmetic">; +def ArrayParameter : DiagGroup<"array-parameter">; def AutoDisableVptrSanitizer : DiagGroup<"auto-disable-vptr-sanitizer">; def Availability : DiagGroup<"availability">; def Section : DiagGroup<"section">; @@ -978,6 +979,7 @@ def Extra : DiagGroup<"extra", [ ]>; def Most : DiagGroup<"most", [ + ArrayParameter, BoolOperation, CharSubscript, Comment, diff --git a/clang/include/clang/Basic/DiagnosticSemaKinds.td b/clang/include/clang/Basic/DiagnosticSemaKinds.td index c811cd855d503..fd10bd9c70e6a 100644 --- a/clang/include/clang/Basic/DiagnosticSemaKinds.td +++ b/clang/include/clang/Basic/DiagnosticSemaKinds.td @@ -9400,6 +9400,12 @@ def warn_array_index_exceeds_max_addressable_bounds : Warning< def note_array_declared_here : Note< "array %0 declared here">; +def warn_inconsistent_array_form : Warning< + "argument %0 of type %1 with mismatched bound">, + InGroup<ArrayParameter>, DefaultIgnore; +def note_previous_declaration_as : Note< + "previously declared as %0 here">; + def warn_printf_insufficient_data_args : Warning< "more '%%' conversions than data arguments">, InGroup<FormatInsufficientArgs>; def warn_printf_data_arg_not_used : Warning< diff --git a/clang/lib/Sema/SemaDecl.cpp b/clang/lib/Sema/SemaDecl.cpp index d6c89d525cdc2..927d81826425b 100644 --- a/clang/lib/Sema/SemaDecl.cpp +++ b/clang/lib/Sema/SemaDecl.cpp @@ -3207,6 +3207,39 @@ static void mergeParamDeclAttributes(ParmVarDecl *newDecl, if (!foundAny) newDecl->dropAttrs(); } +static bool EquivalentArrayTypes(QualType Old, QualType New, + const ASTContext &Ctx) { + + auto NoSizeInfo = [&Ctx](QualType Ty) { + if (Ty->isIncompleteArrayType() || Ty->isPointerType()) + return true; + if (const auto *VAT = Ctx.getAsVariableArrayType(Ty)) + return VAT->getSizeModifier() == ArrayType::ArraySizeModifier::Star; + return false; + }; + + // `type[]` is equivalent to `type *` and `type[*]`. + if (NoSizeInfo(Old) && NoSizeInfo(New)) + return true; + + // Don't try to compare VLA sizes, unless one of them has the star modifier. + if (Old->isVariableArrayType() && New->isVariableArrayType()) { + const auto *OldVAT = Ctx.getAsVariableArrayType(Old); + const auto *NewVAT = Ctx.getAsVariableArrayType(New); + if ((OldVAT->getSizeModifier() == ArrayType::ArraySizeModifier::Star) ^ + (NewVAT->getSizeModifier() == ArrayType::ArraySizeModifier::Star)) + return false; + return true; + } + + // Only compare size, ignore Size modifiers and CVR. + if (Old->isConstantArrayType() && New->isConstantArrayType()) + return Ctx.getAsConstantArrayType(Old)->getSize() == + Ctx.getAsConstantArrayType(New)->getSize(); + + return Old == New; +} + static void mergeParamDeclTypes(ParmVarDecl *NewParam, const ParmVarDecl *OldParam, Sema &S) { @@ -3232,6 +3265,19 @@ static void mergeParamDeclTypes(ParmVarDecl *NewParam, NewParam->setType(NewT); } } + const auto *OldParamDT = dyn_cast<DecayedType>(OldParam->getType()); + const auto *NewParamDT = dyn_cast<DecayedType>(NewParam->getType()); + if (OldParamDT && NewParamDT && + OldParamDT->getPointeeType() == NewParamDT->getPointeeType()) { + QualType OldParamOT = OldParamDT->getOriginalType(); + QualType NewParamOT = NewParamDT->getOriginalType(); + if (!EquivalentArrayTypes(OldParamOT, NewParamOT, S.getASTContext())) { + S.Diag(NewParam->getLocation(), diag::warn_inconsistent_array_form) + << NewParam << NewParamOT; + S.Diag(OldParam->getLocation(), diag::note_previous_declaration_as) + << OldParamOT; + } + } } namespace { diff --git a/clang/test/Misc/warning-wall.c b/clang/test/Misc/warning-wall.c index a4a79bec934af..e57c5d6d501da 100644 --- a/clang/test/Misc/warning-wall.c +++ b/clang/test/Misc/warning-wall.c @@ -3,6 +3,7 @@ RUN: FileCheck --input-file=%t %s CHECK:-Wall CHECK-NEXT: -Wmost +CHECK-NEXT: -Warray-parameter CHECK-NEXT: -Wbool-operation CHECK-NEXT: -Wbitwise-instead-of-logical CHECK-NEXT: -Wchar-subscripts diff --git a/clang/test/Sema/array-parameter.c b/clang/test/Sema/array-parameter.c new file mode 100644 index 0000000000000..2aa9ab0cdc17c --- /dev/null +++ b/clang/test/Sema/array-parameter.c @@ -0,0 +1,35 @@ +// RUN: %clang_cc1 -triple x86_64-pc-linux-gnu -fsyntax-only -Warray-parameter -verify %s +void f0(int a[]); +void f0(int *a); // no warning + +void f1(int a[]); // expected-note {{previously declared as 'int[]' here}} +void f1(int a[2]); // expected-warning {{argument 'a' of type 'int[2]' with mismatched bound}} + +void f2(int a[3]); // expected-note {{previously declared as 'int[3]' here}} +void f2(int a[2]); // expected-warning {{argument 'a' of type 'int[2]' with mismatched bound}} + +void f3(int a[const 2]); +void f3(int a[2]); // no warning + +void f4(int a[static 2]); +void f4(int a[2]); // no warning + +void f5(int a[restrict 2]); +void f5(int a[2]); // no warning + +void f6(int a[volatile 2]); +void f6(int a[2]); // no warning + +void f7(int a[*]); +void f7(int a[]); // no warning + +void f8(int n, int a[*]); // expected-note {{previously declared as 'int[*]' here}} +void f8(int n, int a[n]); // expected-warning {{argument 'a' of type 'int[n]' with mismatched bound}} + +void f9(int *a); +void f9(int a[2]); +void f9(int a[]); // expected-warning {{argument 'a' of type 'int[]' with mismatched bound}} + // expected-note@-2 {{previously declared as 'int[2]' here}} +void f9(int a[2]) // expected-warning {{argument 'a' of type 'int[2]' with mismatched bound}} + // expected-note@-3 {{previously declared as 'int[]' here}} +{} diff --git a/clang/test/Sema/array-parameter.cpp b/clang/test/Sema/array-parameter.cpp new file mode 100644 index 0000000000000..6842226c71ea7 --- /dev/null +++ b/clang/test/Sema/array-parameter.cpp @@ -0,0 +1,18 @@ +// RUN: %clang_cc1 -triple x86_64-pc-linux-gnu -fsyntax-only -Warray-parameter -verify %s + +template <int N> +void func(int i[10]); // expected-note {{previously declared as 'int[10]' here}} + +template <int N> +void func(int i[N]); // expected-warning {{argument 'i' of type 'int[N]' with mismatched bound}} + +template <int N> +void func(int (&Val)[N]); + +template <> +void func<10>(int (&Val)[10]) { +} + +static constexpr int Extent = 10; +void funk(int i[10]); +void funk(int i[Extent]); // no-warning _______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits