aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorSebastian Redl <sebastian.redl@getdesigned.at>2010-02-03 21:21:43 +0000
committerSebastian Redl <sebastian.redl@getdesigned.at>2010-02-03 21:21:43 +0000
commitd9bafa76f8d6eb9e4f4974ed322217f8df6bb82e (patch)
tree9cf872e4c9dda96f96407751cc0e07a322074121
parent3d0ad58b28e0d50fca7f21c6a078b05370510288 (diff)
In some contexts, type declarations cannot occur. Pass this information down to ParseClassSpecifier, to make its decision easier. Fixes PR6200.
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@95255 91177308-0d34-0410-b5e6-96231b3b80d8
-rw-r--r--include/clang/Parse/Parser.h6
-rw-r--r--lib/Parse/ParseDecl.cpp10
-rw-r--r--lib/Parse/ParseDeclCXX.cpp14
-rw-r--r--lib/Parse/ParseExprCXX.cpp7
-rw-r--r--test/CXX/dcl.decl/dcl.name/p1.cpp16
5 files changed, 42 insertions, 11 deletions
diff --git a/include/clang/Parse/Parser.h b/include/clang/Parse/Parser.h
index 33f653d8f9..71aa38a155 100644
--- a/include/clang/Parse/Parser.h
+++ b/include/clang/Parse/Parser.h
@@ -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,
diff --git a/lib/Parse/ParseDecl.cpp b/lib/Parse/ParseDecl.cpp
index 5a5f5092db..9960238300 100644
--- a/lib/Parse/ParseDecl.cpp
+++ b/lib/Parse/ParseDecl.cpp
@@ -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;
}
diff --git a/lib/Parse/ParseDeclCXX.cpp b/lib/Parse/ParseDeclCXX.cpp
index f95fedc4e3..07bae1c7a4 100644
--- a/lib/Parse/ParseDeclCXX.cpp
+++ b/lib/Parse/ParseDeclCXX.cpp
@@ -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.
diff --git a/lib/Parse/ParseExprCXX.cpp b/lib/Parse/ParseExprCXX.cpp
index ca50ef4000..0dbe1ea838 100644
--- a/lib/Parse/ParseExprCXX.cpp
+++ b/lib/Parse/ParseExprCXX.cpp
@@ -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;
}
diff --git a/test/CXX/dcl.decl/dcl.name/p1.cpp b/test/CXX/dcl.decl/dcl.name/p1.cpp
new file mode 100644
index 0000000000..7586007cc7
--- /dev/null
+++ b/test/CXX/dcl.decl/dcl.name/p1.cpp
@@ -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;
+ }
+}