aboutsummaryrefslogtreecommitdiff
path: root/lib/Parse/Parser.cpp
diff options
context:
space:
mode:
authorSean Hunt <scshunt@csclub.uwaterloo.ca>2011-05-23 23:14:04 +0000
committerSean Hunt <scshunt@csclub.uwaterloo.ca>2011-05-23 23:14:04 +0000
commitcd10dec673680fd18a2e5a27646173780c059d32 (patch)
tree64c35ae79c23d4e5bd7172e1cbaa4798af93857c /lib/Parse/Parser.cpp
parente6a11a62d1d66d10a87d81ed697348d66d59adf7 (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.cpp107
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);