diff options
| author | Douglas Gregor <dgregor@apple.com> | 2011-11-07 20:56:01 +0000 | 
|---|---|---|
| committer | Douglas Gregor <dgregor@apple.com> | 2011-11-07 20:56:01 +0000 | 
| commit | 5d1b4e3d1f63a7761337cfc4535eb10d5ee3ec4a (patch) | |
| tree | 6f75dadf4870230820e1f48deb2d30fc04ccb9d9 /clang/lib | |
| parent | 7f076cb6cc537a1ef77bf2a16549394f03605d33 (diff) | |
| download | bcm5719-llvm-5d1b4e3d1f63a7761337cfc4535eb10d5ee3ec4a.tar.gz bcm5719-llvm-5d1b4e3d1f63a7761337cfc4535eb10d5ee3ec4a.zip  | |
When we notice that a member function is defined with "= delete" or "=
default", make a note of which is used when creating the
initial declaration. Previously, we would wait until later to handle
default/delete as a definition, but this is too late: when adding the
declaration, we already treated the declaration as "user-provided"
when in fact it was merely "user-declared".
Fixes PR10861 and PR10442, along with a bunch of FIXMEs.
llvm-svn: 144011
Diffstat (limited to 'clang/lib')
| -rw-r--r-- | clang/lib/AST/DeclCXX.cpp | 10 | ||||
| -rw-r--r-- | clang/lib/Parse/ParseCXXInlineMethods.cpp | 8 | ||||
| -rw-r--r-- | clang/lib/Parse/ParseDeclCXX.cpp | 16 | ||||
| -rw-r--r-- | clang/lib/Parse/Parser.cpp | 2 | ||||
| -rw-r--r-- | clang/lib/Sema/SemaDecl.cpp | 26 | ||||
| -rw-r--r-- | clang/lib/Sema/SemaTemplate.cpp | 2 | 
6 files changed, 42 insertions, 22 deletions
diff --git a/clang/lib/AST/DeclCXX.cpp b/clang/lib/AST/DeclCXX.cpp index b8c20e4b06d..b86cf281188 100644 --- a/clang/lib/AST/DeclCXX.cpp +++ b/clang/lib/AST/DeclCXX.cpp @@ -451,8 +451,7 @@ void CXXRecordDecl::addedMember(Decl *D) {        //    -- class X has no virtual functions [...]        data().HasTrivialCopyAssignment = false;        data().HasTrivialMoveAssignment = false; -      // FIXME: Destructor? - +                    // C++0x [class]p7:        //   A standard-layout class is a class that: [...]        //    -- has no virtual functions @@ -574,9 +573,10 @@ NotASpecialMember:;      // This bit is the C++03 POD bit, not the 0x one.      data().PlainOldData = false; -    // C++0x [class.dtor]p5:  -    //   A destructor is trivial if it is not user-provided and [...] -    if (DD->isUserProvided()) +    // C++11 [class.dtor]p5:  +    //   A destructor is trivial if it is not user-provided and if +    //    -- the destructor is not virtual. +    if (DD->isUserProvided() || DD->isVirtual())        data().HasTrivialDestructor = false;      return; diff --git a/clang/lib/Parse/ParseCXXInlineMethods.cpp b/clang/lib/Parse/ParseCXXInlineMethods.cpp index 04c05d0cc38..65f7f56fe93 100644 --- a/clang/lib/Parse/ParseCXXInlineMethods.cpp +++ b/clang/lib/Parse/ParseCXXInlineMethods.cpp @@ -24,8 +24,10 @@ using namespace clang;  Decl *Parser::ParseCXXInlineMethodDef(AccessSpecifier AS,                                        AttributeList *AccessAttrs,                                        ParsingDeclarator &D, -                                const ParsedTemplateInfo &TemplateInfo, -                                const VirtSpecifiers& VS, ExprResult& Init) { +                                      const ParsedTemplateInfo &TemplateInfo, +                                      const VirtSpecifiers& VS,  +                                      FunctionDefinitionKind DefinitionKind, +                                      ExprResult& Init) {    assert(D.isFunctionDeclarator() && "This isn't a function declarator!");    assert((Tok.is(tok::l_brace) || Tok.is(tok::colon) || Tok.is(tok::kw_try) ||            Tok.is(tok::equal)) && @@ -36,7 +38,7 @@ Decl *Parser::ParseCXXInlineMethodDef(AccessSpecifier AS,            TemplateInfo.TemplateParams ? TemplateInfo.TemplateParams->size() : 0);    Decl *FnD; -  D.setFunctionDefinition(true); +  D.setFunctionDefinitionKind(DefinitionKind);    if (D.getDeclSpec().isFriendSpecified())      FnD = Actions.ActOnFriendFunctionDecl(getCurScope(), D,                                            move(TemplateParams)); diff --git a/clang/lib/Parse/ParseDeclCXX.cpp b/clang/lib/Parse/ParseDeclCXX.cpp index 721d185f539..04c94a053d6 100644 --- a/clang/lib/Parse/ParseDeclCXX.cpp +++ b/clang/lib/Parse/ParseDeclCXX.cpp @@ -1779,25 +1779,27 @@ void Parser::ParseCXXClassMemberDeclaration(AccessSpecifier AS,          HasInitializer = true;      } -    bool IsDefinition = false; +    FunctionDefinitionKind DefinitionKind = FDK_Declaration;      // function-definition:      //      // In C++11, a non-function declarator followed by an open brace is a      // braced-init-list for an in-class member initialization, not an      // erroneous function definition.      if (Tok.is(tok::l_brace) && !getLang().CPlusPlus0x) { -      IsDefinition = true; +      DefinitionKind = FDK_Definition;      } else if (DeclaratorInfo.isFunctionDeclarator()) {        if (Tok.is(tok::l_brace) || Tok.is(tok::colon) || Tok.is(tok::kw_try)) { -        IsDefinition = true; +        DefinitionKind = FDK_Definition;        } else if (Tok.is(tok::equal)) {          const Token &KW = NextToken(); -        if (KW.is(tok::kw_default) || KW.is(tok::kw_delete)) -          IsDefinition = true; +        if (KW.is(tok::kw_default)) +          DefinitionKind = FDK_Defaulted; +        else if (KW.is(tok::kw_delete)) +          DefinitionKind = FDK_Deleted;        }      } -    if (IsDefinition) { +    if (DefinitionKind) {        if (!DeclaratorInfo.isFunctionDeclarator()) {          Diag(Tok, diag::err_func_def_no_params);          ConsumeBrace(); @@ -1825,7 +1827,7 @@ void Parser::ParseCXXClassMemberDeclaration(AccessSpecifier AS,        Decl *FunDecl =          ParseCXXInlineMethodDef(AS, AccessAttrs, DeclaratorInfo, TemplateInfo, -                                VS, Init); +                                VS, DefinitionKind, Init);        for (unsigned i = 0, ni = LateParsedAttrs.size(); i < ni; ++i) {          LateParsedAttrs[i]->setDecl(FunDecl); diff --git a/clang/lib/Parse/Parser.cpp b/clang/lib/Parse/Parser.cpp index 6e84e429684..b4d41ef4823 100644 --- a/clang/lib/Parse/Parser.cpp +++ b/clang/lib/Parse/Parser.cpp @@ -876,7 +876,7 @@ Decl *Parser::ParseFunctionDefinition(ParsingDeclarator &D,      ParseScope BodyScope(this, Scope::FnScope|Scope::DeclScope);      Scope *ParentScope = getCurScope()->getParent(); -    D.setFunctionDefinition(true); +    D.setFunctionDefinitionKind(FDK_Definition);      Decl *DP = Actions.HandleDeclarator(ParentScope, D,                                          move(TemplateParameterLists));      D.complete(DP); diff --git a/clang/lib/Sema/SemaDecl.cpp b/clang/lib/Sema/SemaDecl.cpp index 05f48707aa2..d71cd5f7d54 100644 --- a/clang/lib/Sema/SemaDecl.cpp +++ b/clang/lib/Sema/SemaDecl.cpp @@ -3145,7 +3145,7 @@ static bool RebuildDeclaratorInCurrentInstantiation(Sema &S, Declarator &D,  }  Decl *Sema::ActOnDeclarator(Scope *S, Declarator &D) { -  D.setFunctionDefinition(false); +  D.setFunctionDefinitionKind(FDK_Declaration);    return HandleDeclarator(S, D, MultiTemplateParamsArg(*this));  } @@ -4803,7 +4803,7 @@ Sema::ActOnFunctionDeclarator(Scope *S, Declarator &D, DeclContext *DC,      // scope specifier, or is the object of a friend declaration, the      // lexical context will be different from the semantic context.      NewFD->setLexicalDeclContext(CurContext); -     +              // Match up the template parameter lists with the scope specifier, then      // determine whether we have a template or a template specialization.      bool Invalid = false; @@ -4995,10 +4995,26 @@ Sema::ActOnFunctionDeclarator(Scope *S, Declarator &D, DeclContext *DC,        NewFD->setAccess(AS_public);      } +    // If a function is defined as defaulted or deleted, mark it as such now. +    switch (D.getFunctionDefinitionKind()) { +      case FDK_Declaration: +      case FDK_Definition: +        break; +         +      case FDK_Defaulted: +        NewFD->setDefaulted(); +        break; +         +      case FDK_Deleted: +        NewFD->setDeletedAsWritten(); +        break; +    } +      if (isa<CXXMethodDecl>(NewFD) && DC == CurContext &&          D.isFunctionDefinition()) { -      // A method is implicitly inline if it's defined in its class -      // definition. +      // C++ [class.mfct]p2: +      //   A member function may be defined (8.4) in its class definition, in  +      //   which case it is an inline member function (7.1.2)        NewFD->setImplicitlyInline();      } @@ -6885,7 +6901,7 @@ Decl *Sema::ActOnStartOfFunctionDef(Scope *FnBodyScope,    assert(D.isFunctionDeclarator() && "Not a function declarator!");    Scope *ParentScope = FnBodyScope->getParent(); -  D.setFunctionDefinition(true); +  D.setFunctionDefinitionKind(FDK_Definition);    Decl *DP = HandleDeclarator(ParentScope, D,                                MultiTemplateParamsArg(*this));    return ActOnStartOfFunctionDef(FnBodyScope, DP); diff --git a/clang/lib/Sema/SemaTemplate.cpp b/clang/lib/Sema/SemaTemplate.cpp index 2d7e85094aa..8ec4c195f91 100644 --- a/clang/lib/Sema/SemaTemplate.cpp +++ b/clang/lib/Sema/SemaTemplate.cpp @@ -5219,7 +5219,7 @@ Decl *Sema::ActOnStartOfFunctionTemplateDef(Scope *FnBodyScope,    Scope *ParentScope = FnBodyScope->getParent(); -  D.setFunctionDefinition(true); +  D.setFunctionDefinitionKind(FDK_Definition);    Decl *DP = HandleDeclarator(ParentScope, D,                                move(TemplateParameterLists));    if (FunctionTemplateDecl *FunctionTemplate  | 

