forked from OSchip/llvm-project
Patch for implementation of C++'s object model. This is
work in progress. llvm-svn: 73782
This commit is contained in:
parent
2028e25325
commit
423a81f259
|
@ -439,6 +439,9 @@ public:
|
|||
TemplateOrInstantiation = Template;
|
||||
}
|
||||
|
||||
/// getDefaultConstructor - Returns the default constructor for this class
|
||||
CXXConstructorDecl *getDefaultConstructor(ASTContext &Context);
|
||||
|
||||
/// getDestructor - Returns the destructor decl for this class.
|
||||
const CXXDestructorDecl *getDestructor(ASTContext &Context);
|
||||
|
||||
|
@ -638,6 +641,10 @@ class CXXConstructorDecl : public CXXMethodDecl {
|
|||
/// explicitly defaulted (i.e., defined with " = default") will have
|
||||
/// @c !Implicit && ImplicitlyDefined.
|
||||
bool ImplicitlyDefined : 1;
|
||||
|
||||
/// ImplicitMustBeDefined - Implicit constructor was used to create an
|
||||
/// object of its class type. It must be defined.
|
||||
bool ImplicitMustBeDefined : 1;
|
||||
|
||||
/// FIXME: Add support for base and member initializers.
|
||||
|
||||
|
@ -645,7 +652,8 @@ class CXXConstructorDecl : public CXXMethodDecl {
|
|||
DeclarationName N, QualType T,
|
||||
bool isExplicit, bool isInline, bool isImplicitlyDeclared)
|
||||
: CXXMethodDecl(CXXConstructor, RD, L, N, T, false, isInline),
|
||||
Explicit(isExplicit), ImplicitlyDefined(false) {
|
||||
Explicit(isExplicit), ImplicitlyDefined(false),
|
||||
ImplicitMustBeDefined(false) {
|
||||
setImplicit(isImplicitlyDeclared);
|
||||
}
|
||||
|
||||
|
@ -676,6 +684,17 @@ public:
|
|||
ImplicitlyDefined = ID;
|
||||
}
|
||||
|
||||
/// isImplicitMustBeDefined - Whether a definition must be synthesized for
|
||||
/// the implicit constructor.
|
||||
bool isImplicitMustBeDefined() const {
|
||||
return isImplicit() && ImplicitMustBeDefined;
|
||||
}
|
||||
|
||||
/// setImplicitMustBeDefined - constructor must be implicitly defined.
|
||||
void setImplicitMustBeDefined() {
|
||||
ImplicitMustBeDefined = true;
|
||||
}
|
||||
|
||||
/// isDefaultConstructor - Whether this constructor is a default
|
||||
/// constructor (C++ [class.ctor]p5), which can be used to
|
||||
/// default-initialize a class of this type.
|
||||
|
|
|
@ -573,6 +573,14 @@ def err_param_default_argument_references_this : Error<
|
|||
def err_param_default_argument_nonfunc : Error<
|
||||
"default arguments can only be specified for parameters in a function "
|
||||
"declaration">;
|
||||
def err_defining_default_ctor : Error<
|
||||
"cannot define the default constructor for %0, because %1 does not "
|
||||
"have any default constructor">;
|
||||
def not_previous_class_decl : Note<
|
||||
"class %0 declared here">;
|
||||
def err_unintialized_member : Error<
|
||||
"cannot define the default constructor for %0, because of "
|
||||
"unintialized %select{reference|const}1 member">;
|
||||
|
||||
def err_use_of_default_argument_to_function_declared_later : Error<
|
||||
"use of default argument to function %0 that is declared later in class %1">;
|
||||
|
|
|
@ -184,10 +184,28 @@ void CXXRecordDecl::addConversionFunction(ASTContext &Context,
|
|||
Conversions.addOverload(ConvDecl);
|
||||
}
|
||||
|
||||
|
||||
CXXConstructorDecl *
|
||||
CXXRecordDecl::getDefaultConstructor(ASTContext &Context) {
|
||||
QualType ClassType = Context.getTypeDeclType(this);
|
||||
DeclarationName ConstructorName
|
||||
= Context.DeclarationNames.getCXXConstructorName(
|
||||
Context.getCanonicalType(ClassType.getUnqualifiedType()));
|
||||
|
||||
DeclContext::lookup_const_iterator Con, ConEnd;
|
||||
for (llvm::tie(Con, ConEnd) = lookup(Context, ConstructorName);
|
||||
Con != ConEnd; ++Con) {
|
||||
CXXConstructorDecl *Constructor = cast<CXXConstructorDecl>(*Con);
|
||||
if (Constructor->isDefaultConstructor())
|
||||
return Constructor;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
const CXXDestructorDecl *
|
||||
CXXRecordDecl::getDestructor(ASTContext &Context) {
|
||||
QualType ClassType = Context.getTypeDeclType(this);
|
||||
|
||||
|
||||
DeclarationName Name
|
||||
= Context.DeclarationNames.getCXXDestructorName(ClassType);
|
||||
|
||||
|
|
|
@ -1533,6 +1533,11 @@ public:
|
|||
CXXConstructorDecl *Constructor,
|
||||
QualType DeclInitType,
|
||||
Expr **Exprs, unsigned NumExprs);
|
||||
|
||||
/// DefineImplicitDefaultConstructor - Checks for feasibilityt of
|
||||
/// defining this constructor as the default constructor.
|
||||
void DefineImplicitDefaultConstructor(SourceLocation CurrentLocation,
|
||||
CXXConstructorDecl *Constructor);
|
||||
|
||||
/// MaybeBindToTemporary - If the passed in expression has a record type with
|
||||
/// a non-trivial destructor, this will return CXXBindTemporaryExpr. Otherwise
|
||||
|
|
|
@ -2732,8 +2732,12 @@ void Sema::ActOnUninitializedDecl(DeclPtrTy dcl) {
|
|||
IK_Default);
|
||||
if (!Constructor)
|
||||
Var->setInvalidDecl();
|
||||
else if (!RD->hasTrivialConstructor())
|
||||
InitializeVarWithConstructor(Var, Constructor, InitType, 0, 0);
|
||||
else {
|
||||
if (!RD->hasTrivialConstructor())
|
||||
InitializeVarWithConstructor(Var, Constructor, InitType, 0, 0);
|
||||
// Check for valid construction.
|
||||
DefineImplicitDefaultConstructor(Var->getLocation(), Constructor);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -1793,7 +1793,7 @@ Sema::DeclPtrTy Sema::ActOnNamespaceAliasDef(Scope *S,
|
|||
return DeclPtrTy();
|
||||
}
|
||||
|
||||
NamespaceAliasDecl *AliasDecl =
|
||||
NamespaceAliasDecl *AliasDecl =
|
||||
NamespaceAliasDecl::Create(Context, CurContext, NamespaceLoc, AliasLoc,
|
||||
Alias, SS.getRange(),
|
||||
(NestedNameSpecifier *)SS.getScopeRep(),
|
||||
|
@ -1803,6 +1803,80 @@ Sema::DeclPtrTy Sema::ActOnNamespaceAliasDef(Scope *S,
|
|||
return DeclPtrTy::make(AliasDecl);
|
||||
}
|
||||
|
||||
void Sema::DefineImplicitDefaultConstructor(SourceLocation CurrentLocation,
|
||||
CXXConstructorDecl *Constructor) {
|
||||
if (!Constructor->isDefaultConstructor() ||
|
||||
!Constructor->isImplicit() || Constructor->isImplicitMustBeDefined())
|
||||
return;
|
||||
|
||||
CXXRecordDecl *ClassDecl
|
||||
= cast<CXXRecordDecl>(Constructor->getDeclContext());
|
||||
assert(ClassDecl && "InitializeVarWithConstructor - invalid constructor");
|
||||
// Before the implicitly-declared default constructor for a class is
|
||||
// implicitly defined, all the implicitly-declared default constructors
|
||||
// for its base class and its non-static data members shall have been
|
||||
// implicitly defined.
|
||||
bool err = false;
|
||||
for (CXXRecordDecl::base_class_iterator Base = ClassDecl->bases_begin();
|
||||
Base != ClassDecl->bases_end(); ++Base) {
|
||||
CXXRecordDecl *BaseClassDecl
|
||||
= cast<CXXRecordDecl>(Base->getType()->getAsRecordType()->getDecl());
|
||||
if (!BaseClassDecl->hasTrivialConstructor()) {
|
||||
if (CXXConstructorDecl *BaseCtor =
|
||||
BaseClassDecl->getDefaultConstructor(Context)) {
|
||||
if (BaseCtor->isImplicit())
|
||||
BaseCtor->setImplicitMustBeDefined();
|
||||
}
|
||||
else {
|
||||
Diag(CurrentLocation, diag::err_defining_default_ctor)
|
||||
<< ClassDecl->getNameAsCString() << BaseClassDecl->getNameAsCString();
|
||||
Diag(BaseClassDecl->getLocation(), diag::not_previous_class_decl)
|
||||
<< BaseClassDecl->getNameAsCString();
|
||||
err = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
for (CXXRecordDecl::field_iterator Field = ClassDecl->field_begin(Context);
|
||||
Field != ClassDecl->field_end(Context);
|
||||
++Field) {
|
||||
QualType FieldType = Context.getCanonicalType((*Field)->getType());
|
||||
if (const ArrayType *Array = Context.getAsArrayType(FieldType))
|
||||
FieldType = Array->getElementType();
|
||||
if (const RecordType *FieldClassType = FieldType->getAsRecordType()) {
|
||||
CXXRecordDecl *FieldClassDecl
|
||||
= cast<CXXRecordDecl>(FieldClassType->getDecl());
|
||||
if (!FieldClassDecl->hasTrivialConstructor())
|
||||
if (CXXConstructorDecl *FieldCtor =
|
||||
FieldClassDecl->getDefaultConstructor(Context)) {
|
||||
if (FieldCtor->isImplicit())
|
||||
FieldCtor->setImplicitMustBeDefined();
|
||||
}
|
||||
else {
|
||||
Diag(CurrentLocation, diag::err_defining_default_ctor)
|
||||
<< ClassDecl->getNameAsCString() <<
|
||||
FieldClassDecl->getNameAsCString();
|
||||
Diag(FieldClassDecl->getLocation(), diag::not_previous_class_decl)
|
||||
<< FieldClassDecl->getNameAsCString();
|
||||
err = true;
|
||||
}
|
||||
}
|
||||
else if (FieldType->isReferenceType()) {
|
||||
Diag(CurrentLocation, diag::err_unintialized_member)
|
||||
<< ClassDecl->getNameAsCString() << 0;
|
||||
Diag((*Field)->getLocation(), diag::note_declared_at);
|
||||
err = true;
|
||||
}
|
||||
else if (FieldType.isConstQualified()) {
|
||||
Diag(CurrentLocation, diag::err_unintialized_member)
|
||||
<< ClassDecl->getNameAsCString() << 1;
|
||||
Diag((*Field)->getLocation(), diag::note_declared_at);
|
||||
err = true;
|
||||
}
|
||||
}
|
||||
if (!err)
|
||||
Constructor->setImplicitMustBeDefined();
|
||||
}
|
||||
|
||||
void Sema::InitializeVarWithConstructor(VarDecl *VD,
|
||||
CXXConstructorDecl *Constructor,
|
||||
QualType DeclInitType,
|
||||
|
@ -1878,6 +1952,9 @@ void Sema::AddCXXDirectInitializerToDecl(DeclPtrTy Dcl,
|
|||
VDecl->setCXXDirectInitializer(true);
|
||||
InitializeVarWithConstructor(VDecl, Constructor, DeclInitType,
|
||||
(Expr**)Exprs.release(), NumExprs);
|
||||
// An implicitly-declared default constructor for a class is implicitly
|
||||
// defined when it is used to creat an object of its class type.
|
||||
DefineImplicitDefaultConstructor(VDecl->getLocation(), Constructor);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
|
|
@ -0,0 +1,56 @@
|
|||
// RUN: clang-cc -fsyntax-only -verify %s
|
||||
|
||||
struct X1 { // has no implicit default constructor
|
||||
X1(int);
|
||||
};
|
||||
|
||||
struct X2 : X1 { // expected-note {{class X2 declared here}} \
|
||||
// expected-note {{class X2 declared here}}
|
||||
X2(int);
|
||||
};
|
||||
|
||||
struct X3 : public X2 {
|
||||
};
|
||||
X3 x3; // expected-error {{cannot define the default constructor for X3, because X2 does not have any default constructor}}
|
||||
|
||||
|
||||
struct X4 {
|
||||
X2 x2;
|
||||
X2 & rx2; // expected-note {{declared at}}
|
||||
};
|
||||
|
||||
X4 x4; // expected-error {{cannot define the default constructor for X4, because X2 does not have any default constructor}} \
|
||||
// expected-error {{cannot define the default constructor for X4, because of unintialized reference member}}
|
||||
|
||||
|
||||
struct Y1 { // has no implicit default constructor
|
||||
Y1(int);
|
||||
};
|
||||
|
||||
struct Y2 : Y1 {
|
||||
Y2(int);
|
||||
Y2();
|
||||
};
|
||||
|
||||
struct Y3 : public Y2 {
|
||||
};
|
||||
Y3 y3;
|
||||
|
||||
struct Y4 {
|
||||
Y2 y2;
|
||||
};
|
||||
|
||||
Y4 y4;
|
||||
|
||||
// More tests
|
||||
|
||||
|
||||
struct Z1 {
|
||||
int& z; // expected-note {{declared at}}
|
||||
const int c1; // expected-note {{declared at}}
|
||||
volatile int v1;
|
||||
};
|
||||
|
||||
Z1 z1; // expected-error {{cannot define the default constructor for Z1, because of unintialized const member}} \
|
||||
// expected-error {{cannot define the default constructor for Z1, because of unintialized reference member}}
|
||||
|
Loading…
Reference in New Issue