Index: cfe/trunk/lib/AST/ExprConstant.cpp =================================================================== --- cfe/trunk/lib/AST/ExprConstant.cpp +++ cfe/trunk/lib/AST/ExprConstant.cpp @@ -1627,8 +1627,17 @@ // C++1y: A constant initializer for an object o [...] may also invoke // constexpr constructors for o and its subobjects even if those objects // are of non-literal class types. - if (Info.getLangOpts().CPlusPlus14 && This && - Info.EvaluatingDecl == This->getLValueBase()) + // + // C++11 missed this detail for aggregates, so classes like this: + // struct foo_t { union { int i; volatile int j; } u; }; + // are not (obviously) initializable like so: + // __attribute__((__require_constant_initialization__)) + // static const foo_t x = {{0}}; + // because "i" is a subobject with non-literal initialization (due to the + // volatile member of the union). See: + // http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_active.html#1677 + // Therefore, we use the C++1y behavior. + if (This && Info.EvaluatingDecl == This->getLValueBase()) return true; // Prvalue constant expressions must be of literal types. Index: cfe/trunk/test/CXX/basic/basic.start/basic.start.init/p2.cpp =================================================================== --- cfe/trunk/test/CXX/basic/basic.start/basic.start.init/p2.cpp +++ cfe/trunk/test/CXX/basic/basic.start/basic.start.init/p2.cpp @@ -0,0 +1,21 @@ +// RUN: %clang_cc1 -verify %s -pedantic-errors -std=c++11 +// RUN: %clang_cc1 -verify %s -pedantic-errors -std=c++14 +// expected-no-diagnostics + +struct foo_t { + union { + int i; + volatile int j; + } u; +}; + +__attribute__((__require_constant_initialization__)) +static const foo_t x = {{0}}; + +union foo_u { + int i; + volatile int j; +}; + +__attribute__((__require_constant_initialization__)) +static const foo_u y = {0}; Index: cfe/trunk/test/CodeGenCXX/global-array-destruction.cpp =================================================================== --- cfe/trunk/test/CodeGenCXX/global-array-destruction.cpp +++ cfe/trunk/test/CodeGenCXX/global-array-destruction.cpp @@ -39,7 +39,7 @@ T t[2][3] = { 1.0, 2, 3.0, 4, 5.0, 6, 7.0, 8, 9.0, 10, 11.0, 12 }; // CHECK: call {{.*}} @__cxa_atexit -// CHECK: getelementptr inbounds ({{.*}} bitcast {{.*}}* @t to %struct.T*), i64 6 +// CHECK: getelementptr inbounds ({{.*}} getelementptr inbounds ([2 x [3 x {{.*}}]], [2 x [3 x {{.*}}]]* @t, i32 0, i32 0, i32 0), i64 6) // CHECK: call void @_ZN1TD1Ev // CHECK: icmp eq {{.*}} @t // CHECK: br i1 {{.*}} @@ -47,9 +47,9 @@ static T t2[2][3] = { 1.0, 2, 3.0, 4, 5.0, 6, 7.0, 8, 9.0, 10, 11.0, 12 }; // CHECK: call {{.*}} @__cxa_atexit -// CHECK: getelementptr inbounds ({{.*}} bitcast {{.*}}* @_ZL2t2 to %struct.T*), i64 6 +// CHECK: getelementptr inbounds ({{.*}} getelementptr inbounds ([2 x [3 x {{.*}}]], [2 x [3 x {{.*}}]]* @_ZL2t2, i32 0, i32 0, i32 0), i64 6) // CHECK: call void @_ZN1TD1Ev -// CHECK: icmp eq {{.*}} @_ZL2t +// CHECK: icmp eq {{.*}} @_ZL2t2 // CHECK: br i1 {{.*}} using U = T[2][3];