aboutsummaryrefslogtreecommitdiff
path: root/lib/Sema/SemaDecl.cpp
diff options
context:
space:
mode:
authorDouglas Gregor <dgregor@apple.com>2008-11-05 15:29:30 +0000
committerDouglas Gregor <dgregor@apple.com>2008-11-05 15:29:30 +0000
commitf03d7c7af2ca8555c513ba7667acffb667445ecd (patch)
treeccbec86bd811939366a570861a353ef170d69763 /lib/Sema/SemaDecl.cpp
parent7ad8390f7992ab7f19b1460c5f0b9d96f165c4e9 (diff)
Implement C++ copy-initialization for declarations. There is now some
duplication in the handling of copy-initialization by constructor, which occurs both for initialization of a declaration and for overloading. The initialization code is due for some refactoring. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@58756 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'lib/Sema/SemaDecl.cpp')
-rw-r--r--lib/Sema/SemaDecl.cpp69
1 files changed, 59 insertions, 10 deletions
diff --git a/lib/Sema/SemaDecl.cpp b/lib/Sema/SemaDecl.cpp
index a10470e0d4..5dc571c0ee 100644
--- a/lib/Sema/SemaDecl.cpp
+++ b/lib/Sema/SemaDecl.cpp
@@ -627,7 +627,9 @@ StringLiteral *Sema::IsStringLiteralInit(Expr *Init, QualType DeclType) {
return 0;
}
-bool Sema::CheckInitializerTypes(Expr *&Init, QualType &DeclType) {
+bool Sema::CheckInitializerTypes(Expr *&Init, QualType &DeclType,
+ SourceLocation InitLoc,
+ std::string InitEntity) {
// C++ [dcl.init.ref]p1:
// A variable declared to be a T&, that is “reference to type T”
// (8.3.2), shall be initialized by an object, or function, of
@@ -638,7 +640,7 @@ bool Sema::CheckInitializerTypes(Expr *&Init, QualType &DeclType) {
// C99 6.7.8p3: The type of the entity to be initialized shall be an array
// of unknown size ("[]") or an object type that is not a variable array type.
if (const VariableArrayType *VAT = Context.getAsVariableArrayType(DeclType))
- return Diag(VAT->getSizeExpr()->getLocStart(),
+ return Diag(InitLoc,
diag::err_variable_object_no_init,
VAT->getSizeExpr()->getSourceRange());
@@ -648,6 +650,50 @@ bool Sema::CheckInitializerTypes(Expr *&Init, QualType &DeclType) {
if (StringLiteral *strLiteral = IsStringLiteralInit(Init, DeclType))
return CheckStringLiteralInit(strLiteral, DeclType);
+ // C++ [dcl.init]p14:
+ // -- If the destination type is a (possibly cv-qualified) class
+ // type:
+ if (getLangOptions().CPlusPlus && DeclType->isRecordType()) {
+ QualType DeclTypeC = Context.getCanonicalType(DeclType);
+ QualType InitTypeC = Context.getCanonicalType(Init->getType());
+
+ // -- If the initialization is direct-initialization, or if it is
+ // copy-initialization where the cv-unqualified version of the
+ // source type is the same class as, or a derived class of, the
+ // class of the destination, constructors are considered.
+ if ((DeclTypeC.getUnqualifiedType() == InitTypeC.getUnqualifiedType()) ||
+ IsDerivedFrom(InitTypeC, DeclTypeC)) {
+ CXXConstructorDecl *Constructor
+ = PerformInitializationByConstructor(DeclType, &Init, 1,
+ InitLoc, Init->getSourceRange(),
+ InitEntity, IK_Copy);
+ return Constructor == 0;
+ }
+
+ // -- Otherwise (i.e., for the remaining copy-initialization
+ // cases), user-defined conversion sequences that can
+ // convert from the source type to the destination type or
+ // (when a conversion function is used) to a derived class
+ // thereof are enumerated as described in 13.3.1.4, and the
+ // best one is chosen through overload resolution
+ // (13.3). If the conversion cannot be done or is
+ // ambiguous, the initialization is ill-formed. The
+ // function selected is called with the initializer
+ // expression as its argument; if the function is a
+ // constructor, the call initializes a temporary of the
+ // destination type.
+ // FIXME: We're pretending to do copy elision here; return to
+ // this when we have ASTs for such things.
+ if (PerformImplicitConversion(Init, DeclType))
+ return Diag(InitLoc,
+ diag::err_typecheck_convert_incompatible,
+ DeclType.getAsString(), InitEntity,
+ "initializing",
+ Init->getSourceRange());
+ else
+ return false;
+ }
+
// C99 6.7.8p16.
if (DeclType->isArrayType())
return Diag(Init->getLocStart(),
@@ -1574,7 +1620,8 @@ void Sema::AddInitializerToDecl(DeclTy *dcl, ExprTy *init) {
Diag(VDecl->getLocation(), diag::err_block_extern_cant_init);
VDecl->setInvalidDecl();
} else if (!VDecl->isInvalidDecl()) {
- if (CheckInitializerTypes(Init, DclT))
+ if (CheckInitializerTypes(Init, DclT, VDecl->getLocation(),
+ VDecl->getName()))
VDecl->setInvalidDecl();
// C++ 3.6.2p2, allow dynamic initialization of static initializers.
@@ -1587,7 +1634,8 @@ void Sema::AddInitializerToDecl(DeclTy *dcl, ExprTy *init) {
if (VDecl->getStorageClass() == VarDecl::Extern)
Diag(VDecl->getLocation(), diag::warn_extern_init);
if (!VDecl->isInvalidDecl())
- if (CheckInitializerTypes(Init, DclT))
+ if (CheckInitializerTypes(Init, DclT, VDecl->getLocation(),
+ VDecl->getName()))
VDecl->setInvalidDecl();
// C++ 3.6.2p2, allow dynamic initialization of static initializers.
@@ -1642,12 +1690,13 @@ void Sema::ActOnUninitializedDecl(DeclTy *dcl) {
if (const ArrayType *Array = Context.getAsArrayType(Type))
InitType = Array->getElementType();
if (InitType->isRecordType()) {
- CXXConstructorDecl *Constructor
- = PerformDirectInitForClassType(InitType, 0, 0, Var->getLocation(),
- SourceRange(Var->getLocation(),
- Var->getLocation()),
- Var->getName(),
- /*HasInitializer=*/false);
+ const CXXConstructorDecl *Constructor
+ = PerformInitializationByConstructor(InitType, 0, 0,
+ Var->getLocation(),
+ SourceRange(Var->getLocation(),
+ Var->getLocation()),
+ Var->getName(),
+ IK_Default);
if (!Constructor)
Var->setInvalidDecl();
}