summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJordan Rose <jordan_rose@apple.com>2017-10-24 02:17:07 +0000
committerJordan Rose <jordan_rose@apple.com>2017-10-24 02:17:07 +0000
commitbca81dc70a81c58378cc853256544386194ced1d (patch)
tree78c9ee657de4b2b5c3b85513acdc7ac93032d946
parentfbbb8c17f50e6bb450a12965d30ac47a12c9aa58 (diff)
Unnamed bitfields don't block constant evaluation of constexpr ctors
C++14 [dcl.constexpr]p4 states that in the body of a constexpr constructor, > every non-variant non-static data member and base class sub-object shall be initialized However, [class.bit]p2 notes that > Unnamed bit-fields are not members and cannot be initialized. Therefore, we should make sure to filter them out of the check that all fields are initialized. Fixing this makes the constant evaluator a bit smarter, and specifically allows constexpr constructors to avoid tripping -Wglobal-constructors when the type contains unnamed bitfields. Reviewed at https://reviews.llvm.org/D39035. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@316408 91177308-0d34-0410-b5e6-96231b3b80d8
-rw-r--r--lib/AST/ExprConstant.cpp3
-rw-r--r--test/SemaCXX/constant-expression-cxx11.cpp16
-rw-r--r--test/SemaCXX/warn-global-constructors.cpp19
3 files changed, 38 insertions, 0 deletions
diff --git a/lib/AST/ExprConstant.cpp b/lib/AST/ExprConstant.cpp
index c25b3b6322..c09c99386c 100644
--- a/lib/AST/ExprConstant.cpp
+++ b/lib/AST/ExprConstant.cpp
@@ -1818,6 +1818,9 @@ static bool CheckConstantExpression(EvalInfo &Info, SourceLocation DiagLoc,
}
}
for (const auto *I : RD->fields()) {
+ if (I->isUnnamedBitfield())
+ continue;
+
if (!CheckConstantExpression(Info, DiagLoc, I->getType(),
Value.getStructField(I->getFieldIndex())))
return false;
diff --git a/test/SemaCXX/constant-expression-cxx11.cpp b/test/SemaCXX/constant-expression-cxx11.cpp
index 68b82c7d96..51dd6199e6 100644
--- a/test/SemaCXX/constant-expression-cxx11.cpp
+++ b/test/SemaCXX/constant-expression-cxx11.cpp
@@ -1931,6 +1931,22 @@ namespace Bitfields {
};
static_assert(X::f(3) == -1, "3 should truncate to -1");
}
+
+ struct HasUnnamedBitfield {
+ unsigned a;
+ unsigned : 20;
+ unsigned b;
+
+ constexpr HasUnnamedBitfield() : a(), b() {}
+ constexpr HasUnnamedBitfield(unsigned a, unsigned b) : a(a), b(b) {}
+ };
+
+ void testUnnamedBitfield() {
+ const HasUnnamedBitfield zero{};
+ int a = 1 / zero.b; // expected-warning {{division by zero is undefined}}
+ const HasUnnamedBitfield oneZero{1, 0};
+ int b = 1 / oneZero.b; // expected-warning {{division by zero is undefined}}
+ }
}
namespace ZeroSizeTypes {
diff --git a/test/SemaCXX/warn-global-constructors.cpp b/test/SemaCXX/warn-global-constructors.cpp
index 856826414a..430f239a3e 100644
--- a/test/SemaCXX/warn-global-constructors.cpp
+++ b/test/SemaCXX/warn-global-constructors.cpp
@@ -126,3 +126,22 @@ namespace pr20420 {
void *array_storage[1];
const int &global_reference = *(int *)array_storage;
}
+
+namespace bitfields {
+ struct HasUnnamedBitfield {
+ unsigned a;
+ unsigned : 20;
+ unsigned b;
+
+ constexpr HasUnnamedBitfield() : a(), b() {}
+ constexpr HasUnnamedBitfield(unsigned a, unsigned b) : a(a), b(b) {}
+ explicit HasUnnamedBitfield(unsigned a) {}
+ };
+
+ const HasUnnamedBitfield zeroConst{};
+ HasUnnamedBitfield zeroMutable{};
+ const HasUnnamedBitfield explicitConst{1, 2};
+ HasUnnamedBitfield explicitMutable{1, 2};
+ const HasUnnamedBitfield nonConstexprConst{1}; // expected-warning {{global constructor}}
+ HasUnnamedBitfield nonConstexprMutable{1}; // expected-warning {{global constructor}}
+}