forked from OSchip/llvm-project
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:
parent
2f750f3b5a
commit
2b37272c11
|
@ -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,
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
@ -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.
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue