diff options
Diffstat (limited to 'lib')
-rw-r--r-- | lib/AST/DeclCXX.cpp | 6 | ||||
-rw-r--r-- | lib/AST/ExprConstant.cpp | 7 | ||||
-rw-r--r-- | lib/CodeGen/CGDecl.cpp | 14 | ||||
-rw-r--r-- | lib/Sema/SemaType.cpp | 3 |
4 files changed, 17 insertions, 13 deletions
diff --git a/lib/AST/DeclCXX.cpp b/lib/AST/DeclCXX.cpp index d5221031a5..aa24e9b625 100644 --- a/lib/AST/DeclCXX.cpp +++ b/lib/AST/DeclCXX.cpp @@ -800,11 +800,7 @@ NotASpecialMember:; } // Record if this field is the first non-literal field or base. - // As a slight variation on the standard, we regard mutable members as being - // non-literal, since mutating a constexpr variable would break C++11 - // constant expression semantics. - if ((!hasNonLiteralTypeFieldsOrBases() && !T->isLiteralType()) || - Field->isMutable()) + if (!hasNonLiteralTypeFieldsOrBases() && !T->isLiteralType()) data().HasNonLiteralTypeFieldsOrBases = true; if (Field->hasInClassInitializer()) { diff --git a/lib/AST/ExprConstant.cpp b/lib/AST/ExprConstant.cpp index 48e0c6f7da..e43884e376 100644 --- a/lib/AST/ExprConstant.cpp +++ b/lib/AST/ExprConstant.cpp @@ -1453,6 +1453,13 @@ static bool ExtractSubobject(EvalInfo &Info, const Expr *E, O = &O->getArrayFiller(); ObjType = CAT->getElementType(); } else if (const FieldDecl *Field = getAsField(Sub.Entries[I])) { + if (Field->isMutable()) { + Info.Diag(E->getExprLoc(), diag::note_constexpr_ltor_mutable, 1) + << Field; + Info.Note(Field->getLocation(), diag::note_declared_at); + return false; + } + // Next subobject is a class, struct or union field. RecordDecl *RD = ObjType->castAs<RecordType>()->getDecl(); if (RD->isUnion()) { diff --git a/lib/CodeGen/CGDecl.cpp b/lib/CodeGen/CGDecl.cpp index 82f7fed7ba..3d32091a4b 100644 --- a/lib/CodeGen/CGDecl.cpp +++ b/lib/CodeGen/CGDecl.cpp @@ -773,11 +773,15 @@ CodeGenFunction::EmitAutoVarAlloca(const VarDecl &D) { // emit it as a global instead. if (CGM.getCodeGenOpts().MergeAllConstants && Ty.isConstQualified() && !NRVO && !isByRef && Ty->isLiteralType()) { - EmitStaticVarDecl(D, llvm::GlobalValue::InternalLinkage); - - emission.Address = 0; // signal this condition to later callbacks - assert(emission.wasEmittedAsGlobal()); - return emission; + CXXRecordDecl *RD = + Ty->getBaseElementTypeUnsafe()->getAsCXXRecordDecl(); + if (!RD || !RD->hasMutableFields()) { + EmitStaticVarDecl(D, llvm::GlobalValue::InternalLinkage); + + emission.Address = 0; // signal this condition to later callbacks + assert(emission.wasEmittedAsGlobal()); + return emission; + } } // Otherwise, tell the initialization code that we're in this case. diff --git a/lib/Sema/SemaType.cpp b/lib/Sema/SemaType.cpp index daf0b683b6..9fd611b5fe 100644 --- a/lib/Sema/SemaType.cpp +++ b/lib/Sema/SemaType.cpp @@ -4302,9 +4302,6 @@ bool Sema::RequireLiteralType(SourceLocation Loc, QualType T, Diag((*I)->getLocation(), diag::note_non_literal_field) << RD << (*I) << (*I)->getType(); return true; - } else if ((*I)->isMutable()) { - Diag((*I)->getLocation(), diag::note_non_literal_mutable_field) << RD; - return true; } } } else if (!RD->hasTrivialDestructor()) { |