summaryrefslogtreecommitdiffstats
path: root/clang/lib
diff options
context:
space:
mode:
authorRichard Smith <richard-llvm@metafoo.co.uk>2011-12-02 00:30:33 +0000
committerRichard Smith <richard-llvm@metafoo.co.uk>2011-12-02 00:30:33 +0000
commitd572f82e490b5dd4e0578ca3420004ecd97969cb (patch)
treeb952642c42855b3fd9e3bf9dda29373b8b27bc8d /clang/lib
parent3aac38e90f1151f31fecf479884a9f9f45d9da32 (diff)
downloadbcm5719-llvm-d572f82e490b5dd4e0578ca3420004ecd97969cb.tar.gz
bcm5719-llvm-d572f82e490b5dd4e0578ca3420004ecd97969cb.zip
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. llvm-svn: 145654
Diffstat (limited to 'clang/lib')
-rw-r--r--clang/lib/CodeGen/CGDecl.cpp17
1 files changed, 10 insertions, 7 deletions
diff --git a/clang/lib/CodeGen/CGDecl.cpp b/clang/lib/CodeGen/CGDecl.cpp
index 562cc5bb909..59efea0dae1 100644
--- a/clang/lib/CodeGen/CGDecl.cpp
+++ b/clang/lib/CodeGen/CGDecl.cpp
@@ -739,11 +739,13 @@ CodeGenFunction::EmitAutoVarAlloca(const VarDecl &D) {
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 @@ CodeGenFunction::EmitAutoVarAlloca(const VarDecl &D) {
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
OpenPOWER on IntegriCloud