<div class="gmail_quote">On 23 May 2011 16:14, Sean Hunt <span dir="ltr"><<a href="mailto:scshunt@csclub.uwaterloo.ca">scshunt@csclub.uwaterloo.ca</a>></span> wrote:<br><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex;">
Author: coppro<br>
Date: Mon May 23 18:14:04 2011<br>
New Revision: 131933<br>
<br>
URL: <a href="http://llvm.org/viewvc/llvm-project?rev=131933&view=rev" target="_blank">http://llvm.org/viewvc/llvm-project?rev=131933&view=rev</a><br>
Log:<br>
Implement explicit specialization of explicitly-defaulted constructors.<br>
The general out-of-line case (including explicit instantiation mostly<br>
works except that the definition is being lost somewhere between the AST<br>
and CodeGen, so the definition is never emitted.<br>
<br>
Modified:<br>
cfe/trunk/lib/AST/Decl.cpp<br>
cfe/trunk/lib/Parse/Parser.cpp<br>
cfe/trunk/lib/Sema/SemaDeclCXX.cpp<br>
cfe/trunk/lib/Sema/SemaTemplateInstantiateDecl.cpp<br>
<br>
Modified: cfe/trunk/lib/AST/Decl.cpp<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/AST/Decl.cpp?rev=131933&r1=131932&r2=131933&view=diff" target="_blank">http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/AST/Decl.cpp?rev=131933&r1=131932&r2=131933&view=diff</a><br>
==============================================================================<br>
--- cfe/trunk/lib/AST/Decl.cpp (original)<br>
+++ cfe/trunk/lib/AST/Decl.cpp Mon May 23 18:14:04 2011<br>
@@ -1438,7 +1438,7 @@<br>
<br>
bool FunctionDecl::isDefined(const FunctionDecl *&Definition) const {<br>
for (redecl_iterator I = redecls_begin(), E = redecls_end(); I != E; ++I) {<br>
- if (I->IsDeleted || I->Body || I->IsLateTemplateParsed) {<br>
+ if (I->IsDeleted || I->IsDefaulted || I->Body || I->IsLateTemplateParsed) {<br>
Definition = I->IsDeleted ? I->getCanonicalDecl() : *I;<br>
return true;<br>
}<br>
<br>
Modified: cfe/trunk/lib/Parse/Parser.cpp<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Parse/Parser.cpp?rev=131933&r1=131932&r2=131933&view=diff" target="_blank">http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Parse/Parser.cpp?rev=131933&r1=131932&r2=131933&view=diff</a><br>
==============================================================================<br>
--- cfe/trunk/lib/Parse/Parser.cpp (original)<br>
+++ cfe/trunk/lib/Parse/Parser.cpp Mon May 23 18:14:04 2011<br>
@@ -832,78 +832,13 @@<br>
if (FTI.isKNRPrototype())<br>
ParseKNRParamDeclarations(D);<br>
<br>
- if (Tok.is(tok::equal)) {<br>
- assert(getLang().CPlusPlus && "Only C++ function definitions have '='");<br>
- ConsumeToken();<br>
-<br>
- Decl *Decl = 0;<br>
- // Here we complete the declaration as if it were normal<br>
- switch (TemplateInfo.Kind) {<br>
- case ParsedTemplateInfo::NonTemplate:<br>
- Decl = Actions.ActOnDeclarator(getCurScope(), D, true);<br>
- break;<br>
-<br>
- case ParsedTemplateInfo::Template:<br>
- case ParsedTemplateInfo::ExplicitSpecialization:<br>
- Decl = Actions.ActOnTemplateDeclarator(getCurScope(),<br>
- MultiTemplateParamsArg(Actions,<br>
- TemplateInfo.TemplateParams->data(),<br>
- TemplateInfo.TemplateParams->size()),<br>
- D);<br>
- break;<br>
-<br>
- case ParsedTemplateInfo::ExplicitInstantiation: {<br>
- DeclResult Result<br>
- = Actions.ActOnExplicitInstantiation(getCurScope(),<br>
- TemplateInfo.ExternLoc,<br>
- TemplateInfo.TemplateLoc,<br>
- D);<br>
- if (Result.isInvalid()) {<br>
- SkipUntil(tok::semi);<br>
- return 0;<br>
- }<br>
-<br>
- Decl = Result.get();<br>
- break;<br>
- }<br>
- }<br>
-<br>
- bool Delete = false;<br>
- SourceLocation KWLoc;<br>
- if (Tok.is(tok::kw_delete)) {<br>
- if (!getLang().CPlusPlus0x)<br>
- Diag(Tok, diag::warn_deleted_function_accepted_as_extension);<br>
-<br>
- KWLoc = ConsumeToken();<br>
- Actions.SetDeclDeleted(Decl, KWLoc);<br>
- Delete = true;<br>
- } else if (Tok.is(tok::kw_default)) {<br>
- if (!getLang().CPlusPlus0x)<br>
- Diag(Tok, diag::warn_defaulted_function_accepted_as_extension);<br>
-<br>
- KWLoc = ConsumeToken();<br>
- Actions.SetDeclDefaulted(Decl, KWLoc);<br>
- } else {<br>
- llvm_unreachable("function definition after = not 'delete' or 'default'");<br>
- }<br>
-<br>
- if (Tok.is(tok::comma)) {<br>
- Diag(KWLoc, diag::err_default_delete_in_multiple_declaration)<br>
- << Delete;<br>
- SkipUntil(tok::semi);<br>
- } else {<br>
- ExpectAndConsume(tok::semi, diag::err_expected_semi_after,<br>
- Delete ? "delete" : "default", tok::semi);<br>
- }<br>
-<br>
- return Decl;<br>
- }<br>
<br>
// We should have either an opening brace or, in a C++ constructor,<br>
// we may have a colon.<br>
if (Tok.isNot(tok::l_brace) &&<br>
(!getLang().CPlusPlus ||<br>
- (Tok.isNot(tok::colon) && Tok.isNot(tok::kw_try)))) {<br>
+ (Tok.isNot(tok::colon) && Tok.isNot(tok::kw_try) &&<br>
+ Tok.isNot(tok::equal)))) {<br>
Diag(Tok, diag::err_expected_fn_body);<br>
<br>
// Skip over garbage, until we get to '{'. Don't eat the '{'.<br>
@@ -951,7 +886,6 @@<br>
return DP;<br>
}<br>
<br>
-<br>
// Enter a scope for the function body.<br>
ParseScope BodyScope(this, Scope::FnScope|Scope::DeclScope);<br>
<br>
@@ -972,6 +906,43 @@<br>
// safe because we're always the sole owner.<br>
D.getMutableDeclSpec().abort();<br>
<br>
+ if (Tok.is(tok::equal)) {<br>
+ assert(getLang().CPlusPlus && "Only C++ function definitions have '='");<br>
+ ConsumeToken();<br>
+<br>
+ Actions.ActOnFinishFunctionBody(Res, 0, false);<br>
+<br>
+ bool Delete = false;<br>
+ SourceLocation KWLoc;<br>
+ if (Tok.is(tok::kw_delete)) {<br>
+ if (!getLang().CPlusPlus0x)<br>
+ Diag(Tok, diag::warn_deleted_function_accepted_as_extension);<br>
+<br>
+ KWLoc = ConsumeToken();<br>
+ Actions.SetDeclDeleted(Res, KWLoc);<br>
+ Delete = true;<br>
+ } else if (Tok.is(tok::kw_default)) {<br>
+ if (!getLang().CPlusPlus0x)<br>
+ Diag(Tok, diag::warn_defaulted_function_accepted_as_extension);<br>
+<br>
+ KWLoc = ConsumeToken();<br>
+ Actions.SetDeclDefaulted(Res, KWLoc);<br>
+ } else {<br>
+ llvm_unreachable("function definition after = not 'delete' or 'default'");<br>
+ }<br>
+<br>
+ if (Tok.is(tok::comma)) {<br>
+ Diag(KWLoc, diag::err_default_delete_in_multiple_declaration)<br>
+ << Delete;<br>
+ SkipUntil(tok::semi);<br>
+ } else {<br>
+ ExpectAndConsume(tok::semi, diag::err_expected_semi_after,<br>
+ Delete ? "delete" : "default", tok::semi);<br>
+ }<br>
+<br>
+ return Res;<br>
+ }<br>
+<br>
if (Tok.is(tok::kw_try))<br>
return ParseFunctionTryBlock(Res, BodyScope);<br>
<br>
<br>
Modified: cfe/trunk/lib/Sema/SemaDeclCXX.cpp<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaDeclCXX.cpp?rev=131933&r1=131932&r2=131933&view=diff" target="_blank">http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaDeclCXX.cpp?rev=131933&r1=131932&r2=131933&view=diff</a><br>
==============================================================================<br>
--- cfe/trunk/lib/Sema/SemaDeclCXX.cpp (original)<br>
+++ cfe/trunk/lib/Sema/SemaDeclCXX.cpp Mon May 23 18:14:04 2011<br>
@@ -6011,7 +6011,8 @@<br>
void Sema::DefineImplicitDefaultConstructor(SourceLocation CurrentLocation,<br>
CXXConstructorDecl *Constructor) {<br>
assert((Constructor->isDefaulted() && Constructor->isDefaultConstructor() &&<br>
- !Constructor->isUsed(false) && !Constructor->isDeleted()) &&<br>
+ !Constructor->doesThisDeclarationHaveABody() &&<br>
+ !Constructor->isDeleted()) &&<br>
"DefineImplicitDefaultConstructor - call it for implicit default ctor");<br>
<br>
CXXRecordDecl *ClassDecl = Constructor->getParent();<br>
@@ -6303,7 +6304,8 @@<br>
<br>
void Sema::DefineImplicitDestructor(SourceLocation CurrentLocation,<br>
CXXDestructorDecl *Destructor) {<br>
- assert((Destructor->isDefaulted() && !Destructor->isUsed(false)) &&<br>
+ assert((Destructor->isDefaulted() &&<br>
+ !Destructor->doesThisDeclarationHaveABody()) &&<br>
"DefineImplicitDestructor - call it for implicit default dtor");<br>
CXXRecordDecl *ClassDecl = Destructor->getParent();<br>
assert(ClassDecl && "DefineImplicitDestructor - invalid destructor");<br>
@@ -6750,7 +6752,7 @@<br>
assert((CopyAssignOperator->isDefaulted() &&<br>
CopyAssignOperator->isOverloadedOperator() &&<br>
CopyAssignOperator->getOverloadedOperator() == OO_Equal &&<br>
- !CopyAssignOperator->isUsed(false)) &&<br>
+ !CopyAssignOperator->doesThisDeclarationHaveABody()) &&<br>
"DefineImplicitCopyAssignment called for wrong function");<br>
<br>
CXXRecordDecl *ClassDecl = CopyAssignOperator->getParent();<br>
@@ -7228,7 +7230,7 @@<br>
CXXConstructorDecl *CopyConstructor) {<br>
assert((CopyConstructor->isDefaulted() &&<br>
CopyConstructor->isCopyConstructor() &&<br>
- !CopyConstructor->isUsed(false)) &&<br>
+ !CopyConstructor->doesThisDeclarationHaveABody()) &&<br>
"DefineImplicitCopyConstructor - call it for implicit copy ctor");<br>
<br>
CXXRecordDecl *ClassDecl = CopyConstructor->getParent();<br>
@@ -8673,8 +8675,15 @@<br>
MD->setDefaulted();<br>
MD->setExplicitlyDefaulted();<br>
<br>
- // We'll check it when the record is done<br>
- if (MD == MD->getCanonicalDecl())<br>
+ // If this definition appears within the record, do the checking when<br>
+ // the record is complete.<br>
+ const FunctionDecl *Primary = MD;<br>
+ if (MD->getTemplatedKind() != FunctionDecl::TK_NonTemplate)<br>
+ // Find the uninstantiated declaration that actually had the '= default'<br>
+ // on it.<br>
+ MD->getTemplateInstantiationPattern()->isDefined(Primary);<br>
+<br>
+ if (Primary == Primary->getCanonicalDecl())<br>
return;<br>
<br>
switch (Member) {<br>
<br>
Modified: cfe/trunk/lib/Sema/SemaTemplateInstantiateDecl.cpp<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaTemplateInstantiateDecl.cpp?rev=131933&r1=131932&r2=131933&view=diff" target="_blank">http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaTemplateInstantiateDecl.cpp?rev=131933&r1=131932&r2=131933&view=diff</a><br>
==============================================================================<br>
--- cfe/trunk/lib/Sema/SemaTemplateInstantiateDecl.cpp (original)<br>
+++ cfe/trunk/lib/Sema/SemaTemplateInstantiateDecl.cpp Mon May 23 18:14:04 2011<br>
@@ -2320,6 +2320,9 @@<br>
Stmt *Pattern = 0;<br>
if (PatternDecl)<br>
Pattern = PatternDecl->getBody(PatternDecl);<br>
+ if (!Pattern)<br>
+ // Try to find a defaulted definition<br>
+ PatternDecl->isDefined(PatternDecl);<br>
<br>
// Postpone late parsed template instantiations.<br>
if (PatternDecl && PatternDecl->isLateTemplateParsed() &&<br>
@@ -2337,7 +2340,7 @@<br>
Pattern = PatternDecl->getBody(PatternDecl);<br>
}<br>
<br>
- if (!Pattern) {<br>
+ if (!Pattern && !PatternDecl->isDefaulted()) {<br></blockquote><div><br></div><div>This breaks IWYU where Pattern is not NULL but PatternDecl is. Did you mean "if (!Pattern && PatternDecl && ...)" like the code above it? Note that there's an if (PatternDecl) inside the if-body.</div>
<div><br></div><div>Nick</div><div> </div><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex;">
if (DefinitionRequired) {<br>
if (Function->getPrimaryTemplate())<br>
Diag(PointOfInstantiation,<br>
@@ -2432,21 +2435,29 @@<br>
MultiLevelTemplateArgumentList TemplateArgs =<br>
getTemplateInstantiationArgs(Function, 0, false, PatternDecl);<br>
<br>
- // If this is a constructor, instantiate the member initializers.<br>
- if (const CXXConstructorDecl *Ctor =<br>
- dyn_cast<CXXConstructorDecl>(PatternDecl)) {<br>
- InstantiateMemInitializers(cast<CXXConstructorDecl>(Function), Ctor,<br>
- TemplateArgs);<br>
- }<br>
+ if (PatternDecl->isDefaulted()) {<br>
+ ActOnFinishFunctionBody(Function, 0, /*IsInstantiation=*/true);<br>
<br>
- // Instantiate the function body.<br>
- StmtResult Body = SubstStmt(Pattern, TemplateArgs);<br>
+ SetDeclDefaulted(Function, PatternDecl->getLocation());<br>
<br>
- if (Body.isInvalid())<br>
- Function->setInvalidDecl();<br>
-<br>
- ActOnFinishFunctionBody(Function, Body.get(),<br>
- /*IsInstantiation=*/true);<br>
+ return;<br>
+ } else {<br>
+ // If this is a constructor, instantiate the member initializers.<br>
+ if (const CXXConstructorDecl *Ctor =<br>
+ dyn_cast<CXXConstructorDecl>(PatternDecl)) {<br>
+ InstantiateMemInitializers(cast<CXXConstructorDecl>(Function), Ctor,<br>
+ TemplateArgs);<br>
+ }<br>
+<br>
+ // Instantiate the function body.<br>
+ StmtResult Body = SubstStmt(Pattern, TemplateArgs);<br>
+<br>
+ if (Body.isInvalid())<br>
+ Function->setInvalidDecl();<br>
+<br>
+ ActOnFinishFunctionBody(Function, Body.get(),<br>
+ /*IsInstantiation=*/true);<br>
+ }<br>
<br>
PerformDependentDiagnostics(PatternDecl, TemplateArgs);<br>
<br>
<br>
<br>
_______________________________________________<br>
cfe-commits mailing list<br>
<a href="mailto:cfe-commits@cs.uiuc.edu">cfe-commits@cs.uiuc.edu</a><br>
<a href="http://lists.cs.uiuc.edu/mailman/listinfo/cfe-commits" target="_blank">http://lists.cs.uiuc.edu/mailman/listinfo/cfe-commits</a><br>
</blockquote></div><br>