summaryrefslogtreecommitdiffstats
path: root/clang/lib
diff options
context:
space:
mode:
authorDouglas Gregor <dgregor@apple.com>2009-01-16 18:33:17 +0000
committerDouglas Gregor <dgregor@apple.com>2009-01-16 18:33:17 +0000
commitdd04d33e3abd2cb144a680cf9bb3b1c3e94746af (patch)
treea47f8cd7c89baedf1aaa6bd72038636e3c069165 /clang/lib
parent867df5460641c5cfb9919fe0bdc33813ecc5dca5 (diff)
downloadbcm5719-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.cpp28
-rw-r--r--clang/lib/AST/StmtPrinter.cpp13
-rw-r--r--clang/lib/AST/StmtSerialization.cpp38
-rw-r--r--clang/lib/Sema/SemaExprCXX.cpp43
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.
OpenPOWER on IntegriCloud