diff options
author | serge-sans-paille <sguelton@redhat.com> | 2022-06-28 11:01:55 +0200 |
---|---|---|
committer | serge-sans-paille <sguelton@redhat.com> | 2022-07-18 12:45:52 +0200 |
commit | f764dc99b37e1e6428724a61f36bcb49c015dc70 (patch) | |
tree | 63232db1fb62062e17a95f4cbaf5e562d3304432 /clang/lib/Sema/SemaChecking.cpp | |
parent | 432cbd7827202e4316225820f3f90417b9fcce6c (diff) | |
download | llvm-f764dc99b37e1e6428724a61f36bcb49c015dc70.zip llvm-f764dc99b37e1e6428724a61f36bcb49c015dc70.tar.gz llvm-f764dc99b37e1e6428724a61f36bcb49c015dc70.tar.bz2 |
[clang] Introduce -fstrict-flex-arrays=<n> for stricter handling of flexible arrays
Some code [0] consider that trailing arrays are flexible, whatever their size.
Support for these legacy code has been introduced in
f8f632498307d22e10fab0704548b270b15f1e1e but it prevents evaluation of
__builtin_object_size and __builtin_dynamic_object_size in some legit cases.
Introduce -fstrict-flex-arrays=<n> to have stricter conformance when it is
desirable.
n = 0: current behavior, any trailing array member is a flexible array. The default.
n = 1: any trailing array member of undefined, 0 or 1 size is a flexible array member
n = 2: any trailing array member of undefined or 0 size is a flexible array member
This takes into account two specificities of clang: array bounds as macro id
disqualify FAM, as well as non standard layout.
Similar patch for gcc discuss here: https://gcc.gnu.org/bugzilla/show_bug.cgi?id=101836
[0] https://docs.freebsd.org/en/books/developers-handbook/sockets/#sockets-essential-functions
Diffstat (limited to 'clang/lib/Sema/SemaChecking.cpp')
-rw-r--r-- | clang/lib/Sema/SemaChecking.cpp | 42 |
1 files changed, 32 insertions, 10 deletions
diff --git a/clang/lib/Sema/SemaChecking.cpp b/clang/lib/Sema/SemaChecking.cpp index 5112b78..dae51d0 100644 --- a/clang/lib/Sema/SemaChecking.cpp +++ b/clang/lib/Sema/SemaChecking.cpp @@ -15830,11 +15830,26 @@ void Sema::CheckCastAlign(Expr *Op, QualType T, SourceRange TRange) { /// We avoid emitting out-of-bounds access warnings for such arrays as they are /// commonly used to emulate flexible arrays in C89 code. static bool IsTailPaddedMemberArray(Sema &S, const llvm::APInt &Size, - const NamedDecl *ND) { - if (Size != 1 || !ND) return false; + const NamedDecl *ND, + unsigned StrictFlexArraysLevel) { + if (!ND) + return false; + + if (StrictFlexArraysLevel >= 2 && Size != 0) + return false; + + if (StrictFlexArraysLevel == 1 && Size.ule(1)) + return false; + + // FIXME: While the default -fstrict-flex-arrays=0 permits Size>1 trailing + // arrays to be treated as flexible-array-members, we still emit diagnostics + // as if they are not. Pending further discussion... + if (StrictFlexArraysLevel == 0 && Size != 1) + return false; const FieldDecl *FD = dyn_cast<FieldDecl>(ND); - if (!FD) return false; + if (!FD) + return false; // Don't consider sizes resulting from macro expansions or template argument // substitution to form C89 tail-padded arrays. @@ -15857,10 +15872,13 @@ static bool IsTailPaddedMemberArray(Sema &S, const llvm::APInt &Size, } const RecordDecl *RD = dyn_cast<RecordDecl>(FD->getDeclContext()); - if (!RD) return false; - if (RD->isUnion()) return false; + if (!RD) + return false; + if (RD->isUnion()) + return false; if (const CXXRecordDecl *CRD = dyn_cast<CXXRecordDecl>(RD)) { - if (!CRD->isStandardLayout()) return false; + if (!CRD->isStandardLayout()) + return false; } // See if this is the last field decl in the record. @@ -15988,9 +16006,14 @@ void Sema::CheckArrayAccess(const Expr *BaseExpr, const Expr *IndexExpr, // example). In this case we have no information about whether the array // access exceeds the array bounds. However we can still diagnose an array // access which precedes the array bounds. + // + // FIXME: this check should be redundant with the IsUnboundedArray check + // above. if (BaseType->isIncompleteType()) return; + // FIXME: this check should belong to the IsTailPaddedMemberArray call + // below. llvm::APInt size = ArrayTy->getSize(); if (!size.isStrictlyPositive()) return; @@ -16023,10 +16046,9 @@ void Sema::CheckArrayAccess(const Expr *BaseExpr, const Expr *IndexExpr, if (AllowOnePastEnd ? index.ule(size) : index.ult(size)) return; - // Also don't warn for arrays of size 1 which are members of some - // structure. These are often used to approximate flexible arrays in C89 - // code. - if (IsTailPaddedMemberArray(*this, size, ND)) + // Also don't warn for Flexible Array Member emulation. + const unsigned StrictFlexArraysLevel = getLangOpts().StrictFlexArrays; + if (IsTailPaddedMemberArray(*this, size, ND, StrictFlexArraysLevel)) return; // Suppress the warning if the subscript expression (as identified by the |