diff options
author | Anders Carlsson <andersca@mac.com> | 2009-08-27 05:08:22 +0000 |
---|---|---|
committer | Anders Carlsson <andersca@mac.com> | 2009-08-27 05:08:22 +0000 |
commit | e7624a75b74633ff9c54d1c60ace2707fe298008 (patch) | |
tree | 87f042f8aca1c7cd8b17a564f02d1be106809f44 | |
parent | bb60a509f47a95a4ed9366ec1fc65850da654d38 (diff) |
Add a BuildCXXTemporaryObjectExpr and use it so default arguments will be instantiated correctly for temporary object expressions.
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@80206 91177308-0d34-0410-b5e6-96231b3b80d8
-rw-r--r-- | lib/Sema/Sema.h | 6 | ||||
-rw-r--r-- | lib/Sema/SemaDeclCXX.cpp | 33 | ||||
-rw-r--r-- | lib/Sema/SemaExprCXX.cpp | 17 | ||||
-rw-r--r-- | test/SemaCXX/default-argument-temporaries.cpp | 11 |
4 files changed, 58 insertions, 9 deletions
diff --git a/lib/Sema/Sema.h b/lib/Sema/Sema.h index 52aa1a010b..a5a0723256 100644 --- a/lib/Sema/Sema.h +++ b/lib/Sema/Sema.h @@ -1774,6 +1774,12 @@ public: bool Elidable, Expr **Exprs, unsigned NumExprs); + OwningExprResult BuildCXXTemporaryObjectExpr(CXXConstructorDecl *Cons, + QualType writtenTy, + SourceLocation tyBeginLoc, + MultiExprArg Args, + SourceLocation rParenLoc); + /// BuildCXXDefaultArgExpr - Creates a CXXDefaultArgExpr, instantiating /// the default expr if needed. OwningExprResult BuildCXXDefaultArgExpr(SourceLocation CallLoc, diff --git a/lib/Sema/SemaDeclCXX.cpp b/lib/Sema/SemaDeclCXX.cpp index e93624af15..2f797daea3 100644 --- a/lib/Sema/SemaDeclCXX.cpp +++ b/lib/Sema/SemaDeclCXX.cpp @@ -2467,7 +2467,7 @@ Sema::BuildCXXConstructExpr(QualType DeclInitType, Elidable, Exprs, NumExprs)); - // default arguments must be added to constructor call expression. + // Default arguments must be added to constructor call expression. FunctionDecl *FDecl = cast<FunctionDecl>(Constructor); unsigned NumArgsInProto = FDecl->param_size(); for (unsigned j = NumExprs; j != NumArgsInProto; j++) { @@ -2484,6 +2484,37 @@ Sema::BuildCXXConstructExpr(QualType DeclInitType, return move(Temp); } +Sema::OwningExprResult +Sema::BuildCXXTemporaryObjectExpr(CXXConstructorDecl *Constructor, + QualType Ty, + SourceLocation TyBeginLoc, + MultiExprArg Args, + SourceLocation RParenLoc) { + CXXTemporaryObjectExpr *E + = new (Context) CXXTemporaryObjectExpr(Context, Constructor, Ty, TyBeginLoc, + (Expr **)Args.get(), + Args.size(), RParenLoc); + + ExprOwningPtr<CXXTemporaryObjectExpr> Temp(this, E); + + // Default arguments must be added to constructor call expression. + FunctionDecl *FDecl = cast<FunctionDecl>(Constructor); + unsigned NumArgsInProto = FDecl->param_size(); + for (unsigned j = Args.size(); j != NumArgsInProto; j++) { + ParmVarDecl *Param = FDecl->getParamDecl(j); + + OwningExprResult ArgExpr = BuildCXXDefaultArgExpr(TyBeginLoc, FDecl, Param); + if (ArgExpr.isInvalid()) + return ExprError(); + + Temp->setArg(j, ArgExpr.takeAs<Expr>()); + } + + Args.release(); + return move(Temp); +} + + bool Sema::InitializeVarWithConstructor(VarDecl *VD, CXXConstructorDecl *Constructor, QualType DeclInitType, diff --git a/lib/Sema/SemaExprCXX.cpp b/lib/Sema/SemaExprCXX.cpp index a4c3b0dd59..85924948da 100644 --- a/lib/Sema/SemaExprCXX.cpp +++ b/lib/Sema/SemaExprCXX.cpp @@ -239,9 +239,8 @@ Sema::ActOnCXXTypeConstructExpr(SourceRange TypeRange, TypeTy *TypeRep, if (const RecordType *RT = Ty->getAs<RecordType>()) { CXXRecordDecl *Record = cast<CXXRecordDecl>(RT->getDecl()); - // FIXME: We should always create a CXXTemporaryObjectExpr here unless - // both the ctor and dtor are trivial. - if (NumExprs > 1 || Record->hasUserDeclaredConstructor()) { + if (NumExprs > 1 || !Record->hasTrivialConstructor() || + !Record->hasTrivialDestructor()) { CXXConstructorDecl *Constructor = PerformInitializationByConstructor(Ty, Exprs, NumExprs, TypeRange.getBegin(), @@ -253,11 +252,13 @@ Sema::ActOnCXXTypeConstructExpr(SourceRange TypeRange, TypeTy *TypeRep, if (!Constructor) return ExprError(); - exprs.release(); - Expr *E = new (Context) CXXTemporaryObjectExpr(Context, Constructor, - Ty, TyBeginLoc, Exprs, - NumExprs, RParenLoc); - return MaybeBindToTemporary(E); + OwningExprResult Result = + BuildCXXTemporaryObjectExpr(Constructor, Ty, TyBeginLoc, + move(exprs), RParenLoc); + if (Result.isInvalid()) + return ExprError(); + + return MaybeBindToTemporary(Result.takeAs<Expr>()); } // Fall through to value-initialize an object of class type that diff --git a/test/SemaCXX/default-argument-temporaries.cpp b/test/SemaCXX/default-argument-temporaries.cpp new file mode 100644 index 0000000000..232351dcff --- /dev/null +++ b/test/SemaCXX/default-argument-temporaries.cpp @@ -0,0 +1,11 @@ +// RUN: clang-cc -fsyntax-only -verify %s +struct B { B(void* = 0); }; + +struct A { + A(B b = B()) { } +}; + +void f() { + (void)B(); + (void)A(); +} |