diff options
author | Sean Hunt <scshunt@csclub.uwaterloo.ca> | 2011-05-06 01:42:00 +0000 |
---|---|---|
committer | Sean Hunt <scshunt@csclub.uwaterloo.ca> | 2011-05-06 01:42:00 +0000 |
commit | fe2695eec167b28578825576863228f86b392f24 (patch) | |
tree | 74e67eb09b681ca0d1d28c1b4637dc5faa2055d9 /lib | |
parent | 5f802e51406664ca9b6e0d57fc7ce37ea97a1c65 (diff) |
Do defaulted constructors properly.
Explictly defaultedness is correctly reflected on the AST, but there are
no changes to how that affects the definition of functions or much else
really.
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@130974 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'lib')
-rw-r--r-- | lib/Parse/ParseDecl.cpp | 4 | ||||
-rw-r--r-- | lib/Parse/ParseDeclCXX.cpp | 11 | ||||
-rw-r--r-- | lib/Sema/SemaDecl.cpp | 63 | ||||
-rw-r--r-- | lib/Sema/SemaDeclCXX.cpp | 7 |
4 files changed, 72 insertions, 13 deletions
diff --git a/lib/Parse/ParseDecl.cpp b/lib/Parse/ParseDecl.cpp index a20e90bd0e..a4c323979d 100644 --- a/lib/Parse/ParseDecl.cpp +++ b/lib/Parse/ParseDecl.cpp @@ -966,6 +966,10 @@ 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); } else { if (getLang().CPlusPlus && D.getCXXScopeSpec().isSet()) { EnterScope(0); diff --git a/lib/Parse/ParseDeclCXX.cpp b/lib/Parse/ParseDeclCXX.cpp index 7247c0724e..d263f96e26 100644 --- a/lib/Parse/ParseDeclCXX.cpp +++ b/lib/Parse/ParseDeclCXX.cpp @@ -1648,6 +1648,7 @@ void Parser::ParseCXXClassMemberDeclaration(AccessSpecifier AS, ExprResult BitfieldSize; ExprResult Init; bool Deleted = false; + SourceLocation DefLoc; while (1) { // member-declarator: @@ -1679,6 +1680,10 @@ void Parser::ParseCXXClassMemberDeclaration(AccessSpecifier AS, Diag(Tok, diag::warn_deleted_function_accepted_as_extension); ConsumeToken(); Deleted = true; + } else if (Tok.is(tok::kw_default)) { + if (!getLang().CPlusPlus0x) + Diag(Tok, diag::warn_defaulted_function_accepted_as_extension); + DefLoc = ConsumeToken(); } else { Init = ParseInitializer(); if (Init.isInvalid()) @@ -1706,6 +1711,9 @@ void Parser::ParseCXXClassMemberDeclaration(AccessSpecifier AS, Decl *ThisDecl = 0; if (DS.isFriendSpecified()) { + if (DefLoc.isValid()) + Diag(DefLoc, diag::err_default_special_members); + // TODO: handle initializers, bitfields, 'delete' ThisDecl = Actions.ActOnFriendFunctionDecl(getCurScope(), DeclaratorInfo, /*IsDefinition*/ false, @@ -1717,7 +1725,7 @@ void Parser::ParseCXXClassMemberDeclaration(AccessSpecifier AS, BitfieldSize.release(), VS, Init.release(), /*IsDefinition*/Deleted, - Deleted); + Deleted, DefLoc); } if (ThisDecl) DeclsInGroup.push_back(ThisDecl); @@ -1744,6 +1752,7 @@ void Parser::ParseCXXClassMemberDeclaration(AccessSpecifier AS, BitfieldSize = 0; Init = 0; Deleted = false; + DefLoc = SourceLocation(); // Attributes are only allowed on the second declarator. MaybeParseGNUAttributes(DeclaratorInfo); diff --git a/lib/Sema/SemaDecl.cpp b/lib/Sema/SemaDecl.cpp index 2a63c91135..0bf984d40a 100644 --- a/lib/Sema/SemaDecl.cpp +++ b/lib/Sema/SemaDecl.cpp @@ -2919,7 +2919,8 @@ bool Sema::DiagnoseClassNameShadow(DeclContext *DC, Decl *Sema::HandleDeclarator(Scope *S, Declarator &D, MultiTemplateParamsArg TemplateParamLists, - bool IsFunctionDefinition) { + bool IsFunctionDefinition, + SourceLocation DefLoc) { // TODO: consider using NameInfo for diagnostic. DeclarationNameInfo NameInfo = GetNameForDeclarator(D); DeclarationName Name = NameInfo.getName(); @@ -2962,7 +2963,6 @@ Decl *Sema::HandleDeclarator(Scope *S, Declarator &D, << D.getCXXScopeSpec().getRange(); return 0; } - bool IsDependentContext = DC->isDependentContext(); if (!IsDependentContext && @@ -3121,6 +3121,9 @@ Decl *Sema::HandleDeclarator(Scope *S, Declarator &D, bool Redeclaration = false; if (D.getDeclSpec().getStorageClassSpec() == DeclSpec::SCS_typedef) { + if (DefLoc.isValid()) + Diag(DefLoc, diag::err_default_special_members); + if (TemplateParamLists.size()) { Diag(D.getIdentifierLoc(), diag::err_template_typedef); return 0; @@ -3130,8 +3133,9 @@ Decl *Sema::HandleDeclarator(Scope *S, Declarator &D, } else if (R->isFunctionType()) { New = ActOnFunctionDeclarator(S, D, DC, R, TInfo, Previous, move(TemplateParamLists), - IsFunctionDefinition, Redeclaration); + IsFunctionDefinition, Redeclaration, DefLoc); } else { + assert(!DefLoc.isValid() && "We should have caught this in a caller"); New = ActOnVariableDeclarator(S, D, DC, R, TInfo, Previous, move(TemplateParamLists), Redeclaration); @@ -4003,7 +4007,8 @@ Sema::ActOnFunctionDeclarator(Scope* S, Declarator& D, DeclContext* DC, QualType R, TypeSourceInfo *TInfo, LookupResult &Previous, MultiTemplateParamsArg TemplateParamLists, - bool IsFunctionDefinition, bool &Redeclaration) { + bool IsFunctionDefinition, bool &Redeclaration, + SourceLocation DefLoc) { assert(R.getTypePtr()->isFunctionType()); // TODO: consider using NameInfo for diagnostic. @@ -4060,6 +4065,8 @@ Sema::ActOnFunctionDeclarator(Scope* S, Declarator& D, DeclContext* DC, bool isFunctionTemplateSpecialization = false; if (!getLangOptions().CPlusPlus) { + assert(!DefLoc.isValid() && "Defaulted functions are a C++ feature"); + // Determine whether the function was written with a // prototype. This true when: // - there is a prototype in the declarator, or @@ -4104,12 +4111,25 @@ Sema::ActOnFunctionDeclarator(Scope* S, Declarator& D, DeclContext* DC, R = CheckConstructorDeclarator(D, R, SC); // Create the new declaration - NewFD = CXXConstructorDecl::Create(Context, + CXXConstructorDecl *NewCD = CXXConstructorDecl::Create( + Context, cast<CXXRecordDecl>(DC), D.getSourceRange().getBegin(), NameInfo, R, TInfo, isExplicit, isInline, /*isImplicitlyDeclared=*/false); + + NewFD = NewCD; + + if (DefLoc.isValid()) { + if (NewCD->isDefaultConstructor() || + NewCD->isCopyOrMoveConstructor()) { + NewFD->setDefaulted(); + NewFD->setExplicitlyDefaulted(); + } else { + Diag(DefLoc, diag::err_default_special_members); + } + } } else if (Name.getNameKind() == DeclarationName::CXXDestructorName) { // This is a C++ destructor declaration. if (DC->isRecord()) { @@ -4122,6 +4142,11 @@ Sema::ActOnFunctionDeclarator(Scope* S, Declarator& D, DeclContext* DC, isInline, /*isImplicitlyDeclared=*/false); isVirtualOkay = true; + + if (DefLoc.isValid()) { + NewFD->setDefaulted(); + NewFD->setExplicitlyDefaulted(); + } } else { Diag(D.getIdentifierLoc(), diag::err_destructor_not_member); @@ -4140,6 +4165,9 @@ Sema::ActOnFunctionDeclarator(Scope* S, Declarator& D, DeclContext* DC, return 0; } + if (DefLoc.isValid()) + Diag(DefLoc, diag::err_default_special_members); + CheckConversionDeclarator(D, R, SC); NewFD = CXXConversionDecl::Create(Context, cast<CXXRecordDecl>(DC), D.getSourceRange().getBegin(), @@ -4178,14 +4206,29 @@ Sema::ActOnFunctionDeclarator(Scope* S, Declarator& D, DeclContext* DC, isStatic = true; // This is a C++ method declaration. - NewFD = CXXMethodDecl::Create(Context, cast<CXXRecordDecl>(DC), - D.getSourceRange().getBegin(), - NameInfo, R, TInfo, - isStatic, SCAsWritten, isInline, - SourceLocation()); + CXXMethodDecl *NewMD = CXXMethodDecl::Create( + Context, cast<CXXRecordDecl>(DC), + D.getSourceRange().getBegin(), + NameInfo, R, TInfo, + isStatic, SCAsWritten, isInline, + SourceLocation()); + NewFD = NewMD; isVirtualOkay = !isStatic; + + if (DefLoc.isValid()) { + if (NewMD->isCopyAssignmentOperator() /* || + NewMD->isMoveAssignmentOperator() */) { + NewFD->setDefaulted(); + NewFD->setExplicitlyDefaulted(); + } else { + Diag(DefLoc, diag::err_default_special_members); + } + } } else { + if (DefLoc.isValid()) + Diag(DefLoc, diag::err_default_special_members); + // Determine whether the function was written with a // prototype. This true when: // - we're in C++ (where every function has a prototype), diff --git a/lib/Sema/SemaDeclCXX.cpp b/lib/Sema/SemaDeclCXX.cpp index 525cb81c80..ca5fdd1fdd 100644 --- a/lib/Sema/SemaDeclCXX.cpp +++ b/lib/Sema/SemaDeclCXX.cpp @@ -963,7 +963,7 @@ Sema::ActOnCXXMemberDeclarator(Scope *S, AccessSpecifier AS, Declarator &D, MultiTemplateParamsArg TemplateParameterLists, ExprTy *BW, const VirtSpecifiers &VS, ExprTy *InitExpr, bool IsDefinition, - bool Deleted) { + bool Deleted, SourceLocation DefLoc) { const DeclSpec &DS = D.getDeclSpec(); DeclarationNameInfo NameInfo = GetNameForDeclarator(D); DeclarationName Name = NameInfo.getName(); @@ -1028,6 +1028,8 @@ Sema::ActOnCXXMemberDeclarator(Scope *S, AccessSpecifier AS, Declarator &D, if (isInstField) { CXXScopeSpec &SS = D.getCXXScopeSpec(); + if (DefLoc.isValid()) + Diag(DefLoc, diag::err_default_special_members); if (SS.isSet() && !SS.isInvalid()) { // The user provided a superfluous scope specifier inside a class @@ -1053,7 +1055,8 @@ Sema::ActOnCXXMemberDeclarator(Scope *S, AccessSpecifier AS, Declarator &D, AS); assert(Member && "HandleField never returns null"); } else { - Member = HandleDeclarator(S, D, move(TemplateParameterLists), IsDefinition); + Member = HandleDeclarator(S, D, move(TemplateParameterLists), IsDefinition, + DefLoc); if (!Member) { return 0; } |