From e4246a633b13197634225971b25df0cbdcec0c5d Mon Sep 17 00:00:00 2001 From: Sean Hunt Date: Thu, 12 May 2011 06:15:49 +0000 Subject: [PATCH] Properly parse the 'default' and 'delete' keywords. They are actually grammatically considered definitions and parsed accordingly. This fixes the outstanding bugs regarding defaulting functions after their declarations. We now really nicely diagnose the following construct (try it!) int foo() = delete, bar; Still todo: Defaulted functions other than default constructors Test cases (including for the above construct) git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@131228 91177308-0d34-0410-b5e6-96231b3b80d8 --- include/clang/Basic/DiagnosticCommonKinds.td | 2 + include/clang/Basic/DiagnosticParseKinds.td | 3 + include/clang/Basic/DiagnosticSemaKinds.td | 2 - include/clang/Parse/Parser.h | 2 +- include/clang/Sema/Sema.h | 14 ++-- lib/Parse/ParseCXXInlineMethods.cpp | 39 +++++++++- lib/Parse/ParseDecl.cpp | 17 ++-- lib/Parse/ParseDeclCXX.cpp | 51 ++++++------ lib/Parse/Parser.cpp | 81 +++++++++++++++++++- lib/Sema/SemaDecl.cpp | 37 +++------ lib/Sema/SemaDeclCXX.cpp | 44 ++++++++--- 11 files changed, 213 insertions(+), 79 deletions(-) diff --git a/include/clang/Basic/DiagnosticCommonKinds.td b/include/clang/Basic/DiagnosticCommonKinds.td index 4383555c11..50110fb537 100644 --- a/include/clang/Basic/DiagnosticCommonKinds.td +++ b/include/clang/Basic/DiagnosticCommonKinds.td @@ -56,6 +56,8 @@ 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">; +def err_deleted_non_function : Error< + "only functions can have deleted definitions">; // Sema && Lex def ext_longlong : Extension< diff --git a/include/clang/Basic/DiagnosticParseKinds.td b/include/clang/Basic/DiagnosticParseKinds.td index 3a8a708afa..45275ea367 100644 --- a/include/clang/Basic/DiagnosticParseKinds.td +++ b/include/clang/Basic/DiagnosticParseKinds.td @@ -343,6 +343,9 @@ def err_operator_string_not_empty : Error< // Classes. def err_anon_type_definition : Error< "declaration of anonymous %0 must be a definition">; +def err_default_delete_in_multiple_declaration : Error< + "'= %select{default|delete}0' is a function definition and must occur in a " + "standalone declaration">; def err_cxx0x_attribute_forbids_arguments : Error< "C++0x attribute '%0' cannot have an argument list">; diff --git a/include/clang/Basic/DiagnosticSemaKinds.td b/include/clang/Basic/DiagnosticSemaKinds.td index 2ab02d60e1..8d5951f3f3 100644 --- a/include/clang/Basic/DiagnosticSemaKinds.td +++ b/include/clang/Basic/DiagnosticSemaKinds.td @@ -553,8 +553,6 @@ def err_type_defined_in_alias_template : Error< def note_pure_virtual_function : Note< "unimplemented pure virtual method %0 in %1">; -def err_deleted_non_function : Error< - "only functions can have deleted definitions">; def err_deleted_decl_not_first : Error< "deleted definition must be first declaration">; diff --git a/include/clang/Parse/Parser.h b/include/clang/Parse/Parser.h index 613acb1cbc..e54b00c821 100644 --- a/include/clang/Parse/Parser.h +++ b/include/clang/Parse/Parser.h @@ -1000,7 +1000,7 @@ private: DeclGroupPtrTy ParseExternalDeclaration(ParsedAttributesWithRange &attrs, ParsingDeclSpec *DS = 0); - bool isDeclarationAfterDeclarator() const; + bool isDeclarationAfterDeclarator(); bool isStartOfFunctionDefinition(const ParsingDeclarator &Declarator); DeclGroupPtrTy ParseDeclarationOrFunctionDefinition(ParsedAttributes &attrs, AccessSpecifier AS = AS_none); diff --git a/include/clang/Sema/Sema.h b/include/clang/Sema/Sema.h index 3abc970de2..27833f562a 100644 --- a/include/clang/Sema/Sema.h +++ b/include/clang/Sema/Sema.h @@ -931,12 +931,12 @@ public: SourceLocation NameLoc, const Token &NextToken); - Decl *ActOnDeclarator(Scope *S, Declarator &D); + Decl *ActOnDeclarator(Scope *S, Declarator &D, + bool IsFunctionDefintion = false); Decl *HandleDeclarator(Scope *S, Declarator &D, MultiTemplateParamsArg TemplateParameterLists, - bool IsFunctionDefinition, - SourceLocation DefaultLoc = SourceLocation()); + bool IsFunctionDefinition); void RegisterLocallyScopedExternCDecl(NamedDecl *ND, const LookupResult &Previous, Scope *S); @@ -964,8 +964,7 @@ public: LookupResult &Previous, MultiTemplateParamsArg TemplateParamLists, bool IsFunctionDefinition, - bool &Redeclaration, - SourceLocation DefaultLoc = SourceLocation()); + bool &Redeclaration); bool AddOverriddenMethods(CXXRecordDecl *DC, CXXMethodDecl *MD); void DiagnoseHiddenVirtualMethods(CXXRecordDecl *DC, CXXMethodDecl *MD); void CheckFunctionDeclaration(Scope *S, @@ -997,6 +996,7 @@ public: void ActOnInitializerError(Decl *Dcl); void ActOnCXXForRangeDecl(Decl *D); void SetDeclDeleted(Decl *dcl, SourceLocation DelLoc); + void SetDeclDefaulted(Decl *dcl, SourceLocation DefaultLoc); void FinalizeDeclaration(Decl *D); DeclGroupPtrTy FinalizeDeclaratorGroup(Scope *S, const DeclSpec &DS, Decl **Group, @@ -3126,9 +3126,7 @@ public: Declarator &D, MultiTemplateParamsArg TemplateParameterLists, Expr *BitfieldWidth, const VirtSpecifiers &VS, - Expr *Init, bool IsDefinition, - bool Deleted = false, - SourceLocation DefaultLoc = SourceLocation()); + Expr *Init, bool IsDefinition); MemInitResult ActOnMemInitializer(Decl *ConstructorD, Scope *S, diff --git a/lib/Parse/ParseCXXInlineMethods.cpp b/lib/Parse/ParseCXXInlineMethods.cpp index 1e1a0e2b07..dee00275e7 100644 --- a/lib/Parse/ParseCXXInlineMethods.cpp +++ b/lib/Parse/ParseCXXInlineMethods.cpp @@ -25,8 +25,9 @@ Decl *Parser::ParseCXXInlineMethodDef(AccessSpecifier AS, ParsingDeclarator &D, const ParsedTemplateInfo &TemplateInfo, const VirtSpecifiers& VS, ExprResult& Init) { assert(D.isFunctionDeclarator() && "This isn't a function declarator!"); - assert((Tok.is(tok::l_brace) || Tok.is(tok::colon) || Tok.is(tok::kw_try)) && - "Current token not a '{', ':' or 'try'!"); + assert((Tok.is(tok::l_brace) || Tok.is(tok::colon) || Tok.is(tok::kw_try) || + Tok.is(tok::equal)) && + "Current token not a '{', ':', '=', or 'try'!"); MultiTemplateParamsArg TemplateParams(Actions, TemplateInfo.TemplateParams ? TemplateInfo.TemplateParams->data() : 0, @@ -48,6 +49,40 @@ Decl *Parser::ParseCXXInlineMethodDef(AccessSpecifier AS, ParsingDeclarator &D, D.complete(FnD); + if (Tok.is(tok::equal)) { + ConsumeToken(); + + bool Delete = false; + SourceLocation KWLoc; + if (Tok.is(tok::kw_delete)) { + if (!getLang().CPlusPlus0x) + Diag(Tok, diag::warn_deleted_function_accepted_as_extension); + + KWLoc = ConsumeToken(); + Actions.SetDeclDeleted(FnD, KWLoc); + Delete = true; + } else if (Tok.is(tok::kw_default)) { + if (!getLang().CPlusPlus0x) + Diag(Tok, diag::warn_defaulted_function_accepted_as_extension); + + KWLoc = ConsumeToken(); + Actions.SetDeclDefaulted(FnD, KWLoc); + } else { + llvm_unreachable("function definition after = not 'delete' or 'default'"); + } + + if (Tok.is(tok::comma)) { + Diag(KWLoc, diag::err_default_delete_in_multiple_declaration) + << Delete; + SkipUntil(tok::semi); + } else { + ExpectAndConsume(tok::semi, diag::err_expected_semi_after, + Delete ? "delete" : "default", tok::semi); + } + + return FnD; + } + // In delayed template parsing mode, if we are within a class template // or if we are about to parse function member template then consume // the tokens and store them for parsing at the end of the translation unit. diff --git a/lib/Parse/ParseDecl.cpp b/lib/Parse/ParseDecl.cpp index c54a0ed707..d7b90f129c 100644 --- a/lib/Parse/ParseDecl.cpp +++ b/lib/Parse/ParseDecl.cpp @@ -968,14 +968,17 @@ Decl *Parser::ParseDeclarationAfterDeclaratorAndAttributes(Declarator &D, diag::err_invalid_equalequal_after_declarator)) { ConsumeToken(); if (Tok.is(tok::kw_delete)) { - SourceLocation DelLoc = ConsumeToken(); - - if (!getLang().CPlusPlus0x) - Diag(DelLoc, diag::warn_deleted_function_accepted_as_extension); - - Actions.SetDeclDeleted(ThisDecl, DelLoc); + if (D.isFunctionDeclarator()) + Diag(ConsumeToken(), diag::err_default_delete_in_multiple_declaration) + << 1 /* delete */; + else + Diag(ConsumeToken(), diag::err_deleted_non_function); } else if (Tok.is(tok::kw_default)) { - Diag(ConsumeToken(), diag::err_default_special_members); + if (D.isFunctionDeclarator()) + Diag(Tok, diag::err_default_delete_in_multiple_declaration) + << 1 /* delete */; + else + Diag(ConsumeToken(), 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 ecf66a79db..91b55d5b58 100644 --- a/lib/Parse/ParseDeclCXX.cpp +++ b/lib/Parse/ParseDeclCXX.cpp @@ -1614,10 +1614,21 @@ void Parser::ParseCXXClassMemberDeclaration(AccessSpecifier AS, SkipUntil(tok::comma, true, true); } + bool IsDefinition = false; // function-definition: - if (Tok.is(tok::l_brace) - || (DeclaratorInfo.isFunctionDeclarator() && - (Tok.is(tok::colon) || Tok.is(tok::kw_try)))) { + if (Tok.is(tok::l_brace)) { + IsDefinition = true; + } else if (DeclaratorInfo.isFunctionDeclarator()) { + if (Tok.is(tok::colon) || Tok.is(tok::kw_try)) { + IsDefinition = true; + } else if (Tok.is(tok::equal)) { + const Token &KW = NextToken(); + if (KW.is(tok::kw_default) || KW.is(tok::kw_delete)) + IsDefinition = true; + } + } + + if (IsDefinition) { if (!DeclaratorInfo.isFunctionDeclarator()) { Diag(Tok, diag::err_func_def_no_params); ConsumeBrace(); @@ -1644,9 +1655,11 @@ void Parser::ParseCXXClassMemberDeclaration(AccessSpecifier AS, } ParseCXXInlineMethodDef(AS, DeclaratorInfo, TemplateInfo, VS, Init); - // Consume the optional ';' - if (Tok.is(tok::semi)) + + // Consume the ';' - it's optional unless we have a delete or default + if (Tok.is(tok::semi)) { ConsumeToken(); + } return; } @@ -1658,8 +1671,6 @@ void Parser::ParseCXXClassMemberDeclaration(AccessSpecifier AS, llvm::SmallVector DeclsInGroup; ExprResult BitfieldSize; - bool Deleted = false; - SourceLocation DefaultLoc; while (1) { // member-declarator: @@ -1687,14 +1698,17 @@ void Parser::ParseCXXClassMemberDeclaration(AccessSpecifier AS, if (Tok.is(tok::equal)) { ConsumeToken(); if (Tok.is(tok::kw_delete)) { - if (!getLang().CPlusPlus0x) - Diag(Tok, diag::warn_deleted_function_accepted_as_extension); - ConsumeToken(); - Deleted = true; + if (DeclaratorInfo.isFunctionDeclarator()) + Diag(ConsumeToken(), diag::err_default_delete_in_multiple_declaration) + << 1 /* delete */; + else + Diag(ConsumeToken(), diag::err_deleted_non_function); } else if (Tok.is(tok::kw_default)) { - if (!getLang().CPlusPlus0x) - Diag(Tok, diag::warn_defaulted_function_accepted_as_extension); - DefaultLoc = ConsumeToken(); + if (DeclaratorInfo.isFunctionDeclarator()) + Diag(Tok, diag::err_default_delete_in_multiple_declaration) + << 1 /* delete */; + else + Diag(ConsumeToken(), diag::err_default_special_members); } else { Init = ParseInitializer(); if (Init.isInvalid()) @@ -1722,9 +1736,6 @@ void Parser::ParseCXXClassMemberDeclaration(AccessSpecifier AS, Decl *ThisDecl = 0; if (DS.isFriendSpecified()) { - if (DefaultLoc.isValid()) - Diag(DefaultLoc, diag::err_default_special_members); - // TODO: handle initializers, bitfields, 'delete' ThisDecl = Actions.ActOnFriendFunctionDecl(getCurScope(), DeclaratorInfo, /*IsDefinition*/ false, @@ -1734,9 +1745,7 @@ void Parser::ParseCXXClassMemberDeclaration(AccessSpecifier AS, DeclaratorInfo, move(TemplateParams), BitfieldSize.release(), - VS, Init.release(), - /*IsDefinition*/Deleted, - Deleted, DefaultLoc); + VS, Init.release(), false); } if (ThisDecl) DeclsInGroup.push_back(ThisDecl); @@ -1762,8 +1771,6 @@ void Parser::ParseCXXClassMemberDeclaration(AccessSpecifier AS, VS.clear(); BitfieldSize = 0; Init = 0; - Deleted = false; - DefaultLoc = SourceLocation(); // Attributes are only allowed on the second declarator. MaybeParseGNUAttributes(DeclaratorInfo); diff --git a/lib/Parse/Parser.cpp b/lib/Parse/Parser.cpp index 263a4916b6..4e4819e9fc 100644 --- a/lib/Parse/Parser.cpp +++ b/lib/Parse/Parser.cpp @@ -677,7 +677,14 @@ Parser::ParseExternalDeclaration(ParsedAttributesWithRange &attrs, /// \brief Determine whether the current token, if it occurs after a /// declarator, continues a declaration or declaration list. -bool Parser::isDeclarationAfterDeclarator() const { +bool Parser::isDeclarationAfterDeclarator() { + // Check for '= delete' or '= default' + if (getLang().CPlusPlus && Tok.is(tok::equal)) { + const Token &KW = NextToken(); + if (KW.is(tok::kw_default) || KW.is(tok::kw_delete)) + return false; + } + return Tok.is(tok::equal) || // int X()= -> not a function def Tok.is(tok::comma) || // int X(), -> not a function def Tok.is(tok::semi) || // int X(); -> not a function def @@ -698,6 +705,11 @@ bool Parser::isStartOfFunctionDefinition(const ParsingDeclarator &Declarator) { if (!getLang().CPlusPlus && Declarator.getFunctionTypeInfo().isKNRPrototype()) return isDeclarationSpecifier(); + + if (getLang().CPlusPlus && Tok.is(tok::equal)) { + const Token &KW = NextToken(); + return KW.is(tok::kw_default) || KW.is(tok::kw_delete); + } return Tok.is(tok::colon) || // X() : Base() {} (used for ctors) Tok.is(tok::kw_try); // X() try { ... } @@ -820,6 +832,73 @@ Decl *Parser::ParseFunctionDefinition(ParsingDeclarator &D, if (FTI.isKNRPrototype()) ParseKNRParamDeclarations(D); + if (Tok.is(tok::equal)) { + assert(getLang().CPlusPlus && "Only C++ function definitions have '='"); + ConsumeToken(); + + Decl *Decl = 0; + // Here we complete the declaration as if it were normal + switch (TemplateInfo.Kind) { + case ParsedTemplateInfo::NonTemplate: + Decl = Actions.ActOnDeclarator(getCurScope(), D, true); + break; + + case ParsedTemplateInfo::Template: + case ParsedTemplateInfo::ExplicitSpecialization: + Decl = Actions.ActOnTemplateDeclarator(getCurScope(), + MultiTemplateParamsArg(Actions, + TemplateInfo.TemplateParams->data(), + TemplateInfo.TemplateParams->size()), + D); + break; + + case ParsedTemplateInfo::ExplicitInstantiation: { + DeclResult Result + = Actions.ActOnExplicitInstantiation(getCurScope(), + TemplateInfo.ExternLoc, + TemplateInfo.TemplateLoc, + D); + if (Result.isInvalid()) { + SkipUntil(tok::semi); + return 0; + } + + Decl = Result.get(); + break; + } + } + + bool Delete = false; + SourceLocation KWLoc; + if (Tok.is(tok::kw_delete)) { + if (!getLang().CPlusPlus0x) + Diag(Tok, diag::warn_deleted_function_accepted_as_extension); + + KWLoc = ConsumeToken(); + Actions.SetDeclDeleted(Decl, KWLoc); + Delete = true; + } else if (Tok.is(tok::kw_default)) { + if (!getLang().CPlusPlus0x) + Diag(Tok, diag::warn_defaulted_function_accepted_as_extension); + + KWLoc = ConsumeToken(); + Actions.SetDeclDefaulted(Decl, KWLoc); + } else { + llvm_unreachable("function definition after = not 'delete' or 'default'"); + } + + if (Tok.is(tok::comma)) { + Diag(KWLoc, diag::err_default_delete_in_multiple_declaration) + << Delete; + SkipUntil(tok::semi); + } else { + ExpectAndConsume(tok::semi, diag::err_expected_semi_after, + Delete ? "delete" : "default", tok::semi); + } + + return Decl; + } + // We should have either an opening brace or, in a C++ constructor, // we may have a colon. if (Tok.isNot(tok::l_brace) && diff --git a/lib/Sema/SemaDecl.cpp b/lib/Sema/SemaDecl.cpp index 972d080fc9..58b807fb2a 100644 --- a/lib/Sema/SemaDecl.cpp +++ b/lib/Sema/SemaDecl.cpp @@ -2913,8 +2913,10 @@ static bool RebuildDeclaratorInCurrentInstantiation(Sema &S, Declarator &D, return false; } -Decl *Sema::ActOnDeclarator(Scope *S, Declarator &D) { - return HandleDeclarator(S, D, MultiTemplateParamsArg(*this), false); +Decl *Sema::ActOnDeclarator(Scope *S, Declarator &D, + bool IsFunctionDefinition) { + return HandleDeclarator(S, D, MultiTemplateParamsArg(*this), + IsFunctionDefinition); } /// DiagnoseClassNameShadow - Implement C++ [class.mem]p13: @@ -2939,8 +2941,7 @@ bool Sema::DiagnoseClassNameShadow(DeclContext *DC, Decl *Sema::HandleDeclarator(Scope *S, Declarator &D, MultiTemplateParamsArg TemplateParamLists, - bool IsFunctionDefinition, - SourceLocation DefaultLoc) { + bool IsFunctionDefinition) { // TODO: consider using NameInfo for diagnostic. DeclarationNameInfo NameInfo = GetNameForDeclarator(D); DeclarationName Name = NameInfo.getName(); @@ -3141,9 +3142,6 @@ Decl *Sema::HandleDeclarator(Scope *S, Declarator &D, bool Redeclaration = false; if (D.getDeclSpec().getStorageClassSpec() == DeclSpec::SCS_typedef) { - if (DefaultLoc.isValid()) - Diag(DefaultLoc, diag::err_default_special_members); - if (TemplateParamLists.size()) { Diag(D.getIdentifierLoc(), diag::err_template_typedef); return 0; @@ -3153,10 +3151,8 @@ Decl *Sema::HandleDeclarator(Scope *S, Declarator &D, } else if (R->isFunctionType()) { New = ActOnFunctionDeclarator(S, D, DC, R, TInfo, Previous, move(TemplateParamLists), - IsFunctionDefinition, Redeclaration, - DefaultLoc); + IsFunctionDefinition, Redeclaration); } else { - assert(!DefaultLoc.isValid() && "We should have caught this in a caller"); New = ActOnVariableDeclarator(S, D, DC, R, TInfo, Previous, move(TemplateParamLists), Redeclaration); @@ -4028,8 +4024,7 @@ Sema::ActOnFunctionDeclarator(Scope* S, Declarator& D, DeclContext* DC, QualType R, TypeSourceInfo *TInfo, LookupResult &Previous, MultiTemplateParamsArg TemplateParamLists, - bool IsFunctionDefinition, bool &Redeclaration, - SourceLocation DefaultLoc) { + bool IsFunctionDefinition, bool &Redeclaration) { assert(R.getTypePtr()->isFunctionType()); // TODO: consider using NameInfo for diagnostic. @@ -4086,8 +4081,6 @@ Sema::ActOnFunctionDeclarator(Scope* S, Declarator& D, DeclContext* DC, bool isFunctionTemplateSpecialization = false; if (!getLangOptions().CPlusPlus) { - assert(!DefaultLoc.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 @@ -4689,7 +4682,7 @@ Sema::ActOnFunctionDeclarator(Scope* S, Declarator& D, DeclContext* DC, } else if (!IsFunctionDefinition && D.getCXXScopeSpec().isSet() && !isFriend && !isFunctionTemplateSpecialization && - !isExplicitSpecialization && !DefaultLoc.isValid()) { + !isExplicitSpecialization) { // An out-of-line member function declaration must also be a // definition (C++ [dcl.meaning]p1). // Note that this is not the case for explicit specializations of @@ -4700,8 +4693,8 @@ Sema::ActOnFunctionDeclarator(Scope* S, Declarator& D, DeclContext* DC, << D.getCXXScopeSpec().getRange(); } } - - + + // Handle attributes. We need to have merged decls when handling attributes // (for example to check for conflicts, etc). // FIXME: This needs to happen before we merge declarations. Then, @@ -4774,16 +4767,6 @@ Sema::ActOnFunctionDeclarator(Scope* S, Declarator& D, DeclContext* DC, } } - if (DefaultLoc.isValid()) { - CXXMethodDecl *MD = dyn_cast(NewFD); - if (MD && getSpecialMember(MD) != CXXInvalid) { - MD->setExplicitlyDefaulted(); - MD->setDefaulted(); - } else { - Diag(DefaultLoc, diag::err_default_special_members); - } - } - return NewFD; } diff --git a/lib/Sema/SemaDeclCXX.cpp b/lib/Sema/SemaDeclCXX.cpp index 13e2819f7b..b98777bad7 100644 --- a/lib/Sema/SemaDeclCXX.cpp +++ b/lib/Sema/SemaDeclCXX.cpp @@ -1025,8 +1025,7 @@ Decl * Sema::ActOnCXXMemberDeclarator(Scope *S, AccessSpecifier AS, Declarator &D, MultiTemplateParamsArg TemplateParameterLists, ExprTy *BW, const VirtSpecifiers &VS, - ExprTy *InitExpr, bool IsDefinition, - bool Deleted, SourceLocation DefaultLoc) { + ExprTy *InitExpr, bool IsDefinition) { const DeclSpec &DS = D.getDeclSpec(); DeclarationNameInfo NameInfo = GetNameForDeclarator(D); DeclarationName Name = NameInfo.getName(); @@ -1091,9 +1090,6 @@ Sema::ActOnCXXMemberDeclarator(Scope *S, AccessSpecifier AS, Declarator &D, if (isInstField) { CXXScopeSpec &SS = D.getCXXScopeSpec(); - if (DefaultLoc.isValid()) - Diag(DefaultLoc, diag::err_default_special_members); - if (SS.isSet() && !SS.isInvalid()) { // The user provided a superfluous scope specifier inside a class // definition: @@ -1118,8 +1114,7 @@ Sema::ActOnCXXMemberDeclarator(Scope *S, AccessSpecifier AS, Declarator &D, AS); assert(Member && "HandleField never returns null"); } else { - Member = HandleDeclarator(S, D, move(TemplateParameterLists), IsDefinition, - DefaultLoc); + Member = HandleDeclarator(S, D, move(TemplateParameterLists), IsDefinition); if (!Member) { return 0; } @@ -1189,8 +1184,6 @@ Sema::ActOnCXXMemberDeclarator(Scope *S, AccessSpecifier AS, Declarator &D, if (Init) AddInitializerToDecl(Member, Init, false, DS.getTypeSpecType() == DeclSpec::TST_auto); - if (Deleted) // FIXME: Source location is not very good. - SetDeclDeleted(Member, D.getSourceRange().getBegin()); FinalizeDeclaration(Member); @@ -7865,6 +7858,39 @@ void Sema::SetDeclDeleted(Decl *Dcl, SourceLocation DelLoc) { Fn->setDeletedAsWritten(); } +void Sema::SetDeclDefaulted(Decl *Dcl, SourceLocation DefaultLoc) { + CXXMethodDecl *MD = dyn_cast(Dcl); + + if (MD) { + CXXSpecialMember Member = getSpecialMember(MD); + if (Member == CXXInvalid) { + Diag(DefaultLoc, diag::err_default_special_members); + return; + } + + MD->setDefaulted(); + MD->setExplicitlyDefaulted(); + + // We'll check it when the record is done + if (MD == MD->getCanonicalDecl()) + return; + + switch (Member) { + case CXXDefaultConstructor: { + CXXConstructorDecl *CD = cast(MD); + CheckExplicitlyDefaultedDefaultConstructor(CD); + DefineImplicitDefaultConstructor(DefaultLoc, CD); + break; + } + default: + // FIXME: Do the rest once we have functions + break; + } + } else { + Diag(DefaultLoc, diag::err_default_special_members); + } +} + static void SearchForReturnInStmt(Sema &Self, Stmt *S) { for (Stmt::child_range CI = S->children(); CI; ++CI) { Stmt *SubStmt = *CI; -- 2.40.0