[cfe-commits] r131933 - in /cfe/trunk/lib: AST/Decl.cpp Parse/Parser.cpp Sema/SemaDeclCXX.cpp Sema/SemaTemplateInstantiateDecl.cpp
Nick Lewycky
nlewycky at google.com
Wed May 25 14:56:22 PDT 2011
On 23 May 2011 16:14, Sean Hunt <scshunt at csclub.uwaterloo.ca> wrote:
> Author: coppro
> Date: Mon May 23 18:14:04 2011
> New Revision: 131933
>
> URL: http://llvm.org/viewvc/llvm-project?rev=131933&view=rev
> Log:
> 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.
>
> Modified:
> cfe/trunk/lib/AST/Decl.cpp
> cfe/trunk/lib/Parse/Parser.cpp
> cfe/trunk/lib/Sema/SemaDeclCXX.cpp
> cfe/trunk/lib/Sema/SemaTemplateInstantiateDecl.cpp
>
> Modified: cfe/trunk/lib/AST/Decl.cpp
> URL:
> http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/AST/Decl.cpp?rev=131933&r1=131932&r2=131933&view=diff
>
> ==============================================================================
> --- cfe/trunk/lib/AST/Decl.cpp (original)
> +++ cfe/trunk/lib/AST/Decl.cpp Mon May 23 18:14:04 2011
> @@ -1438,7 +1438,7 @@
>
> bool FunctionDecl::isDefined(const FunctionDecl *&Definition) const {
> for (redecl_iterator I = redecls_begin(), E = redecls_end(); I != E; ++I)
> {
> - if (I->IsDeleted || I->Body || I->IsLateTemplateParsed) {
> + if (I->IsDeleted || I->IsDefaulted || I->Body ||
> I->IsLateTemplateParsed) {
> Definition = I->IsDeleted ? I->getCanonicalDecl() : *I;
> return true;
> }
>
> Modified: cfe/trunk/lib/Parse/Parser.cpp
> URL:
> http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Parse/Parser.cpp?rev=131933&r1=131932&r2=131933&view=diff
>
> ==============================================================================
> --- cfe/trunk/lib/Parse/Parser.cpp (original)
> +++ cfe/trunk/lib/Parse/Parser.cpp Mon May 23 18:14:04 2011
> @@ -832,78 +832,13 @@
> 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 @@
> return DP;
> }
>
> -
> // Enter a scope for the function body.
> ParseScope BodyScope(this, Scope::FnScope|Scope::DeclScope);
>
> @@ -972,6 +906,43 @@
> // 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);
>
>
> Modified: cfe/trunk/lib/Sema/SemaDeclCXX.cpp
> URL:
> http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaDeclCXX.cpp?rev=131933&r1=131932&r2=131933&view=diff
>
> ==============================================================================
> --- cfe/trunk/lib/Sema/SemaDeclCXX.cpp (original)
> +++ cfe/trunk/lib/Sema/SemaDeclCXX.cpp Mon May 23 18:14:04 2011
> @@ -6011,7 +6011,8 @@
> void Sema::DefineImplicitDefaultConstructor(SourceLocation
> CurrentLocation,
> CXXConstructorDecl
> *Constructor) {
> assert((Constructor->isDefaulted() && Constructor->isDefaultConstructor()
> &&
> - !Constructor->isUsed(false) && !Constructor->isDeleted()) &&
> + !Constructor->doesThisDeclarationHaveABody() &&
> + !Constructor->isDeleted()) &&
> "DefineImplicitDefaultConstructor - call it for implicit default
> ctor");
>
> CXXRecordDecl *ClassDecl = Constructor->getParent();
> @@ -6303,7 +6304,8 @@
>
> void Sema::DefineImplicitDestructor(SourceLocation CurrentLocation,
> CXXDestructorDecl *Destructor) {
> - assert((Destructor->isDefaulted() && !Destructor->isUsed(false)) &&
> + assert((Destructor->isDefaulted() &&
> + !Destructor->doesThisDeclarationHaveABody()) &&
> "DefineImplicitDestructor - call it for implicit default dtor");
> CXXRecordDecl *ClassDecl = Destructor->getParent();
> assert(ClassDecl && "DefineImplicitDestructor - invalid destructor");
> @@ -6750,7 +6752,7 @@
> assert((CopyAssignOperator->isDefaulted() &&
> CopyAssignOperator->isOverloadedOperator() &&
> CopyAssignOperator->getOverloadedOperator() == OO_Equal &&
> - !CopyAssignOperator->isUsed(false)) &&
> + !CopyAssignOperator->doesThisDeclarationHaveABody()) &&
> "DefineImplicitCopyAssignment called for wrong function");
>
> CXXRecordDecl *ClassDecl = CopyAssignOperator->getParent();
> @@ -7228,7 +7230,7 @@
> CXXConstructorDecl *CopyConstructor) {
> assert((CopyConstructor->isDefaulted() &&
> CopyConstructor->isCopyConstructor() &&
> - !CopyConstructor->isUsed(false)) &&
> + !CopyConstructor->doesThisDeclarationHaveABody()) &&
> "DefineImplicitCopyConstructor - call it for implicit copy ctor");
>
> CXXRecordDecl *ClassDecl = CopyConstructor->getParent();
> @@ -8673,8 +8675,15 @@
> MD->setDefaulted();
> MD->setExplicitlyDefaulted();
>
> - // We'll check it when the record is done
> - if (MD == MD->getCanonicalDecl())
> + // If this definition appears within the record, do the checking when
> + // the record is complete.
> + const FunctionDecl *Primary = MD;
> + if (MD->getTemplatedKind() != FunctionDecl::TK_NonTemplate)
> + // Find the uninstantiated declaration that actually had the '=
> default'
> + // on it.
> + MD->getTemplateInstantiationPattern()->isDefined(Primary);
> +
> + if (Primary == Primary->getCanonicalDecl())
> return;
>
> switch (Member) {
>
> Modified: cfe/trunk/lib/Sema/SemaTemplateInstantiateDecl.cpp
> URL:
> http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaTemplateInstantiateDecl.cpp?rev=131933&r1=131932&r2=131933&view=diff
>
> ==============================================================================
> --- cfe/trunk/lib/Sema/SemaTemplateInstantiateDecl.cpp (original)
> +++ cfe/trunk/lib/Sema/SemaTemplateInstantiateDecl.cpp Mon May 23 18:14:04
> 2011
> @@ -2320,6 +2320,9 @@
> Stmt *Pattern = 0;
> if (PatternDecl)
> Pattern = PatternDecl->getBody(PatternDecl);
> + if (!Pattern)
> + // Try to find a defaulted definition
> + PatternDecl->isDefined(PatternDecl);
>
> // Postpone late parsed template instantiations.
> if (PatternDecl && PatternDecl->isLateTemplateParsed() &&
> @@ -2337,7 +2340,7 @@
> Pattern = PatternDecl->getBody(PatternDecl);
> }
>
> - if (!Pattern) {
> + if (!Pattern && !PatternDecl->isDefaulted()) {
>
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.
Nick
> if (DefinitionRequired) {
> if (Function->getPrimaryTemplate())
> Diag(PointOfInstantiation,
> @@ -2432,21 +2435,29 @@
> MultiLevelTemplateArgumentList TemplateArgs =
> getTemplateInstantiationArgs(Function, 0, false, PatternDecl);
>
> - // If this is a constructor, instantiate the member initializers.
> - if (const CXXConstructorDecl *Ctor =
> - dyn_cast<CXXConstructorDecl>(PatternDecl)) {
> - InstantiateMemInitializers(cast<CXXConstructorDecl>(Function), Ctor,
> - TemplateArgs);
> - }
> + if (PatternDecl->isDefaulted()) {
> + ActOnFinishFunctionBody(Function, 0, /*IsInstantiation=*/true);
>
> - // Instantiate the function body.
> - StmtResult Body = SubstStmt(Pattern, TemplateArgs);
> + SetDeclDefaulted(Function, PatternDecl->getLocation());
>
> - if (Body.isInvalid())
> - Function->setInvalidDecl();
> -
> - ActOnFinishFunctionBody(Function, Body.get(),
> - /*IsInstantiation=*/true);
> + return;
> + } else {
> + // If this is a constructor, instantiate the member initializers.
> + if (const CXXConstructorDecl *Ctor =
> + dyn_cast<CXXConstructorDecl>(PatternDecl)) {
> + InstantiateMemInitializers(cast<CXXConstructorDecl>(Function), Ctor,
> + TemplateArgs);
> + }
> +
> + // Instantiate the function body.
> + StmtResult Body = SubstStmt(Pattern, TemplateArgs);
> +
> + if (Body.isInvalid())
> + Function->setInvalidDecl();
> +
> + ActOnFinishFunctionBody(Function, Body.get(),
> + /*IsInstantiation=*/true);
> + }
>
> PerformDependentDiagnostics(PatternDecl, TemplateArgs);
>
>
>
> _______________________________________________
> cfe-commits mailing list
> cfe-commits at cs.uiuc.edu
> http://lists.cs.uiuc.edu/mailman/listinfo/cfe-commits
>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.llvm.org/pipermail/cfe-commits/attachments/20110525/374d450a/attachment.html>
More information about the cfe-commits
mailing list