Bug 517326: [9] support advanced deprecation

Change-Id: I726e24aea0b368e8ffe678bc39c580c27ac4f6ef
diff --git a/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/regression/BatchCompilerTest.java b/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/regression/BatchCompilerTest.java
index 26e421b..a61bd01 100644
--- a/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/regression/BatchCompilerTest.java
+++ b/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/regression/BatchCompilerTest.java
@@ -864,6 +864,7 @@
         "      paramAssign          assignment to a parameter\n" + 
         "      pkgDefaultMethod   + attempt to override package-default method\n" + 
         "      raw                + usage of raw type\n" + 
+        "      removal            + deprecation marked for removal\n" + 
         "      resource           + (pot.) unsafe usage of resource of type Closeable\n" + 
         "      semicolon            unnecessary semicolon, empty statement\n" + 
         "      serial             + missing serialVersionUID\n" + 
@@ -1075,6 +1076,7 @@
 			"		<option key=\"org.eclipse.jdt.core.compiler.problem.syntacticNullAnalysisForFields\" value=\"disabled\"/>\n" +
 			"		<option key=\"org.eclipse.jdt.core.compiler.problem.syntheticAccessEmulation\" value=\"ignore\"/>\n" + 
 			"		<option key=\"org.eclipse.jdt.core.compiler.problem.tasks\" value=\"warning\"/>\n" + 
+			"		<option key=\"org.eclipse.jdt.core.compiler.problem.terminalDeprecation\" value=\"warning\"/>\n" +
 			"		<option key=\"org.eclipse.jdt.core.compiler.problem.typeParameterHiding\" value=\"warning\"/>\n" + 
 			"		<option key=\"org.eclipse.jdt.core.compiler.problem.unavoidableGenericTypeProblems\" value=\"enabled\"/>\n" + 
 			"		<option key=\"org.eclipse.jdt.core.compiler.problem.uncheckedTypeOperation\" value=\"warning\"/>\n" + 
diff --git a/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/regression/CompilerInvocationTests.java b/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/regression/CompilerInvocationTests.java
index 5da04c5..d8076a6 100644
--- a/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/regression/CompilerInvocationTests.java
+++ b/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/regression/CompilerInvocationTests.java
@@ -903,6 +903,7 @@
 		expectedProblemAttributes.put("OuterLocalMustBeEffectivelyFinal", new ProblemAttributes(CategorizedProblem.CAT_INTERNAL));
 		expectedProblemAttributes.put("OuterLocalMustBeFinal", new ProblemAttributes(CategorizedProblem.CAT_INTERNAL));
 		expectedProblemAttributes.put("OverridingDeprecatedMethod", new ProblemAttributes(CategorizedProblem.CAT_DEPRECATION));
+		expectedProblemAttributes.put("OverridingTerminallyDeprecatedMethod", new ProblemAttributes(CategorizedProblem.CAT_DEPRECATION));
 		expectedProblemAttributes.put("OverridingMethodWithoutSuperInvocation", new ProblemAttributes(CategorizedProblem.CAT_POTENTIAL_PROGRAMMING_PROBLEM));
 		expectedProblemAttributes.put("OverridingNonVisibleMethod", new ProblemAttributes(CategorizedProblem.CAT_NAME_SHADOWING_CONFLICT));
 		expectedProblemAttributes.put("PackageCollidesWithType", new ProblemAttributes(CategorizedProblem.CAT_TYPE));
@@ -1118,6 +1119,10 @@
 		expectedProblemAttributes.put("UsingDeprecatedField", new ProblemAttributes(CategorizedProblem.CAT_DEPRECATION));
 		expectedProblemAttributes.put("UsingDeprecatedMethod", new ProblemAttributes(CategorizedProblem.CAT_DEPRECATION));
 		expectedProblemAttributes.put("UsingDeprecatedType", new ProblemAttributes(CategorizedProblem.CAT_DEPRECATION));
+		expectedProblemAttributes.put("UsingTerminallyDeprecatedConstructor", new ProblemAttributes(CategorizedProblem.CAT_DEPRECATION));
+		expectedProblemAttributes.put("UsingTerminallyDeprecatedField", new ProblemAttributes(CategorizedProblem.CAT_DEPRECATION));
+		expectedProblemAttributes.put("UsingTerminallyDeprecatedMethod", new ProblemAttributes(CategorizedProblem.CAT_DEPRECATION));
+		expectedProblemAttributes.put("UsingTerminallyDeprecatedType", new ProblemAttributes(CategorizedProblem.CAT_DEPRECATION));
 		expectedProblemAttributes.put("VarargsElementTypeNotVisible", new ProblemAttributes(CategorizedProblem.CAT_MEMBER));
 		expectedProblemAttributes.put("VarargsElementTypeNotVisibleForConstructor", new ProblemAttributes(CategorizedProblem.CAT_MEMBER));
 		expectedProblemAttributes.put("VarargsConflict", new ProblemAttributes(CategorizedProblem.CAT_MEMBER));
@@ -1771,6 +1776,7 @@
 		expectedProblemAttributes.put("OuterLocalMustBeEffectivelyFinal", SKIP);
 		expectedProblemAttributes.put("OuterLocalMustBeFinal", SKIP);
 		expectedProblemAttributes.put("OverridingDeprecatedMethod", new ProblemAttributes(JavaCore.COMPILER_PB_DEPRECATION));
+		expectedProblemAttributes.put("OverridingTerminallyDeprecatedMethod", new ProblemAttributes(JavaCore.COMPILER_PB_TERMINAL_DEPRECATION));
 		expectedProblemAttributes.put("OverridingMethodWithoutSuperInvocation", new ProblemAttributes(JavaCore.COMPILER_PB_OVERRIDING_METHOD_WITHOUT_SUPER_INVOCATION));
 		expectedProblemAttributes.put("OverridingNonVisibleMethod", new ProblemAttributes(JavaCore.COMPILER_PB_OVERRIDING_PACKAGE_DEFAULT_METHOD));
 		expectedProblemAttributes.put("PackageCollidesWithType", SKIP);
@@ -1986,6 +1992,10 @@
 		expectedProblemAttributes.put("UsingDeprecatedField", new ProblemAttributes(JavaCore.COMPILER_PB_DEPRECATION));
 		expectedProblemAttributes.put("UsingDeprecatedMethod", new ProblemAttributes(JavaCore.COMPILER_PB_DEPRECATION));
 		expectedProblemAttributes.put("UsingDeprecatedType", new ProblemAttributes(JavaCore.COMPILER_PB_DEPRECATION));
