[clang] cc5b772 - [clang] Introduce -Warray-parameter

via cfe-commits cfe-commits at lists.llvm.org
Fri Jul 8 13:37:27 PDT 2022


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 at -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 at -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


        


More information about the cfe-commits mailing list