lebedev.ri created this revision. lebedev.ri added reviewers: rjmccall, rsmith, erichkeane.
https://reviews.llvm.org/rC337815 / https://reviews.llvm.org/D49508 had to cannibalize one bit of `CastExprBitfields::BasePathSize` in order to squeeze `PartOfExplicitCast` boolean. That reduced the maximal value of `PartOfExplicitCast` from 9 bits (~512) down to 8 bits (~256). Apparently, that mattered. Too bad there weren't any tests. It caused PR38356 <https://bugs.llvm.org/show_bug.cgi?id=38356>. So we need to increase `PartOfExplicitCast` back at least to 9 bits, or a bit more. For obvious reasons, we can't do that in `CastExprBitfields` - that would blow up the size of every `Expr`. So we need to either just add a variable into the `CastExpr` (as done here), or use `llvm::TrailingObjects`. The latter does not seem to be straight-forward. Perhaps, that needs to be done not for the `CastExpr` itself, but for all of it's `final` children. Repository: rC Clang https://reviews.llvm.org/D50050 Files: include/clang/AST/Expr.h include/clang/AST/Stmt.h test/CodeGenCXX/castexpr-basepathsize-threshold.cpp Index: test/CodeGenCXX/castexpr-basepathsize-threshold.cpp =================================================================== --- /dev/null +++ test/CodeGenCXX/castexpr-basepathsize-threshold.cpp @@ -0,0 +1,27 @@ +// RUN: %clang_cc1 %s -emit-llvm -o - + +// https://bugs.llvm.org/show_bug.cgi?id=38356 +// We only check that we do not crash. + +template <typename a, a b(unsigned), int c, unsigned...> +struct d : d<a, b, c - 1> {}; +template <typename a, a b(unsigned), unsigned... e> +struct d<a, b, 0, e...> { + a f[0]; +}; +struct g { + static g h(unsigned); +}; +struct i { + void j() const; + // Current maximum depth of recursive template instantiation is 1024, + // thus, this \/ threshold value is used here. BasePathSize in CastExpr might + // not fit it, so we are testing that we do fit it. + // If -ftemplate-depth= is provided, larger values (4096 and up) cause crashes + // elsewhere. + d<g, g::h, (1U << 10U) - 2U> f; +}; +void i::j() const { + const void *k{f.f}; + (void)k; +} Index: include/clang/AST/Stmt.h =================================================================== --- include/clang/AST/Stmt.h +++ include/clang/AST/Stmt.h @@ -204,7 +204,6 @@ unsigned Kind : 6; unsigned PartOfExplicitCast : 1; // Only set for ImplicitCastExpr. - unsigned BasePathSize : 32 - 6 - 1 - NumExprBits; }; class CallExprBitfields { Index: include/clang/AST/Expr.h =================================================================== --- include/clang/AST/Expr.h +++ include/clang/AST/Expr.h @@ -2790,17 +2790,21 @@ private: Stmt *Op; + // BasePathSize needs to have width of 9 bits (or more, up to 14(?) bits), + // so it does not fit into CastExprBitfields, where we only have 8 bits left. + unsigned BasePathSize : 14; + bool CastConsistency() const; const CXXBaseSpecifier * const *path_buffer() const { return const_cast<CastExpr*>(this)->path_buffer(); } CXXBaseSpecifier **path_buffer(); void setBasePathSize(unsigned basePathSize) { - CastExprBits.BasePathSize = basePathSize; - assert(CastExprBits.BasePathSize == basePathSize && - "basePathSize doesn't fit in bits of CastExprBits.BasePathSize!"); + BasePathSize = basePathSize; + assert(BasePathSize == basePathSize && + "basePathSize doesn't fit in bits of BasePathSize!"); } protected: @@ -2859,8 +2863,8 @@ typedef CXXBaseSpecifier **path_iterator; typedef const CXXBaseSpecifier * const *path_const_iterator; - bool path_empty() const { return CastExprBits.BasePathSize == 0; } - unsigned path_size() const { return CastExprBits.BasePathSize; } + bool path_empty() const { return BasePathSize == 0; } + unsigned path_size() const { return BasePathSize; } path_iterator path_begin() { return path_buffer(); } path_iterator path_end() { return path_buffer() + path_size(); } path_const_iterator path_begin() const { return path_buffer(); }
Index: test/CodeGenCXX/castexpr-basepathsize-threshold.cpp =================================================================== --- /dev/null +++ test/CodeGenCXX/castexpr-basepathsize-threshold.cpp @@ -0,0 +1,27 @@ +// RUN: %clang_cc1 %s -emit-llvm -o - + +// https://bugs.llvm.org/show_bug.cgi?id=38356 +// We only check that we do not crash. + +template <typename a, a b(unsigned), int c, unsigned...> +struct d : d<a, b, c - 1> {}; +template <typename a, a b(unsigned), unsigned... e> +struct d<a, b, 0, e...> { + a f[0]; +}; +struct g { + static g h(unsigned); +}; +struct i { + void j() const; + // Current maximum depth of recursive template instantiation is 1024, + // thus, this \/ threshold value is used here. BasePathSize in CastExpr might + // not fit it, so we are testing that we do fit it. + // If -ftemplate-depth= is provided, larger values (4096 and up) cause crashes + // elsewhere. + d<g, g::h, (1U << 10U) - 2U> f; +}; +void i::j() const { + const void *k{f.f}; + (void)k; +} Index: include/clang/AST/Stmt.h =================================================================== --- include/clang/AST/Stmt.h +++ include/clang/AST/Stmt.h @@ -204,7 +204,6 @@ unsigned Kind : 6; unsigned PartOfExplicitCast : 1; // Only set for ImplicitCastExpr. - unsigned BasePathSize : 32 - 6 - 1 - NumExprBits; }; class CallExprBitfields { Index: include/clang/AST/Expr.h =================================================================== --- include/clang/AST/Expr.h +++ include/clang/AST/Expr.h @@ -2790,17 +2790,21 @@ private: Stmt *Op; + // BasePathSize needs to have width of 9 bits (or more, up to 14(?) bits), + // so it does not fit into CastExprBitfields, where we only have 8 bits left. + unsigned BasePathSize : 14; + bool CastConsistency() const; const CXXBaseSpecifier * const *path_buffer() const { return const_cast<CastExpr*>(this)->path_buffer(); } CXXBaseSpecifier **path_buffer(); void setBasePathSize(unsigned basePathSize) { - CastExprBits.BasePathSize = basePathSize; - assert(CastExprBits.BasePathSize == basePathSize && - "basePathSize doesn't fit in bits of CastExprBits.BasePathSize!"); + BasePathSize = basePathSize; + assert(BasePathSize == basePathSize && + "basePathSize doesn't fit in bits of BasePathSize!"); } protected: @@ -2859,8 +2863,8 @@ typedef CXXBaseSpecifier **path_iterator; typedef const CXXBaseSpecifier * const *path_const_iterator; - bool path_empty() const { return CastExprBits.BasePathSize == 0; } - unsigned path_size() const { return CastExprBits.BasePathSize; } + bool path_empty() const { return BasePathSize == 0; } + unsigned path_size() const { return BasePathSize; } path_iterator path_begin() { return path_buffer(); } path_iterator path_end() { return path_buffer() + path_size(); } path_const_iterator path_begin() const { return path_buffer(); }
_______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits