Interp.cpp 15 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502
  1. //===------- Interp.cpp - Interpreter for the constexpr VM ------*- C++ -*-===//
  2. //
  3. // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
  4. // See https://llvm.org/LICENSE.txt for license information.
  5. // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
  6. //
  7. //===----------------------------------------------------------------------===//
  8. #include "Interp.h"
  9. #include <limits>
  10. #include <vector>
  11. #include "Function.h"
  12. #include "InterpFrame.h"
  13. #include "InterpStack.h"
  14. #include "Opcode.h"
  15. #include "PrimType.h"
  16. #include "Program.h"
  17. #include "State.h"
  18. #include "clang/AST/ASTContext.h"
  19. #include "clang/AST/ASTDiagnostic.h"
  20. #include "clang/AST/CXXInheritance.h"
  21. #include "clang/AST/Expr.h"
  22. #include "clang/AST/ExprCXX.h"
  23. #include "llvm/ADT/APSInt.h"
  24. using namespace clang;
  25. using namespace clang::interp;
  26. //===----------------------------------------------------------------------===//
  27. // Ret
  28. //===----------------------------------------------------------------------===//
  29. template <PrimType Name, class T = typename PrimConv<Name>::T>
  30. static bool Ret(InterpState &S, CodePtr &PC, APValue &Result) {
  31. S.CallStackDepth--;
  32. const T &Ret = S.Stk.pop<T>();
  33. assert(S.Current->getFrameOffset() == S.Stk.size() && "Invalid frame");
  34. if (!S.checkingPotentialConstantExpression())
  35. S.Current->popArgs();
  36. if (InterpFrame *Caller = S.Current->Caller) {
  37. PC = S.Current->getRetPC();
  38. delete S.Current;
  39. S.Current = Caller;
  40. S.Stk.push<T>(Ret);
  41. } else {
  42. delete S.Current;
  43. S.Current = nullptr;
  44. if (!ReturnValue<T>(Ret, Result))
  45. return false;
  46. }
  47. return true;
  48. }
  49. static bool RetVoid(InterpState &S, CodePtr &PC, APValue &Result) {
  50. S.CallStackDepth--;
  51. assert(S.Current->getFrameOffset() == S.Stk.size() && "Invalid frame");
  52. if (!S.checkingPotentialConstantExpression())
  53. S.Current->popArgs();
  54. if (InterpFrame *Caller = S.Current->Caller) {
  55. PC = S.Current->getRetPC();
  56. delete S.Current;
  57. S.Current = Caller;
  58. } else {
  59. delete S.Current;
  60. S.Current = nullptr;
  61. }
  62. return true;
  63. }
  64. static bool RetValue(InterpState &S, CodePtr &Pt, APValue &Result) {
  65. llvm::report_fatal_error("Interpreter cannot return values");
  66. }
  67. //===----------------------------------------------------------------------===//
  68. // Jmp, Jt, Jf
  69. //===----------------------------------------------------------------------===//
  70. static bool Jmp(InterpState &S, CodePtr &PC, int32_t Offset) {
  71. PC += Offset;
  72. return true;
  73. }
  74. static bool Jt(InterpState &S, CodePtr &PC, int32_t Offset) {
  75. if (S.Stk.pop<bool>()) {
  76. PC += Offset;
  77. }
  78. return true;
  79. }
  80. static bool Jf(InterpState &S, CodePtr &PC, int32_t Offset) {
  81. if (!S.Stk.pop<bool>()) {
  82. PC += Offset;
  83. }
  84. return true;
  85. }
  86. static bool CheckInitialized(InterpState &S, CodePtr OpPC, const Pointer &Ptr,
  87. AccessKinds AK) {
  88. if (Ptr.isInitialized())
  89. return true;
  90. if (!S.checkingPotentialConstantExpression()) {
  91. const SourceInfo &Loc = S.Current->getSource(OpPC);
  92. S.FFDiag(Loc, diag::note_constexpr_access_uninit) << AK << false;
  93. }
  94. return false;
  95. }
  96. static bool CheckActive(InterpState &S, CodePtr OpPC, const Pointer &Ptr,
  97. AccessKinds AK) {
  98. if (Ptr.isActive())
  99. return true;
  100. // Get the inactive field descriptor.
  101. const FieldDecl *InactiveField = Ptr.getField();
  102. // Walk up the pointer chain to find the union which is not active.
  103. Pointer U = Ptr.getBase();
  104. while (!U.isActive()) {
  105. U = U.getBase();
  106. }
  107. // Find the active field of the union.
  108. Record *R = U.getRecord();
  109. assert(R && R->isUnion() && "Not a union");
  110. const FieldDecl *ActiveField = nullptr;
  111. for (unsigned I = 0, N = R->getNumFields(); I < N; ++I) {
  112. const Pointer &Field = U.atField(R->getField(I)->Offset);
  113. if (Field.isActive()) {
  114. ActiveField = Field.getField();
  115. break;
  116. }
  117. }
  118. const SourceInfo &Loc = S.Current->getSource(OpPC);
  119. S.FFDiag(Loc, diag::note_constexpr_access_inactive_union_member)
  120. << AK << InactiveField << !ActiveField << ActiveField;
  121. return false;
  122. }
  123. static bool CheckTemporary(InterpState &S, CodePtr OpPC, const Pointer &Ptr,
  124. AccessKinds AK) {
  125. if (auto ID = Ptr.getDeclID()) {
  126. if (!Ptr.isStaticTemporary())
  127. return true;
  128. if (Ptr.getDeclDesc()->getType().isConstQualified())
  129. return true;
  130. if (S.P.getCurrentDecl() == ID)
  131. return true;
  132. const SourceInfo &E = S.Current->getSource(OpPC);
  133. S.FFDiag(E, diag::note_constexpr_access_static_temporary, 1) << AK;
  134. S.Note(Ptr.getDeclLoc(), diag::note_constexpr_temporary_here);
  135. return false;
  136. }
  137. return true;
  138. }
  139. static bool CheckGlobal(InterpState &S, CodePtr OpPC, const Pointer &Ptr) {
  140. if (auto ID = Ptr.getDeclID()) {
  141. if (!Ptr.isStatic())
  142. return true;
  143. if (S.P.getCurrentDecl() == ID)
  144. return true;
  145. S.FFDiag(S.Current->getLocation(OpPC), diag::note_constexpr_modify_global);
  146. return false;
  147. }
  148. return true;
  149. }
  150. namespace clang {
  151. namespace interp {
  152. bool CheckExtern(InterpState &S, CodePtr OpPC, const Pointer &Ptr) {
  153. if (!Ptr.isExtern())
  154. return true;
  155. if (!S.checkingPotentialConstantExpression()) {
  156. auto *VD = Ptr.getDeclDesc()->asValueDecl();
  157. const SourceInfo &Loc = S.Current->getSource(OpPC);
  158. S.FFDiag(Loc, diag::note_constexpr_ltor_non_constexpr, 1) << VD;
  159. S.Note(VD->getLocation(), diag::note_declared_at);
  160. }
  161. return false;
  162. }
  163. bool CheckArray(InterpState &S, CodePtr OpPC, const Pointer &Ptr) {
  164. if (!Ptr.isUnknownSizeArray())
  165. return true;
  166. const SourceInfo &E = S.Current->getSource(OpPC);
  167. S.FFDiag(E, diag::note_constexpr_unsized_array_indexed);
  168. return false;
  169. }
  170. bool CheckLive(InterpState &S, CodePtr OpPC, const Pointer &Ptr,
  171. AccessKinds AK) {
  172. if (Ptr.isZero()) {
  173. const auto &Src = S.Current->getSource(OpPC);
  174. if (Ptr.isField())
  175. S.FFDiag(Src, diag::note_constexpr_null_subobject) << CSK_Field;
  176. else
  177. S.FFDiag(Src, diag::note_constexpr_access_null) << AK;
  178. return false;
  179. }
  180. if (!Ptr.isLive()) {
  181. const auto &Src = S.Current->getSource(OpPC);
  182. bool IsTemp = Ptr.isTemporary();
  183. S.FFDiag(Src, diag::note_constexpr_lifetime_ended, 1) << AK << !IsTemp;
  184. if (IsTemp)
  185. S.Note(Ptr.getDeclLoc(), diag::note_constexpr_temporary_here);
  186. else
  187. S.Note(Ptr.getDeclLoc(), diag::note_declared_at);
  188. return false;
  189. }
  190. return true;
  191. }
  192. bool CheckNull(InterpState &S, CodePtr OpPC, const Pointer &Ptr,
  193. CheckSubobjectKind CSK) {
  194. if (!Ptr.isZero())
  195. return true;
  196. const SourceInfo &Loc = S.Current->getSource(OpPC);
  197. S.FFDiag(Loc, diag::note_constexpr_null_subobject) << CSK;
  198. return false;
  199. }
  200. bool CheckRange(InterpState &S, CodePtr OpPC, const Pointer &Ptr,
  201. AccessKinds AK) {
  202. if (!Ptr.isOnePastEnd())
  203. return true;
  204. const SourceInfo &Loc = S.Current->getSource(OpPC);
  205. S.FFDiag(Loc, diag::note_constexpr_access_past_end) << AK;
  206. return false;
  207. }
  208. bool CheckRange(InterpState &S, CodePtr OpPC, const Pointer &Ptr,
  209. CheckSubobjectKind CSK) {
  210. if (!Ptr.isElementPastEnd())
  211. return true;
  212. const SourceInfo &Loc = S.Current->getSource(OpPC);
  213. S.FFDiag(Loc, diag::note_constexpr_past_end_subobject) << CSK;
  214. return false;
  215. }
  216. bool CheckConst(InterpState &S, CodePtr OpPC, const Pointer &Ptr) {
  217. assert(Ptr.isLive() && "Pointer is not live");
  218. if (!Ptr.isConst()) {
  219. return true;
  220. }
  221. const QualType Ty = Ptr.getType();
  222. const SourceInfo &Loc = S.Current->getSource(OpPC);
  223. S.FFDiag(Loc, diag::note_constexpr_modify_const_type) << Ty;
  224. return false;
  225. }
  226. bool CheckMutable(InterpState &S, CodePtr OpPC, const Pointer &Ptr) {
  227. assert(Ptr.isLive() && "Pointer is not live");
  228. if (!Ptr.isMutable()) {
  229. return true;
  230. }
  231. const SourceInfo &Loc = S.Current->getSource(OpPC);
  232. const FieldDecl *Field = Ptr.getField();
  233. S.FFDiag(Loc, diag::note_constexpr_access_mutable, 1) << AK_Read << Field;
  234. S.Note(Field->getLocation(), diag::note_declared_at);
  235. return false;
  236. }
  237. bool CheckLoad(InterpState &S, CodePtr OpPC, const Pointer &Ptr) {
  238. if (!CheckLive(S, OpPC, Ptr, AK_Read))
  239. return false;
  240. if (!CheckExtern(S, OpPC, Ptr))
  241. return false;
  242. if (!CheckRange(S, OpPC, Ptr, AK_Read))
  243. return false;
  244. if (!CheckInitialized(S, OpPC, Ptr, AK_Read))
  245. return false;
  246. if (!CheckActive(S, OpPC, Ptr, AK_Read))
  247. return false;
  248. if (!CheckTemporary(S, OpPC, Ptr, AK_Read))
  249. return false;
  250. if (!CheckMutable(S, OpPC, Ptr))
  251. return false;
  252. return true;
  253. }
  254. bool CheckStore(InterpState &S, CodePtr OpPC, const Pointer &Ptr) {
  255. if (!CheckLive(S, OpPC, Ptr, AK_Assign))
  256. return false;
  257. if (!CheckExtern(S, OpPC, Ptr))
  258. return false;
  259. if (!CheckRange(S, OpPC, Ptr, AK_Assign))
  260. return false;
  261. if (!CheckGlobal(S, OpPC, Ptr))
  262. return false;
  263. if (!CheckConst(S, OpPC, Ptr))
  264. return false;
  265. return true;
  266. }
  267. bool CheckInvoke(InterpState &S, CodePtr OpPC, const Pointer &Ptr) {
  268. if (!CheckLive(S, OpPC, Ptr, AK_MemberCall))
  269. return false;
  270. if (!CheckExtern(S, OpPC, Ptr))
  271. return false;
  272. if (!CheckRange(S, OpPC, Ptr, AK_MemberCall))
  273. return false;
  274. return true;
  275. }
  276. bool CheckInit(InterpState &S, CodePtr OpPC, const Pointer &Ptr) {
  277. if (!CheckLive(S, OpPC, Ptr, AK_Assign))
  278. return false;
  279. if (!CheckRange(S, OpPC, Ptr, AK_Assign))
  280. return false;
  281. return true;
  282. }
  283. bool CheckCallable(InterpState &S, CodePtr OpPC, const Function *F) {
  284. if (F->isVirtual()) {
  285. if (!S.getLangOpts().CPlusPlus20) {
  286. const SourceLocation &Loc = S.Current->getLocation(OpPC);
  287. S.CCEDiag(Loc, diag::note_constexpr_virtual_call);
  288. return false;
  289. }
  290. }
  291. if (!F->isConstexpr()) {
  292. const SourceLocation &Loc = S.Current->getLocation(OpPC);
  293. if (S.getLangOpts().CPlusPlus11) {
  294. const FunctionDecl *DiagDecl = F->getDecl();
  295. // If this function is not constexpr because it is an inherited
  296. // non-constexpr constructor, diagnose that directly.
  297. auto *CD = dyn_cast<CXXConstructorDecl>(DiagDecl);
  298. if (CD && CD->isInheritingConstructor()) {
  299. auto *Inherited = CD->getInheritedConstructor().getConstructor();
  300. if (!Inherited->isConstexpr())
  301. DiagDecl = CD = Inherited;
  302. }
  303. // FIXME: If DiagDecl is an implicitly-declared special member function
  304. // or an inheriting constructor, we should be much more explicit about why
  305. // it's not constexpr.
  306. if (CD && CD->isInheritingConstructor())
  307. S.FFDiag(Loc, diag::note_constexpr_invalid_inhctor, 1)
  308. << CD->getInheritedConstructor().getConstructor()->getParent();
  309. else
  310. S.FFDiag(Loc, diag::note_constexpr_invalid_function, 1)
  311. << DiagDecl->isConstexpr() << (bool)CD << DiagDecl;
  312. S.Note(DiagDecl->getLocation(), diag::note_declared_at);
  313. } else {
  314. S.FFDiag(Loc, diag::note_invalid_subexpr_in_const_expr);
  315. }
  316. return false;
  317. }
  318. return true;
  319. }
  320. bool CheckThis(InterpState &S, CodePtr OpPC, const Pointer &This) {
  321. if (!This.isZero())
  322. return true;
  323. const SourceInfo &Loc = S.Current->getSource(OpPC);
  324. bool IsImplicit = false;
  325. if (auto *E = dyn_cast_or_null<CXXThisExpr>(Loc.asExpr()))
  326. IsImplicit = E->isImplicit();
  327. if (S.getLangOpts().CPlusPlus11)
  328. S.FFDiag(Loc, diag::note_constexpr_this) << IsImplicit;
  329. else
  330. S.FFDiag(Loc);
  331. return false;
  332. }
  333. bool CheckPure(InterpState &S, CodePtr OpPC, const CXXMethodDecl *MD) {
  334. if (!MD->isPure())
  335. return true;
  336. const SourceInfo &E = S.Current->getSource(OpPC);
  337. S.FFDiag(E, diag::note_constexpr_pure_virtual_call, 1) << MD;
  338. S.Note(MD->getLocation(), diag::note_declared_at);
  339. return false;
  340. }
  341. static void DiagnoseUninitializedSubobject(InterpState &S, const SourceInfo &SI,
  342. QualType SubObjType,
  343. SourceLocation SubObjLoc) {
  344. S.FFDiag(SI, diag::note_constexpr_uninitialized) << true << SubObjType;
  345. if (SubObjLoc.isValid())
  346. S.Note(SubObjLoc, diag::note_constexpr_subobject_declared_here);
  347. }
  348. static bool CheckFieldsInitialized(InterpState &S, CodePtr OpPC,
  349. const Pointer &BasePtr, const Record *R);
  350. static bool CheckArrayInitialized(InterpState &S, CodePtr OpPC,
  351. const Pointer &BasePtr,
  352. const ConstantArrayType *CAT) {
  353. bool Result = true;
  354. size_t NumElems = CAT->getSize().getZExtValue();
  355. QualType ElemType = CAT->getElementType();
  356. if (isa<RecordType>(ElemType.getTypePtr())) {
  357. const Record *R = BasePtr.getElemRecord();
  358. for (size_t I = 0; I != NumElems; ++I) {
  359. Pointer ElemPtr = BasePtr.atIndex(I).narrow();
  360. Result &= CheckFieldsInitialized(S, OpPC, ElemPtr, R);
  361. }
  362. } else if (auto *ElemCAT = dyn_cast<ConstantArrayType>(ElemType)) {
  363. for (size_t I = 0; I != NumElems; ++I) {
  364. Pointer ElemPtr = BasePtr.atIndex(I).narrow();
  365. Result &= CheckArrayInitialized(S, OpPC, ElemPtr, ElemCAT);
  366. }
  367. } else {
  368. for (size_t I = 0; I != NumElems; ++I) {
  369. if (!BasePtr.atIndex(I).isInitialized()) {
  370. DiagnoseUninitializedSubobject(S, S.Current->getSource(OpPC), ElemType,
  371. BasePtr.getFieldDesc()->getLocation());
  372. Result = false;
  373. }
  374. }
  375. }
  376. return Result;
  377. }
  378. static bool CheckFieldsInitialized(InterpState &S, CodePtr OpPC,
  379. const Pointer &BasePtr, const Record *R) {
  380. assert(R);
  381. bool Result = true;
  382. // Check all fields of this record are initialized.
  383. for (const Record::Field &F : R->fields()) {
  384. Pointer FieldPtr = BasePtr.atField(F.Offset);
  385. QualType FieldType = F.Decl->getType();
  386. if (FieldType->isRecordType()) {
  387. Result &= CheckFieldsInitialized(S, OpPC, FieldPtr, FieldPtr.getRecord());
  388. } else if (FieldType->isArrayType()) {
  389. const auto *CAT =
  390. cast<ConstantArrayType>(FieldType->getAsArrayTypeUnsafe());
  391. Result &= CheckArrayInitialized(S, OpPC, FieldPtr, CAT);
  392. } else if (!FieldPtr.isInitialized()) {
  393. DiagnoseUninitializedSubobject(S, S.Current->getSource(OpPC),
  394. F.Decl->getType(), F.Decl->getLocation());
  395. Result = false;
  396. }
  397. }
  398. return Result;
  399. }
  400. bool CheckCtorCall(InterpState &S, CodePtr OpPC, const Pointer &This) {
  401. assert(!This.isZero());
  402. const Record *R = This.getRecord();
  403. return CheckFieldsInitialized(S, OpPC, This, R);
  404. }
  405. bool Interpret(InterpState &S, APValue &Result) {
  406. // The current stack frame when we started Interpret().
  407. // This is being used by the ops to determine wheter
  408. // to return from this function and thus terminate
  409. // interpretation.
  410. const InterpFrame *StartFrame = S.Current;
  411. assert(!S.Current->isRoot());
  412. CodePtr PC = S.Current->getPC();
  413. // Empty program.
  414. if (!PC)
  415. return true;
  416. for (;;) {
  417. auto Op = PC.read<Opcode>();
  418. CodePtr OpPC = PC;
  419. switch (Op) {
  420. #define GET_INTERP
  421. #include "Opcodes.inc"
  422. #undef GET_INTERP
  423. }
  424. }
  425. }
  426. } // namespace interp
  427. } // namespace clang