diff options
author | Sean Hunt <scshunt@csclub.uwaterloo.ca> | 2011-05-23 23:14:04 +0000 |
---|---|---|
committer | Sean Hunt <scshunt@csclub.uwaterloo.ca> | 2011-05-23 23:14:04 +0000 |
commit | cd10dec673680fd18a2e5a27646173780c059d32 (patch) | |
tree | 64c35ae79c23d4e5bd7172e1cbaa4798af93857c /lib/Parse/Parser.cpp | |
parent | e6a11a62d1d66d10a87d81ed697348d66d59adf7 (diff) |
Implement explicit specialization of explicitly-defaulted constructors.
The general out-of-line case (including explicit instantiation mostly
works except that the definition is being lost somewhere between the AST
and CodeGen, so the definition is never emitted.
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@131933 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'lib/Parse/Parser.cpp')
-rw-r--r-- | lib/Parse/Parser.cpp | 107 |
1 files changed, 39 insertions, 68 deletions
diff --git a/lib/Parse/Parser.cpp b/lib/Parse/Parser.cpp index 4e4819e9fc..a706f439a1 100644 --- a/lib/Parse/Parser.cpp +++ b/lib/Parse/Parser.cpp @@ -832,78 +832,13 @@ 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) && (!getLang().CPlusPlus || - (Tok.isNot(tok::colon) && Tok.isNot(tok::kw_try)))) { + (Tok.isNot(tok::colon) && Tok.isNot(tok::kw_try) && + Tok.isNot(tok::equal)))) { Diag(Tok, diag::err_expected_fn_body); // Skip over garbage, until we get to '{'. Don't eat the '{'. @@ -951,7 +886,6 @@ Decl *Parser::ParseFunctionDefinition(ParsingDeclarator &D, return DP; } - // Enter a scope for the function body. ParseScope BodyScope(this, Scope::FnScope|Scope::DeclScope); @@ -972,6 +906,43 @@ Decl *Parser::ParseFunctionDefinition(ParsingDeclarator &D, // safe because we're always the sole owner. D.getMutableDeclSpec().abort(); + if (Tok.is(tok::equal)) { + assert(getLang().CPlusPlus && "Only C++ function definitions have '='"); + ConsumeToken(); + + Actions.ActOnFinishFunctionBody(Res, 0, false); + + 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(Res, 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(Res, 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 Res; + } + if (Tok.is(tok::kw_try)) return ParseFunctionTryBlock(Res, BodyScope); |