Bug 571082 - [16] Implicit canonical constructor bindings don't get the
annotations from record declaration

Change-Id: I827731874f89e75296d238aa3cdbf3c0904c90a3
Signed-off-by: Jay Arthanareeswaran <jarthana@in.ibm.com>
diff --git a/org.eclipse.jdt.compiler.apt.tests/lib/apttestprocessors8.jar b/org.eclipse.jdt.compiler.apt.tests/lib/apttestprocessors8.jar
index 6015cd8..2484202 100644
--- a/org.eclipse.jdt.compiler.apt.tests/lib/apttestprocessors8.jar
+++ b/org.eclipse.jdt.compiler.apt.tests/lib/apttestprocessors8.jar
Binary files differ
diff --git a/org.eclipse.jdt.compiler.apt.tests/processors8/org/eclipse/jdt/compiler/apt/tests/processors/elements/RecordElementProcessor.java b/org.eclipse.jdt.compiler.apt.tests/processors8/org/eclipse/jdt/compiler/apt/tests/processors/elements/RecordElementProcessor.java
index 7b70533..6a86926 100644
--- a/org.eclipse.jdt.compiler.apt.tests/processors8/org/eclipse/jdt/compiler/apt/tests/processors/elements/RecordElementProcessor.java
+++ b/org.eclipse.jdt.compiler.apt.tests/processors8/org/eclipse/jdt/compiler/apt/tests/processors/elements/RecordElementProcessor.java
@@ -1,5 +1,5 @@
 /*******************************************************************************
- * Copyright (c) 2020 IBM Corporation.
+ * Copyright (c) 2020, 2021 IBM Corporation.
  *
  * This program and the accompanying materials
  * are made available under the terms of the Eclipse Public License 2.0
@@ -8,6 +8,10 @@
  *
  * SPDX-License-Identifier: EPL-2.0
  *
+ * 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:
  *     IBM Corporation - initial API and implementation
  *******************************************************************************/
@@ -128,6 +132,10 @@
 		testRecords4();
 		testRecords5();
 		testRecords6();
