From: Richard Smith Date: Mon, 26 Nov 2012 08:32:48 +0000 (+0000) Subject: PR14428: When instantiating a 'new' expression, if we had a non-dependent X-Git-Url: http://review.tizen.org/git/?a=commitdiff_plain;h=dd2ca571ae371469ffaaa898920572d34c1baa0a;p=platform%2Fupstream%2Fllvm.git PR14428: When instantiating a 'new' expression, if we had a non-dependent initialization, don't rebuild it. Remove a couple of hacks which were trying to work around this. Fix the special case for one-argument CXXConstructExprs to not apply if the one argument is a default argument. llvm-svn: 168582 --- diff --git a/clang/lib/Sema/SemaExprCXX.cpp b/clang/lib/Sema/SemaExprCXX.cpp index c9d7860..3b2da04 100644 --- a/clang/lib/Sema/SemaExprCXX.cpp +++ b/clang/lib/Sema/SemaExprCXX.cpp @@ -1041,13 +1041,6 @@ Sema::BuildCXXNew(SourceRange Range, bool UseGlobal, } else if (Initializer && isa(Initializer)) initStyle = CXXNewExpr::ListInit; else { - // In template instantiation, the initializer could be a CXXDefaultArgExpr - // unwrapped from a CXXConstructExpr that was implicitly built. There is no - // particularly sane way we can handle this (especially since it can even - // occur for array new), so we throw the initializer away and have it be - // rebuilt. - if (Initializer && isa(Initializer)) - Initializer = 0; assert((!Initializer || isa(Initializer) || isa(Initializer)) && "Initializer expression that cannot have been implicitly created."); @@ -1056,20 +1049,20 @@ Sema::BuildCXXNew(SourceRange Range, bool UseGlobal, Expr **Inits = &Initializer; unsigned NumInits = Initializer ? 1 : 0; - if (initStyle == CXXNewExpr::CallInit) { - if (ParenListExpr *List = dyn_cast(Initializer)) { - Inits = List->getExprs(); - NumInits = List->getNumExprs(); - } else if (CXXConstructExpr *CCE = dyn_cast(Initializer)){ - if (!isa(CCE)) { - // Can happen in template instantiation. Since this is just an implicit - // construction, we just take it apart and rebuild it. - Inits = CCE->getArgs(); - NumInits = CCE->getNumArgs(); - } - } + if (ParenListExpr *List = dyn_cast_or_null(Initializer)) { + assert(initStyle == CXXNewExpr::CallInit && "paren init for non-call init"); + Inits = List->getExprs(); + NumInits = List->getNumExprs(); } + // Determine whether we've already built the initializer. + bool HaveCompleteInit = false; + if (Initializer && isa(Initializer) && + !isa(Initializer)) + HaveCompleteInit = true; + else if (Initializer && isa(Initializer)) + HaveCompleteInit = true; + // C++11 [decl.spec.auto]p6. Deduce the type which 'auto' stands in for. AutoType *AT = 0; if (TypeMayContainAuto && @@ -1341,9 +1334,12 @@ Sema::BuildCXXNew(SourceRange Range, bool UseGlobal, } } + // If we can perform the initialization, and we've not already done so, + // do it now. if (!AllocType->isDependentType() && !Expr::hasAnyTypeDependentArguments( - llvm::makeArrayRef(Inits, NumInits))) { + llvm::makeArrayRef(Inits, NumInits)) && + !HaveCompleteInit) { // C++11 [expr.new]p15: // A new-expression that creates an object of type T initializes that // object as follows: diff --git a/clang/lib/Sema/TreeTransform.h b/clang/lib/Sema/TreeTransform.h index 5b5122f..72175de 100644 --- a/clang/lib/Sema/TreeTransform.h +++ b/clang/lib/Sema/TreeTransform.h @@ -7749,8 +7749,9 @@ ExprResult TreeTransform::TransformCXXConstructExpr(CXXConstructExpr *E) { // CXXConstructExprs are always implicit, so when we have a // 1-argument construction we just transform that argument. - if (E->getNumArgs() == 1 || - (E->getNumArgs() > 1 && getDerived().DropCallArgument(E->getArg(1)))) + if ((E->getNumArgs() == 1 || + (E->getNumArgs() > 1 && getDerived().DropCallArgument(E->getArg(1)))) && + (!getDerived().DropCallArgument(E->getArg(0)))) return getDerived().TransformExpr(E->getArg(0)); TemporaryBase Rebase(*this, /*FIXME*/E->getLocStart(), DeclarationName()); diff --git a/clang/test/SemaTemplate/default-expr-arguments.cpp b/clang/test/SemaTemplate/default-expr-arguments.cpp index 4e76a5a..14b072a 100644 --- a/clang/test/SemaTemplate/default-expr-arguments.cpp +++ b/clang/test/SemaTemplate/default-expr-arguments.cpp @@ -306,7 +306,7 @@ namespace PR12581 { namespace PR13758 { template struct move_from { - T invalid; // expected-error {{field has incomplete type 'void'}} + T invalid; }; template struct unordered_map { @@ -315,9 +315,10 @@ namespace PR13758 { }; template void StripedHashTable() { - new unordered_map(); // expected-note {{in instantiation of template class 'PR13758::move_from' requested here}} + new unordered_map(); + new unordered_map; } void tt() { - StripedHashTable(); // expected-note {{in instantiation of function template specialization 'PR13758::StripedHashTable' requested here}} + StripedHashTable(); } }