Bug 534608 - Stack overflow in MethodInfo.getModifers() after recent
changes in JDT
diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/classfmt/AnnotationMethodInfo.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/classfmt/AnnotationMethodInfo.java
index a1bea9e..2cac7b0 100644
--- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/classfmt/AnnotationMethodInfo.java
+++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/classfmt/AnnotationMethodInfo.java
@@ -102,6 +102,9 @@
 	this.defaultValue = defaultValue;
 
 	this.accessFlags = methodInfo.accessFlags;
+//{ObjectTeams:
+	this.callBaseCtor = methodInfo.callBaseCtor;
+// SH}
 	this.attributeBytes = methodInfo.attributeBytes;
 	this.descriptor = methodInfo.descriptor;
 	this.exceptionNames = methodInfo.exceptionNames;
diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/classfmt/MethodInfo.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/classfmt/MethodInfo.java
index cc72520..2bb2ddf 100644
--- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/classfmt/MethodInfo.java
+++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/classfmt/MethodInfo.java
@@ -27,13 +27,13 @@
 import java.util.LinkedList;
 
 import org.eclipse.jdt.core.compiler.CharOperation;
-import org.eclipse.jdt.internal.compiler.ast.ASTNode;
 import org.eclipse.jdt.internal.compiler.codegen.AttributeNamesConstants;
 import org.eclipse.jdt.internal.compiler.codegen.ConstantPool;
 import org.eclipse.jdt.internal.compiler.env.IBinaryAnnotation;
 import org.eclipse.jdt.internal.compiler.env.IBinaryMethod;
 import org.eclipse.jdt.internal.compiler.env.IBinaryTypeAnnotation;
 import org.eclipse.jdt.internal.compiler.lookup.BinaryTypeBinding;
+import org.eclipse.jdt.internal.compiler.lookup.ExtraCompilerModifiers;
 import org.eclipse.jdt.internal.compiler.lookup.LookupEnvironment;
 import org.eclipse.jdt.internal.compiler.lookup.MethodBinding;
 import org.eclipse.jdt.internal.compiler.lookup.TagBits;
@@ -75,9 +75,7 @@
     /* After reading a method its attributes are stored here. */
     private LinkedList<AbstractAttribute> methodAttributes = new LinkedList<AbstractAttribute>();
     // more bits decoded from attributes:
-    protected int otModifiers;
-	// constants for the above:
-	static final int AccCallsBaseCtor = ASTNode.Bit1;
+    protected boolean callBaseCtor;
 // SH}
 
 public static MethodInfo createMethod(byte classFileBytes[], int offsets[], int offset, long version) {
@@ -177,15 +175,12 @@
 }
 
 //{ObjectTeams
-public void setAccessFlags (int flags) {
-	this.accessFlags = flags;
-}
 // special flag which needs to be added to the regular access flags:
 public void setCallsBaseCtor() {
-	this.otModifiers |= AccCallsBaseCtor;
+	this.callBaseCtor = true;
 }
 public boolean callsBaseCtor() {
-	return (this.otModifiers & AccCallsBaseCtor) != 0;
+	return this.callBaseCtor;
 }
 public void maybeRegister(
         BinaryTypeBinding clazz,
@@ -512,6 +507,9 @@
 }
 private synchronized void readModifierRelatedAttributes() {
 	int flags = u2At(0);
+//{ObjectTeams:
+	int otFlags = 0;
+// SH}
 	int attributesCount = u2At(6);
 	int readOffset = 8;
 	for (int i = 0; i < attributesCount; i++) {
@@ -538,12 +536,20 @@
 //{ObjectTeams: read method attributes
 					break;
 				default:
-					readOTAttribute(attributeName, this, readOffset+6, this.structOffset, this.constantPoolOffsets);
+					otFlags |= readOTAttribute(attributeName, this, readOffset+6, this.structOffset, this.constantPoolOffsets);
 // SH}
 			}
 		}
 		readOffset += (6 + u4At(readOffset + 2));
 	}
+//{ObjectTeams: combine sets of modifiers
+	if (otFlags != 0) {
+		if ((otFlags & ExtraCompilerModifiers.AccVisibilityMASK) != 0) {
+			flags &= ~ExtraCompilerModifiers.AccVisibilityMASK; // replace those bits
+		}
+		flags |= otFlags;
+	}
+// SH}
 	this.accessFlags = flags;
 }
 //{ObjectTeams: OT method attributes:
@@ -556,7 +562,7 @@
      * @param aStructOffset (subtract when indexing via constantPoolOffsets)
      * @param someConstantPoolOffsets
      */
