ryee88 updated this revision to Diff 49866.

http://reviews.llvm.org/D16965

Files:
  include/clang/Basic/DiagnosticSemaKinds.td
  lib/Sema/SemaDecl.cpp
  test/Parser/cxx-class.cpp

Index: test/Parser/cxx-class.cpp
===================================================================
--- test/Parser/cxx-class.cpp
+++ test/Parser/cxx-class.cpp
@@ -98,17 +98,36 @@
     // expected-error{{unknown type name 'UnknownType'}}
 }
 
-namespace nns_decl {
-  struct A {
-    struct B;
+namespace NestedNameSpecifiers {
+  struct OuterStruct {
+    struct InnerStruct;
   };
-  namespace N {
-    union C;
+  namespace UnionOuterNamespace {
+    union UnionInner;
   }
-  struct A::B; // expected-error {{forward declaration of struct cannot have a 
nested name specifier}}
-  union N::C; // expected-error {{forward declaration of union cannot have a 
nested name specifier}}
+       class OuterClass{
+               class InnerClass;
+       };
+
+  struct OuterStruct::InnerStruct; // expected-error {{forward declaration of 
struct cannot have a nested name specifier}}
+  struct ::NestedNameSpecifiers::OuterStruct::InnerStruct; // expected-error 
{{forward declaration of struct cannot have a nested name specifier}}
+
+  union UnionOuterNamespace::UnionInner; // expected-error {{forward 
declaration of union cannot have a nested name specifier}}
+  union ::NestedNameSpecifiers::UnionOuterNamespace::UnionInner; // 
expected-error {{forward declaration of union cannot have a nested name 
specifier}}
+
+  class OuterClass::InnerClass; // expected-error {{forward declaration of 
class cannot have a nested name specifier}}
+  class ::NestedNameSpecifiers::OuterClass::InnerClass; // expected-error 
{{forward declaration of class cannot have a nested name specifier}}
 }
 
+// Testing the global "nested" name qualifier
+class GlobalSpecifierOuterClass {class InnerClass;};
+class ::GlobalSpecifierOuterClass; // expected-error {{forward declaration of 
qualified class not allowed}} expected-warning {{extra qualification on member 
'GlobalSpecifierOuterClass'}}
+class GlobalSpecifierOuterClass;
+// specializations of qualified type introduction?
+class GlobalSpecifierOuterClass::InnerClass; // expected-error {{forward 
declaration of class cannot have a nested name specifier}}
+class ::GlobalSpecifierOuterClass::InnerClass; // expected-error {{forward 
declaration of class cannot have a nested name specifier}}
+
+
 // PR13775: Don't assert here.
 namespace PR13775 {
   class bar
Index: lib/Sema/SemaDecl.cpp
===================================================================
--- lib/Sema/SemaDecl.cpp
+++ lib/Sema/SemaDecl.cpp
@@ -3799,6 +3799,17 @@
   if (Tag && SS.isNotEmpty() && !Tag->isCompleteDefinition() &&
       !IsExplicitInstantiation && !IsExplicitSpecialization &&
       !isa<ClassTemplatePartialSpecializationDecl>(Tag)) {
+    
+    // Per C++ standard [n3485] 3.4.4 Elaborated type specifiers, section 3:
+    // "Cannot introduce an qualified".
+    // A clang::NestedNameSpecifier can represent many kinds of specifiers.
+    // A global-specifier with no nested-name-specifier requires a different
+    // diagnostic from a nested-name specifier.
+    unsigned diagId = ( SS.getScopeRep()->getKind() == 
NestedNameSpecifier::Global &&
+      !SS.getScopeRep()->getPrefix() )
+      ? diag::err_standalone_class_specifier
+      : diagId = diag::err_standalone_class_nested_name_specifier;
+
     // Per C++ [dcl.type.elab]p1, a class declaration cannot have a
     // nested-name-specifier unless it is an explicit instantiation
     // or an explicit specialization.
@@ -3807,8 +3818,9 @@
     // obvious intent of DR1819.
     //
     // Per C++ [dcl.enum]p1, an opaque-enum-declaration can't either.
-    Diag(SS.getBeginLoc(), diag::err_standalone_class_nested_name_specifier)
-        << GetDiagnosticTypeSpecifierID(DS.getTypeSpecType()) << SS.getRange();
+    Diag(SS.getBeginLoc(), diagId)
+      << GetDiagnosticTypeSpecifierID(DS.getTypeSpecType()) << SS.getRange();
+
     return nullptr;
   }
 
Index: include/clang/Basic/DiagnosticSemaKinds.td
===================================================================
--- include/clang/Basic/DiagnosticSemaKinds.td
+++ include/clang/Basic/DiagnosticSemaKinds.td
@@ -5266,6 +5266,9 @@
 def err_standalone_class_nested_name_specifier : Error<
   "forward declaration of %select{class|struct|interface|union|enum}0 cannot "
   "have a nested name specifier">;
+def err_standalone_class_specifier : Error<
+  "forward declaration of qualified 
%select{class|struct|interface|union|enum}0 "
+       "not allowed">;
 def err_typecheck_sclass_func : Error<"illegal storage class on function">;
 def err_static_block_func : Error<
   "function declared in block scope cannot have 'static' storage class">;


Index: test/Parser/cxx-class.cpp
===================================================================
--- test/Parser/cxx-class.cpp
+++ test/Parser/cxx-class.cpp
@@ -98,17 +98,36 @@
     // expected-error{{unknown type name 'UnknownType'}}
 }
 
