forked from OSchip/llvm-project
ParseCXXSimpleTypeSpecifier can only be called on things that are
verified to be simple type specifiers, so there is no need for it to call TryAnnotateTypeOrScopeToken. Make MaybeParseCXXScopeSpecifier reject ::new and ::delete with a hard error now that it may never be transitively called in a context where these are legal. This allows me to start disentangling things more. llvm-svn: 61659
This commit is contained in:
parent
e4e5532e05
commit
45ddec319e
|
@ -1309,6 +1309,8 @@ DIAG(err_array_new_needs_size, ERROR,
|
||||||
"array size must be specified in new expressions")
|
"array size must be specified in new expressions")
|
||||||
DIAG(err_bad_new_type, ERROR,
|
DIAG(err_bad_new_type, ERROR,
|
||||||
"cannot allocate %select{function|incomplete|reference}1 type %0 with new")
|
"cannot allocate %select{function|incomplete|reference}1 type %0 with new")
|
||||||
|
DIAG(err_invalid_qualified_new_delete, ERROR,
|
||||||
|
"invalid use of ::%select{new|delete}0")
|
||||||
DIAG(err_new_array_nonconst, ERROR,
|
DIAG(err_new_array_nonconst, ERROR,
|
||||||
"only the first dimension of an allocated array may be non-const")
|
"only the first dimension of an allocated array may be non-const")
|
||||||
DIAG(err_array_size_not_integral, ERROR,
|
DIAG(err_array_size_not_integral, ERROR,
|
||||||
|
|
|
@ -20,6 +20,9 @@ using namespace clang;
|
||||||
/// MaybeParseCXXScopeSpecifier - Parse global scope or nested-name-specifier.
|
/// MaybeParseCXXScopeSpecifier - Parse global scope or nested-name-specifier.
|
||||||
/// Returns true if a nested-name-specifier was parsed from the token stream.
|
/// Returns true if a nested-name-specifier was parsed from the token stream.
|
||||||
///
|
///
|
||||||
|
/// Note that this routine emits an error if you call it with ::new or ::delete
|
||||||
|
/// as the current tokens, so only call it in contexts where these are invalid.
|
||||||
|
///
|
||||||
/// '::'[opt] nested-name-specifier
|
/// '::'[opt] nested-name-specifier
|
||||||
/// '::'
|
/// '::'
|
||||||
///
|
///
|
||||||
|
@ -36,7 +39,7 @@ bool Parser::MaybeParseCXXScopeSpecifier(CXXScopeSpec &SS,
|
||||||
|
|
||||||
if (Tok.is(tok::annot_cxxscope)) {
|
if (Tok.is(tok::annot_cxxscope)) {
|
||||||
assert(GlobalQualifier == 0 &&
|
assert(GlobalQualifier == 0 &&
|
||||||
"Cannot have :: followed by a resolve annotation scope");
|
"Cannot have :: followed by a resolved annotation scope");
|
||||||
SS.setScopeRep(Tok.getAnnotationValue());
|
SS.setScopeRep(Tok.getAnnotationValue());
|
||||||
SS.setRange(Tok.getAnnotationRange());
|
SS.setRange(Tok.getAnnotationRange());
|
||||||
ConsumeToken();
|
ConsumeToken();
|
||||||
|
@ -48,27 +51,33 @@ bool Parser::MaybeParseCXXScopeSpecifier(CXXScopeSpec &SS,
|
||||||
(Tok.isNot(tok::identifier) || NextToken().isNot(tok::coloncolon)))
|
(Tok.isNot(tok::identifier) || NextToken().isNot(tok::coloncolon)))
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
// ::new and ::delete aren't nested-name-specifiers, so parsing the :: as
|
|
||||||
// a scope specifier only makes things more complicated.
|
|
||||||
if (GlobalQualifier == 0 && Tok.is(tok::coloncolon)) {
|
|
||||||
Token Next = NextToken();
|
|
||||||
if (Next.is(tok::kw_new) || Next.is(tok::kw_delete))
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (GlobalQualifier) {
|
if (GlobalQualifier) {
|
||||||
// Pre-parsed '::'.
|
// Pre-parsed '::'.
|
||||||
SS.setBeginLoc(GlobalQualifier->getLocation());
|
SS.setBeginLoc(GlobalQualifier->getLocation());
|
||||||
SS.setScopeRep(Actions.ActOnCXXGlobalScopeSpecifier(CurScope,
|
SS.setScopeRep(Actions.ActOnCXXGlobalScopeSpecifier(CurScope,
|
||||||
GlobalQualifier->getLocation()));
|
GlobalQualifier->getLocation()));
|
||||||
SS.setEndLoc(GlobalQualifier->getLocation());
|
SS.setEndLoc(GlobalQualifier->getLocation());
|
||||||
|
|
||||||
|
assert(Tok.isNot(tok::kw_new) && Tok.isNot(tok::kw_delete) &&
|
||||||
|
"Never called with preparsed :: qualifier and with new/delete");
|
||||||
} else {
|
} else {
|
||||||
SS.setBeginLoc(Tok.getLocation());
|
SS.setBeginLoc(Tok.getLocation());
|
||||||
|
|
||||||
// '::'
|
// '::' - Global scope qualifier.
|
||||||
if (Tok.is(tok::coloncolon)) {
|
if (Tok.is(tok::coloncolon)) {
|
||||||
// Global scope.
|
|
||||||
SourceLocation CCLoc = ConsumeToken();
|
SourceLocation CCLoc = ConsumeToken();
|
||||||
|
|
||||||
|
// ::new and ::delete aren't nested-name-specifiers, and
|
||||||
|
// MaybeParseCXXScopeSpecifier is never called in a context where one could
|
||||||
|
// exist. This means that if we see it, we have a syntax error.
|
||||||
|
if (Tok.is(tok::kw_new) || Tok.is(tok::kw_delete)) {
|
||||||
|
Diag(Tok, diag::err_invalid_qualified_new_delete)
|
||||||
|
<< Tok.is(tok::kw_delete);
|
||||||
|
SS.setBeginLoc(SourceLocation());
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Global scope.
|
||||||
SS.setScopeRep(Actions.ActOnCXXGlobalScopeSpecifier(CurScope, CCLoc));
|
SS.setScopeRep(Actions.ActOnCXXGlobalScopeSpecifier(CurScope, CCLoc));
|
||||||
SS.setEndLoc(CCLoc);
|
SS.setEndLoc(CCLoc);
|
||||||
}
|
}
|
||||||
|
@ -450,14 +459,14 @@ Parser::OwningExprResult Parser::ParseCXXCondition() {
|
||||||
/// typedef-name
|
/// typedef-name
|
||||||
///
|
///
|
||||||
void Parser::ParseCXXSimpleTypeSpecifier(DeclSpec &DS) {
|
void Parser::ParseCXXSimpleTypeSpecifier(DeclSpec &DS) {
|
||||||
// Annotate typenames and C++ scope specifiers.
|
|
||||||
TryAnnotateTypeOrScopeToken();
|
|
||||||
|
|
||||||
DS.SetRangeStart(Tok.getLocation());
|
DS.SetRangeStart(Tok.getLocation());
|
||||||
const char *PrevSpec;
|
const char *PrevSpec;
|
||||||
SourceLocation Loc = Tok.getLocation();
|
SourceLocation Loc = Tok.getLocation();
|
||||||
|
|
||||||
switch (Tok.getKind()) {
|
switch (Tok.getKind()) {
|
||||||
|
case tok::identifier: // foo::bar
|
||||||
|
case tok::coloncolon: // ::foo::bar
|
||||||
|
assert(0 && "Annotation token should already be formed!");
|
||||||
default:
|
default:
|
||||||
assert(0 && "Not a simple-type-specifier token!");
|
assert(0 && "Not a simple-type-specifier token!");
|
||||||
abort();
|
abort();
|
||||||
|
|
|
@ -743,6 +743,9 @@ Parser::OwningExprResult Parser::ParseSimpleAsm() {
|
||||||
/// ParseDeclarationSpecifiers).
|
/// ParseDeclarationSpecifiers).
|
||||||
///
|
///
|
||||||
/// This returns true if the token was annotated.
|
/// This returns true if the token was annotated.
|
||||||
|
///
|
||||||
|
/// Note that this routine emits an error if you call it with ::new or ::delete
|
||||||
|
/// as the current tokens, so only call it in contexts where these are invalid.
|
||||||
bool Parser::TryAnnotateTypeOrScopeToken(const Token *GlobalQualifier) {
|
bool Parser::TryAnnotateTypeOrScopeToken(const Token *GlobalQualifier) {
|
||||||
// FIXME: what about template-ids?
|
// FIXME: what about template-ids?
|
||||||
if (Tok.is(tok::annot_qualtypename) || Tok.is(tok::annot_cxxscope))
|
if (Tok.is(tok::annot_qualtypename) || Tok.is(tok::annot_cxxscope))
|
||||||
|
@ -809,6 +812,9 @@ bool Parser::TryAnnotateTypeOrScopeToken(const Token *GlobalQualifier) {
|
||||||
/// TryAnnotateScopeToken - Like TryAnnotateTypeOrScopeToken but only
|
/// TryAnnotateScopeToken - Like TryAnnotateTypeOrScopeToken but only
|
||||||
/// annotates C++ scope specifiers. This returns true if the token was
|
/// annotates C++ scope specifiers. This returns true if the token was
|
||||||
/// annotated.
|
/// annotated.
|
||||||
|
///
|
||||||
|
/// Note that this routine emits an error if you call it with ::new or ::delete
|
||||||
|
/// as the current tokens, so only call it in contexts where these are invalid.
|
||||||
bool Parser::TryAnnotateCXXScopeToken() {
|
bool Parser::TryAnnotateCXXScopeToken() {
|
||||||
assert(getLang().CPlusPlus &&
|
assert(getLang().CPlusPlus &&
|
||||||
"Call sites of this function should be guarded by checking for C++");
|
"Call sites of this function should be guarded by checking for C++");
|
||||||
|
|
Loading…
Reference in New Issue