diff --git a/clang/include/clang/Basic/DiagnosticSemaKinds.td b/clang/include/clang/Basic/DiagnosticSemaKinds.td index e027e754477fc..41a4cdbdd0f59 100644 --- a/clang/include/clang/Basic/DiagnosticSemaKinds.td +++ b/clang/include/clang/Basic/DiagnosticSemaKinds.td @@ -9722,6 +9722,12 @@ def warn_array_index_precedes_bounds : Warning< def warn_array_index_exceeds_bounds : Warning< "array index %0 is past the end of the array (that has type %1%select{|, cast to %3}2)">, InGroup; +def warn_vector_index_precedes_bounds : Warning< + "vector index %0 is before the beginning of the vector">, + InGroup; +def warn_vector_index_exceeds_bounds : Warning< + "vector index %0 is past the end of the vector (that has type %1)">, + InGroup; def warn_ptr_arith_exceeds_max_addressable_bounds : Warning< "the pointer incremented by %0 refers past the last possible element for an array in %1-bit " "address space containing %2-bit (%3-byte) elements (max possible %4 element%s5)">, @@ -9732,6 +9738,8 @@ def warn_array_index_exceeds_max_addressable_bounds : Warning< InGroup; def note_array_declared_here : Note< "array %0 declared here">; +def note_vector_declared_here : Note< + "vector %0 declared here">; def warn_inconsistent_array_form : Warning< "argument %0 of type %1 with mismatched bound">, diff --git a/clang/lib/Sema/SemaChecking.cpp b/clang/lib/Sema/SemaChecking.cpp index 1f83dcf07b6f9..30e38439d86a3 100644 --- a/clang/lib/Sema/SemaChecking.cpp +++ b/clang/lib/Sema/SemaChecking.cpp @@ -18001,6 +18001,45 @@ void Sema::CheckArrayAccess(const Expr *BaseExpr, const Expr *IndexExpr, index = -index; } + if (EffectiveType->isVectorType()) { + if (AllowOnePastEnd) { + // Pointer arithmetic on vectors isn't legal, so let's not emit a + // diagnostic since we'll produce an error later anyway. + return; + } + + if (index.isUnsigned() || !index.isNegative()) { + const auto *VT = EffectiveType->castAs(); + if (index.ult(VT->getNumElements())) + return; + + DiagRuntimeBehavior(BaseExpr->getBeginLoc(), BaseExpr, + PDiag(diag::warn_vector_index_exceeds_bounds) + << toString(index, 10, true) << VT->desugar() + << IndexExpr->getSourceRange()); + } else { + DiagRuntimeBehavior(BaseExpr->getBeginLoc(), BaseExpr, + PDiag(diag::warn_vector_index_precedes_bounds) + << toString(index, 10, true) + << IndexExpr->getSourceRange()); + } + + const NamedDecl *ND = nullptr; + // Try harder to find a NamedDecl to point at in the note. + while (const auto *ASE = dyn_cast(BaseExpr)) + BaseExpr = ASE->getBase()->IgnoreParenCasts(); + if (const auto *DRE = dyn_cast(BaseExpr)) + ND = DRE->getDecl(); + if (const auto *ME = dyn_cast(BaseExpr)) + ND = ME->getMemberDecl(); + + if (ND) + DiagRuntimeBehavior(ND->getBeginLoc(), BaseExpr, + PDiag(diag::note_vector_declared_here) << ND); + + return; + } + if (IsUnboundedArray) { if (EffectiveType->isFunctionType()) return; diff --git a/clang/test/Sema/array-bounds-vector.c b/clang/test/Sema/array-bounds-vector.c new file mode 100644 index 0000000000000..e5a940a7d1786 --- /dev/null +++ b/clang/test/Sema/array-bounds-vector.c @@ -0,0 +1,10 @@ +// RUN: %clang_cc1 -fsyntax-only -Warray-bounds -verify %s + +typedef double float64x1_t __attribute__ ((__vector_size__ (sizeof (double)))); +void foo(double i) +{ + float64x1_t j = {i}; // expected-note 2 {{vector 'j' declared here}} + double U = j[0]; + double V = j[1]; // expected-warning {{vector index 1 is past the end of the vector (that has type '__attribute__((__vector_size__(1 * sizeof(double)))) double' (vector of 1 'double' value))}} + double W = j[-1]; // expected-warning {{vector index -1 is before the beginning of the vector}} +}