Implement some framework for defaulted constructors.

There's some unused stuff for now.

llvm-svn: 130912
This commit is contained in:
Alexis Hunt 2011-05-05 03:36:28 +00:00
parent 4f9c367f0b
commit 1adeff92bc
11 changed files with 78 additions and 15 deletions

View File

@ -1501,6 +1501,9 @@ class CXXConstructorDecl : public CXXMethodDecl {
/// @c !Implicit && ImplicitlyDefined.
bool ImplicitlyDefined : 1;
/// IsDefaulted - Whether this constructor was explicitly defaulted
bool ExplicitlyDefaulted : 1;
/// Support for base and member initializers.
/// CtorInitializers - The arguments used to initialize the base
/// or member.
@ -1511,11 +1514,13 @@ class CXXConstructorDecl : public CXXMethodDecl {
const DeclarationNameInfo &NameInfo,
QualType T, TypeSourceInfo *TInfo,
bool isExplicitSpecified, bool isInline,
bool isImplicitlyDeclared)
bool isImplicitlyDeclared, bool isExplicitlyDefaulted)
: CXXMethodDecl(CXXConstructor, RD, StartLoc, NameInfo, T, TInfo, false,
SC_None, isInline, SourceLocation()),
IsExplicitSpecified(isExplicitSpecified), ImplicitlyDefined(false),
CtorInitializers(0), NumCtorInitializers(0) {
ExplicitlyDefaulted(isExplicitlyDefaulted),
CtorInitializers(0), NumCtorInitializers(0)
{
setImplicit(isImplicitlyDeclared);
}
@ -1526,7 +1531,8 @@ public:
const DeclarationNameInfo &NameInfo,
QualType T, TypeSourceInfo *TInfo,
bool isExplicit,
bool isInline, bool isImplicitlyDeclared);
bool isInline, bool isImplicitlyDeclared,
bool isExplicitlyDefaulted);
/// isExplicitSpecified - Whether this constructor declaration has the
/// 'explicit' keyword specified.
@ -1558,6 +1564,28 @@ public:
ImplicitlyDefined = ID;
}
/// isExplicitlyDefaulted - Whether this constructor was explicitly defaulted.
bool isExplicitlyDefaulted() const {
return ExplicitlyDefaulted;
}
/// setExplicitlyDefaulted - Set whether this contructor was explicitly
/// defaulted or not.
void setExplicitlyDefaulted(bool B) {
ExplicitlyDefaulted = B;
}
/// isDefaulted - True if this was either explicitly defaulted or is implicit
bool isDefaulted() const {
return ExplicitlyDefaulted || isImplicit();
}
/// isUserProvided - True if this function was neither defaulted nor deleted
/// on its first declaration.
bool isUserProvided() const {
const CXXConstructorDecl *Canonical = getCanonicalDecl();
return !Canonical->isDefaulted() && !Canonical->isDeleted();
}
/// init_iterator - Iterates through the member/base initializer list.
typedef CXXCtorInitializer **init_iterator;

View File

@ -52,6 +52,10 @@ def err_invalid_storage_class_in_func_decl : Error<
def err_expected_namespace_name : Error<"expected namespace name">;
def ext_variadic_templates : ExtWarn<
"variadic templates are a C++0x extension">, InGroup<CXX0x>;
def err_default_special_members : Error<
"Only special member functions may be defaulted">;
def err_friends_define_only_namespace_scope : Error<
"Cannot define a function with non-namespace scope in a friend declaration">;
// Sema && Lex
def ext_longlong : Extension<

View File

@ -434,6 +434,9 @@ def err_missing_whitespace_digraph : Error<
def warn_deleted_function_accepted_as_extension: ExtWarn<
"deleted function definition accepted as a C++0x extension">, InGroup<CXX0x>;
def warn_defaulted_function_accepted_as_extension: ExtWarn<
"defaulted function definition accepted as a C++0x extension">,
InGroup<CXX0x>;
// C++0x alias-declaration
def ext_alias_declaration : ExtWarn<

View File

