You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

ExplicitConstructorCall.java 9.4KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321
  1. /*******************************************************************************
  2. * Copyright (c) 2000, 2001, 2002 International Business Machines Corp. and others.
  3. * All rights reserved. This program and the accompanying materials
  4. * are made available under the terms of the Common Public License v0.5
  5. * which accompanies this distribution, and is available at
  6. * http://www.eclipse.org/legal/cpl-v05.html
  7. *
  8. * Contributors:
  9. * IBM Corporation - initial API and implementation
  10. ******************************************************************************/
  11. package org.eclipse.jdt.internal.compiler.ast;
  12. import org.eclipse.jdt.internal.compiler.IAbstractSyntaxTreeVisitor;
  13. import org.eclipse.jdt.internal.compiler.codegen.*;
  14. import org.eclipse.jdt.internal.compiler.flow.*;
  15. import org.eclipse.jdt.internal.compiler.lookup.*;
  16. public class ExplicitConstructorCall
  17. extends Statement
  18. implements InvocationSite {
  19. public Expression[] arguments;
  20. public Expression qualification;
  21. public MethodBinding binding;
  22. public int accessMode;
  23. public final static int ImplicitSuper = 1;
  24. public final static int Super = 2;
  25. public final static int This = 3;
  26. public VariableBinding[][] implicitArguments;
  27. boolean discardEnclosingInstance;
  28. MethodBinding syntheticAccessor;
  29. public ExplicitConstructorCall(int accessMode) {
  30. this.accessMode = accessMode;
  31. }
  32. public FlowInfo analyseCode(
  33. BlockScope currentScope,
  34. FlowContext flowContext,
  35. FlowInfo flowInfo) {
  36. // must verify that exceptions potentially thrown by this expression are caught in the method.
  37. try {
  38. ((MethodScope) currentScope).isConstructorCall = true;
  39. // process enclosing instance
  40. if (qualification != null) {
  41. flowInfo =
  42. qualification
  43. .analyseCode(currentScope, flowContext, flowInfo)
  44. .unconditionalInits();
  45. }
  46. // process arguments
  47. if (arguments != null) {
  48. for (int i = 0, max = arguments.length; i < max; i++) {
  49. flowInfo =
  50. arguments[i]
  51. .analyseCode(currentScope, flowContext, flowInfo)
  52. .unconditionalInits();
  53. }
  54. }
  55. ReferenceBinding[] thrownExceptions;
  56. if ((thrownExceptions = binding.thrownExceptions) != NoExceptions) {
  57. // check exceptions
  58. flowContext.checkExceptionHandlers(
  59. thrownExceptions,
  60. (accessMode == ImplicitSuper)
  61. ? (AstNode) currentScope.methodScope().referenceContext
  62. : (AstNode) this,
  63. flowInfo,
  64. currentScope);
  65. }
  66. manageEnclosingInstanceAccessIfNecessary(currentScope);
  67. manageSyntheticAccessIfNecessary(currentScope);
  68. return flowInfo;
  69. } finally {
  70. ((MethodScope) currentScope).isConstructorCall = false;
  71. }
  72. }
  73. /**
  74. * Constructor call code generation
  75. *
  76. * @param currentScope org.eclipse.jdt.internal.compiler.lookup.BlockScope
  77. * @param codeStream org.eclipse.jdt.internal.compiler.codegen.CodeStream
  78. */
  79. public void generateCode(BlockScope currentScope, CodeStream codeStream) {
  80. if ((bits & IsReachableMASK) == 0) {
  81. return;
  82. }
  83. try {
  84. ((MethodScope) currentScope).isConstructorCall = true;
  85. int pc = codeStream.position;
  86. codeStream.aload_0();
  87. // handling innerclass constructor invocation
  88. ReferenceBinding targetType;
  89. if ((targetType = binding.declaringClass).isNestedType()) {
  90. codeStream.generateSyntheticArgumentValues(
  91. currentScope,
  92. targetType,
  93. discardEnclosingInstance ? null : qualification,
  94. this);
  95. }
  96. // regular code gen
  97. if (arguments != null) {
  98. for (int i = 0, max = arguments.length; i < max; i++) {
  99. arguments[i].generateCode(currentScope, codeStream, true);
  100. }
  101. }
  102. if (syntheticAccessor != null) {
  103. // synthetic accessor got some extra arguments appended to its signature, which need values
  104. for (int i = 0,
  105. max = syntheticAccessor.parameters.length - binding.parameters.length;
  106. i < max;
  107. i++) {
  108. codeStream.aconst_null();
  109. }
  110. codeStream.invokespecial(syntheticAccessor);
  111. } else {
  112. codeStream.invokespecial(binding);
  113. }
  114. codeStream.recordPositionsFrom(pc, this.sourceStart);
  115. } finally {
  116. ((MethodScope) currentScope).isConstructorCall = false;
  117. }
  118. }
  119. public boolean isImplicitSuper() {
  120. //return true if I'm of these compiler added statement super();
  121. return (accessMode == ImplicitSuper);
  122. }
  123. public boolean isSuperAccess() {
  124. return accessMode != This;
  125. }
  126. public boolean isTypeAccess() {
  127. return true;
  128. }
  129. /* Inner emulation consists in either recording a dependency
  130. * link only, or performing one level of propagation.
  131. *
  132. * Dependency mechanism is used whenever dealing with source target
  133. * types, since by the time we reach them, we might not yet know their
  134. * exact need.
  135. */
  136. void manageEnclosingInstanceAccessIfNecessary(BlockScope currentScope) {
  137. ReferenceBinding superType;
  138. // perform some emulation work in case there is some and we are inside a local type only
  139. if ((superType = binding.declaringClass).isNestedType()
  140. && currentScope.enclosingSourceType().isLocalType()) {
  141. if (superType.isLocalType()) {
  142. ((LocalTypeBinding) superType).addInnerEmulationDependent(
  143. currentScope,
  144. qualification != null,
  145. true);
  146. // request direct access
  147. } else {
  148. // locally propagate, since we already now the desired shape for sure
  149. currentScope.propagateInnerEmulation(superType, qualification != null, true);
  150. // request direct access
  151. }
  152. }
  153. }
  154. public void manageSyntheticAccessIfNecessary(BlockScope currentScope) {
  155. if (binding.alwaysNeedsAccessMethod()) {
  156. syntheticAccessor = binding.getAccessMethod(true);
  157. return;
  158. }
  159. // perform some emulation work in case there is some and we are inside a local type only
  160. if (binding.isPrivate() && (accessMode != This)) {
  161. if (currentScope
  162. .environment()
  163. .options
  164. .isPrivateConstructorAccessChangingVisibility) {
  165. binding.tagForClearingPrivateModifier();
  166. // constructor will not be dumped as private, no emulation required thus
  167. } else {
  168. syntheticAccessor =
  169. ((SourceTypeBinding) binding.declaringClass).addSyntheticMethod(binding);
  170. currentScope.problemReporter().needToEmulateMethodAccess(binding, this);
  171. }
  172. }
  173. }
  174. public void resolve(BlockScope scope) {
  175. // the return type should be void for a constructor.
  176. // the test is made into getConstructor
  177. // mark the fact that we are in a constructor call.....
  178. // unmark at all returns
  179. try {
  180. ((MethodScope) scope).isConstructorCall = true;
  181. ReferenceBinding receiverType = scope.enclosingSourceType();
  182. //System.err.println("rT: " + receiverType + " scope " + scope);
  183. if (accessMode != This)
  184. receiverType = receiverType.superclass();
  185. if (receiverType == null) {
  186. return;
  187. }
  188. // qualification should be from the type of the enclosingType
  189. if (qualification != null) {
  190. if (accessMode != Super) {
  191. scope.problemReporter().unnecessaryEnclosingInstanceSpecification(
  192. qualification,
  193. receiverType);
  194. }
  195. ReferenceBinding enclosingType = receiverType.enclosingType();
  196. if (enclosingType == null) {
  197. scope.problemReporter().unnecessaryEnclosingInstanceSpecification(
  198. qualification,
  199. receiverType);
  200. discardEnclosingInstance = true;
  201. } else {
  202. TypeBinding qTb = qualification.resolveTypeExpecting(scope, enclosingType);
  203. qualification.implicitWidening(qTb, qTb);
  204. }
  205. }
  206. // arguments buffering for the method lookup
  207. TypeBinding[] argTypes = NoParameters;
  208. if (arguments != null) {
  209. boolean argHasError = false; // typeChecks all arguments
  210. int length = arguments.length;
  211. argTypes = new TypeBinding[length];
  212. for (int i = 0; i < length; i++)
  213. if ((argTypes[i] = arguments[i].resolveType(scope)) == null)
  214. argHasError = true;
  215. if (argHasError)
  216. return;
  217. }
  218. if ((binding = scope.getConstructor(receiverType, argTypes, this))
  219. .isValidBinding()) {
  220. if (isMethodUseDeprecated(binding, scope))
  221. scope.problemReporter().deprecatedMethod(binding, this);
  222. // see for user-implicit widening conversion
  223. if (arguments != null) {
  224. int length = arguments.length;
  225. TypeBinding[] paramTypes = binding.parameters;
  226. for (int i = 0; i < length; i++)
  227. arguments[i].implicitWidening(paramTypes[i], argTypes[i]);
  228. }
  229. } else {
  230. if (binding.declaringClass == null)
  231. binding.declaringClass = receiverType;
  232. scope.problemReporter().invalidConstructor(this, binding);
  233. }
  234. } finally {
  235. ((MethodScope) scope).isConstructorCall = false;
  236. }
  237. }
  238. public void setActualReceiverType(ReferenceBinding receiverType) {
  239. // ignored
  240. }
  241. public void setDepth(int depth) {
  242. // ignore for here
  243. }
  244. public void setFieldIndex(int depth) {
  245. // ignore for here
  246. }
  247. public String toString(int tab) {
  248. String s = tabString(tab);
  249. if (qualification != null)
  250. s = s + qualification.toStringExpression() + "."; //$NON-NLS-1$
  251. if (accessMode == This) {
  252. s = s + "this("; //$NON-NLS-1$
  253. } else {
  254. s = s + "super("; //$NON-NLS-1$
  255. }
  256. if (arguments != null)
  257. for (int i = 0; i < arguments.length; i++) {
  258. s = s + arguments[i].toStringExpression();
  259. if (i != arguments.length - 1)
  260. s = s + ", "; //$NON-NLS-1$
  261. }
  262. s = s + ")"; //$NON-NLS-1$
  263. return s;
  264. }
  265. public void traverse(IAbstractSyntaxTreeVisitor visitor, BlockScope scope) {
  266. if (visitor.visit(this, scope)) {
  267. if (qualification != null) {
  268. qualification.traverse(visitor, scope);
  269. }
  270. if (arguments != null) {
  271. int argumentLength = arguments.length;
  272. for (int i = 0; i < argumentLength; i++)
  273. arguments[i].traverse(visitor, scope);
  274. }
  275. }
  276. visitor.endVisit(this, scope);
  277. }
  278. }