aboutsummaryrefslogtreecommitdiff
path: root/lib/Parse
diff options
context:
space:
mode:
authorChris Lattner <sabre@nondot.org>2009-01-05 00:13:00 +0000
committerChris Lattner <sabre@nondot.org>2009-01-05 00:13:00 +0000
commit55a7cefc846765ac7d142a63f773747a20518d71 (patch)
tree91959d218c8c29b3a09448b825973155430597fe /lib/Parse
parent5e02c47a7085831586344a9728763cb50540c7f7 (diff)
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. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@61659 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'lib/Parse')
-rw-r--r--lib/Parse/ParseExprCXX.cpp39
-rw-r--r--lib/Parse/Parser.cpp6
2 files changed, 30 insertions, 15 deletions
diff --git a/lib/Parse/ParseExprCXX.cpp b/lib/Parse/ParseExprCXX.cpp
index 195b52e988..f9514352ee 100644
--- a/lib/Parse/ParseExprCXX.cpp
+++ b/lib/Parse/ParseExprCXX.cpp
@@ -19,6 +19,9 @@ using namespace clang;
/// MaybeParseCXXScopeSpecifier - Parse global scope or nested-name-specifier.
/// 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
/// '::'
@@ -36,7 +39,7 @@ bool Parser::MaybeParseCXXScopeSpecifier(CXXScopeSpec &SS,
if (Tok.is(tok::annot_cxxscope)) {
assert(GlobalQualifier == 0 &&
- "Cannot have :: followed by a resolve annotation scope");
+ "Cannot have :: followed by a resolved annotation scope");
SS.setScopeRep(Tok.getAnnotationValue());
SS.setRange(Tok.getAnnotationRange());
ConsumeToken();
@@ -48,27 +51,33 @@ bool Parser::MaybeParseCXXScopeSpecifier(CXXScopeSpec &SS,
(Tok.isNot(tok::identifier) || NextToken().isNot(tok::coloncolon)))
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) {
// Pre-parsed '::'.
SS.setBeginLoc(GlobalQualifier->getLocation());
SS.setScopeRep(Actions.ActOnCXXGlobalScopeSpecifier(CurScope,
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 {
SS.setBeginLoc(Tok.getLocation());
- // '::'
+ // '::' - Global scope qualifier.
if (Tok.is(tok::coloncolon)) {
- // Global scope.
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.setEndLoc(CCLoc);
}
@@ -450,18 +459,18 @@ Parser::OwningExprResult Parser::ParseCXXCondition() {
/// typedef-name
///
void Parser::ParseCXXSimpleTypeSpecifier(DeclSpec &DS) {
- // Annotate typenames and C++ scope specifiers.
- TryAnnotateTypeOrScopeToken();
-
DS.SetRangeStart(Tok.getLocation());
const char *PrevSpec;
SourceLocation Loc = Tok.getLocation();
switch (Tok.getKind()) {
+ case tok::identifier: // foo::bar
+ case tok::coloncolon: // ::foo::bar
+ assert(0 && "Annotation token should already be formed!");
default:
assert(0 && "Not a simple-type-specifier token!");
abort();
-
+
// type-name
case tok::annot_qualtypename: {
DS.SetTypeSpecType(DeclSpec::TST_typedef, Loc, PrevSpec,
diff --git a/lib/Parse/Parser.cpp b/lib/Parse/Parser.cpp
index bd334e37bd..02ddb6823f 100644
--- a/lib/Parse/Parser.cpp
+++ b/lib/Parse/Parser.cpp
@@ -743,6 +743,9 @@ Parser::OwningExprResult Parser::ParseSimpleAsm() {
/// ParseDeclarationSpecifiers).
///
/// 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) {
// FIXME: what about template-ids?
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
/// annotates C++ scope specifiers. 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::TryAnnotateCXXScopeToken() {
assert(getLang().CPlusPlus &&
"Call sites of this function should be guarded by checking for C++");