-namespace nns_decl {
-  struct A {
-    struct B;
+namespace NestedNameSpecifiers {
+  struct OuterStruct {
+    struct InnerStruct;
   };
-  namespace N {
-    union C;
+  namespace UnionOuterNamespace {
+    union UnionInner;
   }
-  struct A::B; // expected-error {{forward declaration of struct cannot have a nested name specifier}}
-  union N::C; // expected-error {{forward declaration of union cannot have a nested name specifier}}
+	class OuterClass{
+		class InnerClass;
+	};
+
+  struct OuterStruct::InnerStruct; // expected-error {{forward declaration of struct cannot have a nested name specifier}}
+  struct ::NestedNameSpecifiers::OuterStruct::InnerStruct; // expected-error {{forward declaration of struct cannot have a nested name specifier}}
+
+  union UnionOuterNamespace::UnionInner; // expected-error {{forward declaration of union cannot have a nested name specifier}}
+  union ::NestedNameSpecifiers::UnionOuterNamespace::UnionInner; // expected-error {{forward declaration of union cannot have a nested name specifier}}
+
+  class OuterClass::InnerClass; // expected-error {{forward declaration of class cannot have a nested name specifier}}
+  class ::NestedNameSpecifiers::OuterClass::InnerClass; // expected-error {{forward declaration of class cannot have a nested name specifier}}
 }
 
+// Testing the global "nested" name qualifier
+class GlobalSpecifierOuterClass {class InnerClass;};
+class ::GlobalSpecifierOuterClass; // expected-error {{forward declaration of qualified class not allowed}} expected-warning {{extra qualification on member 'GlobalSpecifierOuterClass'}}
+class GlobalSpecifierOuterClass;
+// specializations of qualified type introduction?
+class GlobalSpecifierOuterClass::InnerClass; // expected-error {{forward declaration of class cannot have a nested name specifier}}
+class ::GlobalSpecifierOuterClass::InnerClass; // expected-error {{forward declaration of class cannot have a nested name specifier}}
+
+
 // PR13775: Don't assert here.
 namespace PR13775 {
   class bar
Index: lib/Sema/SemaDecl.cpp
===================================================================
--- lib/Sema/SemaDecl.cpp
+++ lib/Sema/SemaDecl.cpp
@@ -3799,6 +3799,17 @@
   if (Tag && SS.isNotEmpty() && !Tag->isCompleteDefinition() &&
       !IsExplicitInstantiation && !IsExplicitSpecialization &&
       !isa<ClassTemplatePartialSpecializationDecl>(Tag)) {
+    
+    // Per C++ standard [n3485] 3.4.4 Elaborated type specifiers, section 3:
+    // "Cannot introduce an qualified".
+    // A clang::NestedNameSpecifier can represent many kinds of specifiers.
+    // A global-specifier with no nested-name-specifier requires a different
+    // diagnostic from a nested-name specifier.
+    unsigned diagId = ( SS.getScopeRep()->getKind() == NestedNameSpecifier::Global &&
+      !SS.getScopeRep()->getPrefix() )
+      ? diag::err_standalone_class_specifier
+      : diagId = diag::err_standalone_class_nested_name_specifier;
+
     // Per C++ [dcl.type.elab]p1, a class declaration cannot have a
     // nested-name-specifier unless it is an explicit instantiation
     // or an explicit specialization.
@@ -3807,8 +3818,9 @@
     // obvious intent of DR1819.
     //
     // Per C++ [dcl.enum]p1, an opaque-enum-declaration can't either.
-    Diag(SS.getBeginLoc(), diag::err_standalone_class_nested_name_specifier)
-        << GetDiagnosticTypeSpecifierID(DS.getTypeSpecType()) << SS.getRange();
+    Diag(SS.getBeginLoc(), diagId)
+      << GetDiagnosticTypeSpecifierID(DS.getTypeSpecType()) << SS.getRange();
+
     return nullptr;
   }
 
Index: include/clang/Basic/DiagnosticSemaKinds.td
===================================================================
--- include/clang/Basic/DiagnosticSemaKinds.td
+++ include/clang/Basic/DiagnosticSemaKinds.td
@@ -5266,6 +5266,9 @@
 def err_standalone_class_nested_name_specifier : Error<
   "forward declaration of %select{class|struct|interface|union|enum}0 cannot "
   "have a nested name specifier">;
+def err_standalone_class_specifier : Error<
+  "forward declaration of qualified %select{class|struct|interface|union|enum}0 "
+	"not allowed">;
 def err_typecheck_sclass_func : Error<"illegal storage class on function">;
 def err_static_block_func : Error<
   "function declared in block scope cannot have 'static' storage class">;
_______________________________________________
cfe-commits mailing list
cfe-commits@lists.llvm.org
http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to