]> granicus.if.org Git - clang/commitdiff
[Sema] Improve a -Warray-bounds diagnostic
authorErik Pilkington <erik.pilkington@gmail.com>
Fri, 25 Jan 2019 20:52:45 +0000 (20:52 +0000)
committerErik Pilkington <erik.pilkington@gmail.com>
Fri, 25 Jan 2019 20:52:45 +0000 (20:52 +0000)
Fix a bug where we would compare array sizes with incompatible
element types, and look through explicit casts.

rdar://44800168

Differential revision: https://reviews.llvm.org/D57064

git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@352239 91177308-0d34-0410-b5e6-96231b3b80d8

include/clang/AST/ASTContext.h
include/clang/Basic/DiagnosticSemaKinds.td
lib/Sema/SemaExpr.cpp
test/Sema/static-array.c

index c838018c9f2f82947f7dda948f3442efed544063..fe52f818ea40213cd9f65e92a1b706634b9f977b 100644 (file)
@@ -2088,6 +2088,16 @@ public:
   CharUnits getTypeSizeInChars(QualType T) const;
   CharUnits getTypeSizeInChars(const Type *T) const;
 
+  Optional<CharUnits> getTypeSizeInCharsIfKnown(QualType Ty) const {
+    if (Ty->isIncompleteType() || Ty->isDependentType())
+      return None;
+    return getTypeSizeInChars(Ty);
+  }
+
+  Optional<CharUnits> getTypeSizeInCharsIfKnown(const Type *Ty) const {
+    return getTypeSizeInCharsIfKnown(QualType(Ty, 0));
+  }
+
   /// Return the ABI-specified alignment of a (complete) type \p T, in
   /// bits.
   unsigned getTypeAlign(QualType T) const { return getTypeInfo(T).Align; }
index b1cd8f7046b96cb4119e12121531e9c876833a36..d1d99876c3192c0ca2920018e8dd518c3591758f 100644 (file)
@@ -7841,7 +7841,8 @@ def warn_format_mix_positional_nonpositional_args : Warning<
   "cannot mix positional and non-positional arguments in format string">,
   InGroup<Format>;
 def warn_static_array_too_small : Warning<
-  "array argument is too small; contains %0 elements, callee requires at least %1">,
+  "array argument is too small; %select{contains %0 elements|is of size %0}2,"
+  " callee requires at least %1">,
   InGroup<ArrayBounds>;
 def note_callee_static_array : Note<
   "callee declares array parameter as static here">;
index 3c6a7779560eb38ff3db5b55706f0e33310e85c2..8f3fd162740464a35ad0f128bbc7c1c8bc2fca3e 100644 (file)
@@ -5228,15 +5228,29 @@ Sema::CheckStaticArrayArgument(SourceLocation CallLoc,
     return;
 
   const ConstantArrayType *ArgCAT =
-    Context.getAsConstantArrayType(ArgExpr->IgnoreParenImpCasts()->getType());
+    Context.getAsConstantArrayType(ArgExpr->IgnoreParenCasts()->getType());
   if (!ArgCAT)
     return;
 
-  if (ArgCAT->getSize().ult(CAT->getSize())) {
+  if (getASTContext().hasSameUnqualifiedType(CAT->getElementType(),
+                                             ArgCAT->getElementType())) {
+    if (ArgCAT->getSize().ult(CAT->getSize())) {
+      Diag(CallLoc, diag::warn_static_array_too_small)
+          << ArgExpr->getSourceRange()
+          << (unsigned)ArgCAT->getSize().getZExtValue()
+          << (unsigned)CAT->getSize().getZExtValue() << 0;
+      DiagnoseCalleeStaticArrayParam(*this, Param);
+    }
+    return;
+  }
+
+  Optional<CharUnits> ArgSize =
+      getASTContext().getTypeSizeInCharsIfKnown(ArgCAT);
+  Optional<CharUnits> ParmSize = getASTContext().getTypeSizeInCharsIfKnown(CAT);
+  if (ArgSize && ParmSize && *ArgSize < *ParmSize) {
     Diag(CallLoc, diag::warn_static_array_too_small)
-      << ArgExpr->getSourceRange()
-      << (unsigned) ArgCAT->getSize().getZExtValue()
-      << (unsigned) CAT->getSize().getZExtValue();
+        << ArgExpr->getSourceRange() << (unsigned)ArgSize->getQuantity()
+        << (unsigned)ParmSize->getQuantity() << 1;
     DiagnoseCalleeStaticArrayParam(*this, Param);
   }
 }
index 304485d5af9fd81435eab9023acb374003c56449..cc1043fe9c471a530a85f47b1d1fb042b2b4471d 100644 (file)
@@ -1,8 +1,8 @@
-// RUN: %clang_cc1 -fsyntax-only -fblocks -verify %s
+// RUN: %clang_cc1 -triple x86_64-apple-macosx10.14.0 -fsyntax-only -fblocks -verify %s
 
 void cat0(int a[static 0]) {} // expected-warning {{'static' has no effect on zero-length arrays}}
 
-void cat(int a[static 3]) {} // expected-note 2 {{callee declares array parameter as static here}}
+void cat(int a[static 3]) {} // expected-note 4 {{callee declares array parameter as static here}} expected-note 2 {{passing argument to parameter 'a' here}}
 
 void vat(int i, int a[static i]) {} // expected-note {{callee declares array parameter as static here}}
 
@@ -19,6 +19,14 @@ void f(int *p) {
 
   vat(1, 0); // expected-warning {{null passed to a callee that requires a non-null argument}}
   vat(3, b);
+
+  char d[4];
+  cat((int *)d); // expected-warning {{array argument is too small; is of size 4, callee requires at least 12}}
+  cat(d); // expected-warning {{array argument is too small; is of size 4, callee requires at least 12}} expected-warning {{incompatible pointer types}}
+
+  char e[12];
+  cat((int *)e);
+  cat(e); // expected-warning {{incompatible pointer types}}
 }