+		expectedProblemAttributes.put("UsingTerminallyDeprecatedConstructor", new ProblemAttributes(JavaCore.COMPILER_PB_TERMINAL_DEPRECATION));
+		expectedProblemAttributes.put("UsingTerminallyDeprecatedField", new ProblemAttributes(JavaCore.COMPILER_PB_TERMINAL_DEPRECATION));
+		expectedProblemAttributes.put("UsingTerminallyDeprecatedMethod", new ProblemAttributes(JavaCore.COMPILER_PB_TERMINAL_DEPRECATION));
+		expectedProblemAttributes.put("UsingTerminallyDeprecatedType", new ProblemAttributes(JavaCore.COMPILER_PB_TERMINAL_DEPRECATION));
 		expectedProblemAttributes.put("VarargsConflict", SKIP);
 		expectedProblemAttributes.put("VarargsElementTypeNotVisible", SKIP);
 		expectedProblemAttributes.put("VarargsElementTypeNotVisibleForConstructor", SKIP);
diff --git a/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/regression/Deprecated9Test.java b/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/regression/Deprecated9Test.java
new file mode 100644
index 0000000..993a369
--- /dev/null
+++ b/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/regression/Deprecated9Test.java
@@ -0,0 +1,309 @@
+/*******************************************************************************
+ * Copyright (c) 2017 GK Software AG, and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * This is an implementation of an early-draft specification developed under the Java
+ * Community Process (JCP) and is made available for testing and evaluation purposes
+ * only. The code is not compatible with any specification of the JCP.
+ *
+ * Contributors:
+ *     Stephan Herrmann - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.jdt.core.tests.compiler.regression;
+
+import java.util.HashMap;
+import java.util.Map;
+
+import org.eclipse.jdt.core.JavaCore;
+import org.eclipse.jdt.internal.compiler.impl.CompilerOptions;
+
+import junit.framework.Test;
+
+public class Deprecated9Test extends AbstractRegressionTest {
+	public Deprecated9Test(String name) {
+		super(name);
+	}
+	public static Test suite() {
+		return buildMinimalComplianceTestSuite(testClass(), F_9);
+	}
+
+	static {
+//		TESTS_NAMES = new String[] { "test007" };
+	}
+	// https://bugs.eclipse.org/bugs/show_bug.cgi?id=159709
+	// guard variant for DeprecatedTest#test015 using an annotation
+	public void test002() {
+		Map<String, String> customOptions = new HashMap<>();
+		customOptions.put(JavaCore.COMPILER_PB_DEPRECATION, CompilerOptions.WARNING);
+		customOptions.put(JavaCore.COMPILER_PB_TERMINAL_DEPRECATION, CompilerOptions.ERROR);
+		customOptions.put(CompilerOptions.OPTION_ReportNullReference, CompilerOptions.IGNORE);
+		this.runNegativeTest(
+			true,
+			new String[] {
+				"p/M1.java",
+				"package p;\n" +
+				"public class M1 {\n" +
+				"  void bar() {\n" +
+				"    a.N1.N2.N3 m = null;\n" +
+				"    m.foo();\n" +
+				"  }\n" +
+				"}\n",
+				"a/N1.java",
+				"package a;\n" +
+				"public class N1 {\n" +
+				"  @Deprecated(since=\"1.2\",forRemoval=true)\n" +
+				"  public class N2 {" +
+				"    public void foo() {}" +
+				"    public class N3 {" +
+				"      public void foo() {}" +
+				"    }" +
+				"  }" +
+				"}\n",
+			},
+			null, customOptions,
+			"----------\n" +
+			"1. ERROR in p\\M1.java (at line 4)\n" +
+			"	a.N1.N2.N3 m = null;\n" +
+			"	     ^^\n" +
+			"The type N1.N2 has been deprecated and marked for removal\n" +
+			"----------\n" +
+			"2. ERROR in p\\M1.java (at line 4)\n" +
+			"	a.N1.N2.N3 m = null;\n" +
+			"	        ^^\n" +
+			"The type N1.N2.N3 has been deprecated and marked for removal\n" +
+			"----------\n" +
+			"3. ERROR in p\\M1.java (at line 5)\n" +
+			"	m.foo();\n" +
+			"	  ^^^^^\n" +
+			"The method foo() from the type N1.N2.N3 has been deprecated and marked for removal\n" +
+			"----------\n",
+			JavacTestOptions.Excuse.EclipseWarningConfiguredAsError);
+	}
+	//https://bugs.eclipse.org/bugs/show_bug.cgi?id=191909
+	public void test004() {
+		Map<String, String> customOptions = new HashMap<>();
+		customOptions.put(JavaCore.COMPILER_PB_DEPRECATION, CompilerOptions.WARNING);
+		customOptions.put(JavaCore.COMPILER_PB_TERMINAL_DEPRECATION, CompilerOptions.ERROR);
+		this.runNegativeTest(
+			true,
+			new String[] {
+				"test1/E01.java",
+				"package test1;\n" +
+				"public class E01 {\n" +
+				"	@Deprecated(forRemoval=true,since=\"3\")\n" +
+				"	public static int x = 5, y= 10;\n" +
+				"}",
+				"test1/E02.java",
+				"package test1;\n" +
+				"public class E02 {\n" +
+				"	public void foo() {\n" +
+				"		System.out.println(E01.x);\n" +
+				"		System.out.println(E01.y);\n" +
+				"	}\n" +
+				"}"
+			},
+			null, customOptions,
+			"----------\n" +
+			"1. ERROR in test1\\E02.java (at line 4)\n" +
+			"	System.out.println(E01.x);\n" +
+			"	                       ^\n" +
+			"The field E01.x has been deprecated and marked for removal\n" +
+			"----------\n" +
+			"2. ERROR in test1\\E02.java (at line 5)\n" +
+			"	System.out.println(E01.y);\n" +
+			"	                       ^\n" +
+			"The field E01.y has been deprecated and marked for removal\n" +
+			"----------\n",
+			JavacTestOptions.Excuse.EclipseWarningConfiguredAsError);
+	}
+	// Bug 354536 - compiling package-info.java still depends on the order of compilation units
+	public void test005a() {
+		Map<String, String> customOptions = new HashMap<>();
+		customOptions.put(CompilerOptions.OPTION_ReportDeprecation, CompilerOptions.WARNING);
+		customOptions.put(CompilerOptions.OPTION_ReportTerminalDeprecation, CompilerOptions.ERROR);
+		this.runNegativeTest(
+			true,
+			new String[] {
+				"p1/X.java",
+				"package p1;\n" +
+				"public class X {\n" +
+				"    public static class Inner {" +
+				"        public void foo() {}\n" +
+				"    }\n" +
+				"}\n",
+				"p1/package-info.java",
+				"@java.lang.Deprecated(forRemoval=true)\n" +
+				"package p1;\n",
+				"p2/C.java",
+				"package p2;\n" +
+				"public class C {\n" +
+				"    void bar(p1.X.Inner a) {\n" +
+				"        a.foo();\n" +
+				"    }\n" +
+				"}\n",
+			},
+			null, customOptions,
+			"----------\n" +
+			"1. ERROR in p2\\C.java (at line 3)\n" + 
+			"	void bar(p1.X.Inner a) {\n" + 
+			"	            ^\n" + 
+			"The type X has been deprecated and marked for removal\n" + 
+			"----------\n" + 
+			"2. ERROR in p2\\C.java (at line 3)\n" + 
+			"	void bar(p1.X.Inner a) {\n" + 
+			"	              ^^^^^\n" + 
+			"The type X.Inner has been deprecated and marked for removal\n" + 
+			"----------\n" + 
+			"3. ERROR in p2\\C.java (at line 4)\n" + 
+			"	a.foo();\n" + 
+			"	  ^^^^^\n" + 
+			"The method foo() from the type X.Inner has been deprecated and marked for removal\n" + 
+			"----------\n",
+			JavacTestOptions.Excuse.EclipseWarningConfiguredAsError);
+	}
+	// Bug 354536 - compiling package-info.java still depends on the order of compilation units
+	// - option is disabled
+	public void test005b() {
+		Map<String, String> customOptions = new HashMap<>();
+		customOptions.put(CompilerOptions.OPTION_ReportDeprecation, CompilerOptions.WARNING);
+		customOptions.put(CompilerOptions.OPTION_ReportTerminalDeprecation, CompilerOptions.IGNORE);
+		this.runConformTest(
+			new String[] {
+				"p1/X.java",
+				"package p1;\n" +
+				"public class X {\n" +
+				"    public static class Inner {" +
+				"        public void foo() {}\n" +
+				"    }\n" +
+				"}\n",
+				"p1/package-info.java",
+				"@java.lang.Deprecated(forRemoval=true)\n" +
+				"package p1;\n",
+				"p2/C.java",
+				"package p2;\n" +
+				"public class C {\n" +
+				"    void bar(p1.X.Inner a) {\n" +
+				"        a.foo();\n" +
+				"    }\n" +
+				"}\n",
+			},
+			customOptions);
+	}
+	// Bug 354536 - compiling package-info.java still depends on the order of compilation units
+	// some warnings suppressed
+	public void test005c() {
+		Map<String, String> customOptions = new HashMap<>();
+		customOptions.put(CompilerOptions.OPTION_ReportDeprecation, CompilerOptions.WARNING);
+		customOptions.put(CompilerOptions.OPTION_ReportTerminalDeprecation, CompilerOptions.WARNING);
+		this.runNegativeTest(
+			true,
+			new String[] {
+				"p1/X.java",
+				"package p1;\n" +
+				"public class X {\n" +
+				"    public static class Inner {\n" +
+				"		 @java.lang.Deprecated(forRemoval=true)\n" + 
+				"        public void foo() {}\n" +
+				"    }\n" +
+				"}\n",
+				"p1/package-info.java",
+				"@java.lang.Deprecated(forRemoval=false)\n" +
+				"package p1;\n",
+				"p2/C.java",
+				"package p2;\n" +
+				"public class C {\n" +
+				"	 @SuppressWarnings(\"deprecation\")\n" +
+				"    void bar(p1.X.Inner a) {\n" +
+				"        a.foo();\n" +
+				"    }\n" +
+				"}\n",
+			},
+			null, customOptions,
+			"----------\n" +
+			"1. WARNING in p2\\C.java (at line 5)\n" + 
+			"	a.foo();\n" + 
+			"	  ^^^^^\n" + 
+			"The method foo() from the type X.Inner has been deprecated and marked for removal\n" + 
+			"----------\n",
+			JavacTestOptions.Excuse.EclipseWarningConfiguredAsError);
+	}
+	// https://bugs.eclipse.org/384870 - [compiler] @Deprecated annotation not detected if preceded by other annotation
+	// old-style deprecation
+	public void test006() {
+		Map<String, String> customOptions = new HashMap<>();
+		customOptions.put(CompilerOptions.OPTION_ReportDeprecation, CompilerOptions.WARNING);
+		customOptions.put(CompilerOptions.OPTION_ReportTerminalDeprecation, CompilerOptions.ERROR);
+		this.runNegativeTest(
+			true,
+			new String[] {
+				"test1/E02.java",
+				"package test1;\n" +
+				"public class E02 {\n" +
+				"	public void foo(E01 arg) {\n" +
+				"		// nop\n" +
+				"	}\n" +
+				"}",
+				"test1/E01.java",
+				"package test1;\n" +
+				"@SuppressWarnings(\"all\") @Deprecated(since=\"4\")\n" +
+				"public class E01 {\n" +
+				"	public static int x = 5;\n" +
+				"}"
+			},
+			null, customOptions,
+			"----------\n" + 
+			"1. WARNING in test1\\E02.java (at line 3)\n" + 
+			"	public void foo(E01 arg) {\n" + 
+			"	                ^^^\n" + 
+			"The type E01 is deprecated\n" + 
+			"----------\n",
+			JavacTestOptions.Excuse.EclipseWarningConfiguredAsError);
+	}
+	// method overriding
+	public void test007() {
+		Map<String, String> customOptions = new HashMap<>();
+		customOptions.put(CompilerOptions.OPTION_ReportDeprecation, CompilerOptions.WARNING);
+		customOptions.put(CompilerOptions.OPTION_ReportTerminalDeprecation, CompilerOptions.ERROR);
+		customOptions.put(CompilerOptions.OPTION_ReportDeprecationWhenOverridingDeprecatedMethod, CompilerOptions.ENABLED);
+		this.runNegativeTest(
+			true,
+			new String[] {
+				"p1/X.java",
+				"package p1;\n" +
+				"public class X {\n" +
+				"	 @java.lang.Deprecated(forRemoval=false)\n" +
+				"    public void foo() {}\n" +
+				"	 @java.lang.Deprecated(forRemoval=true)\n" +
+				"	 public void bar() {}\n" +
+				"}\n",
+				"p2/C.java",
+				"package p2;\n" +
+				"import p1.X;\n" +
+				"public class C extends X {\n" +
+				"    @Override public void foo() {}\n" +
+				"    @Override public void bar() {}\n" +
+				"}\n",
+			},
+			null, customOptions,
+			"----------\n" + 
+			"1. WARNING in p2\\C.java (at line 4)\n" + 
+			"	@Override public void foo() {}\n" + 
+			"	                      ^^^^^\n" + 
+			"The method C.foo() overrides a deprecated method from X\n" + 
+			"----------\n" + 
+			"2. ERROR in p2\\C.java (at line 5)\n" + 
+			"	@Override public void bar() {}\n" + 
+			"	                      ^^^^^\n" + 
+			"The method C.bar() overrides a method from X that has been deprecated and marked for removal\n" + 
+			"----------\n",
+			JavacTestOptions.Excuse.EclipseWarningConfiguredAsError);
+	}
+
+	public static Class<?> testClass() {
+		return Deprecated9Test.class;
+	}
+
+}
diff --git a/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/regression/TestAll.java b/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/regression/TestAll.java
index f4f9bc8..38f16b3 100644
--- a/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/regression/TestAll.java
+++ b/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/regression/TestAll.java
@@ -162,6 +162,8 @@
 	since_9.add(ModuleCompilationTests.class);
 	since_9.add(GenericsRegressionTest_9.class);
 	since_9.add(InterfaceMethodsTest_9.class);
+	since_9.add(Deprecated9Test.class);
+
 	
 	// Build final test suite
 	TestSuite all = new TestSuite(TestAll.class.getName());
diff --git a/org.eclipse.jdt.core/batch/org/eclipse/jdt/internal/compiler/batch/Main.java b/org.eclipse.jdt.core/batch/org/eclipse/jdt/internal/compiler/batch/Main.java
index b1f3e2b..e93463f 100644
--- a/org.eclipse.jdt.core/batch/org/eclipse/jdt/internal/compiler/batch/Main.java
+++ b/org.eclipse.jdt.core/batch/org/eclipse/jdt/internal/compiler/batch/Main.java
@@ -3755,6 +3755,7 @@
 		case 'a' :
 			if (token.equals("allDeprecation")) { //$NON-NLS-1$
 				setSeverity(CompilerOptions.OPTION_ReportDeprecation, severity, isEnabling);
+				setSeverity(CompilerOptions.OPTION_ReportTerminalDeprecation, severity, isEnabling);
 				this.options.put(
 					CompilerOptions.OPTION_ReportDeprecationInDeprecatedCode,
 					isEnabling ? CompilerOptions.ENABLED : CompilerOptions.DISABLED);
@@ -4200,6 +4201,15 @@
 				setSeverity(CompilerOptions.OPTION_ReportPotentiallyUnclosedCloseable, severity, isEnabling);
 				setSeverity(CompilerOptions.OPTION_ReportExplicitlyClosedAutoCloseable, severity, isEnabling);
 				return;
+			} else if (token.equals("removal")) { //$NON-NLS-1$
+				setSeverity(CompilerOptions.OPTION_ReportTerminalDeprecation, severity, isEnabling);
+				this.options.put(
+					CompilerOptions.OPTION_ReportDeprecationInDeprecatedCode,
+					CompilerOptions.DISABLED);
+				this.options.put(
+					CompilerOptions.OPTION_ReportDeprecationWhenOverridingDeprecatedMethod,
+					CompilerOptions.DISABLED);
+				return;
 			}
 			break;
 		case 's' :
diff --git a/org.eclipse.jdt.core/batch/org/eclipse/jdt/internal/compiler/batch/messages.properties b/org.eclipse.jdt.core/batch/org/eclipse/jdt/internal/compiler/batch/messages.properties
index 190a0fa..dc47911 100644
--- a/org.eclipse.jdt.core/batch/org/eclipse/jdt/internal/compiler/batch/messages.properties
+++ b/org.eclipse.jdt.core/batch/org/eclipse/jdt/internal/compiler/batch/messages.properties
@@ -413,6 +413,7 @@
 \      paramAssign          assignment to a parameter\n\
 \      pkgDefaultMethod   + attempt to override package-default method\n\
 \      raw                + usage of raw type\n\
+\      removal            + deprecation marked for removal\n\
 \      resource           + (pot.) unsafe usage of resource of type Closeable\n\
 \      semicolon            unnecessary semicolon, empty statement\n\
 \      serial             + missing serialVersionUID\n\
diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/core/compiler/IProblem.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/core/compiler/IProblem.java
index e5f6878..6f4dce4 100644
--- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/core/compiler/IProblem.java
+++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/core/compiler/IProblem.java
@@ -1937,6 +1937,17 @@
 	/** @since 3.13 BETA_JAVA9 */
 	int DuplicateResource = Internal + 1251;
 