+		testRecords7();
+		testRecords8();
+		testRecords9();
+		testRecords10();
 	}
 
 	public void testPreviewFlagTrue() throws IOException {
@@ -521,45 +529,68 @@
         assertTrue("Test returned negative", result);
 	}
 	public void testRecords9() {
-			String[] arr1 = new String[] { "x", "bigInt", "r1", "floatValue", "c", "recordInstance" };
-			TypeKind[] arr2 = new TypeKind[] { TypeKind.INT, TypeKind.DECLARED, TypeKind.DECLARED, TypeKind.FLOAT,
-					TypeKind.DECLARED, TypeKind.DECLARED };
-			List<String> names = Arrays.asList(arr1);
-			List<TypeKind> types = Arrays.asList(arr2);
+		String[] arr1 = new String[] { "x", "bigInt", "r1", "floatValue", "c", "recordInstance" };
+		TypeKind[] arr2 = new TypeKind[] { TypeKind.INT, TypeKind.DECLARED, TypeKind.DECLARED, TypeKind.FLOAT,
+				TypeKind.DECLARED, TypeKind.DECLARED };
+		List<String> names = Arrays.asList(arr1);
+		List<TypeKind> types = Arrays.asList(arr2);
 
-	        Element record = _elementUtils.getTypeElement("records.R3");
-	        List<? extends Element> allElements = record.getEnclosedElements();
-	        List<RecordComponentElement> components = ElementFilter.recordComponentsIn(allElements);
-	        List<ExecutableElement> accessors = components.stream().map
-	                (RecordComponentElement::getAccessor).collect(Collectors.toList());
-	        assertEquals("Size mismatch", names.size(), accessors.size());
-	        for (ExecutableElement accessor : accessors) {
-	            String name = accessor.getSimpleName().toString();
-	            int indexOf = names.indexOf(name);
-	            assertSame("Type kind not same for \"" + name + "\".", types.get(indexOf), accessor.getReturnType().getKind());
-	            assertTrue("should be executable type for \"" + name + "\".", (accessor.asType() instanceof ExecutableType));
-	            assertNull("should be null", accessor.getDefaultValue());
-	            List<? extends AnnotationMirror> mirrors = accessor.getAnnotationMirrors();
-				if (name.equals("c") || name.equals("bigInt") || name.equals("r1")) {
-	            	assertEquals("annotations count mismatch for \"" + name + "\".", 1, mirrors.size());
-	            	Set<? extends ExecutableElement> accessorAnnotations = mirrors.get(0)
-	                        .getElementValues().keySet();
-	            	assertEquals("annotations type element mismatch for \"" + name + "\".", 1, accessorAnnotations.size());
-	            	int val = (int) accessorAnnotations.toArray(new ExecutableElement[0])[0].getDefaultValue()
-	                        .getValue();
-	            	assertEquals("Incorrect default value for \"" + name + "\".", 1, val);
-	            }
-	            if (name.equals("floatValue") || name.equals("x")) {
-	            	assertEquals("annotations count mismatch for \"" + name + "\".", 0, mirrors.size());
-	            }
-	            if (name.equals("recordInstance")) {
-	            	assertEquals("annotations count mismatch for \"" + name + "\".", 2, mirrors.size());
-	            }
-	            assertTrue("Parameters should be empty for \"" + name + "\".", accessor.getParameters().isEmpty());
-	            assertTrue("Thrown types should be empty for \"" + name + "\".", accessor.getThrownTypes().isEmpty());
-	            assertTrue("Type parameters should be empty for \"" + name + "\".", accessor.getTypeParameters().isEmpty());
-	            assertFalse("Should not be default for \"" + name + "\".", accessor.isDefault());
-	            assertFalse("Should not be varargs for \"" + name + "\".", accessor.isVarArgs());
-	        }
+		Element record = _elementUtils.getTypeElement("records.R3");
+		List<? extends Element> allElements = record.getEnclosedElements();
+		List<RecordComponentElement> components = ElementFilter.recordComponentsIn(allElements);
+		List<ExecutableElement> accessors = components.stream().map
+				(RecordComponentElement::getAccessor).collect(Collectors.toList());
+		assertEquals("Size mismatch", names.size(), accessors.size());
+		for (ExecutableElement accessor : accessors) {
+			String name = accessor.getSimpleName().toString();
+			int indexOf = names.indexOf(name);
+			assertSame("Type kind not same for \"" + name + "\".", types.get(indexOf), accessor.getReturnType().getKind());
+			assertTrue("should be executable type for \"" + name + "\".", (accessor.asType() instanceof ExecutableType));
+			assertNull("should be null", accessor.getDefaultValue());
+			List<? extends AnnotationMirror> mirrors = accessor.getAnnotationMirrors();
+			if (name.equals("c") || name.equals("bigInt") || name.equals("r1")) {
+				assertEquals("annotations count mismatch for \"" + name + "\".", 1, mirrors.size());
+				Set<? extends ExecutableElement> accessorAnnotations = mirrors.get(0)
+						.getElementValues().keySet();
+				assertEquals("annotations type element mismatch for \"" + name + "\".", 1, accessorAnnotations.size());
+				int val = (int) accessorAnnotations.toArray(new ExecutableElement[0])[0].getDefaultValue()
+						.getValue();
+				assertEquals("Incorrect default value for \"" + name + "\".", 1, val);
+			}
+			if (name.equals("floatValue") || name.equals("x")) {
+				assertEquals("annotations count mismatch for \"" + name + "\".", 0, mirrors.size());
+			}
+			if (name.equals("recordInstance")) {
+				assertEquals("annotations count mismatch for \"" + name + "\".", 2, mirrors.size());
+			}
+			assertTrue("Parameters should be empty for \"" + name + "\".", accessor.getParameters().isEmpty());
+			assertTrue("Thrown types should be empty for \"" + name + "\".", accessor.getThrownTypes().isEmpty());
+			assertTrue("Type parameters should be empty for \"" + name + "\".", accessor.getTypeParameters().isEmpty());
+			assertFalse("Should not be default for \"" + name + "\".", accessor.isDefault());
+			assertFalse("Should not be varargs for \"" + name + "\".", accessor.isVarArgs());
+		}
+	}
+	public void testRecords10() {
+		Set<? extends Element> elements = roundEnv.getRootElements();
+		TypeElement record = null;
+		for (Element element : elements) {
+			if ("R4".equals(element.getSimpleName().toString())) {
+				record = (TypeElement) element;
+			}
+		}
+		assertNotNull("TypeElement for record should not be null", record);
+
+		List<? extends Element> enclosedElements = record.getEnclosedElements();
+		List<ExecutableElement> methodsIn = ElementFilter.constructorsIn(enclosedElements);
+		assertEquals("incorrect method", 1, methodsIn.size());
+		ExecutableElement m = methodsIn.get(0);
+		verifyAnnotations(m, new String[]{});
+		TypeMirror asType = m.asType();
+		verifyAnnotations(asType, new String[]{});
+		List<? extends VariableElement> parameters = m.getParameters();
+		assertEquals("incorrect parameters", 1, parameters.size());
+		VariableElement var = parameters.get(0);
+		assertEquals("component name incorrect", "i", var.getSimpleName().toString());
+		verifyAnnotations(var, new String[]{"@Marker4()"});
 	}
 }
