Skip to content

Commit 1adeff9

Browse files
committed
Implement some framework for defaulted constructors.
There's some unused stuff for now. llvm-svn: 130912
1 parent 4f9c367 commit 1adeff9

File tree

11 files changed

+78
-15
lines changed

11 files changed

+78
-15
lines changed

clang/include/clang/AST/DeclCXX.h

Lines changed: 31 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1501,6 +1501,9 @@ class CXXConstructorDecl : public CXXMethodDecl {
15011501
/// @c !Implicit && ImplicitlyDefined.
15021502
bool ImplicitlyDefined : 1;
15031503

1504+
/// IsDefaulted - Whether this constructor was explicitly defaulted
1505+
bool ExplicitlyDefaulted : 1;
1506+
15041507
/// Support for base and member initializers.
15051508
/// CtorInitializers - The arguments used to initialize the base
15061509
/// or member.
@@ -1511,11 +1514,13 @@ class CXXConstructorDecl : public CXXMethodDecl {
15111514
const DeclarationNameInfo &NameInfo,
15121515
QualType T, TypeSourceInfo *TInfo,
15131516
bool isExplicitSpecified, bool isInline,
1514-
bool isImplicitlyDeclared)
1517+
bool isImplicitlyDeclared, bool isExplicitlyDefaulted)
15151518
: CXXMethodDecl(CXXConstructor, RD, StartLoc, NameInfo, T, TInfo, false,
15161519
SC_None, isInline, SourceLocation()),
15171520
IsExplicitSpecified(isExplicitSpecified), ImplicitlyDefined(false),
1518-
CtorInitializers(0), NumCtorInitializers(0) {
1521+
ExplicitlyDefaulted(isExplicitlyDefaulted),
1522+
CtorInitializers(0), NumCtorInitializers(0)
1523+
{
15191524
setImplicit(isImplicitlyDeclared);
15201525
}
15211526

@@ -1526,7 +1531,8 @@ class CXXConstructorDecl : public CXXMethodDecl {
15261531
const DeclarationNameInfo &NameInfo,
15271532
QualType T, TypeSourceInfo *TInfo,
15281533
bool isExplicit,
1529-
bool isInline, bool isImplicitlyDeclared);
1534+
bool isInline, bool isImplicitlyDeclared,
1535+
bool isExplicitlyDefaulted);
15301536

15311537
/// isExplicitSpecified - Whether this constructor declaration has the
15321538
/// 'explicit' keyword specified.
@@ -1558,6 +1564,28 @@ class CXXConstructorDecl : public CXXMethodDecl {
15581564
ImplicitlyDefined = ID;
15591565
}
15601566

1567+
/// isExplicitlyDefaulted - Whether this constructor was explicitly defaulted.
1568+
bool isExplicitlyDefaulted() const {
1569+
return ExplicitlyDefaulted;
1570+
}
1571+
/// setExplicitlyDefaulted - Set whether this contructor was explicitly
1572+
/// defaulted or not.
1573+
void setExplicitlyDefaulted(bool B) {
1574+
ExplicitlyDefaulted = B;
1575+
}
1576+
1577+
/// isDefaulted - True if this was either explicitly defaulted or is implicit
1578+
bool isDefaulted() const {
1579+
return ExplicitlyDefaulted || isImplicit();
1580+
}
1581+
1582+
/// isUserProvided - True if this function was neither defaulted nor deleted
1583+
/// on its first declaration.
1584+
bool isUserProvided() const {
1585+
const CXXConstructorDecl *Canonical = getCanonicalDecl();
1586+
return !Canonical->isDefaulted() && !Canonical->isDeleted();
1587+
}
1588+
15611589
/// init_iterator - Iterates through the member/base initializer list.
15621590
typedef CXXCtorInitializer **init_iterator;
15631591

clang/include/clang/Basic/DiagnosticCommonKinds.td

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -52,6 +52,10 @@ def err_invalid_storage_class_in_func_decl : Error<
5252
def err_expected_namespace_name : Error<"expected namespace name">;
5353
def ext_variadic_templates : ExtWarn<
5454
"variadic templates are a C++0x extension">, InGroup<CXX0x>;
55+
def err_default_special_members : Error<
56+
"Only special member functions may be defaulted">;
57+
def err_friends_define_only_namespace_scope : Error<
58+
"Cannot define a function with non-namespace scope in a friend declaration">;
5559

5660
// Sema && Lex
5761
def ext_longlong : Extension<

clang/include/clang/Basic/DiagnosticParseKinds.td

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -434,6 +434,9 @@ def err_missing_whitespace_digraph : Error<
434434

435435
def warn_deleted_function_accepted_as_extension: ExtWarn<
436436
"deleted function definition accepted as a C++0x extension">, InGroup<CXX0x>;
437+
def warn_defaulted_function_accepted_as_extension: ExtWarn<
438+
"defaulted function definition accepted as a C++0x extension">,
439+
InGroup<CXX0x>;
437440