+	/** @since 3.13 BETA_JAVA9 */
+	int UsingTerminallyDeprecatedType = TypeRelated + 1400;
+	/** @since 3.13 BETA_JAVA9 */
+	int UsingTerminallyDeprecatedMethod = MethodRelated + 1401;
+	/** @since 3.13 BETA_JAVA9 */
+	int UsingTerminallyDeprecatedConstructor = MethodRelated + 1402;
+	/** @since 3.13 BETA_JAVA9 */
+	int UsingTerminallyDeprecatedField = FieldRelated + 1403;
+	/** @since 3.13 BETA_JAVA9 */
+	int OverridingTerminallyDeprecatedMethod = MethodRelated + 1404;
+
 	/** @since 3.13 */
 	int RedundantNullDefaultAnnotationLocal = Internal + 1062;
 	
diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/ASTNode.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/ASTNode.java
index 0da08b1..5170e45 100644
--- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/ASTNode.java
+++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/ASTNode.java
@@ -1178,28 +1178,38 @@
 					if (!CharOperation.equals(TypeConstants.JAVA_LANG_DEPRECATED[2], annotationTypeRef.getLastToken())) continue;
 					TypeBinding annotationType = annotations[i].type.resolveType(scope);
 					if(annotationType != null && annotationType.isValidBinding() && annotationType.id == TypeIds.T_JavaLangDeprecated) {
+						long deprecationTagBits = TagBits.AnnotationDeprecated | TagBits.DeprecatedAnnotationResolved;
+						if (scope.compilerOptions().complianceLevel >= ClassFileConstants.JDK9) {
+							for (MemberValuePair memberValuePair : annotations[i].memberValuePairs()) {
+								if (CharOperation.equals(memberValuePair.name, TypeConstants.FOR_REMOVAL)) {
+									if (memberValuePair.value instanceof TrueLiteral)
+										deprecationTagBits |= TagBits.AnnotationTerminallyDeprecated;
+									break;
+								}
+							}
+						}
 						switch (kind) {
 							case Binding.PACKAGE :
 								PackageBinding packageBinding = (PackageBinding) recipient;
-								packageBinding.tagBits |= (TagBits.AnnotationDeprecated | TagBits.DeprecatedAnnotationResolved);
+								packageBinding.tagBits |= deprecationTagBits;
 								return;
 							case Binding.TYPE :
 							case Binding.GENERIC_TYPE :
 							case Binding.TYPE_PARAMETER :
 								ReferenceBinding type = (ReferenceBinding) recipient;
-								type.tagBits |= (TagBits.AnnotationDeprecated | TagBits.DeprecatedAnnotationResolved);
+								type.tagBits |= deprecationTagBits;
 								return;
 							case Binding.METHOD :
 								MethodBinding method = (MethodBinding) recipient;
-								method.tagBits |= (TagBits.AnnotationDeprecated | TagBits.DeprecatedAnnotationResolved);
+								method.tagBits |= deprecationTagBits;
 								return;
 							case Binding.FIELD :
 								FieldBinding field = (FieldBinding) recipient;
-								field.tagBits |= (TagBits.AnnotationDeprecated | TagBits.DeprecatedAnnotationResolved);
+								field.tagBits |= deprecationTagBits;
 								return;
 							case Binding.LOCAL :
 								LocalVariableBinding local = (LocalVariableBinding) recipient;
-								local.tagBits |= (TagBits.AnnotationDeprecated | TagBits.DeprecatedAnnotationResolved);
+								local.tagBits |= deprecationTagBits;
 								return;
 							default:
 								return;
diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/Annotation.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/Annotation.java
index 3eee089..29512a9 100644
--- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/Annotation.java
+++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/Annotation.java
@@ -369,6 +369,15 @@
 			// marker annotations
 			case TypeIds.T_JavaLangDeprecated :
 				tagBits |= TagBits.AnnotationDeprecated;
+				if (scope.compilerOptions().complianceLevel >= ClassFileConstants.JDK9) {
+					for (MemberValuePair memberValuePair : memberValuePairs()) {
+						if (CharOperation.equals(memberValuePair.name, TypeConstants.FOR_REMOVAL)) {
+							if (memberValuePair.value instanceof TrueLiteral)
+								tagBits |= TagBits.AnnotationTerminallyDeprecated;
+							break;
+						}
+					}
+				}
 				break;
 			case TypeIds.T_JavaLangAnnotationDocumented :
 				tagBits |= TagBits.AnnotationDocumented;
diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/impl/CompilerOptions.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/impl/CompilerOptions.java
index 68ac66e..7cc7720 100644
--- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/impl/CompilerOptions.java
+++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/impl/CompilerOptions.java
@@ -61,6 +61,7 @@
 	public static final String OPTION_ReportMethodWithConstructorName = "org.eclipse.jdt.core.compiler.problem.methodWithConstructorName"; //$NON-NLS-1$
 	public static final String OPTION_ReportOverridingPackageDefaultMethod = "org.eclipse.jdt.core.compiler.problem.overridingPackageDefaultMethod"; //$NON-NLS-1$
 	public static final String OPTION_ReportDeprecation = "org.eclipse.jdt.core.compiler.problem.deprecation"; //$NON-NLS-1$
+	public static final String OPTION_ReportTerminalDeprecation = "org.eclipse.jdt.core.compiler.problem.terminalDeprecation"; //$NON-NLS-1$
 	public static final String OPTION_ReportDeprecationInDeprecatedCode = "org.eclipse.jdt.core.compiler.problem.deprecationInDeprecatedCode"; //$NON-NLS-1$
 	public static final String OPTION_ReportDeprecationWhenOverridingDeprecatedMethod = "org.eclipse.jdt.core.compiler.problem.deprecationWhenOverridingDeprecatedMethod"; //$NON-NLS-1$
 	public static final String OPTION_ReportHiddenCatchBlock = "org.eclipse.jdt.core.compiler.problem.hiddenCatchBlock"; //$NON-NLS-1$
@@ -322,6 +323,8 @@
 	public static final int NonNullTypeVariableFromLegacyInvocation = IrritantSet.GROUP2 | ASTNode.Bit21;
 	public static final int UnlikelyCollectionMethodArgumentType = IrritantSet.GROUP2 | ASTNode.Bit22;
 	public static final int UnlikelyEqualsArgumentType = IrritantSet.GROUP2 | ASTNode.Bit23;
+	public static final int UsingTerminallyDeprecatedAPI = IrritantSet.GROUP2 | ASTNode.Bit24;
+
 
 	// Severity level for handlers
 	/** 
@@ -525,6 +528,7 @@
 		"nls", //$NON-NLS-1$
 		"null", //$NON-NLS-1$
 		"rawtypes", //$NON-NLS-1$
+		"removal", //$NON-NLS-1$
 		"resource", //$NON-NLS-1$
 		"restriction", //$NON-NLS-1$		
 		"serial", //$NON-NLS-1$
@@ -580,6 +584,9 @@
 			case UsingDeprecatedAPI :
 			case (InvalidJavadoc | UsingDeprecatedAPI) :
 				return OPTION_ReportDeprecation;
+			case UsingTerminallyDeprecatedAPI :
+			case (InvalidJavadoc | UsingTerminallyDeprecatedAPI) :
+				return OPTION_ReportTerminalDeprecation;
 			case MaskedCatchBlock  :
 				return OPTION_ReportHiddenCatchBlock;
 			case UnusedLocalVariable :
@@ -947,6 +954,9 @@
 			case (InvalidJavadoc | UsingDeprecatedAPI) :
 			case UsingDeprecatedAPI :
 				return "deprecation"; //$NON-NLS-1$
+			case (InvalidJavadoc | UsingTerminallyDeprecatedAPI) :
+			case UsingTerminallyDeprecatedAPI :
+				return "removal"; //$NON-NLS-1$
 			case FinallyBlockNotCompleting :
 				return "finally"; //$NON-NLS-1$
 			case FieldHiding :
@@ -1085,6 +1095,8 @@
 					return IrritantSet.RESOURCE;
 				if ("restriction".equals(warningToken)) //$NON-NLS-1$
 					return IrritantSet.RESTRICTION;
+				if ("removal".equals(warningToken)) //$NON-NLS-1$
+					return IrritantSet.TERMINAL_DEPRECATION;
 				break;
 			case 's' :
 				if ("serial".equals(warningToken)) //$NON-NLS-1$
@@ -1128,6 +1140,7 @@
 		optionsMap.put(OPTION_ReportMethodWithConstructorName, getSeverityString(MethodWithConstructorName));
 		optionsMap.put(OPTION_ReportOverridingPackageDefaultMethod, getSeverityString(OverriddenPackageDefaultMethod));
 		optionsMap.put(OPTION_ReportDeprecation, getSeverityString(UsingDeprecatedAPI));
+		optionsMap.put(OPTION_ReportTerminalDeprecation, getSeverityString(UsingTerminallyDeprecatedAPI));
 		optionsMap.put(OPTION_ReportDeprecationInDeprecatedCode, this.reportDeprecationInsideDeprecatedCode ? ENABLED : DISABLED);
 		optionsMap.put(OPTION_ReportDeprecationWhenOverridingDeprecatedMethod, this.reportDeprecationWhenOverridingDeprecatedMethod ? ENABLED : DISABLED);
 		optionsMap.put(OPTION_ReportHiddenCatchBlock, getSeverityString(MaskedCatchBlock));
@@ -1692,6 +1705,7 @@
 		if ((optionValue = optionsMap.get(OPTION_ReportMethodWithConstructorName)) != null) updateSeverity(MethodWithConstructorName, optionValue);
 		if ((optionValue = optionsMap.get(OPTION_ReportOverridingPackageDefaultMethod)) != null) updateSeverity(OverriddenPackageDefaultMethod, optionValue);
 		if ((optionValue = optionsMap.get(OPTION_ReportDeprecation)) != null) updateSeverity(UsingDeprecatedAPI, optionValue);
+		if ((optionValue = optionsMap.get(OPTION_ReportTerminalDeprecation)) != null) updateSeverity(UsingTerminallyDeprecatedAPI, optionValue);
 		if ((optionValue = optionsMap.get(OPTION_ReportHiddenCatchBlock)) != null) updateSeverity(MaskedCatchBlock, optionValue);
 		if ((optionValue = optionsMap.get(OPTION_ReportUnusedLocal)) != null) updateSeverity(UnusedLocalVariable, optionValue);
 		if ((optionValue = optionsMap.get(OPTION_ReportUnusedParameter)) != null) updateSeverity(UnusedArgument, optionValue);
@@ -1993,6 +2007,7 @@
 		buf.append("\n\t- method with constructor name: ").append(getSeverityString(MethodWithConstructorName)); //$NON-NLS-1$
 		buf.append("\n\t- overridden package default method: ").append(getSeverityString(OverriddenPackageDefaultMethod)); //$NON-NLS-1$
 		buf.append("\n\t- deprecation: ").append(getSeverityString(UsingDeprecatedAPI)); //$NON-NLS-1$
+		buf.append("\n\t- removal: ").append(getSeverityString(UsingTerminallyDeprecatedAPI)); //$NON-NLS-1$
 		buf.append("\n\t- masked catch block: ").append(getSeverityString(MaskedCatchBlock)); //$NON-NLS-1$
 		buf.append("\n\t- unused local variable: ").append(getSeverityString(UnusedLocalVariable)); //$NON-NLS-1$
 		buf.append("\n\t- unused parameter: ").append(getSeverityString(UnusedArgument)); //$NON-NLS-1$
diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/impl/IrritantSet.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/impl/IrritantSet.java
index 8ba156b..07622bc 100644
--- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/impl/IrritantSet.java
+++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/impl/IrritantSet.java
@@ -49,6 +49,7 @@
 	public static final IrritantSet BOXING = new IrritantSet(CompilerOptions.AutoBoxing);
 	public static final IrritantSet CAST = new IrritantSet(CompilerOptions.UnnecessaryTypeCheck);
 	public static final IrritantSet DEPRECATION = new IrritantSet(CompilerOptions.UsingDeprecatedAPI);
+	public static final IrritantSet TERMINAL_DEPRECATION = new IrritantSet(CompilerOptions.UsingTerminallyDeprecatedAPI);
 	public static final IrritantSet DEP_ANN = new IrritantSet(CompilerOptions.MissingDeprecatedAnnotation);
 	public static final IrritantSet FALLTHROUGH = new IrritantSet(CompilerOptions.FallthroughCase);
 	public static final IrritantSet FINALLY = new IrritantSet(CompilerOptions.FinallyBlockNotCompleting);
@@ -125,7 +126,8 @@
 				|CompilerOptions.NonnullParameterAnnotationDropped
 				|CompilerOptions.PessimisticNullAnalysisForFreeTypeVariables
 				|CompilerOptions.NonNullTypeVariableFromLegacyInvocation
-				|CompilerOptions.UnlikelyCollectionMethodArgumentType);
+				|CompilerOptions.UnlikelyCollectionMethodArgumentType
+				|CompilerOptions.UsingTerminallyDeprecatedAPI);
 		// default errors IF AnnotationBasedNullAnalysis is enabled:
 		COMPILER_DEFAULT_ERRORS.set(
 				CompilerOptions.NullSpecViolation
diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/BinaryTypeBinding.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/BinaryTypeBinding.java
index ea212f0..76dda1a 100644
--- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/BinaryTypeBinding.java
+++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/BinaryTypeBinding.java
@@ -535,12 +535,14 @@
 					FieldBinding field = this.fields[i];
 					if (!field.isDeprecated()) {
 						field.modifiers |= ExtraCompilerModifiers.AccDeprecatedImplicitly;
+						field.tagBits |= this.tagBits & TagBits.AnnotationTerminallyDeprecated;
 					}
 				}
 				for (int i = 0, max = this.methods.length; i < max; i++) {
 					MethodBinding method = this.methods[i];
 					if (!method.isDeprecated()) {
 						method.modifiers |= ExtraCompilerModifiers.AccDeprecatedImplicitly;
+						method.tagBits |= this.tagBits & TagBits.AnnotationTerminallyDeprecated;
 					}
 				}
 			}
diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/ClassScope.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/ClassScope.java
index d20f4d3..bc31e72 100644
--- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/ClassScope.java
+++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/ClassScope.java
@@ -530,8 +530,10 @@
 						// local member
 						if (enclosingType.isStrictfp())
 							modifiers |= ClassFileConstants.AccStrictfp;
-						if (enclosingType.isViewedAsDeprecated() && !sourceType.isDeprecated())
+						if (enclosingType.isViewedAsDeprecated() && !sourceType.isDeprecated()) {
 							modifiers |= ExtraCompilerModifiers.AccDeprecatedImplicitly;
+							sourceType.tagBits |= enclosingType.tagBits & TagBits.AnnotationTerminallyDeprecated;
+						}
 						break;
 				}
 				scope = scope.parent;
diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/MemberTypeBinding.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/MemberTypeBinding.java
index 7da4ba3..eec4bb2 100644
--- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/MemberTypeBinding.java
+++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/MemberTypeBinding.java
@@ -78,6 +78,7 @@
 			}
 			if (enclosing.isViewedAsDeprecated()) {
 				this.modifiers |= ExtraCompilerModifiers.AccDeprecatedImplicitly;
+				this.tagBits |= (enclosing.tagBits & TagBits.AnnotationTerminallyDeprecated);
 			}
 		}
 	}
diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/ReferenceBinding.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/ReferenceBinding.java
index bc92b9c..32c3cef 100644
--- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/ReferenceBinding.java
+++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/ReferenceBinding.java
@@ -1616,8 +1616,13 @@
  * Answer true if the receiver is deprecated (or any of its enclosing types)
  */
 public final boolean isViewedAsDeprecated() {
-	return (this.modifiers & (ClassFileConstants.AccDeprecated | ExtraCompilerModifiers.AccDeprecatedImplicitly)) != 0
-			|| getPackage().isViewedAsDeprecated();
+	if ((this.modifiers & (ClassFileConstants.AccDeprecated | ExtraCompilerModifiers.AccDeprecatedImplicitly)) != 0)
+		return true;
+	if (getPackage().isViewedAsDeprecated()) {
+		this.tagBits |= (getPackage().tagBits & TagBits.AnnotationTerminallyDeprecated);
+		return true;
+	}
+	return false;
 }
 
 public ReferenceBinding[] memberTypes() {
diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/SourceTypeBinding.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/SourceTypeBinding.java
index 46d4265..b9cdba3 100644
--- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/SourceTypeBinding.java
+++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/SourceTypeBinding.java
@@ -887,8 +887,10 @@
 	// check @Deprecated annotation
 	getAnnotationTagBits(); // marks as deprecated by side effect
 	ReferenceBinding enclosingType = enclosingType();
-	if (enclosingType != null && enclosingType.isViewedAsDeprecated() && !isDeprecated())
+	if (enclosingType != null && enclosingType.isViewedAsDeprecated() && !isDeprecated()) {
 		this.modifiers |= ExtraCompilerModifiers.AccDeprecatedImplicitly;
+		this.tagBits |= (enclosingType.tagBits & TagBits.AnnotationTerminallyDeprecated);
+	}
 
 	for (int i = 0, length = this.memberTypes.length; i < length; i++)
 		((SourceTypeBinding) this.memberTypes[i]).checkAnnotationsInType();
@@ -1743,8 +1745,10 @@
 		if ((field.getAnnotationTagBits() & TagBits.AnnotationDeprecated) != 0)
 			field.modifiers |= ClassFileConstants.AccDeprecated;
 	}
-	if (isViewedAsDeprecated() && !field.isDeprecated())
+	if (isViewedAsDeprecated() && !field.isDeprecated()) {
 		field.modifiers |= ExtraCompilerModifiers.AccDeprecatedImplicitly;
+		field.tagBits |= this.tagBits & TagBits.AnnotationTerminallyDeprecated;
+	}
 	if (hasRestrictedAccess())
 		field.modifiers |= ExtraCompilerModifiers.AccRestrictedAccess;
 	FieldDeclaration[] fieldDecls = this.scope.referenceContext.fields;
@@ -1849,8 +1853,10 @@
 		if ((method.getAnnotationTagBits() & TagBits.AnnotationDeprecated) != 0)
 			method.modifiers |= ClassFileConstants.AccDeprecated;
 	}
-	if (isViewedAsDeprecated() && !method.isDeprecated())
+	if (isViewedAsDeprecated() && !method.isDeprecated()) {
 		method.modifiers |= ExtraCompilerModifiers.AccDeprecatedImplicitly;
+		method.tagBits |= this.tagBits & TagBits.AnnotationTerminallyDeprecated;
+	}
 	if (hasRestrictedAccess())
 		method.modifiers |= ExtraCompilerModifiers.AccRestrictedAccess;
 
diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/TagBits.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/TagBits.java
index 8cfe4b7..d124c36 100644
--- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/TagBits.java
+++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/TagBits.java
@@ -158,11 +158,14 @@
 	/** From Java 8 */
 	long AnnotationRepeatable = ASTNode.Bit61L; // Only for annotation types and since these cannot have constructors, we can overload HasNonPrivateConstructor.
 
+	/** From Java 9 */
+	long AnnotationTerminallyDeprecated = ASTNode.Bit63L;
 
 	long AllStandardAnnotationsMask =
 				  AnnotationTargetMASK
 				| AnnotationRetentionMASK
 				| AnnotationDeprecated
+				| AnnotationTerminallyDeprecated
 				| AnnotationDocumented
 				| AnnotationInherited
 				| AnnotationOverride
diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/TypeConstants.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/TypeConstants.java
index 794d0a4..39b266f 100644
--- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/TypeConstants.java
+++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/TypeConstants.java
@@ -170,6 +170,7 @@
 	char[][] JAVA_UTIL_OBJECTS = {JAVA, UTIL, "Objects".toCharArray()}; //$NON-NLS-1$
 	char[][] JAVA_UTIL_LIST = {JAVA, UTIL, "List".toCharArray()}; //$NON-NLS-1$
 	char[][] JAVA_LANG_DEPRECATED = {JAVA, LANG, "Deprecated".toCharArray()}; //$NON-NLS-1$
+	char[] FOR_REMOVAL = "forRemoval".toCharArray(); //$NON-NLS-1$
 	char[][] JAVA_LANG_ANNOTATION_DOCUMENTED = {JAVA, LANG, ANNOTATION, "Documented".toCharArray()}; //$NON-NLS-1$
 	char[][] JAVA_LANG_ANNOTATION_INHERITED = {JAVA, LANG, ANNOTATION, "Inherited".toCharArray()}; //$NON-NLS-1$
 	char[][] JAVA_LANG_ANNOTATION_REPEATABLE = {JAVA, LANG, ANNOTATION, "Repeatable".toCharArray()}; //$NON-NLS-1$
diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/problem/ProblemReporter.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/problem/ProblemReporter.java
index be15f50..098060a 100644
--- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/problem/ProblemReporter.java
+++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/problem/ProblemReporter.java
@@ -245,6 +245,13 @@
 		case IProblem.UsingDeprecatedField :
 			return CompilerOptions.UsingDeprecatedAPI;
 
+		case IProblem.OverridingTerminallyDeprecatedMethod :
+		case IProblem.UsingTerminallyDeprecatedType :
+		case IProblem.UsingTerminallyDeprecatedMethod :
+		case IProblem.UsingTerminallyDeprecatedConstructor :
+		case IProblem.UsingTerminallyDeprecatedField :
+			return CompilerOptions.UsingTerminallyDeprecatedAPI;
+
 		case IProblem.LocalVariableIsNeverUsed :
 			return CompilerOptions.UnusedLocalVariable;
 
@@ -712,6 +719,7 @@
 				return CategorizedProblem.CAT_UNNECESSARY_CODE;
 
 			case CompilerOptions.UsingDeprecatedAPI :
+			case CompilerOptions.UsingTerminallyDeprecatedAPI :
 				return CategorizedProblem.CAT_DEPRECATION;
 
 			case CompilerOptions.NonExternalizedString :
@@ -724,6 +732,7 @@
 			case CompilerOptions.MissingJavadocTags :
 			case CompilerOptions.InvalidJavadoc :
 			case CompilerOptions.InvalidJavadoc|CompilerOptions.UsingDeprecatedAPI :
+			case CompilerOptions.InvalidJavadoc|CompilerOptions.UsingTerminallyDeprecatedAPI :
 				return CategorizedProblem.CAT_JAVADOC;
 
 			case CompilerOptions.UncheckedTypeOperation :
@@ -1688,21 +1697,17 @@
 }
 
 public void deprecatedField(FieldBinding field, ASTNode location) {
-	int severity = computeSeverity(IProblem.UsingDeprecatedField);
-	if (severity == ProblemSeverities.Ignore) return;
 	this.handle(
-		IProblem.UsingDeprecatedField,
+		(field.tagBits & TagBits.AnnotationTerminallyDeprecated) == 0 ? IProblem.UsingDeprecatedField : IProblem.UsingTerminallyDeprecatedField,
 		new String[] {new String(field.declaringClass.readableName()), new String(field.name)},
 		new String[] {new String(field.declaringClass.shortReadableName()), new String(field.name)},
-		severity,
 		nodeSourceStart(field, location),
 		nodeSourceEnd(field, location));
 }
 
 public void deprecatedMethod(MethodBinding method, ASTNode location) {
 	boolean isConstructor = method.isConstructor();
-	int severity = computeSeverity(isConstructor ? IProblem.UsingDeprecatedConstructor : IProblem.UsingDeprecatedMethod);
-	if (severity == ProblemSeverities.Ignore) return;
+	boolean terminally = (method.tagBits & TagBits.AnnotationTerminallyDeprecated) != 0;
 	if (isConstructor) {
 		int start = -1;
 		if(location instanceof AllocationExpression) {
@@ -1715,10 +1720,9 @@
 			start = allocationExpression.type.sourceStart;
 		}
 		this.handle(
-			IProblem.UsingDeprecatedConstructor,
+			terminally ? IProblem.UsingTerminallyDeprecatedConstructor : IProblem.UsingDeprecatedConstructor,
 			new String[] {new String(method.declaringClass.readableName()), typesAsString(method, false)},
 			new String[] {new String(method.declaringClass.shortReadableName()), typesAsString(method, true)},
-			severity,
 			(start == -1) ? location.sourceStart : start,
 			location.sourceEnd);
 	} else {
@@ -1729,10 +1733,9 @@
 			start = (int) (((MessageSend)location).nameSourcePosition >>> 32);
 		}
 		this.handle(
-			IProblem.UsingDeprecatedMethod,
+			terminally ? IProblem.UsingTerminallyDeprecatedMethod : IProblem.UsingDeprecatedMethod,
 			new String[] {new String(method.declaringClass.readableName()), new String(method.selector), typesAsString(method, false)},
 			new String[] {new String(method.declaringClass.shortReadableName()), new String(method.selector), typesAsString(method, true)},
-			severity,
 			(start == -1) ? location.sourceStart : start,
 			location.sourceEnd);
 	}
