]> granicus.if.org Git - clang/commitdiff
PR5066: If a declarator cannot have an identifier, and cannot possibly be
authorRichard Smith <richard-llvm@metafoo.co.uk>
Thu, 11 Jul 2013 05:10:21 +0000 (05:10 +0000)
committerRichard Smith <richard-llvm@metafoo.co.uk>
Thu, 11 Jul 2013 05:10:21 +0000 (05:10 +0000)
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;

git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@186061 91177308-0d34-0410-b5e6-96231b3b80d8

include/clang/Basic/DiagnosticParseKinds.td
include/clang/Sema/DeclSpec.h
lib/Parse/ParseDecl.cpp
test/FixIt/fixit.cpp
test/Parser/cxx-decl.cpp
test/Parser/cxx-template-argument.cpp
test/Parser/cxx0x-decl.cpp

index 26030775337fdee8fe0b3b10b6d23445bee3aeb0..d5982e9825d9f678e47aeed3d509a45143e5722e 100644 (file)
@@ -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<
index ef74abe188b025062529889d8fb91cba3e336eab..5924a15b7e4ff793cfc9917ed1e7f0eae2fb3ae4 100644 (file)
@@ -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 {
index 7559aa95965e04eece703d29a4c4952b7d109426..0b276d0b58f55b6e30781f156c3867cb7f4cb142 100644 (file)
@@ -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)) {
index 4e1900a346f8f93f51ec8d53fe65b0c9f766356b..22c1003e8c944d4730e918e2d9774374be0fc468 100644 (file)
@@ -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}}
+}
index 41d305b17642b08a09bed0cf9ac62505adbaeac0..e3f3957d564cfa51bd3c63eeafa1b0620af87c2e 100644 (file)
@@ -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}} \
index afe318df7a1aaf6ee57500a65304aee6ec3dc1a7..a2c69be64630a97741186f00055f74f2cdd6fccc 100644 (file)
@@ -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 {};
index e6cba726ab631b1e56def9742fc25a540d195b4d..3d04bfe81608c4360734ab7797bba888a219791b 100644 (file)
@@ -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}}
+}