summaryrefslogtreecommitdiffstats
path: root/clang/lib/AST/DeclCXX.cpp
diff options
context:
space:
mode:
authorRichard Smith <richard-llvm@metafoo.co.uk>2018-05-07 06:43:30 +0000
committerRichard Smith <richard-llvm@metafoo.co.uk>2018-05-07 06:43:30 +0000
commitb5a317fbf67a711f5cebad6b5c21324be103fa6c (patch)
tree83a71b577c595cf5969715e1e992eb42fb0f21bf /clang/lib/AST/DeclCXX.cpp
parentfac095caba2550c7a49cdd9c0b921c07185dd587 (diff)
downloadbcm5719-llvm-b5a317fbf67a711f5cebad6b5c21324be103fa6c.tar.gz
bcm5719-llvm-b5a317fbf67a711f5cebad6b5c21324be103fa6c.zip
Non-zero-length bit-fields make a class non-empty.
This implements the rule intended by the standard (see LWG 2358) and the rule intended by the Itanium C++ ABI (see https://github.com/itanium-cxx-abi/cxx-abi/pull/51), and makes Clang match the behavior of GCC, ICC, and MSVC. A pedantic reading of both the standard and the ABI indicate that Clang is currently technically correct, but that's not worth much when it's clear that the wording is wrong in both those places. This is an ABI break for classes that derive from a class that is empty other than one or more unnamed non-zero-length bit-fields. Such cases are expected to be rare, but -fclang-abi-compat=6 restores the old behavior just in case. Differential Revision: https://reviews.llvm.org/D45174 llvm-svn: 331620
Diffstat (limited to 'clang/lib/AST/DeclCXX.cpp')
-rw-r--r--clang/lib/AST/DeclCXX.cpp22
1 files changed, 13 insertions, 9 deletions
diff --git a/clang/lib/AST/DeclCXX.cpp b/clang/lib/AST/DeclCXX.cpp
index dd653d8f573..f3b3ed0fa29 100644
--- a/clang/lib/AST/DeclCXX.cpp
+++ b/clang/lib/AST/DeclCXX.cpp
@@ -856,10 +856,10 @@ void CXXRecordDecl::addedMember(Decl *D) {
return;
}
- ASTContext &Context = getASTContext();
-
// Handle non-static data members.
if (const auto *Field = dyn_cast<FieldDecl>(D)) {
+ ASTContext &Context = getASTContext();
+
// C++2a [class]p7:
// A standard-layout class is a class that:
// [...]
@@ -872,8 +872,16 @@ void CXXRecordDecl::addedMember(Decl *D) {
// A declaration for a bit-field that omits the identifier declares an
// unnamed bit-field. Unnamed bit-fields are not members and cannot be
// initialized.
- if (Field->isUnnamedBitfield())
+ if (Field->isUnnamedBitfield()) {
+ // C++ [meta.unary.prop]p4: [LWG2358]
+ // T is a class type [...] with [...] no unnamed bit-fields of non-zero
+ // length
+ if (data().Empty && !Field->isZeroLengthBitField(Context) &&
+ Context.getLangOpts().getClangABICompat() >
+ LangOptions::ClangABI::Ver6)
+ data().Empty = false;
return;
+ }
// C++11 [class]p7:
// A standard-layout class is a class that:
@@ -1220,12 +1228,8 @@ void CXXRecordDecl::addedMember(Decl *D) {
}
// C++14 [meta.unary.prop]p4:
- // T is a class type [...] with [...] no non-static data members other
- // than bit-fields of length 0...
- if (data().Empty) {
- if (!Field->isZeroLengthBitField(Context))
- data().Empty = false;
- }
+ // T is a class type [...] with [...] no non-static data members
+ data().Empty = false;
}
// Handle using declarations of conversion functions.
OpenPOWER on IntegriCloud