forked from OSchip/llvm-project
Teach TryAnnotateTypeOrScopeToken to deal with already-annotated
scope specifiers. Fix a tentative parsing bug that came up in LLVM. Incidentally fixes some random FIXMEs in an existing testcase. llvm-svn: 91734
This commit is contained in:
parent
357e8c94d6
commit
e2ade289be
|
@ -680,10 +680,10 @@ Parser::TPResult Parser::isCXXDeclarationSpecifier() {
|
||||||
// Otherwise, not a typename.
|
// Otherwise, not a typename.
|
||||||
return TPResult::False();
|
return TPResult::False();
|
||||||
|
|
||||||
case tok::coloncolon: // ::foo::bar
|
case tok::coloncolon: // ::foo::bar
|
||||||
if (NextToken().is(tok::kw_new) || // ::new
|
if (NextToken().is(tok::kw_new) || // ::new
|
||||||
NextToken().is(tok::kw_delete)) // ::delete
|
NextToken().is(tok::kw_delete)) // ::delete
|
||||||
return TPResult::False();
|
return TPResult::False();
|
||||||
|
|
||||||
// Annotate typenames and C++ scope specifiers. If we get one, just
|
// Annotate typenames and C++ scope specifiers. If we get one, just
|
||||||
// recurse to handle whatever we get.
|
// recurse to handle whatever we get.
|
||||||
|
@ -750,6 +750,12 @@ Parser::TPResult Parser::isCXXDeclarationSpecifier() {
|
||||||
case tok::kw___forceinline:
|
case tok::kw___forceinline:
|
||||||
return TPResult::True();
|
return TPResult::True();
|
||||||
|
|
||||||
|
case tok::annot_cxxscope: // foo::bar or ::foo::bar, but already parsed
|
||||||
|
// We've already annotated a scope; try to annotate a type.
|
||||||
|
if (!(TryAnnotateTypeOrScopeToken() && Tok.is(tok::annot_typename)))
|
||||||
|
return TPResult::False();
|
||||||
|
// If that succeeded, fallthrough into the generic simple-type-id case.
|
||||||
|
|
||||||
// The ambiguity resides in a simple-type-specifier/typename-specifier
|
// The ambiguity resides in a simple-type-specifier/typename-specifier
|
||||||
// followed by a '('. The '(' could either be the start of:
|
// followed by a '('. The '(' could either be the start of:
|
||||||
//
|
//
|
||||||
|
|
|
@ -880,7 +880,7 @@ Parser::OwningExprResult Parser::ParseSimpleAsm(SourceLocation *EndLoc) {
|
||||||
/// as the current tokens, so only call it in contexts where these are invalid.
|
/// as the current tokens, so only call it in contexts where these are invalid.
|
||||||
bool Parser::TryAnnotateTypeOrScopeToken(bool EnteringContext) {
|
bool Parser::TryAnnotateTypeOrScopeToken(bool EnteringContext) {
|
||||||
assert((Tok.is(tok::identifier) || Tok.is(tok::coloncolon)
|
assert((Tok.is(tok::identifier) || Tok.is(tok::coloncolon)
|
||||||
|| Tok.is(tok::kw_typename)) &&
|
|| Tok.is(tok::kw_typename) || Tok.is(tok::annot_cxxscope)) &&
|
||||||
"Cannot be a type or scope token!");
|
"Cannot be a type or scope token!");
|
||||||
|
|
||||||
if (Tok.is(tok::kw_typename)) {
|
if (Tok.is(tok::kw_typename)) {
|
||||||
|
@ -935,6 +935,9 @@ bool Parser::TryAnnotateTypeOrScopeToken(bool EnteringContext) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Remembers whether the token was originally a scope annotation.
|
||||||
|
bool wasScopeAnnotation = Tok.is(tok::annot_cxxscope);
|
||||||
|
|
||||||
CXXScopeSpec SS;
|
CXXScopeSpec SS;
|
||||||
if (getLang().CPlusPlus)
|
if (getLang().CPlusPlus)
|
||||||
ParseOptionalCXXScopeSpecifier(SS, /*ObjectType=*/0, EnteringContext);
|
ParseOptionalCXXScopeSpecifier(SS, /*ObjectType=*/0, EnteringContext);
|
||||||
|
@ -1017,9 +1020,11 @@ bool Parser::TryAnnotateTypeOrScopeToken(bool EnteringContext) {
|
||||||
Tok.setAnnotationValue(SS.getScopeRep());
|
Tok.setAnnotationValue(SS.getScopeRep());
|
||||||
Tok.setAnnotationRange(SS.getRange());
|
Tok.setAnnotationRange(SS.getRange());
|
||||||
|
|
||||||
// In case the tokens were cached, have Preprocessor replace them with the
|
// In case the tokens were cached, have Preprocessor replace them
|
||||||
// annotation token.
|
// with the annotation token. We don't need to do this if we've
|
||||||
PP.AnnotateCachedTokens(Tok);
|
// just reverted back to the state we were in before being called.
|
||||||
|
if (!wasScopeAnnotation)
|
||||||
|
PP.AnnotateCachedTokens(Tok);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -24,3 +24,43 @@ void f() {
|
||||||
// FIXME: Special case: "++" is postfix here, not prefix
|
// FIXME: Special case: "++" is postfix here, not prefix
|
||||||
// (S())++;
|
// (S())++;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Make sure we do tentative parsing correctly in conditions.
|
||||||
|
typedef int type;
|
||||||
|
struct rec { rec(int); };
|
||||||
|
|
||||||
|
namespace ns {
|
||||||
|
typedef int type;
|
||||||
|
struct rec { rec(int); };
|
||||||
|
}
|
||||||
|
|
||||||
|
struct cls {
|
||||||
|
typedef int type;
|
||||||
|
struct rec { rec(int); };
|
||||||
|
};
|
||||||
|
|
||||||
|
struct result {
|
||||||
|
template <class T> result(T);
|
||||||
|
bool check();
|
||||||
|
};
|
||||||
|
|
||||||
|
void test(int i) {
|
||||||
|
if (result((cls::type) i).check())
|
||||||
|
return;
|
||||||
|
|
||||||
|
if (result((ns::type) i).check())
|
||||||
|
return;
|
||||||
|
|
||||||
|
if (result((::type) i).check())
|
||||||
|
return;
|
||||||
|
|
||||||
|
if (result((cls::rec) i).check())
|
||||||
|
return;
|
||||||
|
|
||||||
|
if (result((ns::rec) i).check())
|
||||||
|
return;
|
||||||
|
|
||||||
|
if (result((::rec) i).check())
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
|
@ -32,11 +32,9 @@ apply1<add_reference, int>::type ir = i;
|
||||||
apply1<add_reference, float>::type fr = i; // expected-error{{non-const lvalue reference to type 'float' cannot bind to a value of unrelated type 'int'}}
|
apply1<add_reference, float>::type fr = i; // expected-error{{non-const lvalue reference to type 'float' cannot bind to a value of unrelated type 'int'}}
|
||||||
|
|
||||||
void test() {
|
void test() {
|
||||||
apply1<add_reference, void>::type t; // expected-note{{in instantiation of template class 'struct apply1<struct add_reference, void>' requested here}} \
|
apply1<add_reference, void>::type t; // expected-note{{in instantiation of template class 'struct apply1<struct add_reference, void>' requested here}}
|
||||||
// FIXME: expected-error{{unexpected type name 'type': expected expression}}
|
|
||||||
|
|
||||||
apply1<bogus, int>::type t2; // expected-note{{in instantiation of template class 'struct apply1<struct bogus, int>' requested here}} \
|
apply1<bogus, int>::type t2; // expected-note{{in instantiation of template class 'struct apply1<struct bogus, int>' requested here}}
|
||||||
// FIXME: expected-error{{unexpected type name 'type': expected expression}}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue