[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