diff --git a/org.eclipse.jdt.compiler.apt.tests/resources/mod_locations/records/mod.records/records/R4.java b/org.eclipse.jdt.compiler.apt.tests/resources/mod_locations/records/mod.records/records/R4.java
new file mode 100644
index 0000000..7c500dd
--- /dev/null
+++ b/org.eclipse.jdt.compiler.apt.tests/resources/mod_locations/records/mod.records/records/R4.java
@@ -0,0 +1,12 @@
+package records;
+
+import java.lang.annotation.ElementType;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.annotation.Target;
+
+record R4(@Marker4 int... i) {}
+
+@Retention(RetentionPolicy.RUNTIME)
+@Target({ElementType.TYPE_USE, ElementType.PARAMETER}) 
+@interface Marker4 {}
diff --git a/org.eclipse.jdt.compiler.apt.tests/src/org/eclipse/jdt/compiler/apt/tests/RecordElementsTests.java b/org.eclipse.jdt.compiler.apt.tests/src/org/eclipse/jdt/compiler/apt/tests/RecordElementsTests.java
index 1d58418..bd8a10f 100644
--- a/org.eclipse.jdt.compiler.apt.tests/src/org/eclipse/jdt/compiler/apt/tests/RecordElementsTests.java
+++ b/org.eclipse.jdt.compiler.apt.tests/src/org/eclipse/jdt/compiler/apt/tests/RecordElementsTests.java
@@ -1,5 +1,5 @@
 /*******************************************************************************
- * Copyright (c) 2020 IBM Corporation.
+ * Copyright (c) 2020, 2021 IBM Corporation.
  *
  * This program and the accompanying materials
  * are made available under the terms of the Eclipse Public License 2.0
@@ -8,6 +8,10 @@
  *
  * SPDX-License-Identifier: EPL-2.0
  *
+ * 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:
  *     IBM Corporation - initial API and implementation
  *******************************************************************************/