438441
// C++0x alias-declaration
439442
def ext_alias_declaration : ExtWarn<

clang/include/clang/Sema/Sema.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3057,7 +3057,7 @@ class Sema {
30573057
MultiTemplateParamsArg TemplateParameterLists,
30583058
Expr *BitfieldWidth, const VirtSpecifiers &VS,
30593059
Expr *Init, bool IsDefinition,
3060-
bool Deleted = false);
3060+
bool Deleted = false, bool Defaulted = false);
30613061

30623062
MemInitResult ActOnMemInitializer(Decl *ConstructorD,
30633063
Scope *S,

clang/lib/AST/ASTImporter.cpp

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2397,7 +2397,8 @@ Decl *ASTNodeImporter::VisitFunctionDecl(FunctionDecl *D) {
23972397
NameInfo, T, TInfo,
23982398
FromConstructor->isExplicit(),
23992399
D->isInlineSpecified(),
2400-
D->isImplicit());
2400+
D->isImplicit(),
2401+
FromConstructor->isExplicitlyDefaulted());
24012402
} else if (isa<CXXDestructorDecl>(D)) {
24022403
ToFunction = CXXDestructorDecl::Create(Importer.getToContext(),
24032404
cast<CXXRecordDecl>(DC),

clang/lib/AST/DeclCXX.cpp

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1301,7 +1301,7 @@ SourceRange CXXCtorInitializer::getSourceRange() const {
13011301
CXXConstructorDecl *
13021302
CXXConstructorDecl::Create(ASTContext &C, EmptyShell Empty) {
13031303
return new (C) CXXConstructorDecl(0, SourceLocation(), DeclarationNameInfo(),
1304-
QualType(), 0, false, false, false);
1304+
QualType(), 0, false, false, false, false);
13051305
}
13061306

13071307
CXXConstructorDecl *
@@ -1311,12 +1311,14 @@ CXXConstructorDecl::Create(ASTContext &C, CXXRecordDecl *RD,
13111311
QualType T, TypeSourceInfo *TInfo,
13121312
bool isExplicit,
13131313
bool isInline,
1314-
bool isImplicitlyDeclared) {
1314+
bool isImplicitlyDeclared,
1315+
bool isExplicitlyDefaulted) {
13151316
assert(NameInfo.getName().getNameKind()
13161317
== DeclarationName::CXXConstructorName &&
13171318
"Name must refer to a constructor");
13181319
return new (C) CXXConstructorDecl(RD, StartLoc, NameInfo, T, TInfo,
1319-
isExplicit, isInline, isImplicitlyDeclared);
1320+
isExplicit, isInline, isImplicitlyDeclared,
1321+
isExplicitlyDefaulted);
13201322
}
13211323

13221324
bool CXXConstructorDecl::isDefaultConstructor() const {

clang/lib/Parse/ParseDecl.cpp

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -966,6 +966,11 @@ Decl *Parser::ParseDeclarationAfterDeclaratorAndAttributes(Declarator &D,
966966
Diag(DelLoc, diag::warn_deleted_function_accepted_as_extension);
967967

968968
Actions.SetDeclDeleted(ThisDecl, DelLoc);
969+
} else if (Tok.is(tok::kw_default)) {
970+
SourceLocation DefLoc = ConsumeToken();
971+
Diag(DefLoc, diag::err_default_special_members);
972+
973+
ThisDecl->setInvalidDecl();
969974
} else {
970975
if (getLang().CPlusPlus && D.getCXXScopeSpec().isSet()) {
971976
EnterScope(0);

clang/lib/Parse/ParseDeclCXX.cpp

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1621,6 +1621,8 @@ void Parser::ParseCXXClassMemberDeclaration(AccessSpecifier AS,
16211621
ExprResult BitfieldSize;
16221622
ExprResult Init;
16231623
bool Deleted = false;
1624+
bool Defaulted = false;
1625+
SourceLocation DefLoc;
16241626

16251627
while (1) {
16261628
// member-declarator:
@@ -1652,6 +1654,11 @@ void Parser::ParseCXXClassMemberDeclaration(AccessSpecifier AS,
16521654
Diag(Tok, diag::warn_deleted_function_accepted_as_extension);
16531655
ConsumeToken();
16541656
Deleted = true;
1657+
} else if (Tok.is(tok::kw_delete)) {
1658+
if (!getLang().CPlusPlus0x)
1659+
Diag(Tok, diag::warn_defaulted_function_accepted_as_extension);
1660+
DefLoc = ConsumeToken();
1661+
Defaulted = true;
16551662
} else {
16561663
Init = ParseInitializer();
16571664
if (Init.isInvalid())
@@ -1683,14 +1690,18 @@ void Parser::ParseCXXClassMemberDeclaration(AccessSpecifier AS,
16831690
ThisDecl = Actions.ActOnFriendFunctionDecl(getCurScope(), DeclaratorInfo,
16841691
/*IsDefinition*/ false,
16851692
move(TemplateParams));
1693+
if (Defaulted) {
1694+
Diag(DefLoc, diag::err_friends_define_only_namespace_scope);
1695+
ThisDecl->setInvalidDecl();
1696+
}
16861697
} else {
16871698
ThisDecl = Actions.ActOnCXXMemberDeclarator(getCurScope(), AS,
16881699
DeclaratorInfo,
16891700
move(TemplateParams),
16901701
BitfieldSize.release(),
16911702
VS, Init.release(),
16921703
/*IsDefinition*/Deleted,
1693-
Deleted);
1704+
Deleted, Defaulted);
16941705
}
16951706
if (ThisDecl)
16961707
DeclsInGroup.push_back(ThisDecl);
@@ -1717,6 +1728,7 @@ void Parser::ParseCXXClassMemberDeclaration(AccessSpecifier AS,
17171728
BitfieldSize = 0;
17181729
Init = 0;
17191730
Deleted = false;
1731+
Defaulted = false;
17201732

17211733
// Attributes are only allowed on the second declarator.
17221734
MaybeParseGNUAttributes(DeclaratorInfo);

clang/lib/Sema/SemaDecl.cpp

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4103,7 +4103,8 @@ Sema::ActOnFunctionDeclarator(Scope* S, Declarator& D, DeclContext* DC,
41034103
D.getSourceRange().getBegin(),
41044104
NameInfo, R, TInfo,
41054105
isExplicit, isInline,
4106-
/*isImplicitlyDeclared=*/false);
4106+
/*isImplicitlyDeclared=*/false,
4107+
/*isExplicitlyDefaulted=*/false);
41074108
} else if (Name.getNameKind() == DeclarationName::CXXDestructorName) {
41084109
// This is a C++ destructor declaration.
41094110
if (DC->isRecord()) {

clang/lib/Sema/SemaDeclCXX.cpp

Lines changed: 10 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -963,7 +963,10 @@ Sema::ActOnCXXMemberDeclarator(Scope *S, AccessSpecifier AS, Declarator &D,
963963
MultiTemplateParamsArg TemplateParameterLists,
964964
ExprTy *BW, const VirtSpecifiers &VS,
965965
ExprTy *InitExpr, bool IsDefinition,
966-
bool Deleted) {
966+
bool Deleted, bool Defaulted) {
967+
// FIXME: Do something with this
968+
(void) Defaulted;
969+
967970
const DeclSpec &DS = D.getDeclSpec();
968971
DeclarationNameInfo NameInfo = GetNameForDeclarator(D);
969972
DeclarationName Name = NameInfo.getName();
@@ -4956,7 +4959,8 @@ CXXConstructorDecl *Sema::DeclareImplicitDefaultConstructor(
49564959
/*TInfo=*/0,
49574960
/*isExplicit=*/false,
49584961
/*isInline=*/true,
4959-
/*isImplicitlyDeclared=*/true);
4962+
/*isImplicitlyDeclared=*/true,
4963+
/*isExplicitlyDefaulted=*/false);
49604964
DefaultCon->setAccess(AS_public);
49614965
DefaultCon->setImplicit();
49624966
DefaultCon->setTrivial(ClassDecl->hasTrivialConstructor());
@@ -5152,7 +5156,8 @@ void Sema::DeclareInheritedConstructors(CXXRecordDecl *ClassDecl) {
51525156
CXXConstructorDecl *NewCtor = CXXConstructorDecl::Create(
51535157
Context, ClassDecl, UsingLoc, DNI, QualType(NewCtorType, 0),
51545158
/*TInfo=*/0, BaseCtor->isExplicit(), /*Inline=*/true,
5155-
/*ImplicitlyDeclared=*/true);
5159+
/*ImplicitlyDeclared=*/true,
5160+
/*isExplicitlyDefaulted*/false);
51565161
NewCtor->setAccess(BaseCtor->getAccess());
51575162

51585163
// Build up the parameter decls and add them.
@@ -6101,7 +6106,8 @@ CXXConstructorDecl *Sema::DeclareImplicitCopyConstructor(
61016106
/*TInfo=*/0,
61026107
/*isExplicit=*/false,
61036108
/*isInline=*/true,
6104-
/*isImplicitlyDeclared=*/true);
6109+
/*isImplicitlyDeclared=*/true,
6110+
/*isExplicitlyDefaulted=*/false);
61056111
CopyConstructor->setAccess(AS_public);
61066112
CopyConstructor->setTrivial(ClassDecl->hasTrivialCopyConstructor());
61076113

0 commit comments

Comments
 (0)