]> granicus.if.org Git - clang/commitdiff
ParseCXXSimpleTypeSpecifier can only be called on things that are
authorChris Lattner <sabre@nondot.org>
Mon, 5 Jan 2009 00:13:00 +0000 (00:13 +0000)
committerChris Lattner <sabre@nondot.org>
Mon, 5 Jan 2009 00:13:00 +0000 (00:13 +0000)
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

include/clang/Basic/DiagnosticKinds.def
lib/Parse/ParseExprCXX.cpp
lib/Parse/Parser.cpp

index d2c82dafc86d25ce807d4b36bd0365dcffdecf9d..ed7bdec4b570f9cb953a581233ff299312f290f5 100644 (file)
@@ -1309,6 +1309,8 @@ DIAG(err_array_new_needs_size, ERROR,
      "array size must be specified in new expressions")
 DIAG(err_bad_new_type, ERROR,
     "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,
      "only the first dimension of an allocated array may be non-const")
 DIAG(err_array_size_not_integral, ERROR,
index 195b52e9885c14a3eeb96b72fa0f166d3d135eb2..f9514352ee71de91a295ff995979d3ffb50d2c85 100644 (file)
@@ -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,
index bd334e37bd90e884dbf5b87bf5a6fafd8c50f578..02ddb6823fb26e3b7c73070d23484965a6d8261d 100644 (file)
@@ -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++");