forked from OSchip/llvm-project
PR5066: If a declarator cannot have an identifier, and cannot possibly be
followed by an identifier, then diagnose an identifier as being a bogus part of the declarator instead of tripping over it. Improves diagnostics for cases like std::vector<const int *p> my_vec; llvm-svn: 186061
This commit is contained in:
parent
c6b5e2499e
commit
9ce302ed9c
|
@ -450,6 +450,7 @@ def err_invalid_operator_on_type : Error<
|
|||
"cannot use %select{dot|arrow}0 operator on a type">;
|
||||
def err_expected_unqualified_id : Error<
|
||||
"expected %select{identifier|unqualified-id}0">;
|
||||
def err_unexpected_unqualified_id : Error<"type-id cannot have a name">;
|
||||
def err_func_def_no_params : Error<
|
||||
"function definition does not declare parameters">;
|
||||
def err_expected_lparen_after_type : Error<
|
||||
|
|
|
@ -1719,6 +1719,38 @@ public:
|
|||
llvm_unreachable("unknown context kind!");
|
||||
}
|
||||
|
||||
/// diagnoseIdentifier - Return true if the identifier is prohibited and
|
||||
/// should be diagnosed (because it cannot be anything else).
|
||||
bool diagnoseIdentifier() const {
|
||||
switch (Context) {
|
||||
case FileContext:
|
||||
case KNRTypeListContext:
|
||||
case MemberContext:
|
||||
case BlockContext:
|
||||
case ForContext:
|
||||
case ConditionContext:
|
||||
case PrototypeContext:
|
||||
case TemplateParamContext:
|
||||
case CXXCatchContext:
|
||||
case ObjCCatchContext:
|
||||
case TypeNameContext:
|
||||
case ConversionIdContext:
|
||||
case ObjCParameterContext:
|
||||
case ObjCResultContext:
|
||||
case BlockLiteralContext:
|
||||
case CXXNewContext:
|
||||
case LambdaExprContext:
|
||||
return false;
|
||||
|
||||
case AliasDeclContext:
|
||||
case AliasTemplateContext:
|
||||
case TemplateTypeArgContext:
|
||||
case TrailingReturnContext:
|
||||
return true;
|
||||
}
|
||||
llvm_unreachable("unknown context kind!");
|
||||
}
|
||||
|
||||
/// mayBeFollowedByCXXDirectInit - Return true if the declarator can be
|
||||
/// followed by a C++ direct initializer, e.g. "int x(1);".
|
||||
bool mayBeFollowedByCXXDirectInit() const {
|
||||
|
|
|
@ -4696,6 +4696,12 @@ void Parser::ParseDirectDeclarator(Declarator &D) {
|
|||
D.SetIdentifier(Tok.getIdentifierInfo(), Tok.getLocation());
|
||||
ConsumeToken();
|
||||
goto PastIdentifier;
|
||||
} else if (Tok.is(tok::identifier) && D.diagnoseIdentifier()) {
|
||||
Diag(Tok.getLocation(), diag::err_unexpected_unqualified_id)
|
||||
<< FixItHint::CreateRemoval(Tok.getLocation());
|
||||
D.SetIdentifier(0, Tok.getLocation());
|
||||
ConsumeToken();
|
||||
goto PastIdentifier;
|
||||
}
|
||||
|
||||
if (Tok.is(tok::l_paren)) {
|
||||
|
|
|
@ -307,3 +307,8 @@ namespace dtor_fixit {
|
|||
// CHECK: fix-it:"{{.*}}":{[[@LINE-1]]:6-[[@LINE-1]]:9}:"foo"
|
||||
};
|
||||
}
|
||||
|
||||
namespace PR5066 {
|
||||
template<typename T> struct X {};
|
||||
X<int *p> x; // expected-error {{type-id cannot have a name}}
|
||||
}
|
||||
|
|
|
@ -187,6 +187,13 @@ namespace PR15017 {
|
|||
// Ensure we produce at least some diagnostic for attributes in C++98.
|
||||
[[]] struct S; // expected-error 2{{}}
|
||||
|
||||
namespace PR5066 {
|
||||
template<typename T> struct X {};
|
||||
X<int N> x; // expected-error {{type-id cannot have a name}}
|
||||
|
||||
using T = int (*T)(); // expected-error {{type-id cannot have a name}} expected-warning {{C++11}}
|
||||
}
|
||||
|
||||
// PR8380
|
||||
extern "" // expected-error {{unknown linkage language}}
|
||||
test6a { ;// expected-error {{C++ requires a type specifier for all declarations}} \
|
||||
|
|
|
@ -5,7 +5,7 @@ template<typename T> struct A {};
|
|||
// Check for template argument lists followed by junk
|
||||
// FIXME: The diagnostics here aren't great...
|
||||
A<int+> int x; // expected-error {{expected '>'}} expected-error {{expected unqualified-id}}
|
||||
A<int x; // expected-error {{expected '>'}}
|
||||
A<int x; // expected-error {{type-id cannot have a name}} expected-error {{expected '>'}}
|
||||
|
||||
// PR8912
|
||||
template <bool> struct S {};
|
||||
|
|
|
@ -73,3 +73,10 @@ enum E
|
|||
[[]] e;
|
||||
|
||||
}
|
||||
|
||||
namespace PR5066 {
|
||||
using T = int (*f)(); // expected-error {{type-id cannot have a name}}
|
||||
template<typename T> using U = int (*f)(); // expected-error {{type-id cannot have a name}}
|
||||
auto f() -> int (*f)(); // expected-error {{type-id cannot have a name}}
|
||||
auto g = []() -> int (*f)() {}; // expected-error {{type-id cannot have a name}}
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue