]> granicus.if.org Git - clang/commitdiff
In some contexts, type declarations cannot occur. Pass this information down to Parse...
authorSebastian Redl <sebastian.redl@getdesigned.at>
Wed, 3 Feb 2010 21:21:43 +0000 (21:21 +0000)
committerSebastian Redl <sebastian.redl@getdesigned.at>
Wed, 3 Feb 2010 21:21:43 +0000 (21:21 +0000)
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@95255 91177308-0d34-0410-b5e6-96231b3b80d8

include/clang/Parse/Parser.h
lib/Parse/ParseDecl.cpp
lib/Parse/ParseDeclCXX.cpp
lib/Parse/ParseExprCXX.cpp
test/CXX/dcl.decl/dcl.name/p1.cpp [new file with mode: 0644]

index 33f653d8f931e6f9893ad58c4d0daac7da5721b9..71aa38a15571dd9152a57c79df2263855d814639 100644 (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,
index 5a5f5092db7fde3d02de448f91951d4c89a93e30..996023830007e41c20156f915a4435b9286860e1 100644 (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;
   }
 
index f95fedc4e3a2b96579abea111bbe8a14715170b4..07bae1c7a4b7bfdf6c11f01321fe9107d4cff0f8 100644 (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.
index ca50ef4000923bef3de9b2ec12a769fa02eba710..0dbe1ea83890532da6785313e4666d2077967eb3 100644 (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;
 }
diff --git a/test/CXX/dcl.decl/dcl.name/p1.cpp b/test/CXX/dcl.decl/dcl.name/p1.cpp
new file mode 100644 (file)
index 0000000..7586007
--- /dev/null
@@ -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;
+  }
+}