clang  19.0.0git
Interp.cpp
Go to the documentation of this file.
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 
9 #include "Interp.h"
10 #include "Function.h"
11 #include "InterpFrame.h"
12 #include "InterpShared.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"
21 #include "clang/AST/DeclObjC.h"
22 #include "clang/AST/Expr.h"
23 #include "clang/AST/ExprCXX.h"
24 #include "llvm/ADT/APSInt.h"
25 #include <limits>
26 #include <vector>
27 
28 using namespace clang;
29 
30 using namespace clang;
31 using namespace clang::interp;
32 
33 static bool RetValue(InterpState &S, CodePtr &Pt, APValue &Result) {
34  llvm::report_fatal_error("Interpreter cannot return values");
35 }
36 
37 //===----------------------------------------------------------------------===//
38 // Jmp, Jt, Jf
39 //===----------------------------------------------------------------------===//
40 
41 static bool Jmp(InterpState &S, CodePtr &PC, int32_t Offset) {
42  PC += Offset;
43  return true;
44 }
45 
46 static bool Jt(InterpState &S, CodePtr &PC, int32_t Offset) {
47  if (S.Stk.pop<bool>()) {
48  PC += Offset;
49  }
50  return true;
51 }
52 
53 static bool Jf(InterpState &S, CodePtr &PC, int32_t Offset) {
54  if (!S.Stk.pop<bool>()) {
55  PC += Offset;
56  }
57  return true;
58 }
59 
61  const ValueDecl *VD) {
62  const SourceInfo &E = S.Current->getSource(OpPC);
63  S.FFDiag(E, diag::note_constexpr_var_init_unknown, 1) << VD;
64  S.Note(VD->getLocation(), diag::note_declared_at) << VD->getSourceRange();
65 }
66 
67 static void diagnoseNonConstVariable(InterpState &S, CodePtr OpPC,
68  const ValueDecl *VD);
70  const ValueDecl *D) {
71  const SourceInfo &E = S.Current->getSource(OpPC);
72 
73  if (isa<ParmVarDecl>(D)) {
74  if (S.getLangOpts().CPlusPlus11) {
75  S.FFDiag(E, diag::note_constexpr_function_param_value_unknown) << D;
76  S.Note(D->getLocation(), diag::note_declared_at) << D->getSourceRange();
77  } else {
78  S.FFDiag(E);
79  }
80  return false;
81  }
82 
83  if (!D->getType().isConstQualified())
84  diagnoseNonConstVariable(S, OpPC, D);
85  else if (const auto *VD = dyn_cast<VarDecl>(D);
86  VD && !VD->getAnyInitializer())
87  diagnoseMissingInitializer(S, OpPC, VD);
88 
89  return false;
90 }
91 
93  const ValueDecl *VD) {
94  if (!S.getLangOpts().CPlusPlus)
95  return;
96 
97  const SourceInfo &Loc = S.Current->getSource(OpPC);
98  if (const auto *VarD = dyn_cast<VarDecl>(VD);
99  VarD && VarD->getType().isConstQualified() &&
100  !VarD->getAnyInitializer()) {
101  diagnoseMissingInitializer(S, OpPC, VD);
102  return;
103  }
104 
105  // Rather random, but this is to match the diagnostic output of the current
106  // interpreter.
107  if (isa<ObjCIvarDecl>(VD))
108  return;
109 
110  if (VD->getType()->isIntegralOrEnumerationType()) {
111  S.FFDiag(Loc, diag::note_constexpr_ltor_non_const_int, 1) << VD;
112  S.Note(VD->getLocation(), diag::note_declared_at);
113  return;
114  }
115 
116  S.FFDiag(Loc,
117  S.getLangOpts().CPlusPlus11 ? diag::note_constexpr_ltor_non_constexpr
118  : diag::note_constexpr_ltor_non_integral,
119  1)
120  << VD << VD->getType();
121  S.Note(VD->getLocation(), diag::note_declared_at);
122 }
123 
124 static bool CheckActive(InterpState &S, CodePtr OpPC, const Pointer &Ptr,
125  AccessKinds AK) {
126  if (Ptr.isActive())
127  return true;
128 
129  // Get the inactive field descriptor.
130  const FieldDecl *InactiveField = Ptr.getField();
131 
132  // Walk up the pointer chain to find the union which is not active.
133  Pointer U = Ptr.getBase();
134  while (!U.isActive()) {
135  U = U.getBase();
136  }
137 
138  // Find the active field of the union.
139  const Record *R = U.getRecord();
140  assert(R && R->isUnion() && "Not a union");
141  const FieldDecl *ActiveField = nullptr;
142  for (unsigned I = 0, N = R->getNumFields(); I < N; ++I) {
143  const Pointer &Field = U.atField(R->getField(I)->Offset);
144  if (Field.isActive()) {
145  ActiveField = Field.getField();
146  break;
147  }
148  }
149 
150  const SourceInfo &Loc = S.Current->getSource(OpPC);
151  S.FFDiag(Loc, diag::note_constexpr_access_inactive_union_member)
152  << AK << InactiveField << !ActiveField << ActiveField;
153  return false;
154 }
155 
156 static bool CheckTemporary(InterpState &S, CodePtr OpPC, const Pointer &Ptr,
157  AccessKinds AK) {
158  if (auto ID = Ptr.getDeclID()) {
159  if (!Ptr.isStaticTemporary())
160  return true;
161 
162  if (Ptr.getDeclDesc()->getType().isConstQualified())
163  return true;
164 
165  if (S.P.getCurrentDecl() == ID)
166  return true;
167 
168  const SourceInfo &E = S.Current->getSource(OpPC);
169  S.FFDiag(E, diag::note_constexpr_access_static_temporary, 1) << AK;
170  S.Note(Ptr.getDeclLoc(), diag::note_constexpr_temporary_here);
171  return false;
172  }
173  return true;
174 }
175 
176 static bool CheckGlobal(InterpState &S, CodePtr OpPC, const Pointer &Ptr) {
177  if (auto ID = Ptr.getDeclID()) {
178  if (!Ptr.isStatic())
179  return true;
180 
181  if (S.P.getCurrentDecl() == ID)
182  return true;
183 
184  S.FFDiag(S.Current->getLocation(OpPC), diag::note_constexpr_modify_global);
185  return false;
186  }
187  return true;
188 }
189 
190 namespace clang {
191 namespace interp {
192 static void popArg(InterpState &S, const Expr *Arg) {
193  PrimType Ty = S.getContext().classify(Arg).value_or(PT_Ptr);
194  TYPE_SWITCH(Ty, S.Stk.discard<T>());
195 }
196 
198  assert(S.Current);
199  const Function *CurFunc = S.Current->getFunction();
200  assert(CurFunc);
201 
202  if (CurFunc->isUnevaluatedBuiltin())
203  return;
204 
205  // Some builtin functions require us to only look at the call site, since
206  // the classified parameter types do not match.
207  if (CurFunc->isBuiltin()) {
208  const auto *CE =
209  cast<CallExpr>(S.Current->Caller->getExpr(S.Current->getRetPC()));
210  for (int32_t I = CE->getNumArgs() - 1; I >= 0; --I) {
211  const Expr *A = CE->getArg(I);
212  popArg(S, A);
213  }
214  return;
215  }
216 
217  if (S.Current->Caller && CurFunc->isVariadic()) {
218  // CallExpr we're look for is at the return PC of the current function, i.e.
219  // in the caller.
220  // This code path should be executed very rarely.
221  unsigned NumVarArgs;
222  const Expr *const *Args = nullptr;
223  unsigned NumArgs = 0;
224  const Expr *CallSite = S.Current->Caller->getExpr(S.Current->getRetPC());
225  if (const auto *CE = dyn_cast<CallExpr>(CallSite)) {
226  Args = CE->getArgs();
227  NumArgs = CE->getNumArgs();
228  } else if (const auto *CE = dyn_cast<CXXConstructExpr>(CallSite)) {
229  Args = CE->getArgs();
230  NumArgs = CE->getNumArgs();
231  } else
232  assert(false && "Can't get arguments from that expression type");
233 
234  assert(NumArgs >= CurFunc->getNumWrittenParams());
235  NumVarArgs = NumArgs - CurFunc->getNumWrittenParams();
236  for (unsigned I = 0; I != NumVarArgs; ++I) {
237  const Expr *A = Args[NumArgs - 1 - I];
238  popArg(S, A);
239  }
240  }
241 
242  // And in any case, remove the fixed parameters (the non-variadic ones)
243  // at the end.
244  S.Current->popArgs();
245 }
246 
247 bool CheckExtern(InterpState &S, CodePtr OpPC, const Pointer &Ptr) {
248  if (!Ptr.isExtern())
249  return true;
250 
251  if (Ptr.isInitialized())
252  return true;
253 
254  if (!S.checkingPotentialConstantExpression() && S.getLangOpts().CPlusPlus) {
255  const auto *VD = Ptr.getDeclDesc()->asValueDecl();
256  diagnoseNonConstVariable(S, OpPC, VD);
257  }
258  return false;
259 }
260 
261 bool CheckArray(InterpState &S, CodePtr OpPC, const Pointer &Ptr) {
262  if (!Ptr.isUnknownSizeArray())
263  return true;
264  const SourceInfo &E = S.Current->getSource(OpPC);
265  S.FFDiag(E, diag::note_constexpr_unsized_array_indexed);
266  return false;
267 }
268 
269 bool CheckLive(InterpState &S, CodePtr OpPC, const Pointer &Ptr,
270  AccessKinds AK) {
271  if (Ptr.isZero()) {
272  const auto &Src = S.Current->getSource(OpPC);
273 
274  if (Ptr.isField())
275  S.FFDiag(Src, diag::note_constexpr_null_subobject) << CSK_Field;
276  else
277  S.FFDiag(Src, diag::note_constexpr_access_null) << AK;
278 
279  return false;
280  }
281 
282  if (!Ptr.isLive()) {
283  const auto &Src = S.Current->getSource(OpPC);
284  bool IsTemp = Ptr.isTemporary();
285 
286  S.FFDiag(Src, diag::note_constexpr_lifetime_ended, 1) << AK << !IsTemp;
287 
288  if (IsTemp)
289  S.Note(Ptr.getDeclLoc(), diag::note_constexpr_temporary_here);
290  else
291  S.Note(Ptr.getDeclLoc(), diag::note_declared_at);
292 
293  return false;
294  }
295 
296  return true;
297 }
298 
299 bool CheckConstant(InterpState &S, CodePtr OpPC, const Descriptor *Desc) {
300  assert(Desc);
301 
302  auto IsConstType = [&S](const VarDecl *VD) -> bool {
303  if (VD->isConstexpr())
304  return true;
305 
306  QualType T = VD->getType();
307  if (S.getLangOpts().CPlusPlus && !S.getLangOpts().CPlusPlus11)
308  return (T->isSignedIntegerOrEnumerationType() ||
310  T.isConstQualified();
311 
312  if (T.isConstQualified())
313  return true;
314 
315  if (const auto *RT = T->getAs<ReferenceType>())
316  return RT->getPointeeType().isConstQualified();
317 
318  if (const auto *PT = T->getAs<PointerType>())
319  return PT->getPointeeType().isConstQualified();
320 
321  return false;
322  };
323 
324  if (const auto *D = Desc->asVarDecl();
325  D && D->hasGlobalStorage() && !IsConstType(D)) {
326  diagnoseNonConstVariable(S, OpPC, D);
327  return S.inConstantContext();
328  }
329 
330  return true;
331 }
332 
333 static bool CheckConstant(InterpState &S, CodePtr OpPC, const Pointer &Ptr) {
334  if (Ptr.isIntegralPointer())
335  return true;
336  return CheckConstant(S, OpPC, Ptr.getDeclDesc());
337 }
338 
339 bool CheckNull(InterpState &S, CodePtr OpPC, const Pointer &Ptr,
340  CheckSubobjectKind CSK) {
341  if (!Ptr.isZero())
342  return true;
343  const SourceInfo &Loc = S.Current->getSource(OpPC);
344  S.FFDiag(Loc, diag::note_constexpr_null_subobject) << CSK;
345  return false;
346 }
347 
348 bool CheckRange(InterpState &S, CodePtr OpPC, const Pointer &Ptr,
349  AccessKinds AK) {
350  if (!Ptr.isOnePastEnd())
351  return true;
352  const SourceInfo &Loc = S.Current->getSource(OpPC);
353  S.FFDiag(Loc, diag::note_constexpr_access_past_end) << AK;
354  return false;
355 }
356 
357 bool CheckRange(InterpState &S, CodePtr OpPC, const Pointer &Ptr,
358  CheckSubobjectKind CSK) {
359  if (!Ptr.isElementPastEnd())
360  return true;
361  const SourceInfo &Loc = S.Current->getSource(OpPC);
362  S.FFDiag(Loc, diag::note_constexpr_past_end_subobject) << CSK;
363  return false;
364 }
365 
366 bool CheckSubobject(InterpState &S, CodePtr OpPC, const Pointer &Ptr,
367  CheckSubobjectKind CSK) {
368  if (!Ptr.isOnePastEnd())
369  return true;
370 
371  const SourceInfo &Loc = S.Current->getSource(OpPC);
372  S.FFDiag(Loc, diag::note_constexpr_past_end_subobject) << CSK;
373  return false;
374 }
375 
376 bool CheckConst(InterpState &S, CodePtr OpPC, const Pointer &Ptr) {
377  assert(Ptr.isLive() && "Pointer is not live");
378  if (!Ptr.isConst())
379  return true;
380 
381  // The This pointer is writable in constructors and destructors,
382  // even if isConst() returns true.
383  if (const Function *Func = S.Current->getFunction();
384  Func && (Func->isConstructor() || Func->isDestructor()) &&
385  Ptr.block() == S.Current->getThis().block()) {
386  return true;
387  }
388 
389  if (!Ptr.isBlockPointer())
390  return false;
391 
392  const QualType Ty = Ptr.getType();
393  const SourceInfo &Loc = S.Current->getSource(OpPC);
394  S.FFDiag(Loc, diag::note_constexpr_modify_const_type) << Ty;
395  return false;
396 }
397 
398 bool CheckMutable(InterpState &S, CodePtr OpPC, const Pointer &Ptr) {
399  assert(Ptr.isLive() && "Pointer is not live");
400  if (!Ptr.isMutable()) {
401  return true;
402  }
403 
404  const SourceInfo &Loc = S.Current->getSource(OpPC);
405  const FieldDecl *Field = Ptr.getField();
406  S.FFDiag(Loc, diag::note_constexpr_access_mutable, 1) << AK_Read << Field;
407  S.Note(Field->getLocation(), diag::note_declared_at);
408  return false;
409 }
410 
411 bool CheckInitialized(InterpState &S, CodePtr OpPC, const Pointer &Ptr,
412  AccessKinds AK) {
413  assert(Ptr.isLive());
414 
415  if (Ptr.isInitialized())
416  return true;
417 
418  if (const auto *VD = Ptr.getDeclDesc()->asVarDecl();
419  VD && VD->hasGlobalStorage()) {
420  const SourceInfo &Loc = S.Current->getSource(OpPC);
421  if (VD->getAnyInitializer()) {
422  S.FFDiag(Loc, diag::note_constexpr_var_init_non_constant, 1) << VD;
423  S.Note(VD->getLocation(), diag::note_declared_at);
424  } else {
425  diagnoseMissingInitializer(S, OpPC, VD);
426  }
427  return false;
428  }
429 
430  if (!S.checkingPotentialConstantExpression()) {
431  S.FFDiag(S.Current->getSource(OpPC), diag::note_constexpr_access_uninit)
432  << AK << /*uninitialized=*/true << S.Current->getRange(OpPC);
433  }
434  return false;
435 }
436 
437 bool CheckGlobalInitialized(InterpState &S, CodePtr OpPC, const Pointer &Ptr) {
438  if (Ptr.isInitialized())
439  return true;
440 
441  assert(S.getLangOpts().CPlusPlus);
442  const auto *VD = cast<VarDecl>(Ptr.getDeclDesc()->asValueDecl());
443  if ((!VD->hasConstantInitialization() &&
444  VD->mightBeUsableInConstantExpressions(S.getCtx())) ||
445  (S.getLangOpts().OpenCL && !S.getLangOpts().CPlusPlus11 &&
446  !VD->hasICEInitializer(S.getCtx()))) {
447  const SourceInfo &Loc = S.Current->getSource(OpPC);
448  S.FFDiag(Loc, diag::note_constexpr_var_init_non_constant, 1) << VD;
449  S.Note(VD->getLocation(), diag::note_declared_at);
450  }
451  return false;
452 }
453 
454 bool CheckLoad(InterpState &S, CodePtr OpPC, const Pointer &Ptr) {
455  if (!CheckLive(S, OpPC, Ptr, AK_Read))
456  return false;
457  if (!CheckConstant(S, OpPC, Ptr))
458  return false;
459 
460  if (!CheckDummy(S, OpPC, Ptr, AK_Read))
461  return false;
462  if (!CheckExtern(S, OpPC, Ptr))
463  return false;
464  if (!CheckRange(S, OpPC, Ptr, AK_Read))
465  return false;
466  if (!CheckActive(S, OpPC, Ptr, AK_Read))
467  return false;
468  if (!CheckInitialized(S, OpPC, Ptr, AK_Read))
469  return false;
470  if (!CheckTemporary(S, OpPC, Ptr, AK_Read))
471  return false;
472  if (!CheckMutable(S, OpPC, Ptr))
473  return false;
474  return true;
475 }
476 
477 bool CheckStore(InterpState &S, CodePtr OpPC, const Pointer &Ptr) {
478  if (!CheckLive(S, OpPC, Ptr, AK_Assign))
479  return false;
480  if (!CheckDummy(S, OpPC, Ptr, AK_Assign))
481  return false;
482  if (!CheckExtern(S, OpPC, Ptr))
483  return false;
484  if (!CheckRange(S, OpPC, Ptr, AK_Assign))
485  return false;
486  if (!CheckGlobal(S, OpPC, Ptr))
487  return false;
488  if (!CheckConst(S, OpPC, Ptr))
489  return false;
490  return true;
491 }
492 
493 bool CheckInvoke(InterpState &S, CodePtr OpPC, const Pointer &Ptr) {
494  if (!CheckLive(S, OpPC, Ptr, AK_MemberCall))
495  return false;
496  if (!CheckExtern(S, OpPC, Ptr))
497  return false;
498  if (!CheckRange(S, OpPC, Ptr, AK_MemberCall))
499  return false;
500  return true;
501 }
502 
503 bool CheckInit(InterpState &S, CodePtr OpPC, const Pointer &Ptr) {
504  if (!CheckLive(S, OpPC, Ptr, AK_Assign))
505  return false;
506  if (!CheckRange(S, OpPC, Ptr, AK_Assign))
507  return false;
508  return true;
509 }
510 
511 bool CheckCallable(InterpState &S, CodePtr OpPC, const Function *F) {
512 
513  if (F->isVirtual() && !S.getLangOpts().CPlusPlus20) {
514  const SourceLocation &Loc = S.Current->getLocation(OpPC);
515  S.CCEDiag(Loc, diag::note_constexpr_virtual_call);
516  return false;
517  }
518 
519  if (!F->isConstexpr()) {
520  const SourceLocation &Loc = S.Current->getLocation(OpPC);
521  if (S.getLangOpts().CPlusPlus11) {
522  const FunctionDecl *DiagDecl = F->getDecl();
523 
524  // Invalid decls have been diagnosed before.
525  if (DiagDecl->isInvalidDecl())
526  return false;
527 
528  // If this function is not constexpr because it is an inherited
529  // non-constexpr constructor, diagnose that directly.
530  const auto *CD = dyn_cast<CXXConstructorDecl>(DiagDecl);
531  if (CD && CD->isInheritingConstructor()) {
532  const auto *Inherited = CD->getInheritedConstructor().getConstructor();
533  if (!Inherited->isConstexpr())
534  DiagDecl = CD = Inherited;
535  }
536 
537  // FIXME: If DiagDecl is an implicitly-declared special member function
538  // or an inheriting constructor, we should be much more explicit about why
539  // it's not constexpr.
540  if (CD && CD->isInheritingConstructor()) {
541  S.FFDiag(Loc, diag::note_constexpr_invalid_inhctor, 1)
542  << CD->getInheritedConstructor().getConstructor()->getParent();
543  S.Note(DiagDecl->getLocation(), diag::note_declared_at);
544  } else {
545  // Don't emit anything if the function isn't defined and we're checking
546  // for a constant expression. It might be defined at the point we're
547  // actually calling it.
548  bool IsExtern = DiagDecl->getStorageClass() == SC_Extern;
549  if (!DiagDecl->isDefined() && !IsExtern &&
550  S.checkingPotentialConstantExpression())
551  return false;
552 
553  // If the declaration is defined _and_ declared 'constexpr', the below
554  // diagnostic doesn't add anything useful.
555  if (DiagDecl->isDefined() && DiagDecl->isConstexpr())
556  return false;
557 
558  S.FFDiag(Loc, diag::note_constexpr_invalid_function, 1)
559  << DiagDecl->isConstexpr() << (bool)CD << DiagDecl;
560  S.Note(DiagDecl->getLocation(), diag::note_declared_at);
561  }
562  } else {
563  S.FFDiag(Loc, diag::note_invalid_subexpr_in_const_expr);
564  }
565  return false;
566  }
567 
568  return true;
569 }
570 
572  if ((S.Current->getDepth() + 1) > S.getLangOpts().ConstexprCallDepth) {
573  S.FFDiag(S.Current->getSource(OpPC),
574  diag::note_constexpr_depth_limit_exceeded)
575  << S.getLangOpts().ConstexprCallDepth;
576  return false;
577  }
578 
579  return true;
580 }
581 
582 bool CheckThis(InterpState &S, CodePtr OpPC, const Pointer &This) {
583  if (!This.isZero())
584  return true;
585 
586  const SourceInfo &Loc = S.Current->getSource(OpPC);
587 
588  bool IsImplicit = false;
589  if (const auto *E = dyn_cast_if_present<CXXThisExpr>(Loc.asExpr()))
590  IsImplicit = E->isImplicit();
591 
592  if (S.getLangOpts().CPlusPlus11)
593  S.FFDiag(Loc, diag::note_constexpr_this) << IsImplicit;
594  else
595  S.FFDiag(Loc);
596 
597  return false;
598 }
599 
600 bool CheckPure(InterpState &S, CodePtr OpPC, const CXXMethodDecl *MD) {
601  if (!MD->isPureVirtual())
602  return true;
603  const SourceInfo &E = S.Current->getSource(OpPC);
604  S.FFDiag(E, diag::note_constexpr_pure_virtual_call, 1) << MD;
605  S.Note(MD->getLocation(), diag::note_declared_at);
606  return false;
607 }
608 
609 bool CheckFloatResult(InterpState &S, CodePtr OpPC, const Floating &Result,
610  APFloat::opStatus Status) {
611  const SourceInfo &E = S.Current->getSource(OpPC);
612 
613  // [expr.pre]p4:
614  // If during the evaluation of an expression, the result is not
615  // mathematically defined [...], the behavior is undefined.
616  // FIXME: C++ rules require us to not conform to IEEE 754 here.
617  if (Result.isNan()) {
618  S.CCEDiag(E, diag::note_constexpr_float_arithmetic)
619  << /*NaN=*/true << S.Current->getRange(OpPC);
620  return S.noteUndefinedBehavior();
621  }
622 
623  // In a constant context, assume that any dynamic rounding mode or FP
624  // exception state matches the default floating-point environment.
625  if (S.inConstantContext())
626  return true;
627 
629 
630  if ((Status & APFloat::opInexact) &&
631  FPO.getRoundingMode() == llvm::RoundingMode::Dynamic) {
632  // Inexact result means that it depends on rounding mode. If the requested
633  // mode is dynamic, the evaluation cannot be made in compile time.
634  S.FFDiag(E, diag::note_constexpr_dynamic_rounding);
635  return false;
636  }
637 
638  if ((Status != APFloat::opOK) &&
639  (FPO.getRoundingMode() == llvm::RoundingMode::Dynamic ||
641  FPO.getAllowFEnvAccess())) {
642  S.FFDiag(E, diag::note_constexpr_float_arithmetic_strict);
643  return false;
644  }
645 
646  if ((Status & APFloat::opStatus::opInvalidOp) &&
648  // There is no usefully definable result.
649  S.FFDiag(E);
650  return false;
651  }
652 
653  return true;
654 }
655 
656 /// We aleady know the given DeclRefExpr is invalid for some reason,
657 /// now figure out why and print appropriate diagnostics.
658 bool CheckDeclRef(InterpState &S, CodePtr OpPC, const DeclRefExpr *DR) {
659  const ValueDecl *D = DR->getDecl();
660  return diagnoseUnknownDecl(S, OpPC, D);
661 }
662 
663 bool CheckDummy(InterpState &S, CodePtr OpPC, const Pointer &Ptr,
664  AccessKinds AK) {
665  if (!Ptr.isDummy())
666  return true;
667 
668  const Descriptor *Desc = Ptr.getDeclDesc();
669  const ValueDecl *D = Desc->asValueDecl();
670  if (!D)
671  return false;
672 
673  if (AK == AK_Read || AK == AK_Increment || AK == AK_Decrement)
674  return diagnoseUnknownDecl(S, OpPC, D);
675 
676  assert(AK == AK_Assign);
677  if (S.getLangOpts().CPlusPlus11) {
678  const SourceInfo &E = S.Current->getSource(OpPC);
679  S.FFDiag(E, diag::note_constexpr_modify_global);
680  }
681  return false;
682 }
683 
685  const CallExpr *CE, unsigned ArgSize) {
686  auto Args = llvm::ArrayRef(CE->getArgs(), CE->getNumArgs());
687  auto NonNullArgs = collectNonNullArgs(F->getDecl(), Args);
688  unsigned Offset = 0;
689  unsigned Index = 0;
690  for (const Expr *Arg : Args) {
691  if (NonNullArgs[Index] && Arg->getType()->isPointerType()) {
692  const Pointer &ArgPtr = S.Stk.peek<Pointer>(ArgSize - Offset);
693  if (ArgPtr.isZero()) {
694  const SourceLocation &Loc = S.Current->getLocation(OpPC);
695  S.CCEDiag(Loc, diag::note_non_null_attribute_failed);
696  return false;
697  }
698  }
699 
700  Offset += align(primSize(S.Ctx.classify(Arg).value_or(PT_Ptr)));
701  ++Index;
702  }
703  return true;
704 }
705 
706 bool Interpret(InterpState &S, APValue &Result) {
707  // The current stack frame when we started Interpret().
708  // This is being used by the ops to determine wheter
709  // to return from this function and thus terminate
710  // interpretation.
711  const InterpFrame *StartFrame = S.Current;
712  assert(!S.Current->isRoot());
713  CodePtr PC = S.Current->getPC();
714 
715  // Empty program.
716  if (!PC)
717  return true;
718 
719  for (;;) {
720  auto Op = PC.read<Opcode>();
721  CodePtr OpPC = PC;
722 
723  switch (Op) {
724 #define GET_INTERP
725 #include "Opcodes.inc"
726 #undef GET_INTERP
727  }
728  }
729 }
730 
731 } // namespace interp
732 } // namespace clang
Defines the clang::ASTContext interface.
static char ID
Definition: Arena.cpp:183
Defines the clang::Expr interface and subclasses for C++ expressions.
unsigned Offset
Definition: Format.cpp:2978
static bool Jmp(InterpState &S, CodePtr &PC, int32_t Offset)
Definition: Interp.cpp:41
static bool CheckActive(InterpState &S, CodePtr OpPC, const Pointer &Ptr, AccessKinds AK)
Definition: Interp.cpp:124
static bool CheckGlobal(InterpState &S, CodePtr OpPC, const Pointer &Ptr)
Definition: Interp.cpp:176
static bool CheckTemporary(InterpState &S, CodePtr OpPC, const Pointer &Ptr, AccessKinds AK)
Definition: Interp.cpp:156
static bool Jt(InterpState &S, CodePtr &PC, int32_t Offset)
Definition: Interp.cpp:46
static void diagnoseNonConstVariable(InterpState &S, CodePtr OpPC, const ValueDecl *VD)
Definition: Interp.cpp:92
static bool RetValue(InterpState &S, CodePtr &Pt, APValue &Result)
Definition: Interp.cpp:33
static bool diagnoseUnknownDecl(InterpState &S, CodePtr OpPC, const ValueDecl *D)
Definition: Interp.cpp:69
static bool Jf(InterpState &S, CodePtr &PC, int32_t Offset)
Definition: Interp.cpp:53
static void diagnoseMissingInitializer(InterpState &S, CodePtr OpPC, const ValueDecl *VD)
Definition: Interp.cpp:60
#define TYPE_SWITCH(Expr, B)
Definition: PrimType.h:117
SourceLocation Loc
Definition: SemaObjC.cpp:755
APValue - This class implements a discriminated union of [uninitialized] [APSInt] [APFloat],...
Definition: APValue.h:122
Represents a static or instance method of a struct/union/class.
Definition: DeclCXX.h:2060
CallExpr - Represents a function call (C99 6.5.2.2, C++ [expr.call]).
Definition: Expr.h:2872
Expr ** getArgs()
Retrieve the call arguments.
Definition: Expr.h:3053
unsigned getNumArgs() const
getNumArgs - Return the number of actual arguments to this call.
Definition: Expr.h:3050
A reference to a declared variable, function, enum, etc.
Definition: Expr.h:1260
ValueDecl * getDecl()
Definition: Expr.h:1328
bool isInvalidDecl() const
Definition: DeclBase.h:594
SourceLocation getLocation() const
Definition: DeclBase.h:445
virtual SourceRange getSourceRange() const LLVM_READONLY
Source range that this declaration covers.
Definition: DeclBase.h:433
This represents one expression.
Definition: Expr.h:110
FPOptions getFPFeaturesInEffect(const LangOptions &LO) const
Returns the set of floating point options that apply to this expression.
Definition: Expr.cpp:3903
LangOptions::FPExceptionModeKind getExceptionMode() const
Definition: LangOptions.h:902
RoundingMode getRoundingMode() const
Definition: LangOptions.h:890
Represents a member of a struct/union/class.
Definition: Decl.h:3060
Represents a function declaration or definition.
Definition: Decl.h:1972
StorageClass getStorageClass() const
Returns the storage class as written in the source.
Definition: Decl.h:2800
bool isConstexpr() const
Whether this is a (C++11) constexpr function or constexpr constructor.
Definition: Decl.h:2435
bool isPureVirtual() const
Whether this virtual function is pure, i.e.
Definition: Decl.h:2325
bool isDefined(const FunctionDecl *&Definition, bool CheckForPendingFriendDefinition=false) const
Returns true if the function has a definition that does not need to be instantiated.
Definition: Decl.cpp:3207
@ FPE_Ignore
Assume that floating-point exceptions are masked.
Definition: LangOptions.h:289
PointerType - C99 6.7.5.1 - Pointer Declarators.
Definition: Type.h:3151
A (possibly-)qualified type.
Definition: Type.h:940
bool isConstQualified() const
Determine whether this type is const-qualified.
Definition: Type.h:7444
Base for LValueReferenceType and RValueReferenceType.
Definition: Type.h:3392
const LangOptions & getLangOpts() const
Definition: Sema.h:519
Encodes a location in the source.
bool isSignedIntegerOrEnumerationType() const
Determines whether this is an integer type that is signed or an enumeration types whose underlying ty...
Definition: Type.cpp:2166
bool isUnsignedIntegerOrEnumerationType() const
Determines whether this is an integer type that is unsigned or an enumeration types whose underlying ...
Definition: Type.cpp:2216
QualType getPointeeType() const
If this is a pointer, ObjC object pointer, or block pointer, this returns the respective pointee.
Definition: Type.cpp:705
bool isIntegralOrEnumerationType() const
Determine whether this type is an integral or enumeration type.
Definition: Type.h:8054
const T * getAs() const
Member-template getAs<specific type>'.
Definition: Type.h:8160
Represent the declaration of a variable (in which case it is an lvalue) a function (in which case it ...
Definition: Decl.h:707
QualType getType() const
Definition: Decl.h:718
Represents a variable declaration or definition.
Definition: Decl.h:919
bool hasGlobalStorage() const
Returns true for all variables that do not have local storage.
Definition: Decl.h:1214
Pointer into the code segment.
Definition: Source.h:30
std::enable_if_t<!std::is_pointer< T >::value, T > read()
Reads data and advances the pointer.
Definition: Source.h:55
Bytecode function.
Definition: Function.h:77
bool isBuiltin() const
Definition: Function.h:183
bool isVirtual() const
Checks if the function is virtual.
Definition: Function.cpp:47
const FunctionDecl * getDecl() const
Returns the original FunctionDecl.
Definition: Function.h:92
bool isUnevaluatedBuiltin() const
Definition: Function.h:185
bool isConstexpr() const
Checks if the function is valid to call in constexpr.
Definition: Function.h:135
unsigned getNumWrittenParams() const
Returns the number of parameter this function takes when it's called, i.e excluding the instance poin...
Definition: Function.h:191
bool isVariadic() const
Definition: Function.h:179
Frame storing local variables.
Definition: InterpFrame.h:28
Interpreter context.
Definition: InterpState.h:35
A pointer to a memory block, live or dead.
Definition: Pointer.h:80
bool isInitialized() const
Checks if an object was initialized.
Definition: Pointer.cpp:220
bool isStatic() const
Checks if the storage is static.
Definition: Pointer.h:444
bool isDummy() const
Checks if the pointer points to a dummy value.
Definition: Pointer.h:490
bool isExtern() const
Checks if the storage is extern.
Definition: Pointer.h:438
bool isActive() const
Checks if the object is active.
Definition: Pointer.h:482
bool isConst() const
Checks if an object or a subfield is mutable.
Definition: Pointer.h:501
bool isMutable() const
Checks if the field is mutable.
Definition: Pointer.h:462
bool isUnknownSizeArray() const
Checks if the structure is an array of unknown size.
Definition: Pointer.h:386
const Descriptor * getDeclDesc() const
Accessor for information about the declaration site.
Definition: Pointer.h:265
bool isIntegralPointer() const
Definition: Pointer.h:422
QualType getType() const
Returns the type of the innermost field.
Definition: Pointer.h:315
bool isLive() const
Checks if the pointer is live.
Definition: Pointer.h:249
bool isStaticTemporary() const
Checks if the storage is a static temporary.
Definition: Pointer.h:459
Pointer getBase() const
Returns a pointer to the object of which this pointer is a field.
Definition: Pointer.h:285
bool isZero() const
Checks if the pointer is null.
Definition: Pointer.h:242
bool isOnePastEnd() const
Checks if the index is one past end.
Definition: Pointer.h:551
bool isElementPastEnd() const
Checks if the pointer is an out-of-bounds element pointer.
Definition: Pointer.h:563
bool isBlockPointer() const
Definition: Pointer.h:421
const Block * block() const
Definition: Pointer.h:530
bool isTemporary() const
Checks if the storage is temporary.
Definition: Pointer.h:451
std::optional< unsigned > getDeclID() const
Returns the declaration ID.
Definition: Pointer.h:508
SourceLocation getDeclLoc() const
Definition: Pointer.h:273
const FieldDecl * getField() const
Returns the field information.
Definition: Pointer.h:432
bool isField() const
Checks if the item is a field in an object.
Definition: Pointer.h:255
Structure/Class descriptor.
Definition: Record.h:25
bool isUnion() const
Checks if the record is a union.
Definition: Record.h:56
const Field * getField(const FieldDecl *FD) const
Returns a field.
Definition: Record.cpp:39
unsigned getNumFields() const
Definition: Record.h:81
Describes the statement/declaration an opcode was generated from.
Definition: Source.h:72
const Expr * asExpr() const
Definition: Source.cpp:35
bool CheckInit(InterpState &S, CodePtr OpPC, const Pointer &Ptr)
Checks if a value can be initialized.
Definition: Interp.cpp:503
bool Interpret(InterpState &S, APValue &Result)
Interpreter entry point.
Definition: Interp.cpp:706
bool CheckDeclRef(InterpState &S, CodePtr OpPC, const DeclRefExpr *DR)
We aleady know the given DeclRefExpr is invalid for some reason, now figure out why and print appropr...
Definition: Interp.cpp:658
bool CheckCallDepth(InterpState &S, CodePtr OpPC)
Checks if calling the currently active function would exceed the allowed call depth.
Definition: Interp.cpp:571
bool CheckThis(InterpState &S, CodePtr OpPC, const Pointer &This)
Checks the 'this' pointer.
Definition: Interp.cpp:582
bool CheckConstant(InterpState &S, CodePtr OpPC, const Descriptor *Desc)
Checks if the Descriptor is of a constexpr or const global variable.
Definition: Interp.cpp:299
bool CheckMutable(InterpState &S, CodePtr OpPC, const Pointer &Ptr)
Checks if a pointer points to a mutable field.
Definition: Interp.cpp:398
bool CheckSubobject(InterpState &S, CodePtr OpPC, const Pointer &Ptr, CheckSubobjectKind CSK)
Checks if Ptr is a one-past-the-end pointer.
Definition: Interp.cpp:366
bool CheckInitialized(InterpState &S, CodePtr OpPC, const Pointer &Ptr, AccessKinds AK)
Definition: Interp.cpp:411
constexpr size_t align(size_t Size)
Aligns a size to the pointer alignment.
Definition: PrimType.h:99
bool CheckRange(InterpState &S, CodePtr OpPC, const Pointer &Ptr, AccessKinds AK)
Checks if a pointer is in range.
Definition: Interp.cpp:348
bool CheckPure(InterpState &S, CodePtr OpPC, const CXXMethodDecl *MD)
Checks if a method is pure virtual.
Definition: Interp.cpp:600
bool This(InterpState &S, CodePtr OpPC)
Definition: Interp.h:1903
bool CheckLive(InterpState &S, CodePtr OpPC, const Pointer &Ptr, AccessKinds AK)
Checks if a pointer is live and accessible.
Definition: Interp.cpp:269
static void popArg(InterpState &S, const Expr *Arg)
Definition: Interp.cpp:192
PrimType
Enumeration of the primitive types of the VM.
Definition: PrimType.h:32
bool CheckStore(InterpState &S, CodePtr OpPC, const Pointer &Ptr)
Checks if a value can be stored in a block.
Definition: Interp.cpp:477
bool CheckNull(InterpState &S, CodePtr OpPC, const Pointer &Ptr, CheckSubobjectKind CSK)
Checks if a pointer is null.
Definition: Interp.cpp:339
bool CheckLoad(InterpState &S, CodePtr OpPC, const Pointer &Ptr)
Checks if a value can be loaded from a block.
Definition: Interp.cpp:454
bool CheckArray(InterpState &S, CodePtr OpPC, const Pointer &Ptr)
Checks if the array is offsetable.
Definition: Interp.cpp:261
bool CheckGlobalInitialized(InterpState &S, CodePtr OpPC, const Pointer &Ptr)
Check if a global variable is initialized.
Definition: Interp.cpp:437
bool CheckNonNullArgs(InterpState &S, CodePtr OpPC, const Function *F, const CallExpr *CE, unsigned ArgSize)
Checks if all the arguments annotated as 'nonnull' are in fact not null.
Definition: Interp.cpp:684
bool CheckDummy(InterpState &S, CodePtr OpPC, const Pointer &Ptr, AccessKinds AK)
Checks if a pointer is a dummy pointer.
Definition: Interp.cpp:663
void cleanupAfterFunctionCall(InterpState &S, CodePtr OpPC)
Definition: Interp.cpp:197
llvm::BitVector collectNonNullArgs(const FunctionDecl *F, const llvm::ArrayRef< const Expr * > &Args)
size_t primSize(PrimType Type)
Returns the size of a primitive type in bytes.
Definition: PrimType.cpp:22
bool CheckExtern(InterpState &S, CodePtr OpPC, const Pointer &Ptr)
Checks if the variable has externally defined storage.
Definition: Interp.cpp:247
bool CheckCallable(InterpState &S, CodePtr OpPC, const Function *F)
Checks if a method can be called.
Definition: Interp.cpp:511
bool CheckConst(InterpState &S, CodePtr OpPC, const Pointer &Ptr)
Checks if a pointer points to const storage.
Definition: Interp.cpp:376
bool CheckInvoke(InterpState &S, CodePtr OpPC, const Pointer &Ptr)
Checks if a method can be invoked on an object.
Definition: Interp.cpp:493
bool CheckFloatResult(InterpState &S, CodePtr OpPC, const Floating &Result, APFloat::opStatus Status)
Checks if the result of a floating-point operation is valid in the current context.
Definition: Interp.cpp:609
The JSON file list parser is used to communicate input to InstallAPI.
@ SC_Extern
Definition: Specifiers.h:248
CheckSubobjectKind
The order of this enum is important for diagnostics.
Definition: State.h:40
@ CSK_Field
Definition: State.h:43
AccessKinds
Kinds of access we can perform on an object, for diagnostics.
Definition: State.h:26
@ AK_Increment
Definition: State.h:30
@ AK_Read
Definition: State.h:27
@ AK_Assign
Definition: State.h:29
@ AK_MemberCall
Definition: State.h:32
@ AK_Decrement
Definition: State.h:31
const FunctionProtoType * T
#define bool
Definition: stdbool.h:24
Describes a memory block created by an allocation site.
Definition: Descriptor.h:91
const ValueDecl * asValueDecl() const
Definition: Descriptor.h:176
QualType getType() const
Definition: Descriptor.cpp:349
const VarDecl * asVarDecl() const
Definition: Descriptor.h:180