diff options
author | Douglas Gregor <dgregor@apple.com> | 2009-01-16 18:33:17 +0000 |
---|---|---|
committer | Douglas Gregor <dgregor@apple.com> | 2009-01-16 18:33:17 +0000 |
commit | dd04d33e3abd2cb144a680cf9bb3b1c3e94746af (patch) | |
tree | a47f8cd7c89baedf1aaa6bd72038636e3c069165 /clang/lib | |
parent | 867df5460641c5cfb9919fe0bdc33813ecc5dca5 (diff) | |
download | bcm5719-llvm-dd04d33e3abd2cb144a680cf9bb3b1c3e94746af.tar.gz bcm5719-llvm-dd04d33e3abd2cb144a680cf9bb3b1c3e94746af.zip |
Part one of handling C++ functional casts. This handles semantic
analysis and AST-building for the cases where we have N != 1
arguments. For N == 1 arguments, we need to finish the C++
implementation of explicit type casts (C++ [expr.cast]).
llvm-svn: 62329
Diffstat (limited to 'clang/lib')
-rw-r--r-- | clang/lib/AST/ExprCXX.cpp | 28 | ||||
-rw-r--r-- | clang/lib/AST/StmtPrinter.cpp | 13 | ||||
-rw-r--r-- | clang/lib/AST/StmtSerialization.cpp | 38 | ||||
-rw-r--r-- | clang/lib/Sema/SemaExprCXX.cpp | 43 |
4 files changed, 105 insertions, 17 deletions
diff --git a/clang/lib/AST/ExprCXX.cpp b/clang/lib/AST/ExprCXX.cpp index 07d794ea437..b21b4136898 100644 --- a/clang/lib/AST/ExprCXX.cpp +++ b/clang/lib/AST/ExprCXX.cpp @@ -61,6 +61,14 @@ Stmt::child_iterator CXXDefaultArgExpr::child_end() { return child_iterator(); } +// CXXTemporaryObjectExpr +Stmt::child_iterator CXXTemporaryObjectExpr::child_begin() { + return child_iterator(Args); +} +Stmt::child_iterator CXXTemporaryObjectExpr::child_end() { + return child_iterator(Args + NumArgs); +} + // CXXZeroInitValueExpr Stmt::child_iterator CXXZeroInitValueExpr::child_begin() { return child_iterator(); @@ -219,3 +227,23 @@ const char *CXXNamedCastExpr::getCastName() const { default: return "<invalid cast>"; } } + +CXXTemporaryObjectExpr::CXXTemporaryObjectExpr(CXXConstructorDecl *Cons, + QualType writtenTy, + SourceLocation tyBeginLoc, + Expr **Args, + unsigned NumArgs, + SourceLocation rParenLoc) + : Expr(CXXTemporaryObjectExprClass, writtenTy), + TyBeginLoc(tyBeginLoc), RParenLoc(rParenLoc), + Constructor(Cons), Args(0), NumArgs(NumArgs) { + if (NumArgs > 0) { + this->Args = new Stmt*[NumArgs]; + for (unsigned i = 0; i < NumArgs; ++i) + this->Args[i] = Args[i]; + } +} + +CXXTemporaryObjectExpr::~CXXTemporaryObjectExpr() { + delete [] Args; +} diff --git a/clang/lib/AST/StmtPrinter.cpp b/clang/lib/AST/StmtPrinter.cpp index 14d30d86739..ea96411e07b 100644 --- a/clang/lib/AST/StmtPrinter.cpp +++ b/clang/lib/AST/StmtPrinter.cpp @@ -989,6 +989,19 @@ void StmtPrinter::VisitCXXFunctionalCastExpr(CXXFunctionalCastExpr *Node) { OS << ")"; } +void StmtPrinter::VisitCXXTemporaryObjectExpr(CXXTemporaryObjectExpr *Node) { + OS << Node->getType().getAsString(); + OS << "("; + for (CXXTemporaryObjectExpr::arg_iterator Arg = Node->arg_begin(), + ArgEnd = Node->arg_end(); + Arg != ArgEnd; ++Arg) { + if (Arg != Node->arg_begin()) + OS << ", "; + PrintExpr(*Arg); + } + OS << ")"; +} + void StmtPrinter::VisitCXXZeroInitValueExpr(CXXZeroInitValueExpr *Node) { OS << Node->getType().getAsString() << "()"; } diff --git a/clang/lib/AST/StmtSerialization.cpp b/clang/lib/AST/StmtSerialization.cpp index 02ccde3da26..39330ce3352 100644 --- a/clang/lib/AST/StmtSerialization.cpp +++ b/clang/lib/AST/StmtSerialization.cpp @@ -13,6 +13,7 @@ //===----------------------------------------------------------------------===// #include "clang/Basic/TypeTraits.h" +#include "clang/AST/DeclCXX.h" #include "clang/AST/Expr.h" #include "clang/AST/ExprCXX.h" #include "clang/AST/ExprObjC.h" @@ -232,6 +233,9 @@ Stmt* Stmt::Create(Deserializer& D, ASTContext& C) { case CXXThisExprClass: return CXXThisExpr::CreateImpl(D, C); + case CXXTemporaryObjectExprClass: + return CXXTemporaryObjectExpr::CreateImpl(D, C); + case CXXZeroInitValueExprClass: return CXXZeroInitValueExpr::CreateImpl(D, C); @@ -1441,6 +1445,40 @@ CXXThisExpr* CXXThisExpr::CreateImpl(llvm::Deserializer& D, ASTContext&) { return new CXXThisExpr(Loc, Ty); } +void CXXTemporaryObjectExpr::EmitImpl(llvm::Serializer& S) const { + S.Emit(getType()); + S.Emit(TyBeginLoc); + S.Emit(RParenLoc); + S.EmitPtr(cast<Decl>(Constructor)); + S.EmitInt(NumArgs); + if (NumArgs > 0) + S.BatchEmitOwnedPtrs(NumArgs, Args); +} + +CXXTemporaryObjectExpr * +CXXTemporaryObjectExpr::CreateImpl(llvm::Deserializer& D, ASTContext& C) { + QualType writtenTy = QualType::ReadVal(D); + SourceLocation tyBeginLoc = SourceLocation::ReadVal(D); + SourceLocation rParenLoc = SourceLocation::ReadVal(D); + CXXConstructorDecl * Cons = cast_or_null<CXXConstructorDecl>(D.ReadPtr<Decl>()); + unsigned NumArgs = D.ReadInt(); + Stmt** Args = 0; + if (NumArgs > 0) { + Args = new Stmt*[NumArgs]; + D.BatchReadOwnedPtrs(NumArgs, Args, C); + } + + CXXTemporaryObjectExpr * Result + = new CXXTemporaryObjectExpr(Cons, writtenTy, tyBeginLoc, + (Expr**)Args, NumArgs, rParenLoc); + + if (NumArgs > 0) + delete [] Args; + + return Result; +} + + void CXXZeroInitValueExpr::EmitImpl(Serializer& S) const { S.Emit(getType()); S.Emit(TyBeginLoc); diff --git a/clang/lib/Sema/SemaExprCXX.cpp b/clang/lib/Sema/SemaExprCXX.cpp index 0a42de06cad..73ac18eb1aa 100644 --- a/clang/lib/Sema/SemaExprCXX.cpp +++ b/clang/lib/Sema/SemaExprCXX.cpp @@ -120,21 +120,7 @@ Sema::ActOnCXXTypeConstructExpr(SourceRange TypeRange, TypeTy *TypeRep, SourceLocation TyBeginLoc = TypeRange.getBegin(); SourceRange FullRange = SourceRange(TyBeginLoc, RParenLoc); - if (const RecordType *RT = Ty->getAsRecordType()) { - // C++ 5.2.3p1: - // If the simple-type-specifier specifies a class type, the class type shall - // be complete. - // - if (!RT->getDecl()->isDefinition()) - return Diag(TyBeginLoc, diag::err_invalid_incomplete_type_use) - << Ty << FullRange; - - unsigned DiagID = PP.getDiagnostics().getCustomDiagID(Diagnostic::Error, - "class constructors are not supported yet"); - return Diag(TyBeginLoc, DiagID); - } - - // C++ 5.2.3p1: + // C++ [expr.type.conv]p1: // If the expression list is a single expression, the type conversion // expression is equivalent (in definedness, and if defined in meaning) to the // corresponding cast expression. @@ -146,7 +132,30 @@ Sema::ActOnCXXTypeConstructExpr(SourceRange TypeRange, TypeTy *TypeRep, Exprs[0], RParenLoc); } - // C++ 5.2.3p1: + if (const RecordType *RT = Ty->getAsRecordType()) { + CXXRecordDecl *Record = cast<CXXRecordDecl>(RT->getDecl()); + + if (NumExprs > 1 || Record->hasUserDeclaredConstructor()) { + CXXConstructorDecl *Constructor + = PerformInitializationByConstructor(Ty, Exprs, NumExprs, + TypeRange.getBegin(), + SourceRange(TypeRange.getBegin(), + RParenLoc), + DeclarationName(), + IK_Direct); + + if (!Constructor) + return true; + + return new CXXTemporaryObjectExpr(Constructor, Ty, TyBeginLoc, + Exprs, NumExprs, RParenLoc); + } + + // Fall through to value-initialize an object of class type that + // doesn't have a user-declared default constructor. + } + + // C++ [expr.type.conv]p1: // If the expression list specifies more than a single value, the type shall // be a class with a suitably declared constructor. // @@ -156,7 +165,7 @@ Sema::ActOnCXXTypeConstructExpr(SourceRange TypeRange, TypeTy *TypeRep, assert(NumExprs == 0 && "Expected 0 expressions"); - // C++ 5.2.3p2: + // C++ [expr.type.conv]p2: // The expression T(), where T is a simple-type-specifier for a non-array // complete object type or the (possibly cv-qualified) void type, creates an // rvalue of the specified type, which is value-initialized. |