summaryrefslogtreecommitdiffstats
path: root/clang/lib/Parse
diff options
context:
space:
mode:
authorJohn McCall <rjmccall@apple.com>2009-08-06 02:15:43 +0000
committerJohn McCall <rjmccall@apple.com>2009-08-06 02:15:43 +0000
commit07e91c04ba33974b00e91c4b468d61d7f0f5a238 (patch)
tree8ba331aae7bcf0dfdf382b4db58b626ca25b1d3e /clang/lib/Parse
parent51eeb36c8c62a07af8eea94303cb8a9dd77b14da (diff)
downloadbcm5719-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.cpp18
-rw-r--r--clang/lib/Parse/ParseCXXInlineMethods.cpp6
-rw-r--r--clang/lib/Parse/ParseDecl.cpp11
-rw-r--r--clang/lib/Parse/ParseDeclCXX.cpp52
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);
OpenPOWER on IntegriCloud