diff options
author | Richard Smith <richard-llvm@metafoo.co.uk> | 2016-12-06 23:52:28 +0000 |
---|---|---|
committer | Richard Smith <richard-llvm@metafoo.co.uk> | 2016-12-06 23:52:28 +0000 |
commit | 122f88d481971b68d05ba12395c3b73ab4b31ab3 (patch) | |
tree | c59ee8196c104634ee39555cc8b9d97ee5d75b5c /clang/lib/AST | |
parent | 2187bb8a89cdbe529ee222bf56d1b7415337cb20 (diff) | |
download | bcm5719-llvm-122f88d481971b68d05ba12395c3b73ab4b31ab3.tar.gz bcm5719-llvm-122f88d481971b68d05ba12395c3b73ab4b31ab3.zip |
[c++17] P0135R1: Guaranteed copy elision.
When an object of class type is initialized from a prvalue of the same type
(ignoring cv qualifications), use the prvalue to initialize the object directly
instead of inserting a redundant elidable call to a copy constructor.
llvm-svn: 288866
Diffstat (limited to 'clang/lib/AST')
-rw-r--r-- | clang/lib/AST/Expr.cpp | 29 | ||||
-rw-r--r-- | clang/lib/AST/ExprConstant.cpp | 3 |
2 files changed, 28 insertions, 4 deletions
diff --git a/clang/lib/AST/Expr.cpp b/clang/lib/AST/Expr.cpp index e43a9c53d90..776a7f996d0 100644 --- a/clang/lib/AST/Expr.cpp +++ b/clang/lib/AST/Expr.cpp @@ -1864,6 +1864,24 @@ bool InitListExpr::isStringLiteralInit() const { return isa<StringLiteral>(Init) || isa<ObjCEncodeExpr>(Init); } +bool InitListExpr::isTransparent() const { + assert(isSemanticForm() && "syntactic form never semantically transparent"); + + // A glvalue InitListExpr is always just sugar. + if (isGLValue()) { + assert(getNumInits() == 1 && "multiple inits in glvalue init list"); + return true; + } + + // Otherwise, we're sugar if and only if we have exactly one initializer that + // is of the same type. + if (getNumInits() != 1 || !getInit(0)) + return false; + + return getType().getCanonicalType() == + getInit(0)->getType().getCanonicalType(); +} + SourceLocation InitListExpr::getLocStart() const { if (InitListExpr *SyntacticForm = getSyntacticForm()) return SyntacticForm->getLocStart(); @@ -2246,12 +2264,15 @@ bool Expr::isUnusedResultAWarning(const Expr *&WarnE, SourceLocation &Loc, // effects (e.g. a placement new with an uninitialized POD). case CXXDeleteExprClass: return false; + case MaterializeTemporaryExprClass: + return cast<MaterializeTemporaryExpr>(this)->GetTemporaryExpr() + ->isUnusedResultAWarning(WarnE, Loc, R1, R2, Ctx); case CXXBindTemporaryExprClass: - return (cast<CXXBindTemporaryExpr>(this) - ->getSubExpr()->isUnusedResultAWarning(WarnE, Loc, R1, R2, Ctx)); + return cast<CXXBindTemporaryExpr>(this)->getSubExpr() + ->isUnusedResultAWarning(WarnE, Loc, R1, R2, Ctx); case ExprWithCleanupsClass: - return (cast<ExprWithCleanups>(this) - ->getSubExpr()->isUnusedResultAWarning(WarnE, Loc, R1, R2, Ctx)); + return cast<ExprWithCleanups>(this)->getSubExpr() + ->isUnusedResultAWarning(WarnE, Loc, R1, R2, Ctx); } } diff --git a/clang/lib/AST/ExprConstant.cpp b/clang/lib/AST/ExprConstant.cpp index 14214bdd0a6..fa5cb8cd732 100644 --- a/clang/lib/AST/ExprConstant.cpp +++ b/clang/lib/AST/ExprConstant.cpp @@ -5670,6 +5670,9 @@ bool RecordExprEvaluator::VisitCastExpr(const CastExpr *E) { } bool RecordExprEvaluator::VisitInitListExpr(const InitListExpr *E) { + if (E->isTransparent()) + return Visit(E->getInit(0)); + const RecordDecl *RD = E->getType()->castAs<RecordType>()->getDecl(); if (RD->isInvalidDecl()) return false; const ASTRecordLayout &Layout = Info.Ctx.getASTRecordLayout(RD); |