[PATCH] D50050: [AST] CastExpr: BasePathSize is not large enough.

Roman Lebedev via Phabricator via cfe-commits cfe-commits at lists.llvm.org
Tue Jul 31 04:10:12 PDT 2018


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(); }


-------------- next part --------------
A non-text attachment was scrubbed...
Name: D50050.158207.patch
Type: text/x-patch
Size: 2936 bytes
Desc: not available
URL: <http://lists.llvm.org/pipermail/cfe-commits/attachments/20180731/5845d670/attachment-0001.bin>


More information about the cfe-commits mailing list