statements.rs 85 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535153615371538153915401541154215431544154515461547154815491550155115521553155415551556155715581559156015611562156315641565156615671568156915701571157215731574157515761577157815791580158115821583158415851586158715881589159015911592159315941595159615971598159916001601160216031604160516061607160816091610161116121613161416151616161716181619162016211622162316241625162616271628162916301631163216331634163516361637163816391640164116421643164416451646164716481649165016511652165316541655165616571658165916601661166216631664166516661667166816691670167116721673167416751676167716781679168016811682168316841685168616871688168916901691169216931694169516961697169816991700170117021703170417051706170717081709171017111712171317141715171617171718171917201721172217231724172517261727172817291730173117321733173417351736173717381739174017411742174317441745174617471748174917501751175217531754175517561757175817591760176117621763176417651766176717681769177017711772177317741775177617771778177917801781178217831784178517861787178817891790179117921793179417951796179717981799180018011802180318041805180618071808180918101811181218131814181518161817181818191820182118221823182418251826182718281829183018311832183318341835183618371838183918401841184218431844184518461847184818491850185118521853185418551856185718581859186018611862186318641865186618671868186918701871187218731874187518761877187818791880188118821883188418851886188718881889189018911892189318941895189618971898189919001901190219031904190519061907190819091910191119121913191419151916191719181919192019211922192319241925192619271928192919301931193219331934193519361937193819391940194119421943194419451946194719481949195019511952195319541955195619571958195919601961196219631964196519661967196819691970197119721973197419751976197719781979198019811982198319841985198619871988198919901991199219931994199519961997199819992000200120022003200420052006200720082009201020112012201320142015201620172018201920202021202220232024202520262027202820292030203120322033203420352036203720382039204020412042204320442045204620472048204920502051205220532054205520562057205820592060206120622063206420652066206720682069207020712072207320742075207620772078207920802081208220832084208520862087208820892090209120922093209420952096209720982099210021012102210321042105210621072108210921102111211221132114211521162117211821192120212121222123212421252126212721282129213021312132213321342135213621372138213921402141214221432144214521462147214821492150215121522153215421552156215721582159216021612162216321642165216621672168216921702171217221732174217521762177217821792180218121822183218421852186218721882189219021912192219321942195219621972198219922002201220222032204220522062207220822092210221122122213221422152216221722182219222022212222222322242225222622272228222922302231223222332234223522362237223822392240224122422243224422452246224722482249225022512252225322542255225622572258225922602261226222632264226522662267226822692270227122722273227422752276227722782279228022812282228322842285228622872288228922902291229222932294229522962297229822992300230123022303230423052306230723082309231023112312231323142315231623172318231923202321232223232324232523262327232823292330233123322333233423352336233723382339234023412342234323442345234623472348234923502351235223532354235523562357235823592360236123622363236423652366236723682369237023712372237323742375237623772378237923802381238223832384238523862387238823892390239123922393239423952396239723982399240024012402240324042405240624072408240924102411241224132414241524162417241824192420242124222423242424252426242724282429243024312432243324342435243624372438243924402441244224432444244524462447244824492450245124522453245424552456245724582459246024612462246324642465246624672468246924702471247224732474247524762477247824792480248124822483248424852486248724882489249024912492249324942495249624972498249925002501250225032504250525062507250825092510251125122513251425152516251725182519252025212522252325242525252625272528252925302531253225332534253525362537253825392540254125422543254425452546254725482549255025512552255325542555255625572558255925602561256225632564256525662567256825692570257125722573257425752576257725782579258025812582258325842585258625872588258925902591259225932594259525962597259825992600260126022603260426052606260726082609261026112612261326142615261626172618261926202621262226232624262526262627262826292630263126322633263426352636
  1. // SPDX-License-Identifier: Apache-2.0
  2. use super::ast::*;
  3. use super::contracts::is_base;
  4. use super::diagnostics::Diagnostics;
  5. use super::eval::check_term_for_constant_overflow;
  6. use super::expression::{
  7. function_call::{available_functions, call_expr, named_call_expr},
  8. ExprContext, ResolveTo,
  9. };
  10. use super::symtable::{LoopScopes, Symtable};
  11. use crate::sema::expression::constructor::{
  12. constructor_named_args, match_constructor_to_args, new,
  13. };
  14. use crate::sema::expression::function_call::{
  15. function_call_expr, function_call_pos_args, named_function_call_expr,
  16. };
  17. use crate::sema::expression::resolve_expression::expression;
  18. use crate::sema::function_annotation::function_body_annotations;
  19. use crate::sema::function_annotation::{unexpected_parameter_annotation, UnresolvedAnnotation};
  20. use crate::sema::symtable::{VariableInitializer, VariableUsage};
  21. use crate::sema::unused_variable::{assigned_variable, check_function_call, used_variable};
  22. use crate::sema::yul::resolve_inline_assembly;
  23. use crate::sema::Recurse;
  24. use crate::Target;
  25. use solang_parser::pt;
  26. use solang_parser::pt::CatchClause;
  27. use solang_parser::pt::CodeLocation;
  28. use solang_parser::pt::OptionalCodeLocation;
  29. use std::collections::{BTreeMap, HashMap, HashSet};
  30. use std::sync::Arc;
  31. pub fn resolve_function_body(
  32. def: &pt::FunctionDefinition,
  33. annotations: &[&pt::Annotation],
  34. file_no: usize,
  35. contract_no: Option<usize>,
  36. function_no: usize,
  37. ns: &mut Namespace,
  38. ) -> Result<(), ()> {
  39. let mut symtable = Symtable::new();
  40. let mut loops = LoopScopes::new();
  41. let mut res = Vec::new();
  42. let context = ExprContext {
  43. file_no,
  44. contract_no,
  45. function_no: Some(function_no),
  46. unchecked: false,
  47. constant: false,
  48. lvalue: false,
  49. yul_function: false,
  50. };
  51. let mut unresolved_annotation: Vec<UnresolvedAnnotation> = Vec::new();
  52. // first add function parameters
  53. for (i, p) in def.params.iter().enumerate() {
  54. let p = p.1.as_ref().unwrap();
  55. if let Some(ref name) = p.name {
  56. if let Some(pos) = symtable.add(
  57. name,
  58. ns.functions[function_no].params[i].ty.clone(),
  59. ns,
  60. VariableInitializer::Solidity(None),
  61. VariableUsage::Parameter,
  62. p.storage.clone(),
  63. ) {
  64. ns.check_shadowing(file_no, contract_no, name);
  65. if p.annotation.is_some() {
  66. unresolved_annotation.push(UnresolvedAnnotation {
  67. parameter_no: i,
  68. var_no: pos,
  69. });
  70. }
  71. symtable.arguments.push(Some(pos));
  72. }
  73. } else {
  74. symtable.arguments.push(None);
  75. }
  76. }
  77. function_body_annotations(
  78. function_no,
  79. annotations,
  80. &unresolved_annotation,
  81. &mut symtable,
  82. &context,
  83. ns,
  84. );
  85. // now that the function arguments have been resolved, we can resolve the bases for
  86. // constructors.
  87. if def.ty == pt::FunctionTy::Constructor {
  88. let contract_no = contract_no.unwrap();
  89. let mut resolve_bases: BTreeMap<usize, pt::Loc> = BTreeMap::new();
  90. let mut all_ok = true;
  91. let mut diagnostics = Diagnostics::default();
  92. for attr in &def.attributes {
  93. if let pt::FunctionAttribute::BaseOrModifier(loc, base) = attr {
  94. match ns.resolve_contract_with_namespace(file_no, &base.name, &mut diagnostics) {
  95. Ok(base_no) => {
  96. if base_no == contract_no || !is_base(base_no, contract_no, ns) {
  97. ns.diagnostics.push(Diagnostic::error(
  98. *loc,
  99. format!(
  100. "contract '{}' is not a base contract of '{}'",
  101. base.name, ns.contracts[contract_no].name,
  102. ),
  103. ));
  104. all_ok = false;
  105. } else if let Some(prev) = resolve_bases.get(&base_no) {
  106. ns.diagnostics.push(Diagnostic::error_with_note(
  107. *loc,
  108. format!("duplicate base contract '{}'", base.name),
  109. *prev,
  110. format!("previous base contract '{}'", base.name),
  111. ));
  112. all_ok = false;
  113. } else if let Some(args) = &base.args {
  114. let mut diagnostics = Diagnostics::default();
  115. // find constructor which matches this
  116. if let Ok((Some(constructor_no), args)) = match_constructor_to_args(
  117. &base.loc,
  118. args,
  119. base_no,
  120. &context,
  121. ns,
  122. &mut symtable,
  123. &mut diagnostics,
  124. ) {
  125. for arg in &args {
  126. used_variable(ns, arg, &mut symtable);
  127. }
  128. ns.functions[function_no]
  129. .bases
  130. .insert(base_no, (base.loc, constructor_no, args));
  131. resolve_bases.insert(base_no, base.loc);
  132. }
  133. ns.diagnostics.extend(diagnostics);
  134. } else {
  135. ns.diagnostics.push(Diagnostic::error(
  136. *loc,
  137. format!(
  138. "missing arguments to constructor of contract '{}'",
  139. base.name
  140. ),
  141. ));
  142. all_ok = false;
  143. }
  144. }
  145. Err(_) => {
  146. all_ok = false;
  147. }
  148. }
  149. }
  150. }
  151. if all_ok && ns.contracts[contract_no].instantiable {
  152. for base in &ns.contracts[contract_no].bases {
  153. // do we have constructor arguments
  154. if base.constructor.is_some() || resolve_bases.contains_key(&base.contract_no) {
  155. continue;
  156. }
  157. // does the contract require arguments
  158. if ns.contracts[base.contract_no].constructor_needs_arguments(ns) {
  159. ns.diagnostics.push(Diagnostic::error(
  160. def.loc,
  161. format!(
  162. "missing arguments to contract '{}' constructor",
  163. ns.contracts[base.contract_no].name
  164. ),
  165. ));
  166. }
  167. }
  168. }
  169. ns.diagnostics.extend(diagnostics);
  170. }
  171. // resolve modifiers on functions
  172. if def.ty == pt::FunctionTy::Function {
  173. let mut modifiers = Vec::new();
  174. let mut diagnostics = Diagnostics::default();
  175. for attr in &def.attributes {
  176. if let pt::FunctionAttribute::BaseOrModifier(_, modifier) = attr {
  177. if modifier.name.identifiers.len() != 1 {
  178. ns.diagnostics.push(Diagnostic::error(
  179. def.loc,
  180. format!("unknown modifier '{}' on function", modifier.name),
  181. ));
  182. } else {
  183. let modifier_name = &modifier.name.identifiers[0];
  184. if let Ok(e) = function_call_pos_args(
  185. &modifier.loc,
  186. modifier_name,
  187. pt::FunctionTy::Modifier,
  188. modifier.args.as_ref().unwrap_or(&Vec::new()),
  189. available_functions(
  190. &modifier_name.name,
  191. false,
  192. context.file_no,
  193. context.contract_no,
  194. ns,
  195. ),
  196. true,
  197. &context,
  198. ns,
  199. ResolveTo::Unknown,
  200. &mut symtable,
  201. &mut diagnostics,
  202. ) {
  203. modifiers.push(e);
  204. }
  205. }
  206. }
  207. }
  208. ns.diagnostics.extend(diagnostics);
  209. ns.functions[function_no].modifiers = modifiers;
  210. }
  211. // If there is no return statement, any unnamed return types will
  212. // implicitly be 0. If there is a return type which is a storage
  213. // reference (e.g. int[] storage), a value must be given via
  214. // a return statement, else the value will not refer to valid storage,
  215. // as 0 is almost certainly an invalid storage key.
  216. let mut return_required = false;
  217. // If any of the return values are named, then the return statement can be omitted at
  218. // the end of the function, and return values may be omitted too. Create variables to
  219. // store the return values
  220. for (i, p) in def.returns.iter().enumerate() {
  221. let ret = &ns.functions[function_no].returns[i];
  222. if let Some(ref name) = p.1.as_ref().unwrap().name {
  223. if let Some(pos) = symtable.add(
  224. name,
  225. ret.ty.clone(),
  226. ns,
  227. VariableInitializer::Solidity(None),
  228. VariableUsage::ReturnVariable,
  229. None,
  230. ) {
  231. ns.check_shadowing(file_no, contract_no, name);
  232. symtable.returns.push(pos);
  233. }
  234. } else {
  235. if ret.ty.is_contract_storage() {
  236. return_required = true;
  237. }
  238. // anonymous return
  239. let id = pt::Identifier {
  240. loc: p.0,
  241. name: "".to_owned(),
  242. };
  243. let pos = symtable
  244. .add(
  245. &id,
  246. ret.ty.clone(),
  247. ns,
  248. VariableInitializer::Solidity(None),
  249. VariableUsage::AnonymousReturnVariable,
  250. None,
  251. )
  252. .unwrap();
  253. symtable.returns.push(pos);
  254. }
  255. }
  256. let body = match def.body {
  257. None => return Ok(()),
  258. Some(ref body) => body,
  259. };
  260. let mut diagnostics = Diagnostics::default();
  261. let reachable = statement(
  262. body,
  263. &mut res,
  264. &context,
  265. &mut symtable,
  266. &mut loops,
  267. ns,
  268. &mut diagnostics,
  269. );
  270. ns.diagnostics.extend(diagnostics);
  271. if reachable? && return_required {
  272. for param in ns.functions[function_no].returns.iter() {
  273. if param.id.is_none() && param.ty.is_contract_storage() {
  274. ns.diagnostics.push(Diagnostic::error(
  275. param.loc,
  276. "storage reference must be given value with a return statement".to_string(),
  277. ));
  278. }
  279. }
  280. }
  281. if def.ty == pt::FunctionTy::Modifier {
  282. let mut has_underscore = false;
  283. // unsure modifier has underscore
  284. fn check_statement(stmt: &Statement, has_underscore: &mut bool) -> bool {
  285. if stmt.is_underscore() {
  286. *has_underscore = true;
  287. false
  288. } else {
  289. true
  290. }
  291. }
  292. for stmt in &mut res {
  293. stmt.recurse(&mut has_underscore, check_statement);
  294. }
  295. if !has_underscore {
  296. ns.diagnostics.push(Diagnostic::error(
  297. body.loc().end_range(),
  298. "missing '_' in modifier".to_string(),
  299. ));
  300. }
  301. }
  302. ns.functions[function_no].body = res;
  303. std::mem::swap(&mut ns.functions[function_no].symtable, &mut symtable);
  304. Ok(())
  305. }
  306. /// Resolve a statement
  307. #[allow(clippy::ptr_arg)]
  308. fn statement(
  309. stmt: &pt::Statement,
  310. res: &mut Vec<Statement>,
  311. context: &ExprContext,
  312. symtable: &mut Symtable,
  313. loops: &mut LoopScopes,
  314. ns: &mut Namespace,
  315. diagnostics: &mut Diagnostics,
  316. ) -> Result<bool, ()> {
  317. let function_no = context.function_no.unwrap();
  318. match stmt {
  319. pt::Statement::VariableDefinition(loc, decl, initializer) => {
  320. let (var_ty, ty_loc) =
  321. resolve_var_decl_ty(&decl.ty, &decl.storage, context, ns, diagnostics)?;
  322. let initializer = if let Some(init) = initializer {
  323. let expr = expression(
  324. init,
  325. context,
  326. ns,
  327. symtable,
  328. diagnostics,
  329. ResolveTo::Type(&var_ty),
  330. )?;
  331. expr.recurse(ns, check_term_for_constant_overflow);
  332. used_variable(ns, &expr, symtable);
  333. Some(Arc::new(expr.cast(
  334. &expr.loc(),
  335. &var_ty,
  336. true,
  337. ns,
  338. diagnostics,
  339. )?))
  340. } else {
  341. None
  342. };
  343. if let Some(pos) = symtable.add(
  344. decl.name.as_ref().unwrap(),
  345. var_ty.clone(),
  346. ns,
  347. VariableInitializer::Solidity(initializer.clone()),
  348. VariableUsage::LocalVariable,
  349. decl.storage.clone(),
  350. ) {
  351. ns.check_shadowing(
  352. context.file_no,
  353. context.contract_no,
  354. decl.name.as_ref().unwrap(),
  355. );
  356. res.push(Statement::VariableDecl(
  357. *loc,
  358. pos,
  359. Parameter {
  360. loc: decl.loc,
  361. ty: var_ty,
  362. ty_loc: Some(ty_loc),
  363. id: Some(decl.name.clone().unwrap()),
  364. indexed: false,
  365. readonly: false,
  366. infinite_size: false,
  367. recursive: false,
  368. annotation: None,
  369. },
  370. initializer,
  371. ));
  372. }
  373. Ok(true)
  374. }
  375. pt::Statement::Block {
  376. statements,
  377. unchecked,
  378. ..
  379. } => {
  380. symtable.new_scope();
  381. let mut reachable = true;
  382. let mut context = context.clone();
  383. context.unchecked |= *unchecked;
  384. for stmt in statements {
  385. if !reachable {
  386. ns.diagnostics.push(Diagnostic::error(
  387. stmt.loc(),
  388. "unreachable statement".to_string(),
  389. ));
  390. return Err(());
  391. }
  392. reachable = statement(stmt, res, &context, symtable, loops, ns, diagnostics)?;
  393. }
  394. symtable.leave_scope();
  395. Ok(reachable)
  396. }
  397. pt::Statement::Break(loc) => {
  398. if loops.do_break() {
  399. res.push(Statement::Break(*loc));
  400. Ok(false)
  401. } else {
  402. diagnostics.push(Diagnostic::error(
  403. stmt.loc(),
  404. "break statement not in loop".to_string(),
  405. ));
  406. Err(())
  407. }
  408. }
  409. pt::Statement::Continue(loc) => {
  410. if loops.do_continue() {
  411. res.push(Statement::Continue(*loc));
  412. Ok(false)
  413. } else {
  414. diagnostics.push(Diagnostic::error(
  415. stmt.loc(),
  416. "continue statement not in loop".to_string(),
  417. ));
  418. Err(())
  419. }
  420. }
  421. pt::Statement::While(loc, cond_expr, body) => {
  422. let expr = expression(
  423. cond_expr,
  424. context,
  425. ns,
  426. symtable,
  427. diagnostics,
  428. ResolveTo::Type(&Type::Bool),
  429. )?;
  430. used_variable(ns, &expr, symtable);
  431. let cond = expr.cast(&expr.loc(), &Type::Bool, true, ns, diagnostics)?;
  432. symtable.new_scope();
  433. let mut body_stmts = Vec::new();
  434. loops.new_scope();
  435. statement(
  436. body,
  437. &mut body_stmts,
  438. context,
  439. symtable,
  440. loops,
  441. ns,
  442. diagnostics,
  443. )?;
  444. symtable.leave_scope();
  445. loops.leave_scope();
  446. res.push(Statement::While(*loc, true, cond, body_stmts));
  447. Ok(true)
  448. }
  449. pt::Statement::DoWhile(loc, body, cond_expr) => {
  450. let expr = expression(
  451. cond_expr,
  452. context,
  453. ns,
  454. symtable,
  455. diagnostics,
  456. ResolveTo::Type(&Type::Bool),
  457. )?;
  458. used_variable(ns, &expr, symtable);
  459. let cond = expr.cast(&expr.loc(), &Type::Bool, true, ns, diagnostics)?;
  460. symtable.new_scope();
  461. let mut body_stmts = Vec::new();
  462. loops.new_scope();
  463. statement(
  464. body,
  465. &mut body_stmts,
  466. context,
  467. symtable,
  468. loops,
  469. ns,
  470. diagnostics,
  471. )?;
  472. symtable.leave_scope();
  473. loops.leave_scope();
  474. res.push(Statement::DoWhile(*loc, true, body_stmts, cond));
  475. Ok(true)
  476. }
  477. pt::Statement::If(loc, cond_expr, then, else_) => {
  478. let expr = expression(
  479. cond_expr,
  480. context,
  481. ns,
  482. symtable,
  483. diagnostics,
  484. ResolveTo::Type(&Type::Bool),
  485. )?;
  486. used_variable(ns, &expr, symtable);
  487. let cond = expr.cast(&expr.loc(), &Type::Bool, true, ns, diagnostics)?;
  488. symtable.new_scope();
  489. let mut then_stmts = Vec::new();
  490. let mut reachable = statement(
  491. then,
  492. &mut then_stmts,
  493. context,
  494. symtable,
  495. loops,
  496. ns,
  497. diagnostics,
  498. )?;
  499. symtable.leave_scope();
  500. let mut else_stmts = Vec::new();
  501. if let Some(stmts) = else_ {
  502. symtable.new_scope();
  503. reachable |= statement(
  504. stmts,
  505. &mut else_stmts,
  506. context,
  507. symtable,
  508. loops,
  509. ns,
  510. diagnostics,
  511. )?;
  512. symtable.leave_scope();
  513. } else {
  514. reachable = true;
  515. }
  516. res.push(Statement::If(*loc, reachable, cond, then_stmts, else_stmts));
  517. Ok(reachable)
  518. }
  519. pt::Statement::Args(loc, _) => {
  520. ns.diagnostics.push(Diagnostic::error(
  521. *loc,
  522. "expected code block, not list of named arguments".to_string(),
  523. ));
  524. Err(())
  525. }
  526. pt::Statement::For(loc, init_stmt, None, next_expr, body_stmt) => {
  527. symtable.new_scope();
  528. let mut init = Vec::new();
  529. if let Some(init_stmt) = init_stmt {
  530. statement(
  531. init_stmt,
  532. &mut init,
  533. context,
  534. symtable,
  535. loops,
  536. ns,
  537. diagnostics,
  538. )?;
  539. }
  540. loops.new_scope();
  541. let mut body = Vec::new();
  542. if let Some(body_stmt) = body_stmt {
  543. statement(
  544. body_stmt,
  545. &mut body,
  546. context,
  547. symtable,
  548. loops,
  549. ns,
  550. diagnostics,
  551. )?;
  552. }
  553. let control = loops.leave_scope();
  554. let reachable = control.no_breaks > 0;
  555. let mut next = None;
  556. if let Some(next_expr) = next_expr {
  557. next = Some(expression(
  558. next_expr,
  559. context,
  560. ns,
  561. symtable,
  562. diagnostics,
  563. ResolveTo::Type(&Type::Bool),
  564. )?);
  565. }
  566. symtable.leave_scope();
  567. res.push(Statement::For {
  568. loc: *loc,
  569. reachable,
  570. init,
  571. next,
  572. cond: None,
  573. body,
  574. });
  575. Ok(reachable)
  576. }
  577. pt::Statement::For(loc, init_stmt, Some(cond_expr), next_expr, body_stmt) => {
  578. symtable.new_scope();
  579. let mut init = Vec::new();
  580. let mut body = Vec::new();
  581. let mut next = None;
  582. if let Some(init_stmt) = init_stmt {
  583. statement(
  584. init_stmt,
  585. &mut init,
  586. context,
  587. symtable,
  588. loops,
  589. ns,
  590. diagnostics,
  591. )?;
  592. }
  593. let cond = expression(
  594. cond_expr,
  595. context,
  596. ns,
  597. symtable,
  598. diagnostics,
  599. ResolveTo::Type(&Type::Bool),
  600. )?;
  601. let cond = cond.cast(&cond_expr.loc(), &Type::Bool, true, ns, diagnostics)?;
  602. // continue goes to next, and if that does exist, cond
  603. loops.new_scope();
  604. let mut body_reachable = match body_stmt {
  605. Some(body_stmt) => statement(
  606. body_stmt,
  607. &mut body,
  608. context,
  609. symtable,
  610. loops,
  611. ns,
  612. diagnostics,
  613. )?,
  614. None => true,
  615. };
  616. let control = loops.leave_scope();
  617. if control.no_continues > 0 {
  618. body_reachable = true;
  619. }
  620. if let Some(next_expr) = next_expr {
  621. if body_reachable {
  622. next = Some(expression(
  623. next_expr,
  624. context,
  625. ns,
  626. symtable,
  627. diagnostics,
  628. ResolveTo::Type(&Type::Bool),
  629. )?);
  630. }
  631. }
  632. symtable.leave_scope();
  633. res.push(Statement::For {
  634. loc: *loc,
  635. reachable: true,
  636. init,
  637. next,
  638. cond: Some(cond),
  639. body,
  640. });
  641. Ok(true)
  642. }
  643. pt::Statement::Return(loc, None) => {
  644. let no_returns = ns.functions[context.function_no.unwrap()].returns.len();
  645. if symtable.returns.len() != no_returns {
  646. ns.diagnostics.push(Diagnostic::error(
  647. *loc,
  648. format!("missing return value, {no_returns} return values expected"),
  649. ));
  650. return Err(());
  651. }
  652. res.push(Statement::Return(*loc, None));
  653. Ok(false)
  654. }
  655. pt::Statement::Return(loc, Some(returns)) => {
  656. let expr = return_with_values(returns, loc, context, symtable, ns, diagnostics)?;
  657. expr.recurse(ns, check_term_for_constant_overflow);
  658. for offset in symtable.returns.iter() {
  659. let elem = symtable.vars.get_mut(offset).unwrap();
  660. elem.assigned = true;
  661. }
  662. res.push(Statement::Return(*loc, Some(expr)));
  663. Ok(false)
  664. }
  665. pt::Statement::Expression(loc, expr) => {
  666. let expr = match expr {
  667. // delete statement
  668. pt::Expression::Delete(_, expr) => {
  669. let expr =
  670. expression(expr, context, ns, symtable, diagnostics, ResolveTo::Unknown)?;
  671. used_variable(ns, &expr, symtable);
  672. return if let Type::StorageRef(_, ty) = expr.ty() {
  673. if expr.ty().is_mapping() {
  674. ns.diagnostics.push(Diagnostic::error(
  675. *loc,
  676. "'delete' cannot be applied to mapping type".to_string(),
  677. ));
  678. return Err(());
  679. }
  680. res.push(Statement::Delete(*loc, ty.as_ref().clone(), expr));
  681. Ok(true)
  682. } else {
  683. ns.diagnostics.push(Diagnostic::warning(
  684. *loc,
  685. "argument to 'delete' should be storage reference".to_string(),
  686. ));
  687. Err(())
  688. };
  689. }
  690. // is it an underscore modifier statement
  691. pt::Expression::Variable(id)
  692. if id.name == "_"
  693. && ns.functions[function_no].ty == pt::FunctionTy::Modifier =>
  694. {
  695. res.push(Statement::Underscore(*loc));
  696. return Ok(true);
  697. }
  698. pt::Expression::FunctionCall(loc, ty, args) => {
  699. let ret = call_expr(
  700. loc,
  701. ty,
  702. args,
  703. true,
  704. context,
  705. ns,
  706. symtable,
  707. diagnostics,
  708. ResolveTo::Discard,
  709. )?;
  710. ret.recurse(ns, check_term_for_constant_overflow);
  711. ret
  712. }
  713. pt::Expression::NamedFunctionCall(loc, ty, args) => {
  714. let ret = named_call_expr(
  715. loc,
  716. ty,
  717. args,
  718. true,
  719. context,
  720. ns,
  721. symtable,
  722. diagnostics,
  723. ResolveTo::Discard,
  724. )?;
  725. ret.recurse(ns, check_term_for_constant_overflow);
  726. ret
  727. }
  728. _ => {
  729. // is it a destructure statement
  730. if let pt::Expression::Assign(_, var, expr) = expr {
  731. if let pt::Expression::List(_, var) = var.as_ref() {
  732. res.push(destructure(
  733. loc,
  734. var,
  735. expr,
  736. context,
  737. symtable,
  738. ns,
  739. diagnostics,
  740. )?);
  741. // if a noreturn function was called, then the destructure would not resolve
  742. return Ok(true);
  743. }
  744. }
  745. // the rest. We don't care about the result
  746. expression(expr, context, ns, symtable, diagnostics, ResolveTo::Unknown)?
  747. }
  748. };
  749. let reachable = expr.tys() != vec![Type::Unreachable];
  750. res.push(Statement::Expression(*loc, reachable, expr));
  751. Ok(reachable)
  752. }
  753. pt::Statement::Try(loc, expr, returns_and_ok, clause_stmts) => {
  754. let (stmt, reachable) = try_catch(
  755. loc,
  756. expr,
  757. returns_and_ok,
  758. clause_stmts,
  759. context,
  760. symtable,
  761. loops,
  762. ns,
  763. diagnostics,
  764. )?;
  765. res.push(stmt);
  766. Ok(reachable)
  767. }
  768. pt::Statement::Emit(loc, ty) => {
  769. if let Ok(emit) = emit_event(loc, ty, context, symtable, ns, diagnostics) {
  770. res.push(emit);
  771. }
  772. Ok(true)
  773. }
  774. pt::Statement::Assembly {
  775. loc,
  776. dialect,
  777. flags,
  778. block,
  779. } => {
  780. if dialect.is_some() && dialect.as_ref().unwrap().string != "evmasm" {
  781. ns.diagnostics.push(Diagnostic::error(
  782. dialect.as_ref().unwrap().loc,
  783. "only evmasm dialect is supported".to_string(),
  784. ));
  785. return Err(());
  786. }
  787. if let Some(flags) = flags {
  788. for flag in flags {
  789. ns.diagnostics.push(Diagnostic::error(
  790. flag.loc,
  791. format!("flag '{}' not supported", flag.string),
  792. ));
  793. }
  794. }
  795. let resolved_asm =
  796. resolve_inline_assembly(loc, &block.statements, context, symtable, ns);
  797. res.push(Statement::Assembly(resolved_asm.0, resolved_asm.1));
  798. Ok(resolved_asm.1)
  799. }
  800. pt::Statement::Revert(loc, path, args) => {
  801. if let Ok(stmt) = revert_pos_arg(loc, path, args, context, symtable, diagnostics, ns) {
  802. res.push(stmt);
  803. }
  804. Ok(false)
  805. }
  806. pt::Statement::RevertNamedArgs(loc, path, args) => {
  807. if let Ok(stmt) = revert_named_arg(loc, path, args, context, symtable, diagnostics, ns)
  808. {
  809. res.push(stmt);
  810. }
  811. Ok(false)
  812. }
  813. pt::Statement::Error(_) => unimplemented!(),
  814. }
  815. }
  816. /// Resolve a revert statement with position arguments, and optional error, e.g.
  817. /// ```ignore
  818. /// revert();
  819. /// revert("the reason why");
  820. /// revert NotEnoughBalance(address);
  821. /// ```
  822. fn revert_pos_arg(
  823. loc: &pt::Loc,
  824. path: &Option<pt::IdentifierPath>,
  825. args: &[pt::Expression],
  826. context: &ExprContext,
  827. symtable: &mut Symtable,
  828. diagnostics: &mut Diagnostics,
  829. ns: &mut Namespace,
  830. ) -> Result<Statement, ()> {
  831. if let Some(path) = path {
  832. let error_no = ns.resolve_error(context.file_no, context.contract_no, path, diagnostics)?;
  833. let mut arguments = Vec::new();
  834. for (pos, arg) in args.iter().enumerate() {
  835. let error = &ns.errors[error_no];
  836. let ty = if let Some(field) = error.fields.get(pos) {
  837. field.ty.clone()
  838. } else {
  839. let _ = expression(arg, context, ns, symtable, diagnostics, ResolveTo::Unknown);
  840. continue;
  841. };
  842. let arg = match expression(
  843. arg,
  844. context,
  845. ns,
  846. symtable,
  847. diagnostics,
  848. ResolveTo::Type(&ty),
  849. ) {
  850. Ok(e) => e,
  851. Err(()) => {
  852. continue;
  853. }
  854. };
  855. match arg.cast(&arg.loc(), &ty, true, ns, diagnostics) {
  856. Ok(expr) => {
  857. arguments.push(expr);
  858. }
  859. Err(()) => {
  860. continue;
  861. }
  862. }
  863. }
  864. let error = &ns.errors[error_no];
  865. if args.len() != error.fields.len() {
  866. ns.diagnostics.push(Diagnostic::error_with_note(
  867. path.loc,
  868. format!(
  869. "error '{}' has {} fields, {} provided",
  870. error.name,
  871. error.fields.len(),
  872. args.len()
  873. ),
  874. error.loc,
  875. format!("definition of '{}'", error.name),
  876. ));
  877. }
  878. if ns.target != Target::EVM {
  879. ns.diagnostics.push(Diagnostic::error(
  880. *loc,
  881. format!("revert with custom errors not supported on {}", ns.target),
  882. ));
  883. }
  884. ns.errors[error_no].used = true;
  885. Ok(Statement::Revert {
  886. loc: *loc,
  887. error_no: Some(error_no),
  888. args: arguments,
  889. })
  890. } else {
  891. let mut arguments = Vec::new();
  892. match args.len() {
  893. 0 => (),
  894. 1 => {
  895. if let Ok(arg) = expression(
  896. &args[0],
  897. context,
  898. ns,
  899. symtable,
  900. diagnostics,
  901. ResolveTo::Type(&Type::String),
  902. ) {
  903. if let Ok(expr) = arg.cast(&arg.loc(), &Type::String, true, ns, diagnostics) {
  904. arguments.push(expr);
  905. }
  906. }
  907. }
  908. count => {
  909. let loc = pt::Loc::File(loc.file_no(), loc.start(), loc.start() + 6);
  910. ns.diagnostics.push(Diagnostic::error(
  911. loc,
  912. format!(
  913. "revert takes either no argument or a single reason string argument, {} provided",
  914. count
  915. ),
  916. ));
  917. for arg in args {
  918. let _ = expression(arg, context, ns, symtable, diagnostics, ResolveTo::Unknown);
  919. }
  920. }
  921. }
  922. Ok(Statement::Revert {
  923. loc: *loc,
  924. error_no: None,
  925. args: arguments,
  926. })
  927. }
  928. }
  929. /// Resolve a revert statement with named arguments, and optional error, e.g.
  930. /// ```ignore
  931. /// revert({foo: 1}); // not allowed
  932. /// revert({reason:"the reason why"}); // not allowed
  933. /// revert NotEnoughBalance({user: address});
  934. /// ```
  935. fn revert_named_arg(
  936. loc: &pt::Loc,
  937. path: &Option<pt::IdentifierPath>,
  938. args: &[pt::NamedArgument],
  939. context: &ExprContext,
  940. symtable: &mut Symtable,
  941. diagnostics: &mut Diagnostics,
  942. ns: &mut Namespace,
  943. ) -> Result<Statement, ()> {
  944. if let Some(path) = path {
  945. let error_no = ns.resolve_error(context.file_no, context.contract_no, path, diagnostics)?;
  946. let error = &ns.errors[error_no];
  947. let unnamed_fields = error
  948. .fields
  949. .iter()
  950. .filter(|param| param.id.is_none())
  951. .count();
  952. if unnamed_fields > 0 {
  953. ns.diagnostics.push(Diagnostic::error_with_note(
  954. path.loc,
  955. format!(
  956. "error '{}' has {} unnamed fields",
  957. error.name, unnamed_fields
  958. ),
  959. error.loc,
  960. format!("definition of '{}'", error.name),
  961. ));
  962. }
  963. let fields: HashMap<String, (usize, Type)> = error
  964. .fields
  965. .iter()
  966. .enumerate()
  967. .filter_map(|(i, p)| {
  968. p.id.as_ref()
  969. .map(|id| (id.name.to_owned(), (i, p.ty.clone())))
  970. })
  971. .collect();
  972. let mut arguments = HashMap::new();
  973. for arg in args {
  974. let error = &ns.errors[error_no];
  975. let name = arg.name.name.as_str();
  976. if let Some((pos, ty)) = fields.get(name) {
  977. if arguments.contains_key(pos) {
  978. diagnostics.push(Diagnostic::error(
  979. arg.name.loc,
  980. format!("duplicate argument with name '{}'", arg.name.name),
  981. ));
  982. let _ = expression(
  983. &arg.expr,
  984. context,
  985. ns,
  986. symtable,
  987. diagnostics,
  988. ResolveTo::Unknown,
  989. );
  990. continue;
  991. }
  992. let arg = match expression(
  993. &arg.expr,
  994. context,
  995. ns,
  996. symtable,
  997. diagnostics,
  998. ResolveTo::Type(ty),
  999. ) {
  1000. Ok(e) => e,
  1001. Err(()) => {
  1002. continue;
  1003. }
  1004. };
  1005. match arg.cast(&arg.loc(), ty, true, ns, diagnostics) {
  1006. Ok(expr) => {
  1007. arguments.insert(*pos, expr);
  1008. }
  1009. Err(()) => {
  1010. continue;
  1011. }
  1012. }
  1013. } else {
  1014. ns.diagnostics.push(Diagnostic::error_with_note(
  1015. arg.name.loc,
  1016. format!("error '{}' has no field called '{}'", error.name, name),
  1017. error.loc,
  1018. format!("definition of '{}'", error.name),
  1019. ));
  1020. let _ = expression(
  1021. &arg.expr,
  1022. context,
  1023. ns,
  1024. symtable,
  1025. diagnostics,
  1026. ResolveTo::Unknown,
  1027. );
  1028. }
  1029. }
  1030. if ns.target != Target::EVM {
  1031. ns.diagnostics.push(Diagnostic::error(
  1032. *loc,
  1033. format!("revert with custom errors not supported on {}", ns.target),
  1034. ));
  1035. }
  1036. let mut args = Vec::new();
  1037. let error = &ns.errors[error_no];
  1038. for pos in 0..error.fields.len() {
  1039. if let Some(arg) = arguments.remove(&pos) {
  1040. args.push(arg);
  1041. } else if let Some(id) = &error.fields[pos].id {
  1042. ns.diagnostics.push(Diagnostic::error_with_note(
  1043. path.loc,
  1044. format!("missing field '{}'", id.name),
  1045. error.loc,
  1046. format!("definition of '{}'", error.name),
  1047. ));
  1048. }
  1049. }
  1050. ns.errors[error_no].used = true;
  1051. Ok(Statement::Revert {
  1052. loc: *loc,
  1053. error_no: Some(error_no),
  1054. args,
  1055. })
  1056. } else {
  1057. ns.diagnostics.push(Diagnostic::error(
  1058. *loc,
  1059. "revert with named arguments requires error type".to_string(),
  1060. ));
  1061. Err(())
  1062. }
  1063. }
  1064. /// Resolve emit event
  1065. fn emit_event(
  1066. loc: &pt::Loc,
  1067. ty: &pt::Expression,
  1068. context: &ExprContext,
  1069. symtable: &mut Symtable,
  1070. ns: &mut Namespace,
  1071. diagnostics: &mut Diagnostics,
  1072. ) -> Result<Statement, ()> {
  1073. let function_no = context.function_no.unwrap();
  1074. let to_stmt =
  1075. |ns: &mut Namespace, event_no: usize, event_loc: pt::Loc, cast_args: Vec<Expression>| {
  1076. if !ns.functions[function_no].emits_events.contains(&event_no) {
  1077. ns.functions[function_no].emits_events.push(event_no);
  1078. }
  1079. Statement::Emit {
  1080. loc: *loc,
  1081. event_no,
  1082. event_loc,
  1083. args: cast_args,
  1084. }
  1085. };
  1086. match ty {
  1087. pt::Expression::FunctionCall(_, ty, args) => {
  1088. let event_loc = ty.loc();
  1089. let mut errors = Diagnostics::default();
  1090. let event_nos =
  1091. match ns.resolve_event(context.file_no, context.contract_no, ty, diagnostics) {
  1092. Ok(nos) => nos,
  1093. Err(_) => {
  1094. for arg in args {
  1095. if let Ok(exp) = expression(
  1096. arg,
  1097. context,
  1098. ns,
  1099. symtable,
  1100. diagnostics,
  1101. ResolveTo::Unknown,
  1102. ) {
  1103. used_variable(ns, &exp, symtable);
  1104. };
  1105. }
  1106. return Err(());
  1107. }
  1108. };
  1109. for event_no in &event_nos {
  1110. let event = &mut ns.events[*event_no];
  1111. event.used = true;
  1112. let mut matches = true;
  1113. if args.len() != event.fields.len() {
  1114. errors.push(Diagnostic::cast_error(
  1115. *loc,
  1116. format!(
  1117. "event type '{}' has {} fields, {} provided",
  1118. event.name,
  1119. event.fields.len(),
  1120. args.len()
  1121. ),
  1122. ));
  1123. matches = false;
  1124. }
  1125. let mut cast_args = Vec::new();
  1126. // check if arguments can be implicitly casted
  1127. for (i, arg) in args.iter().enumerate() {
  1128. let ty = ns.events[*event_no]
  1129. .fields
  1130. .get(i)
  1131. .map(|field| field.ty.clone());
  1132. let resolve_to = ty
  1133. .as_ref()
  1134. .map(ResolveTo::Type)
  1135. .unwrap_or(ResolveTo::Unknown);
  1136. let arg = match expression(arg, context, ns, symtable, &mut errors, resolve_to)
  1137. {
  1138. Ok(e) => e,
  1139. Err(()) => {
  1140. matches = false;
  1141. break;
  1142. }
  1143. };
  1144. used_variable(ns, &arg, symtable);
  1145. if let Some(ty) = &ty {
  1146. match arg.cast(&arg.loc(), ty, true, ns, &mut errors) {
  1147. Ok(expr) => cast_args.push(expr),
  1148. Err(_) => {
  1149. matches = false;
  1150. }
  1151. }
  1152. }
  1153. }
  1154. if matches {
  1155. return Ok(to_stmt(ns, *event_no, event_loc, cast_args));
  1156. } else if event_nos.len() > 1 && diagnostics.extend_non_casting(&errors) {
  1157. return Err(());
  1158. }
  1159. }
  1160. if event_nos.len() == 1 {
  1161. diagnostics.extend(errors);
  1162. } else {
  1163. diagnostics.push(Diagnostic::error(
  1164. *loc,
  1165. "cannot find event which matches signature".to_string(),
  1166. ));
  1167. }
  1168. }
  1169. pt::Expression::NamedFunctionCall(_, ty, args) => {
  1170. let event_loc = ty.loc();
  1171. let mut temp_diagnostics = Diagnostics::default();
  1172. let mut arguments = HashMap::new();
  1173. for arg in args {
  1174. if arguments.contains_key(arg.name.name.as_str()) {
  1175. diagnostics.push(Diagnostic::error(
  1176. arg.name.loc,
  1177. format!("duplicate argument with name '{}'", arg.name.name),
  1178. ));
  1179. let _ = expression(
  1180. &arg.expr,
  1181. context,
  1182. ns,
  1183. symtable,
  1184. diagnostics,
  1185. ResolveTo::Unknown,
  1186. );
  1187. continue;
  1188. }
  1189. arguments.insert(arg.name.name.as_str(), &arg.expr);
  1190. }
  1191. let event_nos = match ns.resolve_event(
  1192. context.file_no,
  1193. context.contract_no,
  1194. ty,
  1195. &mut temp_diagnostics,
  1196. ) {
  1197. Ok(nos) => nos,
  1198. Err(_) => {
  1199. // check arguments for errors
  1200. for (_, arg) in arguments {
  1201. let _ =
  1202. expression(arg, context, ns, symtable, diagnostics, ResolveTo::Unknown);
  1203. }
  1204. return Err(());
  1205. }
  1206. };
  1207. for event_no in &event_nos {
  1208. let event = &mut ns.events[*event_no];
  1209. event.used = true;
  1210. let params_len = event.fields.len();
  1211. let mut matches = true;
  1212. let unnamed_fields = event.fields.iter().filter(|p| p.id.is_none()).count();
  1213. if unnamed_fields > 0 {
  1214. temp_diagnostics.push(Diagnostic::cast_error_with_note(
  1215. *loc,
  1216. format!(
  1217. "event cannot be emmited with named fields as {unnamed_fields} of its fields do not have names"
  1218. ),
  1219. event.loc,
  1220. format!("definition of {}", event.name),
  1221. ));
  1222. matches = false;
  1223. } else if params_len != arguments.len() {
  1224. temp_diagnostics.push(Diagnostic::error(
  1225. *loc,
  1226. format!(
  1227. "event expects {} arguments, {} provided",
  1228. params_len,
  1229. arguments.len()
  1230. ),
  1231. ));
  1232. matches = false;
  1233. }
  1234. let mut cast_args = Vec::new();
  1235. // check if arguments can be implicitly casted
  1236. for i in 0..params_len {
  1237. let param = ns.events[*event_no].fields[i].clone();
  1238. if param.id.is_none() {
  1239. continue;
  1240. }
  1241. let arg = match arguments.get(param.name_as_str()) {
  1242. Some(a) => a,
  1243. None => {
  1244. matches = false;
  1245. temp_diagnostics.push(Diagnostic::cast_error(
  1246. *loc,
  1247. format!(
  1248. "missing argument '{}' to event '{}'",
  1249. param.name_as_str(),
  1250. ns.events[*event_no].name,
  1251. ),
  1252. ));
  1253. continue;
  1254. }
  1255. };
  1256. let arg = match expression(
  1257. arg,
  1258. context,
  1259. ns,
  1260. symtable,
  1261. &mut temp_diagnostics,
  1262. ResolveTo::Type(&param.ty),
  1263. ) {
  1264. Ok(e) => e,
  1265. Err(()) => {
  1266. matches = false;
  1267. continue;
  1268. }
  1269. };
  1270. used_variable(ns, &arg, symtable);
  1271. match arg.cast(&arg.loc(), &param.ty, true, ns, &mut temp_diagnostics) {
  1272. Ok(expr) => cast_args.push(expr),
  1273. Err(_) => {
  1274. matches = false;
  1275. }
  1276. }
  1277. }
  1278. if matches {
  1279. return Ok(to_stmt(ns, *event_no, event_loc, cast_args));
  1280. } else if event_nos.len() > 1 && diagnostics.extend_non_casting(&temp_diagnostics) {
  1281. return Err(());
  1282. }
  1283. }
  1284. if event_nos.len() == 1 {
  1285. diagnostics.extend(temp_diagnostics);
  1286. } else {
  1287. diagnostics.push(Diagnostic::error(
  1288. *loc,
  1289. "cannot find event which matches signature".to_string(),
  1290. ));
  1291. }
  1292. }
  1293. pt::Expression::FunctionCallBlock(_, ty, block) => {
  1294. let _ = ns.resolve_event(context.file_no, context.contract_no, ty, diagnostics);
  1295. diagnostics.push(Diagnostic::error(
  1296. block.loc(),
  1297. "expected event arguments, found code block".to_string(),
  1298. ));
  1299. }
  1300. _ => unreachable!(),
  1301. }
  1302. Err(())
  1303. }
  1304. /// Resolve destructuring assignment
  1305. fn destructure(
  1306. loc: &pt::Loc,
  1307. vars: &[(pt::Loc, Option<pt::Parameter>)],
  1308. expr: &pt::Expression,
  1309. context: &ExprContext,
  1310. symtable: &mut Symtable,
  1311. ns: &mut Namespace,
  1312. diagnostics: &mut Diagnostics,
  1313. ) -> Result<Statement, ()> {
  1314. // first resolve the fields so we know the types
  1315. let mut fields = Vec::new();
  1316. let mut left_tys = Vec::new();
  1317. let mut lcontext = context.clone();
  1318. lcontext.lvalue = true;
  1319. for (_, param) in vars {
  1320. match param {
  1321. None => {
  1322. left_tys.push(None);
  1323. fields.push(DestructureField::None);
  1324. }
  1325. Some(pt::Parameter {
  1326. loc,
  1327. ty,
  1328. storage,
  1329. name: None,
  1330. annotation,
  1331. }) => {
  1332. // The grammar does not allow annotation in destructures, so this assertion shall
  1333. // always be true.
  1334. assert!(annotation.is_none());
  1335. if let Some(storage) = storage {
  1336. diagnostics.push(Diagnostic::error(
  1337. storage.loc(),
  1338. format!("storage modifier '{storage}' not permitted on assignment"),
  1339. ));
  1340. return Err(());
  1341. }
  1342. // ty will just be a normal expression, not a type
  1343. let e = expression(ty, &lcontext, ns, symtable, diagnostics, ResolveTo::Unknown)?;
  1344. match &e {
  1345. Expression::ConstantVariable {
  1346. contract_no: Some(contract_no),
  1347. var_no,
  1348. ..
  1349. } => {
  1350. diagnostics.push(Diagnostic::error(
  1351. *loc,
  1352. format!(
  1353. "cannot assign to constant '{}'",
  1354. ns.contracts[*contract_no].variables[*var_no].name
  1355. ),
  1356. ));
  1357. return Err(());
  1358. }
  1359. Expression::ConstantVariable {
  1360. contract_no: None,
  1361. var_no,
  1362. ..
  1363. } => {
  1364. diagnostics.push(Diagnostic::error(
  1365. *loc,
  1366. format!("cannot assign to constant '{}'", ns.constants[*var_no].name),
  1367. ));
  1368. return Err(());
  1369. }
  1370. Expression::StorageVariable {
  1371. contract_no,
  1372. var_no,
  1373. ..
  1374. } => {
  1375. let store_var = &ns.contracts[*contract_no].variables[*var_no];
  1376. if store_var.immutable
  1377. && !ns.functions[context.function_no.unwrap()].is_constructor()
  1378. {
  1379. diagnostics.push(Diagnostic::error(
  1380. *loc,
  1381. format!(
  1382. "cannot assign to immutable '{}' outside of constructor",
  1383. store_var.name
  1384. ),
  1385. ));
  1386. return Err(());
  1387. }
  1388. }
  1389. Expression::Variable { .. } => (),
  1390. _ => match e.ty() {
  1391. Type::Ref(_) | Type::StorageRef(false, _) => (),
  1392. _ => {
  1393. diagnostics.push(Diagnostic::error(
  1394. *loc,
  1395. "expression is not assignable".to_string(),
  1396. ));
  1397. return Err(());
  1398. }
  1399. },
  1400. }
  1401. assigned_variable(ns, &e, symtable);
  1402. left_tys.push(Some(e.ty()));
  1403. fields.push(DestructureField::Expression(e));
  1404. }
  1405. Some(pt::Parameter {
  1406. loc,
  1407. ty,
  1408. storage,
  1409. name: Some(name),
  1410. annotation,
  1411. }) => {
  1412. // The grammar does not allow annotation in destructures, so this assertion shall
  1413. // always be true.
  1414. assert!(annotation.is_none());
  1415. let (ty, ty_loc) = resolve_var_decl_ty(ty, storage, context, ns, diagnostics)?;
  1416. if let Some(pos) = symtable.add(
  1417. name,
  1418. ty.clone(),
  1419. ns,
  1420. VariableInitializer::Solidity(None),
  1421. VariableUsage::DestructureVariable,
  1422. storage.clone(),
  1423. ) {
  1424. ns.check_shadowing(context.file_no, context.contract_no, name);
  1425. left_tys.push(Some(ty.clone()));
  1426. fields.push(DestructureField::VariableDecl(
  1427. pos,
  1428. Parameter {
  1429. loc: *loc,
  1430. id: Some(name.clone()),
  1431. ty,
  1432. ty_loc: Some(ty_loc),
  1433. indexed: false,
  1434. readonly: false,
  1435. infinite_size: false,
  1436. recursive: false,
  1437. annotation: None,
  1438. },
  1439. ));
  1440. }
  1441. }
  1442. }
  1443. }
  1444. let expr = destructure_values(
  1445. loc,
  1446. expr,
  1447. &left_tys,
  1448. &fields,
  1449. context,
  1450. symtable,
  1451. ns,
  1452. diagnostics,
  1453. )?;
  1454. Ok(Statement::Destructure(*loc, fields, expr))
  1455. }
  1456. fn destructure_values(
  1457. loc: &pt::Loc,
  1458. expr: &pt::Expression,
  1459. left_tys: &[Option<Type>],
  1460. fields: &[DestructureField],
  1461. context: &ExprContext,
  1462. symtable: &mut Symtable,
  1463. ns: &mut Namespace,
  1464. diagnostics: &mut Diagnostics,
  1465. ) -> Result<Expression, ()> {
  1466. let expr = match expr.remove_parenthesis() {
  1467. pt::Expression::FunctionCall(loc, ty, args) => {
  1468. let res = function_call_expr(
  1469. loc,
  1470. ty,
  1471. args,
  1472. context,
  1473. ns,
  1474. symtable,
  1475. diagnostics,
  1476. ResolveTo::Unknown,
  1477. )?;
  1478. check_function_call(ns, &res, symtable);
  1479. res
  1480. }
  1481. pt::Expression::NamedFunctionCall(loc, ty, args) => {
  1482. let res = named_function_call_expr(
  1483. loc,
  1484. ty,
  1485. args,
  1486. context,
  1487. ns,
  1488. symtable,
  1489. diagnostics,
  1490. ResolveTo::Unknown,
  1491. )?;
  1492. check_function_call(ns, &res, symtable);
  1493. res
  1494. }
  1495. pt::Expression::ConditionalOperator(loc, cond, left, right) => {
  1496. let cond = expression(
  1497. cond,
  1498. context,
  1499. ns,
  1500. symtable,
  1501. diagnostics,
  1502. ResolveTo::Type(&Type::Bool),
  1503. )?;
  1504. used_variable(ns, &cond, symtable);
  1505. let left = destructure_values(
  1506. &left.loc(),
  1507. left,
  1508. left_tys,
  1509. fields,
  1510. context,
  1511. symtable,
  1512. ns,
  1513. diagnostics,
  1514. )?;
  1515. used_variable(ns, &left, symtable);
  1516. let right = destructure_values(
  1517. &right.loc(),
  1518. right,
  1519. left_tys,
  1520. fields,
  1521. context,
  1522. symtable,
  1523. ns,
  1524. diagnostics,
  1525. )?;
  1526. used_variable(ns, &right, symtable);
  1527. return Ok(Expression::ConditionalOperator {
  1528. loc: *loc,
  1529. ty: Type::Unreachable,
  1530. cond: Box::new(cond),
  1531. true_option: Box::new(left),
  1532. false_option: Box::new(right),
  1533. });
  1534. }
  1535. _ => {
  1536. let mut list = Vec::new();
  1537. let exprs = parameter_list_to_expr_list(expr, diagnostics)?;
  1538. if exprs.len() != left_tys.len() {
  1539. diagnostics.push(Diagnostic::error(
  1540. *loc,
  1541. format!(
  1542. "destructuring assignment has {} elements on the left and {} on the right",
  1543. left_tys.len(),
  1544. exprs.len(),
  1545. ),
  1546. ));
  1547. return Err(());
  1548. }
  1549. for (i, e) in exprs.iter().enumerate() {
  1550. let e = expression(
  1551. e,
  1552. context,
  1553. ns,
  1554. symtable,
  1555. diagnostics,
  1556. if let Some(ty) = left_tys[i].as_ref() {
  1557. ResolveTo::Type(ty)
  1558. } else {
  1559. ResolveTo::Unknown
  1560. },
  1561. )?;
  1562. match e.ty() {
  1563. Type::Void | Type::Unreachable => {
  1564. diagnostics.push(Diagnostic::error(
  1565. e.loc(),
  1566. "function does not return a value".to_string(),
  1567. ));
  1568. return Err(());
  1569. }
  1570. _ => {
  1571. used_variable(ns, &e, symtable);
  1572. }
  1573. }
  1574. list.push(e);
  1575. }
  1576. Expression::List { loc: *loc, list }
  1577. }
  1578. };
  1579. let mut right_tys = expr.tys();
  1580. // Return type void or unreachable are synthetic
  1581. if right_tys.len() == 1 && (right_tys[0] == Type::Unreachable || right_tys[0] == Type::Void) {
  1582. right_tys.truncate(0);
  1583. }
  1584. if left_tys.len() != right_tys.len() {
  1585. diagnostics.push(Diagnostic::error(
  1586. *loc,
  1587. format!(
  1588. "destructuring assignment has {} elements on the left and {} on the right",
  1589. left_tys.len(),
  1590. right_tys.len()
  1591. ),
  1592. ));
  1593. return Err(());
  1594. }
  1595. // Check that the values can be cast
  1596. for (i, field) in fields.iter().enumerate() {
  1597. if let Some(left_ty) = &left_tys[i] {
  1598. let loc = field.loc_opt().unwrap();
  1599. let _ = Expression::Variable {
  1600. loc,
  1601. ty: right_tys[i].clone(),
  1602. var_no: i,
  1603. }
  1604. .cast(&loc, left_ty.deref_any(), true, ns, diagnostics)?;
  1605. }
  1606. }
  1607. Ok(expr)
  1608. }
  1609. /// Resolve the type of a variable declaration
  1610. fn resolve_var_decl_ty(
  1611. ty: &pt::Expression,
  1612. storage: &Option<pt::StorageLocation>,
  1613. context: &ExprContext,
  1614. ns: &mut Namespace,
  1615. diagnostics: &mut Diagnostics,
  1616. ) -> Result<(Type, pt::Loc), ()> {
  1617. let mut loc_ty = ty.loc();
  1618. let mut var_ty =
  1619. ns.resolve_type(context.file_no, context.contract_no, false, ty, diagnostics)?;
  1620. if let Some(storage) = storage {
  1621. if !var_ty.can_have_data_location() {
  1622. diagnostics.push(Diagnostic::error(
  1623. storage.loc(),
  1624. format!("data location '{storage}' only allowed for array, struct or mapping type"),
  1625. ));
  1626. return Err(());
  1627. }
  1628. if let pt::StorageLocation::Storage(loc) = storage {
  1629. loc_ty.use_end_from(loc);
  1630. var_ty = Type::StorageRef(false, Box::new(var_ty));
  1631. }
  1632. // Note we are completely ignoring memory or calldata data locations. Everything
  1633. // will be stored in memory.
  1634. }
  1635. if var_ty.contains_mapping(ns) && !var_ty.is_contract_storage() {
  1636. diagnostics.push(Diagnostic::error(
  1637. ty.loc(),
  1638. "mapping only allowed in storage".to_string(),
  1639. ));
  1640. return Err(());
  1641. }
  1642. if !var_ty.is_contract_storage() && !var_ty.fits_in_memory(ns) {
  1643. diagnostics.push(Diagnostic::error(
  1644. ty.loc(),
  1645. "type is too large to fit into memory".to_string(),
  1646. ));
  1647. return Err(());
  1648. }
  1649. Ok((var_ty, loc_ty))
  1650. }
  1651. /// Resolve return statement
  1652. fn return_with_values(
  1653. returns: &pt::Expression,
  1654. loc: &pt::Loc,
  1655. context: &ExprContext,
  1656. symtable: &mut Symtable,
  1657. ns: &mut Namespace,
  1658. diagnostics: &mut Diagnostics,
  1659. ) -> Result<Expression, ()> {
  1660. let function_no = context.function_no.unwrap();
  1661. let no_returns = ns.functions[function_no].returns.len();
  1662. let expr_returns = match returns.remove_parenthesis() {
  1663. pt::Expression::FunctionCall(loc, ty, args) => {
  1664. let expr = call_expr(
  1665. loc,
  1666. ty,
  1667. args,
  1668. true,
  1669. context,
  1670. ns,
  1671. symtable,
  1672. diagnostics,
  1673. ResolveTo::Unknown,
  1674. )?;
  1675. used_variable(ns, &expr, symtable);
  1676. expr
  1677. }
  1678. pt::Expression::NamedFunctionCall(loc, ty, args) => {
  1679. let expr = named_call_expr(
  1680. loc,
  1681. ty,
  1682. args,
  1683. true,
  1684. context,
  1685. ns,
  1686. symtable,
  1687. diagnostics,
  1688. ResolveTo::Unknown,
  1689. )?;
  1690. used_variable(ns, &expr, symtable);
  1691. expr
  1692. }
  1693. pt::Expression::ConditionalOperator(loc, cond, left, right) => {
  1694. let cond = expression(
  1695. cond,
  1696. context,
  1697. ns,
  1698. symtable,
  1699. diagnostics,
  1700. ResolveTo::Type(&Type::Bool),
  1701. )?;
  1702. used_variable(ns, &cond, symtable);
  1703. let left = return_with_values(left, &left.loc(), context, symtable, ns, diagnostics)?;
  1704. used_variable(ns, &left, symtable);
  1705. let right =
  1706. return_with_values(right, &right.loc(), context, symtable, ns, diagnostics)?;
  1707. used_variable(ns, &right, symtable);
  1708. return Ok(Expression::ConditionalOperator {
  1709. loc: *loc,
  1710. ty: Type::Unreachable,
  1711. cond: Box::new(cond),
  1712. true_option: Box::new(left),
  1713. false_option: Box::new(right),
  1714. });
  1715. }
  1716. _ => {
  1717. let returns = parameter_list_to_expr_list(returns, diagnostics)?;
  1718. if no_returns > 0 && returns.is_empty() {
  1719. diagnostics.push(Diagnostic::error(
  1720. *loc,
  1721. format!("missing return value, {no_returns} return values expected"),
  1722. ));
  1723. return Err(());
  1724. }
  1725. if no_returns == 0 && !returns.is_empty() {
  1726. diagnostics.push(Diagnostic::error(
  1727. *loc,
  1728. "function has no return values".to_string(),
  1729. ));
  1730. return Err(());
  1731. }
  1732. if no_returns != returns.len() {
  1733. diagnostics.push(Diagnostic::error(
  1734. *loc,
  1735. format!(
  1736. "incorrect number of return values, expected {} but got {}",
  1737. no_returns,
  1738. returns.len(),
  1739. ),
  1740. ));
  1741. return Err(());
  1742. }
  1743. let mut exprs = Vec::new();
  1744. let return_tys = ns.functions[function_no]
  1745. .returns
  1746. .iter()
  1747. .map(|r| r.ty.clone())
  1748. .collect::<Vec<_>>();
  1749. for (expr_return, return_ty) in returns.iter().zip(return_tys) {
  1750. let expr = expression(
  1751. expr_return,
  1752. context,
  1753. ns,
  1754. symtable,
  1755. diagnostics,
  1756. ResolveTo::Type(&return_ty),
  1757. )?;
  1758. let expr = expr.cast(loc, &return_ty, true, ns, diagnostics)?;
  1759. used_variable(ns, &expr, symtable);
  1760. exprs.push(expr);
  1761. }
  1762. return Ok(if exprs.len() == 1 {
  1763. exprs[0].clone()
  1764. } else {
  1765. Expression::List {
  1766. loc: *loc,
  1767. list: exprs,
  1768. }
  1769. });
  1770. }
  1771. };
  1772. let mut expr_return_tys = expr_returns.tys();
  1773. // Return type void or unreachable are synthetic
  1774. if expr_return_tys.len() == 1
  1775. && (expr_return_tys[0] == Type::Unreachable || expr_return_tys[0] == Type::Void)
  1776. {
  1777. expr_return_tys.truncate(0);
  1778. }
  1779. if no_returns > 0 && expr_return_tys.is_empty() {
  1780. diagnostics.push(Diagnostic::error(
  1781. *loc,
  1782. format!("missing return value, {no_returns} return values expected"),
  1783. ));
  1784. return Err(());
  1785. }
  1786. if no_returns == 0 && !expr_return_tys.is_empty() {
  1787. diagnostics.push(Diagnostic::error(
  1788. *loc,
  1789. "function has no return values".to_string(),
  1790. ));
  1791. return Err(());
  1792. }
  1793. if no_returns != expr_return_tys.len() {
  1794. diagnostics.push(Diagnostic::error(
  1795. *loc,
  1796. format!(
  1797. "incorrect number of return values, expected {} but got {}",
  1798. no_returns,
  1799. expr_return_tys.len(),
  1800. ),
  1801. ));
  1802. return Err(());
  1803. }
  1804. let func_returns_tys = ns.functions[function_no]
  1805. .returns
  1806. .iter()
  1807. .map(|r| r.ty.clone())
  1808. .collect::<Vec<_>>();
  1809. // Check that the values can be cast
  1810. let _ = expr_return_tys
  1811. .into_iter()
  1812. .zip(func_returns_tys)
  1813. .enumerate()
  1814. .map(|(i, (expr_return_ty, func_return_ty))| {
  1815. Expression::Variable {
  1816. loc: expr_returns.loc(),
  1817. ty: expr_return_ty,
  1818. var_no: i,
  1819. }
  1820. .cast(&expr_returns.loc(), &func_return_ty, true, ns, diagnostics)
  1821. })
  1822. .collect::<Result<Vec<_>, _>>()?;
  1823. Ok(expr_returns)
  1824. }
  1825. /// The parser generates parameter lists for lists. Sometimes this needs to be a
  1826. /// simple expression list.
  1827. pub fn parameter_list_to_expr_list<'a>(
  1828. e: &'a pt::Expression,
  1829. diagnostics: &mut Diagnostics,
  1830. ) -> Result<Vec<&'a pt::Expression>, ()> {
  1831. match e {
  1832. pt::Expression::List(_, v) => {
  1833. let mut list = Vec::new();
  1834. let mut broken = false;
  1835. for e in v {
  1836. match &e.1 {
  1837. None => {
  1838. diagnostics.push(Diagnostic::error(e.0, "stray comma".to_string()));
  1839. broken = true;
  1840. }
  1841. Some(pt::Parameter {
  1842. name: Some(name),
  1843. annotation,
  1844. ..
  1845. }) => {
  1846. // The grammar does not allow an annotation inside a list
  1847. assert!(annotation.is_none());
  1848. diagnostics.push(Diagnostic::error(
  1849. name.loc,
  1850. "single value expected".to_string(),
  1851. ));
  1852. broken = true;
  1853. }
  1854. Some(pt::Parameter {
  1855. storage: Some(storage),
  1856. annotation,
  1857. ..
  1858. }) => {
  1859. // The grammar does not allow an annotation inside a list
  1860. assert!(annotation.is_none());
  1861. diagnostics.push(Diagnostic::error(
  1862. storage.loc(),
  1863. "storage specified not permitted here".to_string(),
  1864. ));
  1865. broken = true;
  1866. }
  1867. Some(pt::Parameter { annotation, ty, .. }) => {
  1868. // The grammar does not allow an annotation inside a list
  1869. assert!(annotation.is_none());
  1870. list.push(ty);
  1871. }
  1872. }
  1873. }
  1874. if !broken {
  1875. Ok(list)
  1876. } else {
  1877. Err(())
  1878. }
  1879. }
  1880. pt::Expression::Parenthesis(_, e) => Ok(vec![e]),
  1881. e => Ok(vec![e]),
  1882. }
  1883. }
  1884. /// Parse try catch
  1885. #[allow(clippy::type_complexity)]
  1886. fn try_catch(
  1887. loc: &pt::Loc,
  1888. expr: &pt::Expression,
  1889. returns_and_ok: &Option<(Vec<(pt::Loc, Option<pt::Parameter>)>, Box<pt::Statement>)>,
  1890. clause_stmts: &[pt::CatchClause],
  1891. context: &ExprContext,
  1892. symtable: &mut Symtable,
  1893. loops: &mut LoopScopes,
  1894. ns: &mut Namespace,
  1895. diagnostics: &mut Diagnostics,
  1896. ) -> Result<(Statement, bool), ()> {
  1897. if ns.target == Target::Solana {
  1898. diagnostics.push(Diagnostic::error(
  1899. *loc,
  1900. "The try-catch statement is not supported on Solana. Please, go to \
  1901. https://solang.readthedocs.io/en/latest/language/statements.html#try-catch-statement \
  1902. for more information"
  1903. .to_string(),
  1904. ));
  1905. return Err(());
  1906. }
  1907. let mut expr = expr.remove_parenthesis();
  1908. let mut ok = None;
  1909. while let pt::Expression::FunctionCallBlock(_, e, block) = expr {
  1910. if ok.is_some() {
  1911. diagnostics.push(Diagnostic::error(
  1912. block.loc(),
  1913. "unexpected code block".to_string(),
  1914. ));
  1915. return Err(());
  1916. }
  1917. ok = Some(block.as_ref());
  1918. expr = e.as_ref();
  1919. }
  1920. let fcall = match expr.remove_parenthesis() {
  1921. pt::Expression::FunctionCall(loc, ty, args) => {
  1922. let res = match ty.remove_parenthesis() {
  1923. pt::Expression::New(_, ty) => {
  1924. new(loc, ty, args, context, ns, symtable, diagnostics)?
  1925. }
  1926. pt::Expression::FunctionCallBlock(loc, expr, _)
  1927. if matches!(expr.remove_parenthesis(), pt::Expression::New(..)) =>
  1928. {
  1929. new(loc, ty, args, context, ns, symtable, diagnostics)?
  1930. }
  1931. _ => function_call_expr(
  1932. loc,
  1933. ty,
  1934. args,
  1935. context,
  1936. ns,
  1937. symtable,
  1938. diagnostics,
  1939. ResolveTo::Unknown,
  1940. )?,
  1941. };
  1942. check_function_call(ns, &res, symtable);
  1943. res
  1944. }
  1945. pt::Expression::NamedFunctionCall(loc, ty, args) => {
  1946. let res = named_function_call_expr(
  1947. loc,
  1948. ty,
  1949. args,
  1950. context,
  1951. ns,
  1952. symtable,
  1953. diagnostics,
  1954. ResolveTo::Unknown,
  1955. )?;
  1956. check_function_call(ns, &res, symtable);
  1957. res
  1958. }
  1959. pt::Expression::New(loc, call) => {
  1960. let mut call = call.remove_parenthesis();
  1961. while let pt::Expression::FunctionCallBlock(_, expr, block) = call {
  1962. if ok.is_some() {
  1963. ns.diagnostics.push(Diagnostic::error(
  1964. block.loc(),
  1965. "unexpected code block".to_string(),
  1966. ));
  1967. return Err(());
  1968. }
  1969. ok = Some(block.as_ref());
  1970. call = expr.remove_parenthesis();
  1971. }
  1972. match call {
  1973. pt::Expression::FunctionCall(_, ty, args) => {
  1974. let res = new(loc, ty, args, context, ns, symtable, diagnostics)?;
  1975. check_function_call(ns, &res, symtable);
  1976. res
  1977. }
  1978. pt::Expression::NamedFunctionCall(_, ty, args) => {
  1979. let res =
  1980. constructor_named_args(loc, ty, args, context, ns, symtable, diagnostics)?;
  1981. check_function_call(ns, &res, symtable);
  1982. res
  1983. }
  1984. _ => unreachable!(),
  1985. }
  1986. }
  1987. _ => {
  1988. diagnostics.push(Diagnostic::error(
  1989. expr.loc(),
  1990. "try only supports external calls or constructor calls".to_string(),
  1991. ));
  1992. return Err(());
  1993. }
  1994. };
  1995. let mut returns = &Vec::new();
  1996. if let Some((rets, block)) = returns_and_ok {
  1997. if ok.is_some() {
  1998. diagnostics.push(Diagnostic::error(
  1999. block.loc(),
  2000. "unexpected code block".to_string(),
  2001. ));
  2002. return Err(());
  2003. }
  2004. ok = Some(block);
  2005. returns = rets;
  2006. }
  2007. let ok = match ok {
  2008. Some(ok) => ok,
  2009. None => {
  2010. // position after the expression
  2011. let pos = expr.loc().begin_range();
  2012. diagnostics.push(Diagnostic::error(
  2013. pos,
  2014. "code block missing for no catch".to_string(),
  2015. ));
  2016. return Err(());
  2017. }
  2018. };
  2019. symtable.new_scope();
  2020. let mut args = match &fcall {
  2021. Expression::ExternalFunctionCall {
  2022. returns: func_returns,
  2023. ..
  2024. } => {
  2025. let mut func_returns = func_returns.clone();
  2026. if func_returns == vec![Type::Void] {
  2027. func_returns = vec![];
  2028. }
  2029. if !returns.is_empty() && returns.len() != func_returns.len() {
  2030. diagnostics.push(Diagnostic::error(
  2031. expr.loc(),
  2032. format!(
  2033. "try returns list has {} entries while function returns {} values",
  2034. returns.len(),
  2035. func_returns.len()
  2036. ),
  2037. ));
  2038. return Err(());
  2039. }
  2040. func_returns
  2041. }
  2042. Expression::Constructor { contract_no, .. } => match returns.len() {
  2043. 0 => Vec::new(),
  2044. 1 => vec![Type::Contract(*contract_no)],
  2045. _ => {
  2046. diagnostics.push(Diagnostic::error(
  2047. expr.loc(),
  2048. format!(
  2049. "constructor returns single contract, not {} values",
  2050. returns.len()
  2051. ),
  2052. ));
  2053. return Err(());
  2054. }
  2055. },
  2056. _ => {
  2057. diagnostics.push(Diagnostic::error(
  2058. expr.loc(),
  2059. "try only supports external calls or constructor calls".to_string(),
  2060. ));
  2061. return Err(());
  2062. }
  2063. };
  2064. symtable.new_scope();
  2065. let mut params = Vec::new();
  2066. let mut broken = false;
  2067. for param in returns {
  2068. let arg_ty = args.remove(0);
  2069. match &param.1 {
  2070. Some(pt::Parameter {
  2071. annotation: Some(annotation),
  2072. ..
  2073. }) => {
  2074. diagnostics.push(unexpected_parameter_annotation(annotation.loc));
  2075. broken = true;
  2076. }
  2077. Some(pt::Parameter {
  2078. ty, storage, name, ..
  2079. }) => {
  2080. let (ret_ty, ty_loc) = resolve_var_decl_ty(ty, storage, context, ns, diagnostics)?;
  2081. if arg_ty != ret_ty {
  2082. diagnostics.push(Diagnostic::error(
  2083. ty.loc(),
  2084. format!(
  2085. "type '{}' does not match return value of function '{}'",
  2086. ret_ty.to_string(ns),
  2087. arg_ty.to_string(ns)
  2088. ),
  2089. ));
  2090. broken = true;
  2091. }
  2092. if let Some(name) = name {
  2093. if let Some(pos) = symtable.add(
  2094. name,
  2095. ret_ty.clone(),
  2096. ns,
  2097. VariableInitializer::Solidity(None),
  2098. VariableUsage::TryCatchReturns,
  2099. storage.clone(),
  2100. ) {
  2101. ns.check_shadowing(context.file_no, context.contract_no, name);
  2102. params.push((
  2103. Some(pos),
  2104. Parameter {
  2105. loc: param.0,
  2106. ty: ret_ty,
  2107. ty_loc: Some(ty_loc),
  2108. id: Some(name.clone()),
  2109. indexed: false,
  2110. readonly: false,
  2111. infinite_size: false,
  2112. recursive: false,
  2113. annotation: None,
  2114. },
  2115. ));
  2116. }
  2117. } else {
  2118. params.push((
  2119. None,
  2120. Parameter {
  2121. loc: param.0,
  2122. ty: ret_ty,
  2123. ty_loc: Some(ty_loc),
  2124. indexed: false,
  2125. id: None,
  2126. readonly: false,
  2127. infinite_size: false,
  2128. recursive: false,
  2129. annotation: None,
  2130. },
  2131. ));
  2132. }
  2133. }
  2134. None => {
  2135. diagnostics.push(Diagnostic::error(
  2136. param.0,
  2137. "missing return type".to_string(),
  2138. ));
  2139. broken = true;
  2140. }
  2141. }
  2142. }
  2143. if broken {
  2144. return Err(());
  2145. }
  2146. let mut ok_resolved = Vec::new();
  2147. let mut finally_reachable = statement(
  2148. ok,
  2149. &mut ok_resolved,
  2150. context,
  2151. symtable,
  2152. loops,
  2153. ns,
  2154. diagnostics,
  2155. )?;
  2156. symtable.leave_scope();
  2157. let mut clauses_unique = HashSet::new();
  2158. let mut errors_resolved = Vec::new();
  2159. let mut catch_all = None;
  2160. clause_stmts.iter().try_for_each(|clause_stmt| {
  2161. let (loc, name) = match clause_stmt {
  2162. CatchClause::Simple(loc, _, _) => (loc, ""),
  2163. CatchClause::Named(loc, id, _, _) => (loc, id.name.as_str()),
  2164. };
  2165. if !clauses_unique.insert(name) {
  2166. ns.diagnostics.push(Diagnostic::error(
  2167. *loc,
  2168. if name.is_empty() {
  2169. "duplicate catch clause".to_string()
  2170. } else {
  2171. format!("duplicate '{name}' catch clause")
  2172. },
  2173. ));
  2174. return Err(());
  2175. }
  2176. match clause_stmt {
  2177. CatchClause::Simple(_, param, stmt) => {
  2178. symtable.new_scope();
  2179. let mut catch_param = None;
  2180. let mut catch_param_pos = None;
  2181. let mut catch_stmt_resolved = vec![];
  2182. if let Some(param) = param {
  2183. let (catch_ty, ty_loc) =
  2184. resolve_var_decl_ty(&param.ty, &param.storage, context, ns, diagnostics)?;
  2185. if catch_ty != Type::DynamicBytes {
  2186. diagnostics.push(Diagnostic::error(
  2187. param.ty.loc(),
  2188. format!(
  2189. "catch can only take 'bytes memory', not '{}'",
  2190. catch_ty.to_string(ns)
  2191. ),
  2192. ));
  2193. return Err(());
  2194. } else if let Some(annotation) = &param.annotation {
  2195. diagnostics.push(unexpected_parameter_annotation(annotation.loc));
  2196. }
  2197. let mut result = Parameter {
  2198. loc: param.loc,
  2199. ty: Type::DynamicBytes,
  2200. ty_loc: Some(ty_loc),
  2201. id: None,
  2202. indexed: false,
  2203. readonly: false,
  2204. infinite_size: false,
  2205. recursive: false,
  2206. annotation: None,
  2207. };
  2208. if let Some(name) = &param.name {
  2209. if let Some(pos) = symtable.add(
  2210. name,
  2211. catch_ty,
  2212. ns,
  2213. VariableInitializer::Solidity(None),
  2214. VariableUsage::TryCatchErrorBytes,
  2215. param.storage.clone(),
  2216. ) {
  2217. ns.check_shadowing(context.file_no, context.contract_no, name);
  2218. catch_param_pos = Some(pos);
  2219. result.id = Some(name.clone());
  2220. }
  2221. }
  2222. catch_param = Some(result);
  2223. }
  2224. let reachable = statement(
  2225. stmt,
  2226. &mut catch_stmt_resolved,
  2227. context,
  2228. symtable,
  2229. loops,
  2230. ns,
  2231. diagnostics,
  2232. )?;
  2233. finally_reachable |= reachable;
  2234. symtable.leave_scope();
  2235. catch_all = Some(super::ast::CatchClause {
  2236. param: catch_param,
  2237. param_pos: catch_param_pos,
  2238. stmt: catch_stmt_resolved,
  2239. });
  2240. Ok(())
  2241. }
  2242. CatchClause::Named(_, id, param, stmt) => {
  2243. match ns.target {
  2244. Target::Polkadot { .. } if id.name != "Error" => {
  2245. ns.diagnostics.push(Diagnostic::error(
  2246. id.loc,
  2247. format!("only catch 'Error' is supported, not '{}'", id.name),
  2248. ));
  2249. return Err(());
  2250. }
  2251. Target::EVM if id.name != "Error" && id.name != "Panic" => {
  2252. ns.diagnostics.push(Diagnostic::error(
  2253. id.loc,
  2254. format!(
  2255. "only catch 'Error' or 'Panic' is supported, not '{}'",
  2256. id.name
  2257. ),
  2258. ));
  2259. return Err(());
  2260. }
  2261. _ => {
  2262. if let Some(annotation) = &param.annotation {
  2263. ns.diagnostics
  2264. .push(unexpected_parameter_annotation(annotation.loc))
  2265. }
  2266. }
  2267. }
  2268. let (error_ty, ty_loc) =
  2269. resolve_var_decl_ty(&param.ty, &param.storage, context, ns, diagnostics)?;
  2270. if id.name == "Error" && error_ty != Type::String {
  2271. ns.diagnostics.push(Diagnostic::error(
  2272. param.ty.loc(),
  2273. format!(
  2274. "catch Error(...) can only take 'string memory', not '{}'",
  2275. error_ty.to_string(ns)
  2276. ),
  2277. ));
  2278. }
  2279. if id.name == "Panic" && error_ty != Type::Uint(256) {
  2280. ns.diagnostics.push(Diagnostic::error(
  2281. param.ty.loc(),
  2282. format!(
  2283. "catch Panic(...) can only take 'uint256', not '{}'",
  2284. error_ty.to_string(ns)
  2285. ),
  2286. ));
  2287. }
  2288. symtable.new_scope();
  2289. let mut error_pos = None;
  2290. let mut error_stmt_resolved = Vec::new();
  2291. let mut error_param = Parameter {
  2292. loc: id.loc,
  2293. ty: Type::String,
  2294. ty_loc: Some(ty_loc),
  2295. id: None,
  2296. indexed: false,
  2297. readonly: false,
  2298. infinite_size: false,
  2299. recursive: false,
  2300. annotation: None,
  2301. };
  2302. if let Some(name) = &param.name {
  2303. if let Some(pos) = symtable.add(
  2304. name,
  2305. Type::String,
  2306. ns,
  2307. VariableInitializer::Solidity(None),
  2308. VariableUsage::TryCatchErrorString,
  2309. param.storage.clone(),
  2310. ) {
  2311. ns.check_shadowing(context.file_no, context.contract_no, name);
  2312. error_pos = Some(pos);
  2313. error_param.id = Some(name.clone());
  2314. }
  2315. }
  2316. let reachable = statement(
  2317. stmt,
  2318. &mut error_stmt_resolved,
  2319. context,
  2320. symtable,
  2321. loops,
  2322. ns,
  2323. diagnostics,
  2324. )?;
  2325. finally_reachable |= reachable;
  2326. symtable.leave_scope();
  2327. errors_resolved.push((error_pos, error_param, error_stmt_resolved));
  2328. Ok(())
  2329. }
  2330. }
  2331. })?;
  2332. let stmt = Statement::TryCatch(
  2333. *loc,
  2334. finally_reachable,
  2335. TryCatch {
  2336. expr: fcall,
  2337. returns: params,
  2338. errors: errors_resolved
  2339. .iter()
  2340. .map(|(pos, param, stmt)| super::ast::CatchClause {
  2341. param: param.clone().into(),
  2342. param_pos: *pos,
  2343. stmt: stmt.clone(),
  2344. })
  2345. .collect(),
  2346. ok_stmt: ok_resolved,
  2347. catch_all,
  2348. },
  2349. );
  2350. Ok((stmt, finally_reachable))
  2351. }