@@ -32,108 +36,116 @@
 
 	public void testPreviewFlagTrue() throws IOException {
 		JavaCompiler compiler = BatchTestUtils.getEclipseCompiler();
-		internalTestWithPreview(compiler, MODULE_PROC, "15", "testPreviewFlagTrue", null, "records", true);
+		internalTestWithPreview(compiler, MODULE_PROC, "16", "testPreviewFlagTrue", null, "records", true);
 	}
 	public void testRecords1() throws IOException {
 		JavaCompiler compiler = BatchTestUtils.getEclipseCompiler();
-		internalTestWithPreview(compiler, MODULE_PROC, "15", "testRecords1", null, "records", true);
+		internalTestWithPreview(compiler, MODULE_PROC, "16", "testRecords1", null, "records", true);
 	}
 	public void testRecords1Javac() throws Exception {
 		JavaCompiler compiler = ToolProvider.getSystemJavaCompiler();
-		internalTestWithPreview(compiler, MODULE_PROC, "15", "testRecords1", null, "records", true);
+		internalTestWithPreview(compiler, MODULE_PROC, "16", "testRecords1", null, "records", true);
 	}
 	public void testRecords2() throws IOException {
 		JavaCompiler compiler = BatchTestUtils.getEclipseCompiler();
-		internalTestWithPreview(compiler, MODULE_PROC, "15", "testRecords2", null, "records", true);
+		internalTestWithPreview(compiler, MODULE_PROC, "16", "testRecords2", null, "records", true);
 	}
 	public void testRecords2Javac() throws Exception {
 		JavaCompiler compiler = ToolProvider.getSystemJavaCompiler();
-		internalTestWithPreview(compiler, MODULE_PROC, "15", "testRecords2", null, "records", true);
+		internalTestWithPreview(compiler, MODULE_PROC, "16", "testRecords2", null, "records", true);
 	}
 	public void testRecords3() throws IOException {
 		JavaCompiler compiler = BatchTestUtils.getEclipseCompiler();
-		internalTestWithPreview(compiler, MODULE_PROC, "15", "testRecords3", null, "records", true);
+		internalTestWithPreview(compiler, MODULE_PROC, "16", "testRecords3", null, "records", true);
 	}
 	public void testRecords3Javac() throws Exception {
 		JavaCompiler compiler = ToolProvider.getSystemJavaCompiler();
-		internalTestWithPreview(compiler, MODULE_PROC, "15", "testRecords3", null, "records", true);
+		internalTestWithPreview(compiler, MODULE_PROC, "16", "testRecords3", null, "records", true);
 	}
 	public void testRecords3a() throws IOException {
 		JavaCompiler compiler = BatchTestUtils.getEclipseCompiler();
-		internalTestWithPreview(compiler, MODULE_PROC, "15", "testRecords3a", null, "records", true);
+		internalTestWithPreview(compiler, MODULE_PROC, "16", "testRecords3a", null, "records", true);
 	}
 	public void testRecords3aJavac() throws Exception {
 		JavaCompiler compiler = ToolProvider.getSystemJavaCompiler();
-		internalTestWithPreview(compiler, MODULE_PROC, "15", "testRecords3a", null, "records", true);
+		internalTestWithPreview(compiler, MODULE_PROC, "16", "testRecords3a", null, "records", true);
 	}
 	public void testRecords4() throws IOException {
 		JavaCompiler compiler = BatchTestUtils.getEclipseCompiler();
-		internalTestWithPreview(compiler, MODULE_PROC, "15", "testRecords4", null, "records", true);
+		internalTestWithPreview(compiler, MODULE_PROC, "16", "testRecords4", null, "records", true);
 	}
 	public void testRecords4Javac() throws Exception {
 		JavaCompiler compiler = ToolProvider.getSystemJavaCompiler();
-		internalTestWithPreview(compiler, MODULE_PROC, "15", "testRecords4", null, "records", true);
+		internalTestWithPreview(compiler, MODULE_PROC, "16", "testRecords4", null, "records", true);
 	}
 	public void testRecords4a() throws IOException {
 		JavaCompiler compiler = BatchTestUtils.getEclipseCompiler();
-		internalTestWithPreview(compiler, MODULE_PROC, "15", "testRecords4a", null, "records", true);
+		internalTestWithPreview(compiler, MODULE_PROC, "16", "testRecords4a", null, "records", true);
 	}
 	public void testRecords4aJavac() throws Exception {
 		JavaCompiler compiler = ToolProvider.getSystemJavaCompiler();
-		internalTestWithPreview(compiler, MODULE_PROC, "15", "testRecords4a", null, "records", true);
+		internalTestWithPreview(compiler, MODULE_PROC, "16", "testRecords4a", null, "records", true);
 	}
 	public void testRecords5() throws IOException {
 		JavaCompiler compiler = BatchTestUtils.getEclipseCompiler();
-		internalTestWithPreview(compiler, MODULE_PROC, "15", "testRecords5", null, "records", true);
+		internalTestWithPreview(compiler, MODULE_PROC, "16", "testRecords5", null, "records", true);
 	}
 	public void testRecords5Javac() throws IOException {
 		JavaCompiler compiler = ToolProvider.getSystemJavaCompiler();
-		internalTestWithPreview(compiler, MODULE_PROC, "15", "testRecords5", null, "records", true);
+		internalTestWithPreview(compiler, MODULE_PROC, "16", "testRecords5", null, "records", true);
 	}
 	public void testRecords5a() throws IOException {
 		JavaCompiler compiler = BatchTestUtils.getEclipseCompiler();
-		internalTestWithPreview(compiler, MODULE_PROC, "15", "testRecords5a", null, "records", true);
+		internalTestWithPreview(compiler, MODULE_PROC, "16", "testRecords5a", null, "records", true);
 	}
 	public void testRecords5aJavac() throws IOException {
 		JavaCompiler compiler = ToolProvider.getSystemJavaCompiler();
-		internalTestWithPreview(compiler, MODULE_PROC, "15", "testRecords5a", null, "records", true);
+		internalTestWithPreview(compiler, MODULE_PROC, "16", "testRecords5a", null, "records", true);
 	}
 	public void testRecords6() throws IOException {
 		JavaCompiler compiler = BatchTestUtils.getEclipseCompiler();
-		internalTestWithPreview(compiler, MODULE_PROC, "15", "testRecords6", null, "records", true);
+		internalTestWithPreview(compiler, MODULE_PROC, "16", "testRecords6", null, "records", true);
 	}
 	public void testRecords6Javac() throws IOException {
 		JavaCompiler compiler = ToolProvider.getSystemJavaCompiler();
-		internalTestWithPreview(compiler, MODULE_PROC, "15", "testRecords6", null, "records", true);
+		internalTestWithPreview(compiler, MODULE_PROC, "16", "testRecords6", null, "records", true);
 	}
 	public void testRecords7() throws IOException {
 		JavaCompiler compiler = BatchTestUtils.getEclipseCompiler();
-		internalTestWithPreview(compiler, MODULE_PROC, "15", "testRecords7", null, "records", true);
+		internalTestWithPreview(compiler, MODULE_PROC, "16", "testRecords7", null, "records", true);
 	}
 	public void testRecords7Javac() throws IOException {
 		JavaCompiler compiler = ToolProvider.getSystemJavaCompiler();
-		internalTestWithPreview(compiler, MODULE_PROC, "15", "testRecords7", null, "records", true);
+		internalTestWithPreview(compiler, MODULE_PROC, "16", "testRecords7", null, "records", true);
 	}
 	public void testRecords8() throws IOException {
 		JavaCompiler compiler = BatchTestUtils.getEclipseCompiler();
-		internalTestWithPreview(compiler, MODULE_PROC, "15", "testRecords8", null, "records", true);
+		internalTestWithPreview(compiler, MODULE_PROC, "16", "testRecords8", null, "records", true);
 	}
 	public void testRecords8Javac() throws IOException {
 		JavaCompiler compiler = ToolProvider.getSystemJavaCompiler();
-		internalTestWithPreview(compiler, MODULE_PROC, "15", "testRecords8", null, "records", true);
+		internalTestWithPreview(compiler, MODULE_PROC, "16", "testRecords8", null, "records", true);
 	}
 	public void testRecords9() throws IOException {
 		JavaCompiler compiler = BatchTestUtils.getEclipseCompiler();
-		internalTestWithPreview(compiler, MODULE_PROC, "15", "testRecords9", null, "records", true);
+		internalTestWithPreview(compiler, MODULE_PROC, "16", "testRecords9", null, "records", true);
 	}
 	public void testRecords9Javac() throws IOException {
 		JavaCompiler compiler = ToolProvider.getSystemJavaCompiler();
-		internalTestWithPreview(compiler, MODULE_PROC, "15", "testRecords9", null, "records", true);
+		internalTestWithPreview(compiler, MODULE_PROC, "16", "testRecords9", null, "records", true);
+	}
+	public void testRecords10() throws IOException {
+		JavaCompiler compiler = BatchTestUtils.getEclipseCompiler();
+		internalTestWithPreview(compiler, MODULE_PROC, "16", "testRecords10", null, "records", true);
+	}
+	public void testRecords10Javac() throws IOException {
+		JavaCompiler compiler = ToolProvider.getSystemJavaCompiler();
+		internalTestWithPreview(compiler, MODULE_PROC, "16", "testRecords10", null, "records", true);
 	}
 
 	protected void internalTestWithPreview(JavaCompiler compiler, String processor, String compliance,
 			String testMethod, String testClass, String resourceArea, boolean preview) throws IOException {
-		if (!isRunning15()) {
+		if (!isRunning16()) {
 			return;
 		}
 		System.clearProperty(processor);
@@ -162,9 +174,9 @@
 		// if not, it will set it to an error value.
 		assertEquals("succeeded", System.getProperty(processor));
 	}
-	public boolean isRunning15() {
+	public boolean isRunning16() {
 		String specVersion = System.getProperty("java.specification.version");
-		return CompilerOptions.VERSION_15.equals(specVersion);
+		return CompilerOptions.VERSION_16.equals(specVersion);
 	}
 	/* (non-Javadoc)
 	 * @see junit.framework.TestCase#setUp()
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 5db2554..2af91cb 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
@@ -1,5 +1,5 @@
 /*******************************************************************************
- * Copyright (c) 2000, 2020 IBM Corporation and others.
+ * Copyright (c) 2000, 2021 IBM Corporation and others.
  *
  * This program and the accompanying materials
  * are made available under the terms of the Eclipse Public License 2.0
@@ -8,6 +8,10 @@
  *
  * SPDX-License-Identifier: EPL-2.0
  *
+ * 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:
  *     IBM Corporation - initial API and implementation
  *     Matt McCutchen - partial fix for https://bugs.eclipse.org/bugs/show_bug.cgi?id=122995
@@ -883,7 +887,8 @@
 						LocalVariableBinding local = (LocalVariableBinding) recipient;
 						// Note for JDK>=14, this could be LVB or RCB, hence typecasting to VB
 						long otherLocalTagBits = ((VariableBinding) annotationRecipient).tagBits;
-						local.tagBits = otherLocalTagBits;
+						// Make sure we retain the TagBits.IsArgument bit
+						local.tagBits = otherLocalTagBits | (local.tagBits & TagBits.IsArgument);
 						if ((otherLocalTagBits & TagBits.AnnotationSuppressWarnings) == 0) {
 							// None of the annotations is a SuppressWarnings annotation
 							// need to fill the instances array