diff options
| author | John McCall <rjmccall@apple.com> | 2009-08-06 02:15:43 +0000 | 
|---|---|---|
| committer | John McCall <rjmccall@apple.com> | 2009-08-06 02:15:43 +0000 | 
| commit | 07e91c04ba33974b00e91c4b468d61d7f0f5a238 (patch) | |
| tree | 8ba331aae7bcf0dfdf382b4db58b626ca25b1d3e /clang/lib/Parse | |
| parent | 51eeb36c8c62a07af8eea94303cb8a9dd77b14da (diff) | |
| download | bcm5719-llvm-07e91c04ba33974b00e91c4b468d61d7f0f5a238.tar.gz bcm5719-llvm-07e91c04ba33974b00e91c4b468d61d7f0f5a238.zip  | |
First pass at friend semantics.
llvm-svn: 78274
Diffstat (limited to 'clang/lib/Parse')
| -rw-r--r-- | clang/lib/Parse/DeclSpec.cpp | 18 | ||||
| -rw-r--r-- | clang/lib/Parse/ParseCXXInlineMethods.cpp | 6 | ||||
| -rw-r--r-- | clang/lib/Parse/ParseDecl.cpp | 11 | ||||
| -rw-r--r-- | clang/lib/Parse/ParseDeclCXX.cpp | 52 | 
4 files changed, 56 insertions, 31 deletions
diff --git a/clang/lib/Parse/DeclSpec.cpp b/clang/lib/Parse/DeclSpec.cpp index 80078660b65..674164a2604 100644 --- a/clang/lib/Parse/DeclSpec.cpp +++ b/clang/lib/Parse/DeclSpec.cpp @@ -398,6 +398,24 @@ void DeclSpec::Finish(Diagnostic &D, Preprocessor &PP) {      }    } +  // C++ [class.friend]p6: +  //   No storage-class-specifier shall appear in the decl-specifier-seq +  //   of a friend declaration. +  if (isFriendSpecified() && getStorageClassSpec()) { +    DeclSpec::SCS SC = getStorageClassSpec(); +    const char *SpecName = getSpecifierName(SC); + +    SourceLocation SCLoc = getStorageClassSpecLoc(); +    SourceLocation SCEndLoc = SCLoc.getFileLocWithOffset(strlen(SpecName)); + +    Diag(D, SCLoc, SrcMgr, diag::err_friend_storage_spec) +      << SpecName +      << CodeModificationHint::CreateRemoval(SourceRange(SCLoc, SCEndLoc)); + +    ClearStorageClassSpecs(); +  } + +    // Okay, now we can infer the real type.    // TODO: return "auto function" and other bad things based on the real type. diff --git a/clang/lib/Parse/ParseCXXInlineMethods.cpp b/clang/lib/Parse/ParseCXXInlineMethods.cpp index 8afffe3815e..52a812d4ba1 100644 --- a/clang/lib/Parse/ParseCXXInlineMethods.cpp +++ b/clang/lib/Parse/ParseCXXInlineMethods.cpp @@ -27,7 +27,11 @@ Parser::ParseCXXInlineMethodDef(AccessSpecifier AS, Declarator &D) {    assert((Tok.is(tok::l_brace) || Tok.is(tok::colon) || Tok.is(tok::kw_try)) &&           "Current token not a '{', ':' or 'try'!"); -  DeclPtrTy FnD = Actions.ActOnCXXMemberDeclarator(CurScope, AS, D, 0, 0); +  DeclPtrTy FnD; +  if (D.getDeclSpec().isFriendSpecified()) +    FnD = Actions.ActOnFriendDecl(CurScope, &D); +  else +    FnD = Actions.ActOnCXXMemberDeclarator(CurScope, AS, D, 0, 0);    HandleMemberFunctionDefaultArgs(D, FnD); diff --git a/clang/lib/Parse/ParseDecl.cpp b/clang/lib/Parse/ParseDecl.cpp index 42ef7e6c290..a80f57c8ca2 100644 --- a/clang/lib/Parse/ParseDecl.cpp +++ b/clang/lib/Parse/ParseDecl.cpp @@ -708,7 +708,8 @@ bool Parser::ParseImplicitInt(DeclSpec &DS, CXXScopeSpec *SS,  ///  void Parser::ParseDeclarationSpecifiers(DeclSpec &DS,                                          const ParsedTemplateInfo &TemplateInfo, -                                        AccessSpecifier AS) { +                                        AccessSpecifier AS, +                                        DeclSpecContext DSContext) {    DS.SetRangeStart(Tok.getLocation());    while (1) {      bool isInvalid = false; @@ -968,7 +969,13 @@ void Parser::ParseDeclarationSpecifiers(DeclSpec &DS,      // friend      case tok::kw_friend: -      isInvalid = DS.SetFriendSpec(Loc, PrevSpec, DiagID); +      if (DSContext == DSC_class) +        isInvalid = DS.SetFriendSpec(Loc, PrevSpec, DiagID); +      else { +        PrevSpec = ""; // not actually used by the diagnostic +        DiagID = diag::err_friend_invalid_in_context; +        isInvalid = true; +      }        break;      // type-specifier diff --git a/clang/lib/Parse/ParseDeclCXX.cpp b/clang/lib/Parse/ParseDeclCXX.cpp index c0df8a59f7e..5084d8a8315 100644 --- a/clang/lib/Parse/ParseDeclCXX.cpp +++ b/clang/lib/Parse/ParseDeclCXX.cpp @@ -567,15 +567,16 @@ void Parser::ParseClassSpecifier(tok::TokenKind TagTokKind,      }    } -  // There are three options here.  If we have 'struct foo;', then -  // this is a forward declaration.  If we have 'struct foo {...' or +  // There are four options here.  If we have 'struct foo;', then this +  // is either a forward declaration or a friend declaration, which +  // have to be treated differently.  If we have 'struct foo {...' or    // 'struct foo :...' then this is a definition. Otherwise we have    // something like 'struct foo xyz', a reference.    Action::TagUseKind TUK;    if (Tok.is(tok::l_brace) || (getLang().CPlusPlus && Tok.is(tok::colon)))      TUK = Action::TUK_Definition; -  else if (Tok.is(tok::semi) && !DS.isFriendSpecified()) -    TUK = Action::TUK_Declaration; +  else if (Tok.is(tok::semi)) +    TUK = DS.isFriendSpecified() ? Action::TUK_Friend : Action::TUK_Declaration;    else      TUK = Action::TUK_Reference; @@ -600,7 +601,7 @@ void Parser::ParseClassSpecifier(tok::TokenKind TagTokKind,    // to turn that template-id into a type.    bool Owned = false; -  if (TemplateId && TUK != Action::TUK_Reference) { +  if (TemplateId && TUK != Action::TUK_Reference && TUK != Action::TUK_Friend) {      // Explicit specialization, class template partial specialization,      // or explicit instantiation.      ASTTemplateArgsPtr TemplateArgsPtr(Actions,  @@ -727,10 +728,6 @@ void Parser::ParseClassSpecifier(tok::TokenKind TagTokKind,    if (DS.SetTypeSpecType(TagType, StartLoc, PrevSpec, DiagID,                           TagOrTempResult.get().getAs<void>(), Owned))      Diag(StartLoc, DiagID) << PrevSpec; -   -  if (DS.isFriendSpecified()) -    Actions.ActOnFriendDecl(CurScope, DS.getFriendSpecLoc(),  -                            TagOrTempResult.get());  }  /// ParseBaseClause - Parse the base-clause of a C++ class [C++ class.derived].  @@ -951,24 +948,17 @@ void Parser::ParseCXXClassMemberDeclaration(AccessSpecifier AS) {    // decl-specifier-seq:    // Parse the common declaration-specifiers piece.    DeclSpec DS; -  ParseDeclarationSpecifiers(DS, ParsedTemplateInfo(), AS); +  ParseDeclarationSpecifiers(DS, ParsedTemplateInfo(), AS, DSC_class);    if (Tok.is(tok::semi)) {      ConsumeToken(); -    // C++ 9.2p7: The member-declarator-list can be omitted only after a -    // class-specifier or an enum-specifier or in a friend declaration. -    // FIXME: Friend declarations. -    switch (DS.getTypeSpecType()) { -    case DeclSpec::TST_struct: -    case DeclSpec::TST_union: -    case DeclSpec::TST_class: -    case DeclSpec::TST_enum: + +    if (DS.isFriendSpecified()) +      Actions.ActOnFriendDecl(CurScope, &DS); +    else        Actions.ParsedFreeStandingDeclSpec(CurScope, DS); -      return; -    default: -      Diag(DSStart, diag::err_no_declarators); -      return; -    } + +    return;    }    Declarator DeclaratorInfo(DS, Declarator::MemberContext); @@ -1066,11 +1056,17 @@ void Parser::ParseCXXClassMemberDeclaration(AccessSpecifier AS) {      // NOTE: If Sema is the Action module and declarator is an instance field,      // this call will *not* return the created decl; It will return null.      // See Sema::ActOnCXXMemberDeclarator for details. -    DeclPtrTy ThisDecl = Actions.ActOnCXXMemberDeclarator(CurScope, AS, -                                                          DeclaratorInfo, -                                                          BitfieldSize.release(), -                                                          Init.release(), -                                                          Deleted); + +    DeclPtrTy ThisDecl; +    if (DS.isFriendSpecified()) { +      // TODO: handle initializers, bitfields, 'delete' +      ThisDecl = Actions.ActOnFriendDecl(CurScope, &DeclaratorInfo); +    } else +      ThisDecl = Actions.ActOnCXXMemberDeclarator(CurScope, AS, +                                                  DeclaratorInfo, +                                                  BitfieldSize.release(), +                                                  Init.release(), +                                                  Deleted);      if (ThisDecl)        DeclsInGroup.push_back(ThisDecl);  | 

