[cfe-commits] r148987 - in /cfe/trunk: lib/AST/ExprConstant.cpp test/SemaCXX/constant-expression-cxx11.cpp
Richard Smith
richard-llvm at metafoo.co.uk
Wed Jan 25 14:15:11 PST 2012
Author: rsmith
Date: Wed Jan 25 16:15:11 2012
New Revision: 148987
URL: http://llvm.org/viewvc/llvm-project?rev=148987&view=rev
Log:
constexpr: add support for anonymous struct and union members in literal types.
Modified:
cfe/trunk/lib/AST/ExprConstant.cpp
cfe/trunk/test/SemaCXX/constant-expression-cxx11.cpp
Modified: cfe/trunk/lib/AST/ExprConstant.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/AST/ExprConstant.cpp?rev=148987&r1=148986&r2=148987&view=diff
==============================================================================
--- cfe/trunk/lib/AST/ExprConstant.cpp (original)
+++ cfe/trunk/lib/AST/ExprConstant.cpp Wed Jan 25 16:15:11 2012
@@ -1188,6 +1188,15 @@
LVal.addDecl(Info, E, FD);
}
+/// Update LVal to refer to the given indirect field.
+static void HandleLValueIndirectMember(EvalInfo &Info, const Expr *E,
+ LValue &LVal,
+ const IndirectFieldDecl *IFD) {
+ for (IndirectFieldDecl::chain_iterator C = IFD->chain_begin(),
+ CE = IFD->chain_end(); C != CE; ++C)
+ HandleLValueMember(Info, E, LVal, cast<FieldDecl>(*C));
+}
+
/// Get the size of the given type in char units.
static bool HandleSizeof(EvalInfo &Info, QualType Type, CharUnits &Size) {
// sizeof(void), __alignof__(void), sizeof(function) = 1 as a gcc
@@ -1654,10 +1663,13 @@
// Add the member. Note that we cannot build bound member functions here.
if (IncludeMember) {
- // FIXME: Deal with IndirectFieldDecls.
- const FieldDecl *FD = dyn_cast<FieldDecl>(MemPtr.getDecl());
- if (!FD) return 0;
- HandleLValueMember(Info, BO, LV, FD);
+ if (const FieldDecl *FD = dyn_cast<FieldDecl>(MemPtr.getDecl()))
+ HandleLValueMember(Info, BO, LV, FD);
+ else if (const IndirectFieldDecl *IFD =
+ dyn_cast<IndirectFieldDecl>(MemPtr.getDecl()))
+ HandleLValueIndirectMember(Info, BO, LV, IFD);
+ else
+ llvm_unreachable("can't construct reference to bound member function");
}
return MemPtr.getDecl();
@@ -1904,11 +1916,40 @@
Result.getStructField(FD->getFieldIndex()),
Info, Subobject, (*I)->getInit(), CCEK_MemberInit))
return false;
+ } else if (IndirectFieldDecl *IFD = (*I)->getIndirectMember()) {
+ LValue Subobject = This;
+ APValue *Value = &Result;
+ // Walk the indirect field decl's chain to find the object to initialize,
+ // and make sure we've initialized every step along it.
+ for (IndirectFieldDecl::chain_iterator C = IFD->chain_begin(),
+ CE = IFD->chain_end();
+ C != CE; ++C) {
+ FieldDecl *FD = cast<FieldDecl>(*C);
+ CXXRecordDecl *CD = cast<CXXRecordDecl>(FD->getParent());
+ // Switch the union field if it differs. This happens if we had
+ // preceding zero-initialization, and we're now initializing a union
+ // subobject other than the first.
+ // FIXME: In this case, the values of the other subobjects are
+ // specified, since zero-initialization sets all padding bits to zero.
+ if (Value->isUninit() ||
+ (Value->isUnion() && Value->getUnionField() != FD)) {
+ if (CD->isUnion())
+ *Value = APValue(FD);
+ else
+ *Value = APValue(APValue::UninitStruct(), CD->getNumBases(),
+ std::distance(CD->field_begin(), CD->field_end()));
+ }
+ if (CD->isUnion())
+ Value = &Value->getUnionValue();
+ else
+ Value = &Value->getStructField(FD->getFieldIndex());
+ HandleLValueMember(Info, (*I)->getInit(), Subobject, FD);
+ }
+ if (!EvaluateConstantExpression(*Value, Info, Subobject, (*I)->getInit(),
+ CCEK_MemberInit))
+ return false;
} else {
- // FIXME: handle indirect field initializers
- Info.Diag((*I)->getInit()->getExprLoc(),
- diag::note_invalid_subexpr_in_const_expr);
- return false;
+ llvm_unreachable("unknown base initializer kind");
}
}
@@ -2349,18 +2390,20 @@
BaseTy = E->getBase()->getType();
}
- const FieldDecl *FD = dyn_cast<FieldDecl>(E->getMemberDecl());
- // FIXME: Handle IndirectFieldDecls
- if (!FD) return this->Error(E);
- assert(BaseTy->getAs<RecordType>()->getDecl()->getCanonicalDecl() ==
- FD->getParent()->getCanonicalDecl() && "record / field mismatch");
- (void)BaseTy;
-
- HandleLValueMember(this->Info, E, Result, FD);
+ const ValueDecl *MD = E->getMemberDecl();
+ if (const FieldDecl *FD = dyn_cast<FieldDecl>(E->getMemberDecl())) {
+ assert(BaseTy->getAs<RecordType>()->getDecl()->getCanonicalDecl() ==
+ FD->getParent()->getCanonicalDecl() && "record / field mismatch");
+ (void)BaseTy;
+ HandleLValueMember(this->Info, E, Result, FD);
+ } else if (const IndirectFieldDecl *IFD = dyn_cast<IndirectFieldDecl>(MD)) {
+ HandleLValueIndirectMember(this->Info, E, Result, IFD);
+ } else
+ return this->Error(E);
- if (FD->getType()->isReferenceType()) {
+ if (MD->getType()->isReferenceType()) {
CCValue RefValue;
- if (!HandleLValueToRValueConversion(this->Info, E, FD->getType(), Result,
+ if (!HandleLValueToRValueConversion(this->Info, E, MD->getType(), Result,
RefValue))
return false;
return Success(RefValue, E);
Modified: cfe/trunk/test/SemaCXX/constant-expression-cxx11.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/SemaCXX/constant-expression-cxx11.cpp?rev=148987&r1=148986&r2=148987&view=diff
==============================================================================
--- cfe/trunk/test/SemaCXX/constant-expression-cxx11.cpp (original)
+++ cfe/trunk/test/SemaCXX/constant-expression-cxx11.cpp Wed Jan 25 16:15:11 2012
@@ -1046,3 +1046,43 @@
eq = reinterpret_cast<int>((int*)0) // expected-error {{not a constant expression}} expected-note {{reinterpret_cast}}
};
}
+
+namespace IndirectField {
+ struct S {
+ struct { // expected-warning {{GNU extension}}
+ union {
+ struct { // expected-warning {{GNU extension}}
+ int a;
+ int b;
+ };
+ int c;
+ };
+ int d;
+ };
+ union {
+ int e;
+ int f;
+ };
+ constexpr S(int a, int b, int d, int e) : a(a), b(b), d(d), e(e) {}
+ constexpr S(int c, int d, int f) : c(c), d(d), f(f) {}
+ };
+
+ constexpr S s1(1, 2, 3, 4);
+ constexpr S s2(5, 6, 7);
+
+ // FIXME: The diagnostics here do a very poor job of explaining which unnamed
+ // member is active and which is requested.
+ static_assert(s1.a == 1, "");
+ static_assert(s1.b == 2, "");
+ static_assert(s1.c == 0, ""); // expected-error {{constant expression}} expected-note {{union with active member}}
+ static_assert(s1.d == 3, "");
+ static_assert(s1.e == 4, "");
+ static_assert(s1.f == 0, ""); // expected-error {{constant expression}} expected-note {{union with active member}}
+
+ static_assert(s2.a == 0, ""); // expected-error {{constant expression}} expected-note {{union with active member}}
+ static_assert(s2.b == 0, ""); // expected-error {{constant expression}} expected-note {{union with active member}}
+ static_assert(s2.c == 5, "");
+ static_assert(s2.d == 6, "");
+ static_assert(s2.e == 0, ""); // expected-error {{constant expression}} expected-note {{union with active member}}
+ static_assert(s2.f == 7, "");
+}
More information about the cfe-commits
mailing list