-    void readOTAttribute(
+    int readOTAttribute(
             char[]     attributeName,
             MethodInfo info,
             int        readOffset,
@@ -564,15 +570,15 @@
             int[]      someConstantPoolOffsets)
     {
     	if (CharOperation.equals(attributeName, AttributeNamesConstants.CodeName))
-    		return; // optimization only.
+    		return 0; // optimization only.
         if (CharOperation.equals(attributeName, MODIFIERS_NAME))
         {
-            WordValueAttribute.readModifiers(info, readOffset);
+            return WordValueAttribute.readModifiers(info, readOffset);
             // not added to _readAttributes because evaluated immediately.
         }
         else if (CharOperation.equals(attributeName, ROLECLASS_METHOD_MODIFIERS_NAME))
         {
-        	WordValueAttribute.readRoleClassMethodModifiersAttribute(info, readOffset);
+        	return WordValueAttribute.readModifiers(info, readOffset);
             // not added to _readAttributes because evaluated immediately.
         }
         else if (CharOperation.equals(attributeName, CALLS_BASE_CTOR))
@@ -583,6 +589,7 @@
         else if (CharOperation.equals(attributeName, CALLIN_FLAGS))
         {
             this.methodAttributes.add(WordValueAttribute.readCallinFlags(info, readOffset));
+            return ExtraCompilerModifiers.AccCallin;
         }
         else if (CharOperation.equals(attributeName, TYPE_ANCHOR_LIST))
         {
@@ -592,6 +599,7 @@
         {
             this.methodAttributes.add(CopyInheritanceSourceAttribute.readcopyInherSrc(info, readOffset, aStructOffset, someConstantPoolOffsets));
         }
+        return 0;
     }
 
 // SH}
diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/classfmt/MethodInfoWithAnnotations.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/classfmt/MethodInfoWithAnnotations.java
index 53bd90a..02f0a0e 100644
--- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/classfmt/MethodInfoWithAnnotations.java
+++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/classfmt/MethodInfoWithAnnotations.java
@@ -20,6 +20,9 @@
 	this.annotations = annotations;
 
 	this.accessFlags = methodInfo.accessFlags;
+//{ObjectTeams:
+	this.callBaseCtor = methodInfo.callBaseCtor;
+// SH}
 	this.attributeBytes = methodInfo.attributeBytes;
 	this.descriptor = methodInfo.descriptor;
 	this.exceptionNames = methodInfo.exceptionNames;
diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/objectteams/otdt/internal/core/compiler/bytecode/WordValueAttribute.java b/org.eclipse.jdt.core/compiler/org/eclipse/objectteams/otdt/internal/core/compiler/bytecode/WordValueAttribute.java
index 90535c5..93b5a1a 100644
--- a/org.eclipse.jdt.core/compiler/org/eclipse/objectteams/otdt/internal/core/compiler/bytecode/WordValueAttribute.java
+++ b/org.eclipse.jdt.core/compiler/org/eclipse/objectteams/otdt/internal/core/compiler/bytecode/WordValueAttribute.java
@@ -1,7 +1,7 @@
 /**********************************************************************
  * This file is part of "Object Teams Development Tooling"-Software
  *
- * Copyright 2004, 2014 Fraunhofer Gesellschaft, Munich, Germany,
+ * Copyright 2004, 2018 Fraunhofer Gesellschaft, Munich, Germany,
  * for its Fraunhofer Institute for Computer Architecture and Software
  * Technology (FIRST), Berlin, Germany and Technical University Berlin,
  * Germany.
@@ -180,16 +180,16 @@
     }
 
     /**
-     * Read and evaluate a "Modifiers" attribute from byte code.
-     * @param method  this method shall be modified.
+     * Read the value of a "Modifiers" or "RoleClassMethodModifiers" attribute from byte code.
+     * @param method  method to read from
      * @param readOffset where to read
+     * @return the modifier flags
      */
-    public static void readModifiers(
+    public static int readModifiers(
             MethodInfo      method,
             int             readOffset)
     {
-        int  value = method.u2At(readOffset);
-        method.setAccessFlags(value);
+        return method.u2At(readOffset);
     }
 
     /**
@@ -209,12 +209,6 @@
         return new WordValueAttribute(ROLECLASS_METHOD_MODIFIERS_NAME, modifiers);
     }
 
-    public static void readRoleClassMethodModifiersAttribute(MethodInfo info, int readOffset) {
-		int binaryFlags = info.getModifiers() & ~ExtraCompilerModifiers.AccVisibilityMASK; // reset these bits first
-		int newFlags = info.u2At(readOffset);
-    	info.setAccessFlags(binaryFlags | newFlags);
-	}
-
     /**
      * Read and evaluate a "CallinFlags" attribute from byte code.
      * @param method  this method shall be modified.
@@ -225,7 +219,6 @@
             int             readOffset)
     {
         int  value = method.u2At(readOffset);
-        method.setAccessFlags(method.getModifiers()|ExtraCompilerModifiers.AccCallin);
         // create and store an attribute anyway, in order to store the actual bits.
         WordValueAttribute result = callinFlagsAttribute(value);
         result._methodInfo = method;