summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorRichard Smith <richard-llvm@metafoo.co.uk>2012-05-09 20:55:26 +0000
committerRichard Smith <richard-llvm@metafoo.co.uk>2012-05-09 20:55:26 +0000
commit2f07ad5a70148d9f64963af97b6563ccda7ac12f (patch)
treed7783ecdfdd44b2c69147bb0069993548b8503d9
parent1cdb85e048f2d00fb36b2336983501258a279a80 (diff)
downloadbcm5719-llvm-2f07ad5a70148d9f64963af97b6563ccda7ac12f.tar.gz
bcm5719-llvm-2f07ad5a70148d9f64963af97b6563ccda7ac12f.zip
Push the knowledge that we are parsing a type-id/type-name further into the
parser, and use it to emit better diagnostics in cases where an identifer can't be looked up as a type name. llvm-svn: 156508
-rw-r--r--clang/include/clang/Parse/Parser.h2
-rw-r--r--clang/lib/Parse/ParseDecl.cpp7
-rw-r--r--clang/test/CXX/dcl.dcl/dcl.spec/dcl.typedef/p2-0x.cpp4
-rw-r--r--clang/test/CXX/dcl.decl/dcl.meaning/dcl.fct/p9-0x.cpp6
-rw-r--r--clang/test/Parser/cxx-throw.cpp2
-rw-r--r--clang/test/Parser/cxx11-type-specifier.cpp7
6 files changed, 21 insertions, 7 deletions
diff --git a/clang/include/clang/Parse/Parser.h b/clang/include/clang/Parse/Parser.h
index e1d5b53dec9..0ea592fd7ec 100644
--- a/clang/include/clang/Parse/Parser.h
+++ b/clang/include/clang/Parse/Parser.h
@@ -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
};
diff --git a/clang/lib/Parse/ParseDecl.cpp b/clang/lib/Parse/ParseDecl.cpp
index e57db6ff9b2..7ca9e280ca3 100644
--- a/clang/lib/Parse/ParseDecl.cpp
+++ b/clang/lib/Parse/ParseDecl.cpp
@@ -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
diff --git a/clang/test/CXX/dcl.dcl/dcl.spec/dcl.typedef/p2-0x.cpp b/clang/test/CXX/dcl.dcl/dcl.spec/dcl.typedef/p2-0x.cpp
index b06eb01a7fb..89a28adcc65 100644
--- a/clang/test/CXX/dcl.dcl/dcl.spec/dcl.typedef/p2-0x.cpp
+++ b/clang/test/CXX/dcl.dcl/dcl.spec/dcl.typedef/p2-0x.cpp
@@ -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 {
diff --git a/clang/test/CXX/dcl.decl/dcl.meaning/dcl.fct/p9-0x.cpp b/clang/test/CXX/dcl.decl/dcl.meaning/dcl.fct/p9-0x.cpp
index 574a3e7a793..680e9124cb2 100644
--- a/clang/test/CXX/dcl.decl/dcl.meaning/dcl.fct/p9-0x.cpp
+++ b/clang/test/CXX/dcl.decl/dcl.meaning/dcl.fct/p9-0x.cpp
@@ -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}}
diff --git a/clang/test/Parser/cxx-throw.cpp b/clang/test/Parser/cxx-throw.cpp
index d63b6d4cae6..a1be710fb5c 100644
--- a/clang/test/Parser/cxx-throw.cpp
+++ b/clang/test/Parser/cxx-throw.cpp
@@ -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}}
diff --git a/clang/test/Parser/cxx11-type-specifier.cpp b/clang/test/Parser/cxx11-type-specifier.cpp
index 2e629f3ab56..212ffb407b9 100644
--- a/clang/test/Parser/cxx11-type-specifier.cpp
+++ b/clang/test/Parser/cxx11-type-specifier.cpp
@@ -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}}
OpenPOWER on IntegriCloud