]> granicus.if.org Git - clang/commitdiff
Push the knowledge that we are parsing a type-id/type-name further into the
authorRichard Smith <richard-llvm@metafoo.co.uk>
Wed, 9 May 2012 20:55:26 +0000 (20:55 +0000)
committerRichard Smith <richard-llvm@metafoo.co.uk>
Wed, 9 May 2012 20:55:26 +0000 (20:55 +0000)
parser, and use it to emit better diagnostics in cases where an identifer
can't be looked up as a type name.

git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@156508 91177308-0d34-0410-b5e6-96231b3b80d8

include/clang/Parse/Parser.h
lib/Parse/ParseDecl.cpp
test/CXX/dcl.dcl/dcl.spec/dcl.typedef/p2-0x.cpp
test/CXX/dcl.decl/dcl.meaning/dcl.fct/p9-0x.cpp
test/Parser/cxx-throw.cpp
test/Parser/cxx11-type-specifier.cpp

index e1d5b53dec95a4be01d55db2e3a1c1b91fa1ad13..0ea592fd7ec43410e294ca02aac22ceacc57df27 100644 (file)
@@ -1531,7 +1531,7 @@ private:
   enum DeclSpecContext {
     DSC_normal, // normal context
     DSC_class,  // class context, enables 'friend'
-    DSC_type_specifier, // C++ type-specifier-seq
+    DSC_type_specifier, // C++ type-specifier-seq or C specifier-qualifier-list
     DSC_trailing, // C++11 trailing-type-specifier in a trailing return type
     DSC_top_level // top-level/namespace declaration context
   };
index e57db6ff9b26ee2de2847043da3722f6a0e46cd3..7ca9e280ca32339c792eeec020eb9707c1d12b76 100644 (file)
@@ -38,6 +38,8 @@ TypeResult Parser::ParseTypeName(SourceRange *Range,
                                  AccessSpecifier AS,
                                  Decl **OwnedType) {
   DeclSpecContext DSC = getDeclSpecContextFromDeclaratorContext(Context);
+  if (DSC == DSC_normal)
+    DSC = DSC_type_specifier;
 
   // Parse the common declaration-specifiers piece.
   DeclSpec DS(AttrFactory);
@@ -1543,7 +1545,8 @@ void Parser::ParseSpecifierQualifierList(DeclSpec &DS, AccessSpecifier AS,
 
   // Validate declspec for type-name.
   unsigned Specs = DS.getParsedSpecifiers();
-  if (DSC == DSC_type_specifier && !DS.hasTypeSpecifier()) {
+  if ((DSC == DSC_type_specifier || DSC == DSC_trailing) &&
+      !DS.hasTypeSpecifier()) {
     Diag(Tok, diag::err_expected_type);
     DS.SetTypeSpecError();
   } else if (Specs == DeclSpec::PQ_None && !DS.getNumProtocolQualifiers() &&
@@ -1640,7 +1643,7 @@ bool Parser::ParseImplicitInt(DeclSpec &DS, CXXScopeSpec *SS,
   // FIXME: Don't bail out here in languages with no implicit int (like
   // C++ with no -fms-extensions). This is much more likely to be an undeclared
   // type or typo than a use of implicit int.
-  if (DSC != DSC_type_specifier &&
+  if (DSC != DSC_type_specifier && DSC != DSC_trailing &&
       isValidAfterIdentifierInDeclarator(NextToken())) {
     // If this token is valid for implicit int, e.g. "static x = 4", then
     // we just avoid eating the identifier, so it will be parsed as the
index b06eb01a7fb5cbf44bd69a148350be6cd6fd5f28..89a28adcc65c1f911cdaa654de639a6fb8484c89 100644 (file)
@@ -124,9 +124,7 @@ namespace TagName {
 }
 
 namespace CWG1044 {
-  // FIXME: this diagnostic isn't ideal. one diagnostic is enough.
-  using T = T; // expected-error {{type name requires a specifier}} \
-                  expected-error {{expected ';' after alias declaration}}
+  using T = T; // expected-error {{unknown type name 'T'}}
 }
 
 namespace StdExample {
index 574a3e7a79341a5932ef7ca39d9f2275dd57b368..680e9124cb24c79f4b0a2fec079c43d9abf4d8c7 100644 (file)
@@ -1,3 +1,7 @@
 // RUN: %clang_cc1 -fsyntax-only -verify -std=c++11 %s
 
-auto j() -> enum { e3 }; // expected-error{{unnamed enumeration must be a definition}} expected-error {{requires a specifier or qualifier}} expected-error {{without trailing return type}}
+// FIXME: We should catch the case of tag with an incomplete type here (which
+// will necessarily be ill-formed as a trailing return type for a function
+// definition), and recover with a "type cannot be defined in a trailing return
+// type" error.
+auto j() -> enum { e3 }; // expected-error{{unnamed enumeration must be a definition}} expected-error {{expected a type}} expected-error {{without trailing return type}}
index d63b6d4cae6c13de2bb550e7b90a6034b0044940..a1be710fb5c00a3e87a60654076af320e9f3e854 100644 (file)
@@ -13,3 +13,5 @@ void foo() {
   __extension__ throw 1;    // expected-error {{expected expression}}
   (void)throw;              // expected-error {{expected expression}}
 }
+
+void f() throw(static); // expected-error {{expected a type}} expected-error {{does not allow storage class}}
index 2e629f3ab56407db7a5f7807ae02ae7b5ef485c9..212ffb407b995523cc1910e4c5bb94acdff853d5 100644 (file)
@@ -18,3 +18,10 @@ void f() {
   (void) new struct S {}; // expected-error{{'S' can not be defined in a type specifier}}
   (void) new enum E { e }; // expected-error{{'E' can not be defined in a type specifier}}
 }
+
+// And for trailing-type-specifier-seq
+
+// FIXME: Don't treat an ill-formed trailing-return-type the same as no
+//        trailing-return-type, and avoid the second diagnostic.
+auto f() -> unknown; // expected-error{{unknown type name 'unknown'}} \
+                        expected-error{{'auto' return without trailing return type}}