diff --git a/gcc/c-family/c-common.c b/gcc/c-family/c-common.c
index 2156fa8..3e46019 100644
--- a/gcc/c-family/c-common.c
+++ b/gcc/c-family/c-common.c
@@ -9653,4 +9653,42 @@ keyword_is_storage_class_specifier (enum rid keyword)
     }
 }
 
+/* Return true if KEYWORD names a function-specifier [dcl.fct.spec].  */
+
+static bool
+keyword_is_function_specifier (enum rid keyword)
+{
+  switch (keyword)
+    {
+    case RID_INLINE:
+    case RID_VIRTUAL:
+    case RID_EXPLICIT:
+      return true;
+    default:
+      return false;
+    }
+}
+
+/* Return true if KEYWORD names a decl-specifier [dcl.spec] or a
+   declaration-specifier (C99 6.7).  */
+
+bool
+keyword_is_decl_specifier (enum rid keyword)
+{
+  if (keyword_is_storage_class_specifier (keyword)
+      || keyword_is_type_qualifier (keyword)
+      || keyword_is_function_specifier (keyword))
+    return true;
+
+  switch (keyword)
+    {
+    case RID_TYPEDEF:
+    case RID_FRIEND:
+    case RID_CONSTEXPR:
+      return true;
+    default:
+      return false;
+    }
+}
+
 #include "gt-c-family-c-common.h"
diff --git a/gcc/c-family/c-common.h b/gcc/c-family/c-common.h
index 05456d3..406def9 100644
--- a/gcc/c-family/c-common.h
+++ b/gcc/c-family/c-common.h
@@ -741,6 +741,7 @@ extern bool float_const_decimal64_p (void);
 extern bool keyword_begins_type_specifier (enum rid);
 extern bool keyword_is_storage_class_specifier (enum rid);
 extern bool keyword_is_type_qualifier (enum rid);
+extern bool keyword_is_decl_specifier (enum rid);
 
 #define c_sizeof(LOC, T)  c_sizeof_or_alignof_type (LOC, T, true, 1)
 #define c_alignof(LOC, T) c_sizeof_or_alignof_type (LOC, T, false, 1)
diff --git a/gcc/cp/parser.c b/gcc/cp/parser.c
index 41f82ac..4a6a8d0 100644
--- a/gcc/cp/parser.c
+++ b/gcc/cp/parser.c
@@ -16998,18 +16998,15 @@ cp_parser_class_specifier (cp_parser* parser)
 	   class Z { }
 	   static const <type> var = ...;  */
       case CPP_KEYWORD:
-	if (keyword_is_storage_class_specifier (token->keyword)
-	    || keyword_is_type_qualifier (token->keyword))
+	if (keyword_is_decl_specifier (token->keyword))
 	  {
 	    cp_token *lookahead = cp_lexer_peek_nth_token (parser->lexer, 2);
 
-	    if (lookahead->type == CPP_KEYWORD
-		&& !keyword_begins_type_specifier (lookahead->keyword))
-	      want_semicolon = false;
-	    else if (lookahead->type == CPP_NAME)
-	      /* Handling user-defined types here would be nice, but
-		 very tricky.  */
-	      want_semicolon = false;
+	    /* Handling user-defined types here would be nice, but very
+	       tricky.  */
+	    want_semicolon
+	      = (lookahead->type == CPP_KEYWORD
+		 && keyword_begins_type_specifier (lookahead->keyword));
 	  }
 	break;
       default:
diff --git a/gcc/testsuite/g++.dg/parse/semicolon3.C b/gcc/testsuite/g++.dg/parse/semicolon3.C
index a119ef4..bc43b48 100644
--- a/gcc/testsuite/g++.dg/parse/semicolon3.C
+++ b/gcc/testsuite/g++.dg/parse/semicolon3.C
@@ -62,6 +62,48 @@ autotest (void)
   return ok10.a;
 }
 
+struct OK11
+{
+  int a;
+} // no complaints
+  const *ok11_var;
+
+struct OK12
+{
+  int a;
+} // no complaints
+  const &ok12_var = *(new OK12());
+
+struct OK13
+{
+  int a;
+} // no complaints
+  static *ok13_var;
+
+class OK14
+{
+  struct OK14sub
+  {
+    int a;
+  } // no complaints
+    static &ok14_var;
+};
+
+class OK15
+{
+  int a;
+} typedef tOK15;
+
+class OK16
+{
+  int a;
+} typedef *pOK16;
+
+class OK17
+{
+  int a;
+} typedef &rOK16;
+
 struct E1
 {
   int a;
@@ -196,6 +238,13 @@ class E17
     mutable int i;
 } // { dg-error "after class definition" }
 
+class E18
+{
+  int a;
+} // { dg-error "after class definition" }
+
+typedef int E18int;
+
 /* This was the original test from the PR.  */
 
 class C0
diff --git a/gcc/testsuite/g++.dg/parse/semicolon4.C b/gcc/testsuite/g++.dg/parse/semicolon4.C
new file mode 100644
index 0000000..adba7a8
--- /dev/null
+++ b/gcc/testsuite/g++.dg/parse/semicolon4.C
@@ -0,0 +1,37 @@
+// PR c++/46890
+// { dg-do compile }
+
+struct OK1
+{
+  int i;
+} const *ok1_var;		// No complains
+
+struct OK2;
+extern OK2 ok2a_var;
+
+struct OK2
+{
+  int i;
+} const &ok2_var = ok2a_var;	// No complains
+
+struct OK3
+{
+  int i;
+} volatile (ok3_var);		// No complains
+
+struct E1
+{
+  int i;
+} const;			// { dg-error "qualifiers can only be specified for objects and functions" }
+
+void foo (
+struct E2
+{				// { dg-error "types may not be defined in parameter types" }
+  int i;
+} volatile);
+
+void bar (
+struct E3
+{				// { dg-error "types may not be defined in parameter types" }
+  int i;
+} const, int);
diff --git a/gcc/testsuite/g++.dg/pr46890.C b/gcc/testsuite/g++.dg/pr46890.C
new file mode 100644
index 0000000..3ecef5a
--- /dev/null
+++ b/gcc/testsuite/g++.dg/pr46890.C
@@ -0,0 +1,6 @@
+// PR c++/46890
+// { dg-do compile }
+
+struct MdatResource {
+const char *mdatAlloc;
+} const *_resource;
