summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorRoman Lebedev <lebedev.ri@gmail.com>2018-08-01 06:06:16 +0000
committerRoman Lebedev <lebedev.ri@gmail.com>2018-08-01 06:06:16 +0000
commitfefed1b2684e8eb833d407b67661be036dd33064 (patch)
treec971e2c18c61acddc151d0a5a60933c07d33edad
parentf832adb0f1844929953f6920acd0e1586b7c6e55 (diff)
[AST] CastExpr: BasePathSize is not large enough.
Summary: rC337815 / 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 [[ https://bugs.llvm.org/show_bug.cgi?id=38356 | PR38356 ]]. 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. Reviewers: rjmccall, rsmith, erichkeane Reviewed By: rjmccall Subscribers: bricci, hans, cfe-commits, waddlesplash Differential Revision: https://reviews.llvm.org/D50050 git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@338489 91177308-0d34-0410-b5e6-96231b3b80d8
-rw-r--r--include/clang/AST/Expr.h44
-rw-r--r--include/clang/AST/ExprCXX.h33
-rw-r--r--include/clang/AST/ExprObjC.h7
-rw-r--r--include/clang/AST/Stmt.h2
-rw-r--r--lib/AST/Expr.cpp31
-rw-r--r--lib/AST/ExprCXX.cpp32
-rw-r--r--test/CodeGenCXX/castexpr-basepathsize-threshold.cpp27
7 files changed, 148 insertions, 28 deletions
diff --git a/include/clang/AST/Expr.h b/include/clang/AST/Expr.h
index cfb4315aa8..c18fbf05df 100644
--- a/include/clang/AST/Expr.h
+++ b/include/clang/AST/Expr.h
@@ -2787,20 +2787,26 @@ public:
/// representation in the source code (ExplicitCastExpr's derived
/// classes).
class CastExpr : public Expr {
+public:
+ using BasePathSizeTy = unsigned int;
+ static_assert(std::numeric_limits<BasePathSizeTy>::max() >= 16384,
+ "[implimits] Direct and indirect base classes [16384].");
+
private:
Stmt *Op;
bool CastConsistency() const;
+ BasePathSizeTy *BasePathSize();
+
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!");
+ void setBasePathSize(BasePathSizeTy basePathSize) {
+ assert(!path_empty() && basePathSize != 0);
+ *(BasePathSize()) = basePathSize;
}
protected:
@@ -2823,7 +2829,9 @@ protected:
Op(op) {
CastExprBits.Kind = kind;
CastExprBits.PartOfExplicitCast = false;
- setBasePathSize(BasePathSize);
+ CastExprBits.BasePathIsEmpty = BasePathSize == 0;
+ if (!path_empty())
+ setBasePathSize(BasePathSize);
assert(CastConsistency());
}
@@ -2831,7 +2839,9 @@ protected:
CastExpr(StmtClass SC, EmptyShell Empty, unsigned BasePathSize)
: Expr(SC, Empty) {
CastExprBits.PartOfExplicitCast = false;
- setBasePathSize(BasePathSize);
+ CastExprBits.BasePathIsEmpty = BasePathSize == 0;
+ if (!path_empty())
+ setBasePathSize(BasePathSize);
}
public:
@@ -2859,8 +2869,12 @@ public:
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 CastExprBits.BasePathIsEmpty; }
+ unsigned path_size() const {
+ if (path_empty())
+ return 0U;
+ return *(const_cast<CastExpr *>(this)->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(); }
@@ -2908,7 +2922,12 @@ public:
/// @endcode
class ImplicitCastExpr final
: public CastExpr,
- private llvm::TrailingObjects<ImplicitCastExpr, CXXBaseSpecifier *> {
+ private llvm::TrailingObjects<ImplicitCastExpr, CastExpr::BasePathSizeTy,
+ CXXBaseSpecifier *> {
+ size_t numTrailingObjects(OverloadToken<CastExpr::BasePathSizeTy>) const {
+ return path_empty() ? 0 : 1;
+ }
+
private:
ImplicitCastExpr(QualType ty, CastKind kind, Expr *op,
unsigned BasePathLength, ExprValueKind VK)
@@ -3013,7 +3032,8 @@ public:
/// (Type)expr. For example: @c (int)f.
class CStyleCastExpr final
: public ExplicitCastExpr,
- private llvm::TrailingObjects<CStyleCastExpr, CXXBaseSpecifier *> {
+ private llvm::TrailingObjects<CStyleCastExpr, CastExpr::BasePathSizeTy,
+ CXXBaseSpecifier *> {
SourceLocation LPLoc; // the location of the left paren
SourceLocation RPLoc; // the location of the right paren
@@ -3027,6 +3047,10 @@ class CStyleCastExpr final
explicit CStyleCastExpr(EmptyShell Shell, unsigned PathSize)
: ExplicitCastExpr(CStyleCastExprClass, Shell, PathSize) { }
+ size_t numTrailingObjects(OverloadToken<CastExpr::BasePathSizeTy>) const {
+ return path_empty() ? 0 : 1;
+ }
+
public:
static CStyleCastExpr *Create(const ASTContext &Context, QualType T,
ExprValueKind VK, CastKind K,
diff --git a/include/clang/AST/ExprCXX.h b/include/clang/AST/ExprCXX.h
index d7e963badf..7ab8020dec 100644
--- a/include/clang/AST/ExprCXX.h
+++ b/include/clang/AST/ExprCXX.h
@@ -301,7 +301,8 @@ public:
/// \c static_cast<int>(1.0).
class CXXStaticCastExpr final
: public CXXNamedCastExpr,
- private llvm::TrailingObjects<CXXStaticCastExpr, CXXBaseSpecifier *> {
+ private llvm::TrailingObjects<CXXStaticCastExpr, CastExpr::BasePathSizeTy,
+ CXXBaseSpecifier *> {
CXXStaticCastExpr(QualType ty, ExprValueKind vk, CastKind kind, Expr *op,
unsigned pathSize, TypeSourceInfo *writtenTy,
SourceLocation l, SourceLocation RParenLoc,
@@ -312,6 +313,10 @@ class CXXStaticCastExpr final
explicit CXXStaticCastExpr(EmptyShell Empty, unsigned PathSize)
: CXXNamedCastExpr(CXXStaticCastExprClass, Empty, PathSize) {}
+ size_t numTrailingObjects(OverloadToken<CastExpr::BasePathSizeTy>) const {
+ return path_empty() ? 0 : 1;
+ }
+
public:
friend class CastExpr;
friend TrailingObjects;
@@ -337,7 +342,8 @@ public:
/// check to determine how to perform the type conversion.
class CXXDynamicCastExpr final
: public CXXNamedCastExpr,
- private llvm::TrailingObjects<CXXDynamicCastExpr, CXXBaseSpecifier *> {
+ private llvm::TrailingObjects<
+ CXXDynamicCastExpr, CastExpr::BasePathSizeTy, CXXBaseSpecifier *> {
CXXDynamicCastExpr(QualType ty, ExprValueKind VK, CastKind kind,
Expr *op, unsigned pathSize, TypeSourceInfo *writtenTy,
SourceLocation l, SourceLocation RParenLoc,
@@ -348,6 +354,10 @@ class CXXDynamicCastExpr final
explicit CXXDynamicCastExpr(EmptyShell Empty, unsigned pathSize)
: CXXNamedCastExpr(CXXDynamicCastExprClass, Empty, pathSize) {}
+ size_t numTrailingObjects(OverloadToken<CastExpr::BasePathSizeTy>) const {
+ return path_empty() ? 0 : 1;
+ }
+
public:
friend class CastExpr;
friend TrailingObjects;
@@ -380,6 +390,7 @@ public:
class CXXReinterpretCastExpr final
: public CXXNamedCastExpr,
private llvm::TrailingObjects<CXXReinterpretCastExpr,
+ CastExpr::BasePathSizeTy,
CXXBaseSpecifier *> {
CXXReinterpretCastExpr(QualType ty, ExprValueKind vk, CastKind kind,
Expr *op, unsigned pathSize,
@@ -392,6 +403,10 @@ class CXXReinterpretCastExpr final
CXXReinterpretCastExpr(EmptyShell Empty, unsigned pathSize)
: CXXNamedCastExpr(CXXReinterpretCastExprClass, Empty, pathSize) {}
+ size_t numTrailingObjects(OverloadToken<CastExpr::BasePathSizeTy>) const {
+ return path_empty() ? 0 : 1;
+ }
+
public:
friend class CastExpr;
friend TrailingObjects;
@@ -419,7 +434,8 @@ public:
/// value.
class CXXConstCastExpr final
: public CXXNamedCastExpr,
- private llvm::TrailingObjects<CXXConstCastExpr, CXXBaseSpecifier *> {
+ private llvm::TrailingObjects<CXXConstCastExpr, CastExpr::BasePathSizeTy,
+ CXXBaseSpecifier *> {
CXXConstCastExpr(QualType ty, ExprValueKind VK, Expr *op,
TypeSourceInfo *writtenTy, SourceLocation l,
SourceLocation RParenLoc, SourceRange AngleBrackets)
@@ -429,6 +445,10 @@ class CXXConstCastExpr final
explicit CXXConstCastExpr(EmptyShell Empty)
: CXXNamedCastExpr(CXXConstCastExprClass, Empty, 0) {}
+ size_t numTrailingObjects(OverloadToken<CastExpr::BasePathSizeTy>) const {
+ return path_empty() ? 0 : 1;
+ }
+
public:
friend class CastExpr;
friend TrailingObjects;
@@ -1471,7 +1491,8 @@ public:
/// \endcode
class CXXFunctionalCastExpr final
: public ExplicitCastExpr,
- private llvm::TrailingObjects<CXXFunctionalCastExpr, CXXBaseSpecifier *> {
+ private llvm::TrailingObjects<
+ CXXFunctionalCastExpr, CastExpr::BasePathSizeTy, CXXBaseSpecifier *> {
SourceLocation LParenLoc;
SourceLocation RParenLoc;
@@ -1486,6 +1507,10 @@ class CXXFunctionalCastExpr final
explicit CXXFunctionalCastExpr(EmptyShell Shell, unsigned PathSize)
: ExplicitCastExpr(CXXFunctionalCastExprClass, Shell, PathSize) {}
+ size_t numTrailingObjects(OverloadToken<CastExpr::BasePathSizeTy>) const {
+ return path_empty() ? 0 : 1;
+ }
+
public:
friend class CastExpr;
friend TrailingObjects;
diff --git a/include/clang/AST/ExprObjC.h b/include/clang/AST/ExprObjC.h
index bd413fdd33..bb0402c270 100644
--- a/include/clang/AST/ExprObjC.h
+++ b/include/clang/AST/ExprObjC.h
@@ -1571,7 +1571,8 @@ public:
/// \endcode
class ObjCBridgedCastExpr final
: public ExplicitCastExpr,
- private llvm::TrailingObjects<ObjCBridgedCastExpr, CXXBaseSpecifier *> {
+ private llvm::TrailingObjects<
+ ObjCBridgedCastExpr, CastExpr::BasePathSizeTy, CXXBaseSpecifier *> {
friend class ASTStmtReader;
friend class ASTStmtWriter;
friend class CastExpr;
@@ -1581,6 +1582,10 @@ class ObjCBridgedCastExpr final
SourceLocation BridgeKeywordLoc;
unsigned Kind : 2;
+ size_t numTrailingObjects(OverloadToken<CastExpr::BasePathSizeTy>) const {
+ return path_empty() ? 0 : 1;
+ }
+
public:
ObjCBridgedCastExpr(SourceLocation LParenLoc, ObjCBridgeCastKind Kind,
CastKind CK, SourceLocation BridgeKeywordLoc,
diff --git a/include/clang/AST/Stmt.h b/include/clang/AST/Stmt.h
index 2f03b50ad5..aa0f88b710 100644
--- a/include/clang/AST/Stmt.h
+++ b/include/clang/AST/Stmt.h
@@ -204,7 +204,7 @@ protected:
unsigned Kind : 6;
unsigned PartOfExplicitCast : 1; // Only set for ImplicitCastExpr.
- unsigned BasePathSize : 32 - 6 - 1 - NumExprBits;
+ unsigned BasePathIsEmpty : 1;
};
class CallExprBitfields {
diff --git a/lib/AST/Expr.cpp b/lib/AST/Expr.cpp
index dd1996df66..7556c76c38 100644
--- a/lib/AST/Expr.cpp
+++ b/lib/AST/Expr.cpp
@@ -1734,6 +1734,21 @@ NamedDecl *CastExpr::getConversionFunction() const {
return nullptr;
}
+CastExpr::BasePathSizeTy *CastExpr::BasePathSize() {
+ assert(!path_empty());
+ switch (getStmtClass()) {
+#define ABSTRACT_STMT(x)
+#define CASTEXPR(Type, Base) \
+ case Stmt::Type##Class: \
+ return static_cast<Type *>(this) \
+ ->getTrailingObjects<CastExpr::BasePathSizeTy>();
+#define STMT(Type, Base)
+#include "clang/AST/StmtNodes.inc"
+ default:
+ llvm_unreachable("non-cast expressions not possible here");
+ }
+}
+
CXXBaseSpecifier **CastExpr::path_buffer() {
switch (getStmtClass()) {
#define ABSTRACT_STMT(x)
@@ -1772,7 +1787,9 @@ ImplicitCastExpr *ImplicitCastExpr::Create(const ASTContext &C, QualType T,
const CXXCastPath *BasePath,
ExprValueKind VK) {
unsigned PathSize = (BasePath ? BasePath->size() : 0);
- void *Buffer = C.Allocate(totalSizeToAlloc<CXXBaseSpecifier *>(PathSize));
+ void *Buffer =
+ C.Allocate(totalSizeToAlloc<CastExpr::BasePathSizeTy, CXXBaseSpecifier *>(
+ PathSize ? 1 : 0, PathSize));
ImplicitCastExpr *E =
new (Buffer) ImplicitCastExpr(T, Kind, Operand, PathSize, VK);
if (PathSize)
@@ -1783,7 +1800,9 @@ ImplicitCastExpr *ImplicitCastExpr::Create(const ASTContext &C, QualType T,
ImplicitCastExpr *ImplicitCastExpr::CreateEmpty(const ASTContext &C,
unsigned PathSize) {
- void *Buffer = C.Allocate(totalSizeToAlloc<CXXBaseSpecifier *>(PathSize));
+ void *Buffer =
+ C.Allocate(totalSizeToAlloc<CastExpr::BasePathSizeTy, CXXBaseSpecifier *>(
+ PathSize ? 1 : 0, PathSize));
return new (Buffer) ImplicitCastExpr(EmptyShell(), PathSize);
}
@@ -1794,7 +1813,9 @@ CStyleCastExpr *CStyleCastExpr::Create(const ASTContext &C, QualType T,
TypeSourceInfo *WrittenTy,
SourceLocation L, SourceLocation R) {
unsigned PathSize = (BasePath ? BasePath->size() : 0);
- void *Buffer = C.Allocate(totalSizeToAlloc<CXXBaseSpecifier *>(PathSize));
+ void *Buffer =
+ C.Allocate(totalSizeToAlloc<CastExpr::BasePathSizeTy, CXXBaseSpecifier *>(
+ PathSize ? 1 : 0, PathSize));
CStyleCastExpr *E =
new (Buffer) CStyleCastExpr(T, VK, K, Op, PathSize, WrittenTy, L, R);
if (PathSize)
@@ -1805,7 +1826,9 @@ CStyleCastExpr *CStyleCastExpr::Create(const ASTContext &C, QualType T,
CStyleCastExpr *CStyleCastExpr::CreateEmpty(const ASTContext &C,
unsigned PathSize) {
- void *Buffer = C.Allocate(totalSizeToAlloc<CXXBaseSpecifier *>(PathSize));
+ void *Buffer =
+ C.Allocate(totalSizeToAlloc<CastExpr::BasePathSizeTy, CXXBaseSpecifier *>(
+ PathSize ? 1 : 0, PathSize));
return new (Buffer) CStyleCastExpr(EmptyShell(), PathSize);
}
diff --git a/lib/AST/ExprCXX.cpp b/lib/AST/ExprCXX.cpp
index e913a852f6..93d68ec8e0 100644
--- a/lib/AST/ExprCXX.cpp
+++ b/lib/AST/ExprCXX.cpp
@@ -559,7 +559,9 @@ CXXStaticCastExpr *CXXStaticCastExpr::Create(const ASTContext &C, QualType T,
SourceLocation RParenLoc,
SourceRange AngleBrackets) {
unsigned PathSize = (BasePath ? BasePath->size() : 0);
- void *Buffer = C.Allocate(totalSizeToAlloc<CXXBaseSpecifier *>(PathSize));
+ void *Buffer =
+ C.Allocate(totalSizeToAlloc<CastExpr::BasePathSizeTy, CXXBaseSpecifier *>(
+ PathSize ? 1 : 0, PathSize));
auto *E =
new (Buffer) CXXStaticCastExpr(T, VK, K, Op, PathSize, WrittenTy, L,
RParenLoc, AngleBrackets);
@@ -571,7 +573,9 @@ CXXStaticCastExpr *CXXStaticCastExpr::Create(const ASTContext &C, QualType T,
CXXStaticCastExpr *CXXStaticCastExpr::CreateEmpty(const ASTContext &C,
unsigned PathSize) {
- void *Buffer = C.Allocate(totalSizeToAlloc<CXXBaseSpecifier *>(PathSize));
+ void *Buffer =
+ C.Allocate(totalSizeToAlloc<CastExpr::BasePathSizeTy, CXXBaseSpecifier *>(
+ PathSize ? 1 : 0, PathSize));
return new (Buffer) CXXStaticCastExpr(EmptyShell(), PathSize);
}
@@ -584,7 +588,9 @@ CXXDynamicCastExpr *CXXDynamicCastExpr::Create(const ASTContext &C, QualType T,
SourceLocation RParenLoc,
SourceRange AngleBrackets) {
unsigned PathSize = (BasePath ? BasePath->size() : 0);
- void *Buffer = C.Allocate(totalSizeToAlloc<CXXBaseSpecifier *>(PathSize));
+ void *Buffer =
+ C.Allocate(totalSizeToAlloc<CastExpr::BasePathSizeTy, CXXBaseSpecifier *>(
+ PathSize ? 1 : 0, PathSize));
auto *E =
new (Buffer) CXXDynamicCastExpr(T, VK, K, Op, PathSize, WrittenTy, L,
RParenLoc, AngleBrackets);
@@ -596,7 +602,9 @@ CXXDynamicCastExpr *CXXDynamicCastExpr::Create(const ASTContext &C, QualType T,
CXXDynamicCastExpr *CXXDynamicCastExpr::CreateEmpty(const ASTContext &C,
unsigned PathSize) {
- void *Buffer = C.Allocate(totalSizeToAlloc<CXXBaseSpecifier *>(PathSize));
+ void *Buffer =
+ C.Allocate(totalSizeToAlloc<CastExpr::BasePathSizeTy, CXXBaseSpecifier *>(
+ PathSize ? 1 : 0, PathSize));
return new (Buffer) CXXDynamicCastExpr(EmptyShell(), PathSize);
}
@@ -641,7 +649,9 @@ CXXReinterpretCastExpr::Create(const ASTContext &C, QualType T,
SourceLocation RParenLoc,
SourceRange AngleBrackets) {
unsigned PathSize = (BasePath ? BasePath->size() : 0);
- void *Buffer = C.Allocate(totalSizeToAlloc<CXXBaseSpecifier *>(PathSize));
+ void *Buffer =
+ C.Allocate(totalSizeToAlloc<CastExpr::BasePathSizeTy, CXXBaseSpecifier *>(
+ PathSize ? 1 : 0, PathSize));
auto *E =
new (Buffer) CXXReinterpretCastExpr(T, VK, K, Op, PathSize, WrittenTy, L,
RParenLoc, AngleBrackets);
@@ -653,7 +663,9 @@ CXXReinterpretCastExpr::Create(const ASTContext &C, QualType T,
CXXReinterpretCastExpr *
CXXReinterpretCastExpr::CreateEmpty(const ASTContext &C, unsigned PathSize) {
- void *Buffer = C.Allocate(totalSizeToAlloc<CXXBaseSpecifier *>(PathSize));
+ void *Buffer =
+ C.Allocate(totalSizeToAlloc<CastExpr::BasePathSizeTy, CXXBaseSpecifier *>(
+ PathSize ? 1 : 0, PathSize));
return new (Buffer) CXXReinterpretCastExpr(EmptyShell(), PathSize);
}
@@ -676,7 +688,9 @@ CXXFunctionalCastExpr::Create(const ASTContext &C, QualType T, ExprValueKind VK,
const CXXCastPath *BasePath,
SourceLocation L, SourceLocation R) {
unsigned PathSize = (BasePath ? BasePath->size() : 0);
- void *Buffer = C.Allocate(totalSizeToAlloc<CXXBaseSpecifier *>(PathSize));
+ void *Buffer =
+ C.Allocate(totalSizeToAlloc<CastExpr::BasePathSizeTy, CXXBaseSpecifier *>(
+ PathSize ? 1 : 0, PathSize));
auto *E =
new (Buffer) CXXFunctionalCastExpr(T, VK, Written, K, Op, PathSize, L, R);
if (PathSize)
@@ -687,7 +701,9 @@ CXXFunctionalCastExpr::Create(const ASTContext &C, QualType T, ExprValueKind VK,
CXXFunctionalCastExpr *
CXXFunctionalCastExpr::CreateEmpty(const ASTContext &C, unsigned PathSize) {
- void *Buffer = C.Allocate(totalSizeToAlloc<CXXBaseSpecifier *>(PathSize));
+ void *Buffer =
+ C.Allocate(totalSizeToAlloc<CastExpr::BasePathSizeTy, CXXBaseSpecifier *>(
+ PathSize ? 1 : 0, PathSize));
return new (Buffer) CXXFunctionalCastExpr(EmptyShell(), PathSize);
}
diff --git a/test/CodeGenCXX/castexpr-basepathsize-threshold.cpp b/test/CodeGenCXX/castexpr-basepathsize-threshold.cpp
new file mode 100644
index 0000000000..d5c1f603ff
--- /dev/null
+++ b/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;
+}