[cfe-commits] r145654 - in /cfe/trunk: lib/CodeGen/CGDecl.cpp test/CodeGenCXX/const-init.cpp
Richard Smith
richard-llvm at metafoo.co.uk
Thu Dec 1 16:30:33 PST 2011
Author: rsmith
Date: Thu Dec 1 18:30:33 2011
New Revision: 145654
URL: http://llvm.org/viewvc/llvm-project?rev=145654&view=rev
Log:
Fix wrong-code bug when a const automatic variable of struct type has both a
mutable member and a constant initializer. We'd previously promoted such
variables to global constants, resulting in nasal demons if the mutable member
was modified.
This is only a temporary fix. The subtle interplay between isConstantInitializer
and CGExprConstant is very bug-prone; there are some other issues in this area
which I will be addressing in subsequent, more major reworking of this code.
Modified:
cfe/trunk/lib/CodeGen/CGDecl.cpp
cfe/trunk/test/CodeGenCXX/const-init.cpp
Modified: cfe/trunk/lib/CodeGen/CGDecl.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/CGDecl.cpp?rev=145654&r1=145653&r2=145654&view=diff
==============================================================================
--- cfe/trunk/lib/CodeGen/CGDecl.cpp (original)
+++ cfe/trunk/lib/CodeGen/CGDecl.cpp Thu Dec 1 18:30:33 2011
@@ -739,11 +739,13 @@
D.isNRVOVariable();
// If this value is a POD array or struct with a statically
- // determinable constant initializer, there are optimizations we
- // can do.
- // TODO: we can potentially constant-evaluate non-POD structs and
- // arrays as long as the initialization is trivial (e.g. if they
- // have a non-trivial destructor, but not a non-trivial constructor).
+ // determinable constant initializer, there are optimizations we can do.
+ //
+ // TODO: we should constant-evaluate any variable of literal type
+ // as long as it is initialized by a constant expression. Currently,
+ // isConstantInitializer produces wrong answers for structs with
+ // reference or bitfield members, and a few other cases, and checking
+ // for POD-ness protects us from some of these.
if (D.getInit() &&
(Ty->isArrayType() || Ty->isRecordType()) &&
(Ty.isPODType(getContext()) ||
@@ -751,9 +753,10 @@
D.getInit()->isConstantInitializer(getContext(), false)) {
// If the variable's a const type, and it's neither an NRVO
- // candidate nor a __block variable, emit it as a global instead.
+ // candidate nor a __block variable and has no mutable members,
+ // emit it as a global instead.
if (CGM.getCodeGenOpts().MergeAllConstants && Ty.isConstQualified() &&
- !NRVO && !isByRef) {
+ !NRVO && !isByRef && Ty->isLiteralType()) {
EmitStaticVarDecl(D, llvm::GlobalValue::InternalLinkage);
emission.Address = 0; // signal this condition to later callbacks
Modified: cfe/trunk/test/CodeGenCXX/const-init.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CodeGenCXX/const-init.cpp?rev=145654&r1=145653&r2=145654&view=diff
==============================================================================
--- cfe/trunk/test/CodeGenCXX/const-init.cpp (original)
+++ cfe/trunk/test/CodeGenCXX/const-init.cpp Thu Dec 1 18:30:33 2011
@@ -45,3 +45,14 @@
// We don't expect to fold this in the frontend, but make sure it doesn't crash.
// CHECK: @PR9558 = global float 0.000000e+0
float PR9558 = reinterpret_cast<const float&>("asd");
+
+// An initialized const automatic variable cannot be promoted to a constant
+// global if it has a mutable member.
+struct MutableMember {
+ mutable int n;
+};
+int writeToMutable() {
+ // CHECK-NOT: {{.*}}MM{{.*}} = {{.*}}constant
+ const MutableMember MM = { 0 };
+ return ++MM.n;
+}
More information about the cfe-commits
mailing list