mirror of
https://github.com/llvm/llvm-project.git
synced 2025-04-29 12:06:08 +00:00
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,
|
bool ParseOptionalTypeSpecifier(DeclSpec &DS, bool &isInvalid,
|
||||||
const char *&PrevSpec,
|
const char *&PrevSpec,
|
||||||
unsigned &DiagID,
|
unsigned &DiagID,
|
||||||
const ParsedTemplateInfo &TemplateInfo = ParsedTemplateInfo());
|
const ParsedTemplateInfo &TemplateInfo = ParsedTemplateInfo(),
|
||||||
|
bool SuppressDeclarations = false);
|
||||||
|
|
||||||
void ParseSpecifierQualifierList(DeclSpec &DS);
|
void ParseSpecifierQualifierList(DeclSpec &DS);
|
||||||
|
|
||||||
@ -1311,7 +1312,8 @@ private:
|
|||||||
void ParseClassSpecifier(tok::TokenKind TagTokKind, SourceLocation TagLoc,
|
void ParseClassSpecifier(tok::TokenKind TagTokKind, SourceLocation TagLoc,
|
||||||
DeclSpec &DS,
|
DeclSpec &DS,
|
||||||
const ParsedTemplateInfo &TemplateInfo = ParsedTemplateInfo(),
|
const ParsedTemplateInfo &TemplateInfo = ParsedTemplateInfo(),
|
||||||
AccessSpecifier AS = AS_none);
|
AccessSpecifier AS = AS_none,
|
||||||
|
bool SuppressDeclarations = false);
|
||||||
void ParseCXXMemberSpecification(SourceLocation StartLoc, unsigned TagType,
|
void ParseCXXMemberSpecification(SourceLocation StartLoc, unsigned TagType,
|
||||||
DeclPtrTy TagDecl);
|
DeclPtrTy TagDecl);
|
||||||
void ParseCXXClassMemberDeclaration(AccessSpecifier AS,
|
void ParseCXXClassMemberDeclaration(AccessSpecifier AS,
|
||||||
|
@ -1398,7 +1398,8 @@ void Parser::ParseDeclarationSpecifiers(DeclSpec &DS,
|
|||||||
bool Parser::ParseOptionalTypeSpecifier(DeclSpec &DS, bool& isInvalid,
|
bool Parser::ParseOptionalTypeSpecifier(DeclSpec &DS, bool& isInvalid,
|
||||||
const char *&PrevSpec,
|
const char *&PrevSpec,
|
||||||
unsigned &DiagID,
|
unsigned &DiagID,
|
||||||
const ParsedTemplateInfo &TemplateInfo) {
|
const ParsedTemplateInfo &TemplateInfo,
|
||||||
|
bool SuppressDeclarations) {
|
||||||
SourceLocation Loc = Tok.getLocation();
|
SourceLocation Loc = Tok.getLocation();
|
||||||
|
|
||||||
switch (Tok.getKind()) {
|
switch (Tok.getKind()) {
|
||||||
@ -1408,7 +1409,7 @@ bool Parser::ParseOptionalTypeSpecifier(DeclSpec &DS, bool& isInvalid,
|
|||||||
// recurse to handle whatever we get.
|
// recurse to handle whatever we get.
|
||||||
if (TryAnnotateTypeOrScopeToken())
|
if (TryAnnotateTypeOrScopeToken())
|
||||||
return ParseOptionalTypeSpecifier(DS, isInvalid, PrevSpec, DiagID,
|
return ParseOptionalTypeSpecifier(DS, isInvalid, PrevSpec, DiagID,
|
||||||
TemplateInfo);
|
TemplateInfo, SuppressDeclarations);
|
||||||
// Otherwise, not a type specifier.
|
// Otherwise, not a type specifier.
|
||||||
return false;
|
return false;
|
||||||
case tok::coloncolon: // ::foo::bar
|
case tok::coloncolon: // ::foo::bar
|
||||||
@ -1420,7 +1421,7 @@ bool Parser::ParseOptionalTypeSpecifier(DeclSpec &DS, bool& isInvalid,
|
|||||||
// recurse to handle whatever we get.
|
// recurse to handle whatever we get.
|
||||||
if (TryAnnotateTypeOrScopeToken())
|
if (TryAnnotateTypeOrScopeToken())
|
||||||
return ParseOptionalTypeSpecifier(DS, isInvalid, PrevSpec, DiagID,
|
return ParseOptionalTypeSpecifier(DS, isInvalid, PrevSpec, DiagID,
|
||||||
TemplateInfo);
|
TemplateInfo, SuppressDeclarations);
|
||||||
// Otherwise, not a type specifier.
|
// Otherwise, not a type specifier.
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
@ -1526,7 +1527,8 @@ bool Parser::ParseOptionalTypeSpecifier(DeclSpec &DS, bool& isInvalid,
|
|||||||
case tok::kw_union: {
|
case tok::kw_union: {
|
||||||
tok::TokenKind Kind = Tok.getKind();
|
tok::TokenKind Kind = Tok.getKind();
|
||||||
ConsumeToken();
|
ConsumeToken();
|
||||||
ParseClassSpecifier(Kind, Loc, DS, TemplateInfo);
|
ParseClassSpecifier(Kind, Loc, DS, TemplateInfo, AS_none,
|
||||||
|
SuppressDeclarations);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -547,7 +547,7 @@ Parser::TypeResult Parser::ParseClassName(SourceLocation &EndLocation,
|
|||||||
/// ParseClassSpecifier - Parse a C++ class-specifier [C++ class] or
|
/// ParseClassSpecifier - Parse a C++ class-specifier [C++ class] or
|
||||||
/// elaborated-type-specifier [C++ dcl.type.elab]; we can't tell which
|
/// 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
|
/// 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-specifier: [C++ class]
|
||||||
/// class-head '{' member-specification[opt] '}'
|
/// class-head '{' member-specification[opt] '}'
|
||||||
@ -587,7 +587,7 @@ Parser::TypeResult Parser::ParseClassName(SourceLocation &EndLocation,
|
|||||||
void Parser::ParseClassSpecifier(tok::TokenKind TagTokKind,
|
void Parser::ParseClassSpecifier(tok::TokenKind TagTokKind,
|
||||||
SourceLocation StartLoc, DeclSpec &DS,
|
SourceLocation StartLoc, DeclSpec &DS,
|
||||||
const ParsedTemplateInfo &TemplateInfo,
|
const ParsedTemplateInfo &TemplateInfo,
|
||||||
AccessSpecifier AS) {
|
AccessSpecifier AS, bool SuppressDeclarations){
|
||||||
DeclSpec::TST TagType;
|
DeclSpec::TST TagType;
|
||||||
if (TagTokKind == tok::kw_struct)
|
if (TagTokKind == tok::kw_struct)
|
||||||
TagType = DeclSpec::TST_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
|
// have to be treated differently. If we have 'struct foo {...' or
|
||||||
// 'struct foo :...' then this is a definition. Otherwise we have
|
// 'struct foo :...' then this is a definition. Otherwise we have
|
||||||
// something like 'struct foo xyz', a reference.
|
// 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;
|
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()) {
|
if (DS.isFriendSpecified()) {
|
||||||
// C++ [class.friend]p2:
|
// C++ [class.friend]p2:
|
||||||
// A class shall not be defined in a friend declaration.
|
// A class shall not be defined in a friend declaration.
|
||||||
|
@ -763,12 +763,15 @@ bool Parser::ParseCXXTypeSpecifierSeq(DeclSpec &DS) {
|
|||||||
bool isInvalid = 0;
|
bool isInvalid = 0;
|
||||||
|
|
||||||
// Parse one or more of the type specifiers.
|
// 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);
|
Diag(Tok, diag::err_operator_missing_type_specifier);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
while (ParseOptionalTypeSpecifier(DS, isInvalid, PrevSpec, DiagID)) ;
|
while (ParseOptionalTypeSpecifier(DS, isInvalid, PrevSpec, DiagID,
|
||||||
|
ParsedTemplateInfo(), /*SuppressDeclarations*/true))
|
||||||
|
{}
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
16
clang/test/CXX/dcl.decl/dcl.name/p1.cpp
Normal file
16
clang/test/CXX/dcl.decl/dcl.name/p1.cpp
Normal 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;
|
||||||
|
}
|
||||||
|
}
|
Loading…
x
Reference in New Issue
Block a user