@@ -1744,8 +1747,6 @@
 // a deprecated type in a qualified reference (see bug 292510)
 public void deprecatedType(TypeBinding type, ASTNode location, int index) {
 	if (location == null) return; // 1G828DN - no type ref for synthetic arguments
-	int severity = computeSeverity(IProblem.UsingDeprecatedType);
-	if (severity == ProblemSeverities.Ignore) return;
 	type = type.leafComponentType();
 	int sourceStart = -1;
 	if (location instanceof QualifiedTypeReference) { // https://bugs.eclipse.org/bugs/show_bug.cgi?id=300031
@@ -1755,10 +1756,9 @@
 		}
 	}
 	this.handle(
-		IProblem.UsingDeprecatedType,
+		((type.tagBits & TagBits.AnnotationTerminallyDeprecated) == 0) ? IProblem.UsingDeprecatedType : IProblem.UsingTerminallyDeprecatedType,
 		new String[] {new String(type.readableName())},
 		new String[] {new String(type.shortReadableName())},
-		severity,
 		(sourceStart == -1) ? location.sourceStart : sourceStart,
 		nodeSourceEnd(null, location, index));
 }
@@ -6889,7 +6889,8 @@
 }
 public void overridesDeprecatedMethod(MethodBinding localMethod, MethodBinding inheritedMethod) {
 	this.handle(
-		IProblem.OverridingDeprecatedMethod,
+		(inheritedMethod.tagBits & TagBits.AnnotationTerminallyDeprecated) != 0
+				? IProblem.OverridingTerminallyDeprecatedMethod : IProblem.OverridingDeprecatedMethod,
 		new String[] {
 			new String(
 					CharOperation.concat(
diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/problem/messages.properties b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/problem/messages.properties
index 345fcf6..5547966 100644
--- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/problem/messages.properties
+++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/problem/messages.properties
@@ -907,6 +907,14 @@
 1317 = Invalid service implementation {0}, must be a public class or interface type
 1318 = Illegal modifier for module {0}; only open is permitted
 
+# Java 9 - advanced deprecation
+1400 = The type {0} has been deprecated and marked for removal
+1401 = The method {1}({2}) from the type {0} has been deprecated and marked for removal
+1402 = The constructor {0}({1}) has been deprecated and marked for removal
+1403 = The field {0}.{1} has been deprecated and marked for removal
+1404 = The method {0} overrides a method from {1} that has been deprecated and marked for removal
+
+
 ### ELABORATIONS
 ## Access restrictions
 78592 = The type ''{1}'' is not API (restriction on classpath entry ''{0}'')
diff --git a/org.eclipse.jdt.core/model/org/eclipse/jdt/core/JavaCore.java b/org.eclipse.jdt.core/model/org/eclipse/jdt/core/JavaCore.java
index 44a8946..1e38b3f 100644
--- a/org.eclipse.jdt.core/model/org/eclipse/jdt/core/JavaCore.java
+++ b/org.eclipse.jdt.core/model/org/eclipse/jdt/core/JavaCore.java
@@ -416,6 +416,19 @@
 	 */
 	public static final String COMPILER_PB_DEPRECATION = PLUGIN_ID + ".compiler.problem.deprecation"; //$NON-NLS-1$
 	/**
+	 * Compiler option ID: Reporting Terminal Deprecation.
+	 * <p>When enabled, the compiler will signal use of terminally deprecated API either as an
+	 *    error or a warning.</p>
+	 * <dl>
+	 * <dt>Option id:</dt><dd><code>"org.eclipse.jdt.core.compiler.problem.terminalDeprecation"</code></dd>
+	 * <dt>Possible values:</dt><dd><code>{ "error", "warning", "info", "ignore" }</code></dd>
+	 * <dt>Default:</dt><dd><code>"warning"</code></dd>
+	 * </dl>
+	 * @since 3.13 BETA_JAVA9
+	 * @category CompilerOptionID
+	 */
+	public static final String COMPILER_PB_TERMINAL_DEPRECATION = PLUGIN_ID + ".compiler.problem.terminalDeprecation"; //$NON-NLS-1$
+	/**
 	 * Compiler option ID: Reporting Deprecation Inside Deprecated Code.
 	 * <p>When enabled, the compiler will signal use of deprecated API inside deprecated code.</p>
 	 * <p>The severity of the problem is controlled with option {@link #COMPILER_PB_DEPRECATION}.</p>