diff options
Diffstat (limited to 'clang/lib')
-rw-r--r-- | clang/lib/AST/ExprConstant.cpp | 17 |
1 files changed, 12 insertions, 5 deletions
diff --git a/clang/lib/AST/ExprConstant.cpp b/clang/lib/AST/ExprConstant.cpp index 107913ed61b..15b554bf27a 100644 --- a/clang/lib/AST/ExprConstant.cpp +++ b/clang/lib/AST/ExprConstant.cpp @@ -6826,14 +6826,21 @@ static bool tryEvaluateBuiltinObjectSize(const Expr *E, unsigned Type, // struct Foo *F = (struct Foo *)malloc(sizeof(struct Foo) + strlen(Bar)); // strcpy(&F->c[0], Bar); // - // So, if we see that we're examining a 1-length (or 0-length) array at the - // end of a struct with an unknown base, we give up instead of breaking code - // that behaves this way. Note that we only do this when Type=1, because - // Type=3 is a lower bound, so answering conservatively is fine. + // So, if we see that we're examining an array at the end of a struct with an + // unknown base, we give up instead of breaking code that behaves this way. + // Note that we only do this when Type=1, because Type=3 is a lower bound, so + // answering conservatively is fine. + // + // We used to be a bit more aggressive here; we'd only be conservative if the + // array at the end was flexible, or if it had 0 or 1 elements. This broke + // some common standard library extensions (PR30346), but was otherwise + // seemingly fine. It may be useful to reintroduce this behavior with some + // sort of whitelist. OTOH, it seems that GCC is always conservative with the + // last element in structs (if it's an array), so our current behavior is more + // compatible than a whitelisting approach would be. if (End.InvalidBase && SubobjectOnly && Type == 1 && End.Designator.Entries.size() == End.Designator.MostDerivedPathLength && End.Designator.MostDerivedIsArrayElement && - End.Designator.MostDerivedArraySize < 2 && isDesignatorAtObjectEnd(Info.Ctx, End)) return false; |