[-fms-extensions] Permit 'override' in C++98 and 'sealed' as a synonym for 'final'

Summary: Some MS headers use these features.

Reviewers: rnk, rsmith

CC: cfe-commits

Differential Revision: http://llvm-reviews.chandlerc.com/D1948

git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@192936 91177308-0d34-0410-b5e6-96231b3b80d8
diff --git a/test/SemaCXX/MicrosoftExtensions.cpp b/test/SemaCXX/MicrosoftExtensions.cpp
index 723beb4..c5b45a2 100644
--- a/test/SemaCXX/MicrosoftExtensions.cpp
+++ b/test/SemaCXX/MicrosoftExtensions.cpp
@@ -385,3 +385,28 @@
     }
   }
 }
+
+// expected-error@+1 {{'sealed' keyword not permitted with interface types}}
+__interface InterfaceWithSealed sealed {
+};
+
+struct SomeBase {
+  virtual void OverrideMe();
+
+  // expected-note@+2 {{overridden virtual function is here}}
+  // expected-warning@+1 {{'sealed' keyword is a Microsoft extension}}
+  virtual void SealedFunction() sealed;
+};
+
+// expected-note@+2 {{'SealedType' declared here}}
+// expected-warning@+1 {{'sealed' keyword is a Microsoft extension}}
+struct SealedType sealed : SomeBase {
+  // expected-error@+1 {{declaration of 'SealedFunction' overrides a 'sealed' function}}
+  virtual void SealedFunction();
+
+  // expected-warning@+1 {{'override' keyword is a C++11 extension}}
+  virtual void OverrideMe() override;
+};
+
+// expected-error@+1 {{base 'SealedType' is marked 'sealed'}}
+struct InheritFromSealed : SealedType {};
diff --git a/test/SemaCXX/type-traits.cpp b/test/SemaCXX/type-traits.cpp
index d73b2d8..3e47921 100644
--- a/test/SemaCXX/type-traits.cpp
+++ b/test/SemaCXX/type-traits.cpp
@@ -1,4 +1,4 @@
-// RUN: %clang_cc1 -triple x86_64-apple-darwin10 -fsyntax-only -verify -std=gnu++11 %s 
+// RUN: %clang_cc1 -triple x86_64-apple-darwin10 -fsyntax-only -verify -std=gnu++11 -fms-extensions -Wno-microsoft %s
 #define T(b) (b) ? 1 : -1
 #define F(b) (b) ? -1 : 1
 
@@ -308,6 +308,37 @@
 	{ int arr[F(__is_final(PotentiallyFinal<float>))]; }
 }
 
+struct SealedClass sealed {
+};
+
+template<typename T>
+struct PotentiallySealed { };
+
+template<typename T>
+struct PotentiallySealed<T*> sealed { };
+
+template<>
+struct PotentiallySealed<int> sealed { };
+
+void is_sealed()
+{
+	{ int arr[T(__is_sealed(SealedClass))]; }
+	{ int arr[T(__is_sealed(PotentiallySealed<float*>))]; }
+	{ int arr[T(__is_sealed(PotentiallySealed<int>))]; }
+
+	{ int arr[F(__is_sealed(int))]; }
+	{ int arr[F(__is_sealed(Union))]; }
+	{ int arr[F(__is_sealed(Int))]; }
+	{ int arr[F(__is_sealed(IntAr))]; }
+	{ int arr[F(__is_sealed(UnionAr))]; }
+	{ int arr[F(__is_sealed(Derives))]; }
+	{ int arr[F(__is_sealed(ClassType))]; }
+	{ int arr[F(__is_sealed(cvoid))]; }
+	{ int arr[F(__is_sealed(IntArNB))]; }
+	{ int arr[F(__is_sealed(HasAnonymousUnion))]; }
+	{ int arr[F(__is_sealed(PotentiallyFinal<float>))]; }
+}
+
 typedef HasVirt Polymorph;
 struct InheritPolymorph : Polymorph {};