mirror of https://github.com/microsoft/clang.git
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. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@156508 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
parent
f63eee78a3
commit
a971d2410f
|
@ -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
|
||||
};
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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 {
|
||||
|
|
|
@ -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}}
|
||||
|
|
|
@ -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}}
|
||||
|
|
|
@ -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}}
|
||||
|
|
Loading…
Reference in New Issue