serge-sans-paille updated this revision to Diff 442084.
serge-sans-paille added a comment.

Fix handling of `ConstantArrayType`, thanks @aaron.ballman for the hint.


CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D128449/new/

https://reviews.llvm.org/D128449

Files:
  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
  clang/test/Sema/array-parameter.c
  clang/test/Sema/array-parameter.cpp

Index: clang/test/Sema/array-parameter.cpp
===================================================================
--- /dev/null
+++ clang/test/Sema/array-parameter.cpp
@@ -0,0 +1,11 @@
+// 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}}
+
+static constexpr int Extent = 10;
+void funk(int i[10]);
+void funk(int i[Extent]); // no-warning
Index: clang/test/Sema/array-parameter.c
===================================================================
--- /dev/null
+++ 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}}
+{}
Index: clang/test/Misc/warning-wall.c
===================================================================
--- clang/test/Misc/warning-wall.c
+++ clang/test/Misc/warning-wall.c
@@ -3,6 +3,7 @@
 
      CHECK:-Wall
 CHECK-NEXT:  -Wmost
+CHECK-NEXT:    -Warray-parameter
 CHECK-NEXT:    -Wbool-operation
 CHECK-NEXT:    -Wbitwise-instead-of-logical
 CHECK-NEXT:    -Wchar-subscripts
Index: clang/lib/Sema/SemaDecl.cpp
===================================================================
--- clang/lib/Sema/SemaDecl.cpp
+++ clang/lib/Sema/SemaDecl.cpp
@@ -3209,6 +3209,36 @@
   if (!foundAny) newDecl->dropAttrs();
 }
 
+static bool EquivalentArrayTypes(QualType Old, QualType New, Sema &S) {
+  auto NoSizeInfo = [](QualType Ty) {
+    return Ty->isIncompleteArrayType() || Ty->isPointerType() ||
+           (Ty->isVariableArrayType() &&
+            cast<ArrayType>(Ty)->getSizeModifier() ==
+                ArrayType::ArraySizeModifier::Star);
+  };
+
+  // `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 = cast<ArrayType>(Old);
+    const auto *NewVAT = cast<ArrayType>(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 S.getASTContext().getAsConstantArrayType(Old)->getSize() ==
+           S.getASTContext().getAsConstantArrayType(New)->getSize();
+
+  return Old == New;
+}
+
 static void mergeParamDeclTypes(ParmVarDecl *NewParam,
                                 const ParmVarDecl *OldParam,
                                 Sema &S) {
@@ -3234,6 +3264,19 @@
       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)) {
+      S.Diag(NewParam->getLocation(), diag::warn_inconsistent_array_form)
+          << NewParam << NewParamOT;
+      S.Diag(OldParam->getLocation(), diag::note_previous_declaration_as)
+          << OldParamOT;
+    }
+  }
 }
 
 namespace {
Index: clang/include/clang/Basic/DiagnosticSemaKinds.td
===================================================================
--- clang/include/clang/Basic/DiagnosticSemaKinds.td
+++ clang/include/clang/Basic/DiagnosticSemaKinds.td
@@ -9395,6 +9395,12 @@
 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<
Index: clang/include/clang/Basic/DiagnosticGroups.td
===================================================================
--- clang/include/clang/Basic/DiagnosticGroups.td
+++ clang/include/clang/Basic/DiagnosticGroups.td
@@ -31,6 +31,7 @@
 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 Most : DiagGroup<"most", [
+    ArrayParameter,
     BoolOperation,
     CharSubscript,
     Comment,
Index: clang/docs/ReleaseNotes.rst
===================================================================
--- clang/docs/ReleaseNotes.rst
+++ clang/docs/ReleaseNotes.rst
@@ -321,6 +321,9 @@
   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 detects function redefinition,
+  where different definition involve argument type that decay to the same
+  pointer type from different array types.
 
 Deprecated Compiler Flags
 -------------------------
_______________________________________________
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to