In some contexts, type declarations cannot occur. Pass this information down to ParseClassSpecifier, to make its decision easier. Fixes PR6200.

llvm-svn: 95255
This commit is contained in:
Sebastian Redl 2010-02-03 21:21:43 +00:00
parent 2f750f3b5a
commit 2b37272c11
5 changed files with 42 additions and 11 deletions

View File

@ -1065,7 +1065,8 @@ private:
bool ParseOptionalTypeSpecifier(DeclSpec &DS, bool &isInvalid,
const char *&PrevSpec,
unsigned &DiagID,
const ParsedTemplateInfo &TemplateInfo = ParsedTemplateInfo());
const ParsedTemplateInfo &TemplateInfo = ParsedTemplateInfo(),
bool SuppressDeclarations = false);
void ParseSpecifierQualifierList(DeclSpec &DS);
@ -1311,7 +1312,8 @@ private:
void ParseClassSpecifier(tok::TokenKind TagTokKind, SourceLocation TagLoc,
DeclSpec &DS,
const ParsedTemplateInfo &TemplateInfo = ParsedTemplateInfo(),
AccessSpecifier AS = AS_none);
AccessSpecifier AS = AS_none,
bool SuppressDeclarations = false);
void ParseCXXMemberSpecification(SourceLocation StartLoc, unsigned TagType,
DeclPtrTy TagDecl);
void ParseCXXClassMemberDeclaration(AccessSpecifier AS,

View File

@ -1398,7 +1398,8 @@ void Parser::ParseDeclarationSpecifiers(DeclSpec &DS,
bool Parser::ParseOptionalTypeSpecifier(DeclSpec &DS, bool& isInvalid,
const char *&PrevSpec,
unsigned &DiagID,
const ParsedTemplateInfo &TemplateInfo) {
const ParsedTemplateInfo &TemplateInfo,
bool SuppressDeclarations) {
SourceLocation Loc = Tok.getLocation();
switch (Tok.getKind()) {
@ -1408,7 +1409,7 @@ bool Parser::ParseOptionalTypeSpecifier(DeclSpec &DS, bool& isInvalid,
// recurse to handle whatever we get.
if (TryAnnotateTypeOrScopeToken())
return ParseOptionalTypeSpecifier(DS, isInvalid, PrevSpec, DiagID,
TemplateInfo);
TemplateInfo, SuppressDeclarations);
// Otherwise, not a type specifier.
return false;
case tok::coloncolon: // ::foo::bar
@ -1420,7 +1421,7 @@ bool Parser::ParseOptionalTypeSpecifier(DeclSpec &DS, bool& isInvalid,
// recurse to handle whatever we get.
if (TryAnnotateTypeOrScopeToken())
return ParseOptionalTypeSpecifier(DS, isInvalid, PrevSpec, DiagID,
TemplateInfo);
TemplateInfo, SuppressDeclarations);
// Otherwise, not a type specifier.
return false;
@ -1526,7 +1527,8 @@ bool Parser::ParseOptionalTypeSpecifier(DeclSpec &DS, bool& isInvalid,
case tok::kw_union: {
tok::TokenKind Kind = Tok.getKind();
ConsumeToken();
ParseClassSpecifier(Kind, Loc, DS, TemplateInfo);
ParseClassSpecifier(Kind, Loc, DS, TemplateInfo, AS_none,
SuppressDeclarations);
return true;
}

View File

@ -547,7 +547,7 @@ Parser::TypeResult Parser::ParseClassName(SourceLocation &EndLocation,
/// ParseClassSpecifier - Parse a C++ class-specifier [C++ class] or
/// elaborated-type-specifier [C++ dcl.type.elab]; we can't tell which
/// until we reach the start of a definition or see a token that
/// cannot start a definition.
/// cannot start a definition. If SuppressDeclarations is true, we do know.
///
/// class-specifier: [C++ class]
/// class-head '{' member-specification[opt] '}'
@ -587,7 +587,7 @@ Parser::TypeResult Parser::ParseClassName(SourceLocation &EndLocation,
void Parser::ParseClassSpecifier(tok::TokenKind TagTokKind,
SourceLocation StartLoc, DeclSpec &DS,
const ParsedTemplateInfo &TemplateInfo,
AccessSpecifier AS) {
AccessSpecifier AS, bool SuppressDeclarations){
DeclSpec::TST TagType;
if (TagTokKind == tok::kw_struct)
TagType = DeclSpec::TST_struct;
@ -733,8 +733,16 @@ void Parser::ParseClassSpecifier(tok::TokenKind TagTokKind,
// 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.
// However, in some contexts, things look like declarations but are just
// references, e.g.
// new struct s;
// or
// &T::operator struct s;
// For these, SuppressDeclarations is true.
Action::TagUseKind TUK;
if (Tok.is(tok::l_brace) || (getLang().CPlusPlus && Tok.is(tok::colon))) {
if (SuppressDeclarations)
TUK = Action::TUK_Reference;
else if (Tok.is(tok::l_brace) || (getLang().CPlusPlus && Tok.is(tok::colon))){
if (DS.isFriendSpecified()) {
// C++ [class.friend]p2:
// A class shall not be defined in a friend declaration.

View File

@ -763,12 +763,15 @@ bool Parser::ParseCXXTypeSpecifierSeq(DeclSpec &DS) {
bool isInvalid = 0;
// Parse one or more of the type specifiers.
if (!ParseOptionalTypeSpecifier(DS, isInvalid, PrevSpec, DiagID)) {
if (!ParseOptionalTypeSpecifier(DS, isInvalid, PrevSpec, DiagID,
ParsedTemplateInfo(), /*SuppressDeclarations*/true)) {
Diag(Tok, diag::err_operator_missing_type_specifier);
return true;
}
while (ParseOptionalTypeSpecifier(DS, isInvalid, PrevSpec, DiagID)) ;
while (ParseOptionalTypeSpecifier(DS, isInvalid, PrevSpec, DiagID,
ParsedTemplateInfo(), /*SuppressDeclarations*/true))
{}
return false;
}

View File

@ -0,0 +1,16 @@
// RUN: %clang_cc1 -fsyntax-only -verify %s
namespace pr6200 {
struct v {};
struct s {
int i;
operator struct v() { return v(); };
};
void f()
{
// Neither of these is a declaration.
(void)new struct s;
(void)&s::operator struct v;
}
}