@ -3057,7 +3057,7 @@ public:
MultiTemplateParamsArg TemplateParameterLists,
Expr *BitfieldWidth, const VirtSpecifiers &VS,
Expr *Init, bool IsDefinition,
bool Deleted = false);
bool Deleted = false, bool Defaulted = false);
MemInitResult ActOnMemInitializer(Decl *ConstructorD,
Scope *S,

View File

@ -2397,7 +2397,8 @@ Decl *ASTNodeImporter::VisitFunctionDecl(FunctionDecl *D) {
NameInfo, T, TInfo,
FromConstructor->isExplicit(),
D->isInlineSpecified(),
D->isImplicit());
D->isImplicit(),
FromConstructor->isExplicitlyDefaulted());
} else if (isa<CXXDestructorDecl>(D)) {
ToFunction = CXXDestructorDecl::Create(Importer.getToContext(),
cast<CXXRecordDecl>(DC),

View File

@ -1301,7 +1301,7 @@ SourceRange CXXCtorInitializer::getSourceRange() const {
CXXConstructorDecl *
CXXConstructorDecl::Create(ASTContext &C, EmptyShell Empty) {
return new (C) CXXConstructorDecl(0, SourceLocation(), DeclarationNameInfo(),
QualType(), 0, false, false, false);
QualType(), 0, false, false, false, false);
}
CXXConstructorDecl *
@ -1311,12 +1311,14 @@ CXXConstructorDecl::Create(ASTContext &C, CXXRecordDecl *RD,
QualType T, TypeSourceInfo *TInfo,
bool isExplicit,
bool isInline,
bool isImplicitlyDeclared) {
bool isImplicitlyDeclared,
bool isExplicitlyDefaulted) {
assert(NameInfo.getName().getNameKind()
== DeclarationName::CXXConstructorName &&
"Name must refer to a constructor");
return new (C) CXXConstructorDecl(RD, StartLoc, NameInfo, T, TInfo,
isExplicit, isInline, isImplicitlyDeclared);
isExplicit, isInline, isImplicitlyDeclared,
isExplicitlyDefaulted);
}
bool CXXConstructorDecl::isDefaultConstructor() const {

View File

@ -966,6 +966,11 @@ Decl *Parser::ParseDeclarationAfterDeclaratorAndAttributes(Declarator &D,
Diag(DelLoc, diag::warn_deleted_function_accepted_as_extension);
Actions.SetDeclDeleted(ThisDecl, DelLoc);
} else if (Tok.is(tok::kw_default)) {
SourceLocation DefLoc = ConsumeToken();
Diag(DefLoc, diag::err_default_special_members);
ThisDecl->setInvalidDecl();
} else {
if (getLang().CPlusPlus && D.getCXXScopeSpec().isSet()) {
EnterScope(0);

View File

@ -1621,6 +1621,8 @@ void Parser::ParseCXXClassMemberDeclaration(AccessSpecifier AS,
ExprResult BitfieldSize;
ExprResult Init;
bool Deleted = false;
bool Defaulted = false;
SourceLocation DefLoc;
while (1) {
// member-declarator:
@ -1652,6 +1654,11 @@ void Parser::ParseCXXClassMemberDeclaration(AccessSpecifier AS,
Diag(Tok, diag::warn_deleted_function_accepted_as_extension);
ConsumeToken();
Deleted = true;
} else if (Tok.is(tok::kw_delete)) {
if (!getLang().CPlusPlus0x)
Diag(Tok, diag::warn_defaulted_function_accepted_as_extension);
DefLoc = ConsumeToken();
Defaulted = true;
} else {
Init = ParseInitializer();
if (Init.isInvalid())
@ -1683,6 +1690,10 @@ void Parser::ParseCXXClassMemberDeclaration(AccessSpecifier AS,
ThisDecl = Actions.ActOnFriendFunctionDecl(getCurScope(), DeclaratorInfo,
/*IsDefinition*/ false,
move(TemplateParams));
if (Defaulted) {
Diag(DefLoc, diag::err_friends_define_only_namespace_scope);
ThisDecl->setInvalidDecl();
}
} else {
ThisDecl = Actions.ActOnCXXMemberDeclarator(getCurScope(), AS,
DeclaratorInfo,
@ -1690,7 +1701,7 @@ void Parser::ParseCXXClassMemberDeclaration(AccessSpecifier AS,
BitfieldSize.release(),
VS, Init.release(),
/*IsDefinition*/Deleted,
Deleted);
Deleted, Defaulted);
}
if (ThisDecl)
DeclsInGroup.push_back(ThisDecl);
@ -1717,6 +1728,7 @@ void Parser::ParseCXXClassMemberDeclaration(AccessSpecifier AS,
BitfieldSize = 0;
Init = 0;
Deleted = false;
Defaulted = false;
// Attributes are only allowed on the second declarator.
MaybeParseGNUAttributes(DeclaratorInfo);

View File

@ -4103,7 +4103,8 @@ Sema::ActOnFunctionDeclarator(Scope* S, Declarator& D, DeclContext* DC,
D.getSourceRange().getBegin(),
NameInfo, R, TInfo,
isExplicit, isInline,
/*isImplicitlyDeclared=*/false);
/*isImplicitlyDeclared=*/false,
/*isExplicitlyDefaulted=*/false);
} else if (Name.getNameKind() == DeclarationName::CXXDestructorName) {
// This is a C++ destructor declaration.
if (DC->isRecord()) {

View File

@ -963,7 +963,10 @@ Sema::ActOnCXXMemberDeclarator(Scope *S, AccessSpecifier AS, Declarator &D,
MultiTemplateParamsArg TemplateParameterLists,
ExprTy *BW, const VirtSpecifiers &VS,
ExprTy *InitExpr, bool IsDefinition,
bool Deleted) {
bool Deleted, bool Defaulted) {
// FIXME: Do something with this
(void) Defaulted;
const DeclSpec &DS = D.getDeclSpec();
DeclarationNameInfo NameInfo = GetNameForDeclarator(D);
DeclarationName Name = NameInfo.getName();
@ -4956,7 +4959,8 @@ CXXConstructorDecl *Sema::DeclareImplicitDefaultConstructor(
/*TInfo=*/0,
/*isExplicit=*/false,
/*isInline=*/true,
/*isImplicitlyDeclared=*/true);
/*isImplicitlyDeclared=*/true,
/*isExplicitlyDefaulted=*/false);
DefaultCon->setAccess(AS_public);
DefaultCon->setImplicit();
DefaultCon->setTrivial(ClassDecl->hasTrivialConstructor());
@ -5152,7 +5156,8 @@ void Sema::DeclareInheritedConstructors(CXXRecordDecl *ClassDecl) {
CXXConstructorDecl *NewCtor = CXXConstructorDecl::Create(
Context, ClassDecl, UsingLoc, DNI, QualType(NewCtorType, 0),
/*TInfo=*/0, BaseCtor->isExplicit(), /*Inline=*/true,
/*ImplicitlyDeclared=*/true);
/*ImplicitlyDeclared=*/true,
/*isExplicitlyDefaulted*/false);
NewCtor->setAccess(BaseCtor->getAccess());
// Build up the parameter decls and add them.
@ -6101,7 +6106,8 @@ CXXConstructorDecl *Sema::DeclareImplicitCopyConstructor(
/*TInfo=*/0,
/*isExplicit=*/false,
/*isInline=*/true,
/*isImplicitlyDeclared=*/true);
/*isImplicitlyDeclared=*/true,
/*isExplicitlyDefaulted=*/false);
CopyConstructor->setAccess(AS_public);
CopyConstructor->setTrivial(ClassDecl->hasTrivialCopyConstructor());

View File

@ -1330,7 +1330,8 @@ TemplateDeclInstantiator::VisitCXXMethodDecl(CXXMethodDecl *D,
StartLoc, NameInfo, T, TInfo,
Constructor->isExplicit(),
Constructor->isInlineSpecified(),
false);
false,
Constructor->isExplicitlyDefaulted());
} else if (CXXDestructorDecl *Destructor = dyn_cast<CXXDestructorDecl>(D)) {
Method = CXXDestructorDecl::Create(SemaRef.Context, Record,
StartLoc, NameInfo, T, TInfo,