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 <limits> 11 #include <vector> 12 #include "Function.h" 13 #include "InterpFrame.h" 14 #include "InterpStack.h" 15 #include "Opcode.h" 16 #include "PrimType.h" 17 #include "Program.h" 18 #include "State.h" 19 #include "clang/AST/ASTContext.h" 20 #include "clang/AST/ASTDiagnostic.h" 21 #include "clang/AST/CXXInheritance.h" 22 #include "clang/AST/Expr.h" 23 #include "clang/AST/ExprCXX.h" 24 #include "llvm/ADT/APSInt.h" 25 26 using namespace clang; 27 using namespace clang::interp; 28 29 static bool RetValue(InterpState &S, CodePtr &Pt, APValue &Result) { 30 llvm::report_fatal_error("Interpreter cannot return values"); 31 } 32 33 //===----------------------------------------------------------------------===// 34 // Jmp, Jt, Jf 35 //===----------------------------------------------------------------------===// 36 37 static bool Jmp(InterpState &S, CodePtr &PC, int32_t Offset) { 38 PC += Offset; 39 return true; 40 } 41 42 static bool Jt(InterpState &S, CodePtr &PC, int32_t Offset) { 43 if (S.Stk.pop<bool>()) { 44 PC += Offset; 45 } 46 return true; 47 } 48 49 static bool Jf(InterpState &S, CodePtr &PC, int32_t Offset) { 50 if (!S.Stk.pop<bool>()) { 51 PC += Offset; 52 } 53 return true; 54 } 55 56 static void diagnoseNonConstVariable(InterpState &S, CodePtr OpPC, 57 const ValueDecl *VD) { 58 if (!S.getLangOpts().CPlusPlus) 59 return; 60 61 const SourceInfo &Loc = S.Current->getSource(OpPC); 62 63 if (VD->getType()->isIntegralOrEnumerationType()) 64 S.FFDiag(Loc, diag::note_constexpr_ltor_non_const_int, 1) << VD; 65 else 66 S.FFDiag(Loc, 67 S.getLangOpts().CPlusPlus11 68 ? diag::note_constexpr_ltor_non_constexpr 69 : diag::note_constexpr_ltor_non_integral, 70 1) 71 << VD << VD->getType(); 72 S.Note(VD->getLocation(), diag::note_declared_at); 73 } 74 75 static bool CheckActive(InterpState &S, CodePtr OpPC, const Pointer &Ptr, 76 AccessKinds AK) { 77 if (Ptr.isActive()) 78 return true; 79 80 // Get the inactive field descriptor. 81 const FieldDecl *InactiveField = Ptr.getField(); 82 83 // Walk up the pointer chain to find the union which is not active. 84 Pointer U = Ptr.getBase(); 85 while (!U.isActive()) { 86 U = U.getBase(); 87 } 88 89 // Find the active field of the union. 90 const Record *R = U.getRecord(); 91 assert(R && R->isUnion() && "Not a union"); 92 const FieldDecl *ActiveField = nullptr; 93 for (unsigned I = 0, N = R->getNumFields(); I < N; ++I) { 94 const Pointer &Field = U.atField(R->getField(I)->Offset); 95 if (Field.isActive()) { 96 ActiveField = Field.getField(); 97 break; 98 } 99 } 100 101 const SourceInfo &Loc = S.Current->getSource(OpPC); 102 S.FFDiag(Loc, diag::note_constexpr_access_inactive_union_member) 103 << AK << InactiveField << !ActiveField << ActiveField; 104 return false; 105 } 106 107 static bool CheckTemporary(InterpState &S, CodePtr OpPC, const Pointer &Ptr, 108 AccessKinds AK) { 109 if (auto ID = Ptr.getDeclID()) { 110 if (!Ptr.isStaticTemporary()) 111 return true; 112 113 if (Ptr.getDeclDesc()->getType().isConstQualified()) 114 return true; 115 116 if (S.P.getCurrentDecl() == ID) 117 return true; 118 119 const SourceInfo &E = S.Current->getSource(OpPC); 120 S.FFDiag(E, diag::note_constexpr_access_static_temporary, 1) << AK; 121 S.Note(Ptr.getDeclLoc(), diag::note_constexpr_temporary_here); 122 return false; 123 } 124 return true; 125 } 126 127 static bool CheckGlobal(InterpState &S, CodePtr OpPC, const Pointer &Ptr) { 128 if (auto ID = Ptr.getDeclID()) { 129 if (!Ptr.isStatic()) 130 return true; 131 132 if (S.P.getCurrentDecl() == ID) 133 return true; 134 135 S.FFDiag(S.Current->getLocation(OpPC), diag::note_constexpr_modify_global); 136 return false; 137 } 138 return true; 139 } 140 141 namespace clang { 142 namespace interp { 143 static void popArg(InterpState &S, const Expr *Arg) { 144 PrimType Ty = S.getContext().classify(Arg->getType()).value_or(PT_Ptr); 145 TYPE_SWITCH(Ty, S.Stk.discard<T>()); 146 } 147 148 void cleanupAfterFunctionCall(InterpState &S, CodePtr OpPC) { 149 assert(S.Current); 150 const Function *CurFunc = S.Current->getFunction(); 151 assert(CurFunc); 152 153 if (CurFunc->isUnevaluatedBuiltin()) 154 return; 155 156 // Some builtin functions require us to only look at the call site, since 157 // the classified parameter types do not match. 158 if (CurFunc->isBuiltin()) { 159 const auto *CE = 160 cast<CallExpr>(S.Current->Caller->getExpr(S.Current->getRetPC())); 161 for (int32_t I = CE->getNumArgs() - 1; I >= 0; --I) { 162 const Expr *A = CE->getArg(I); 163 popArg(S, A); 164 } 165 return; 166 } 167 168 if (S.Current->Caller && CurFunc->isVariadic()) { 169 // CallExpr we're look for is at the return PC of the current function, i.e. 170 // in the caller. 171 // This code path should be executed very rarely. 172 const auto *CE = 173 cast<CallExpr>(S.Current->Caller->getExpr(S.Current->getRetPC())); 174 unsigned FixedParams = CurFunc->getNumParams(); 175 int32_t ArgsToPop = CE->getNumArgs() - FixedParams; 176 assert(ArgsToPop >= 0); 177 for (int32_t I = ArgsToPop - 1; I >= 0; --I) { 178 const Expr *A = CE->getArg(FixedParams + I); 179 popArg(S, A); 180 } 181 } 182 // And in any case, remove the fixed parameters (the non-variadic ones) 183 // at the end. 184 S.Current->popArgs(); 185 } 186 187 bool CheckExtern(InterpState &S, CodePtr OpPC, const Pointer &Ptr) { 188 if (!Ptr.isExtern()) 189 return true; 190 191 if (!S.checkingPotentialConstantExpression() && S.getLangOpts().CPlusPlus) { 192 const auto *VD = Ptr.getDeclDesc()->asValueDecl(); 193 diagnoseNonConstVariable(S, OpPC, VD); 194 } 195 return false; 196 } 197 198 bool CheckArray(InterpState &S, CodePtr OpPC, const Pointer &Ptr) { 199 if (!Ptr.isUnknownSizeArray()) 200 return true; 201 const SourceInfo &E = S.Current->getSource(OpPC); 202 S.FFDiag(E, diag::note_constexpr_unsized_array_indexed); 203 return false; 204 } 205 206 bool CheckLive(InterpState &S, CodePtr OpPC, const Pointer &Ptr, 207 AccessKinds AK) { 208 if (Ptr.isZero()) { 209 const auto &Src = S.Current->getSource(OpPC); 210 211 if (Ptr.isField()) 212 S.FFDiag(Src, diag::note_constexpr_null_subobject) << CSK_Field; 213 else 214 S.FFDiag(Src, diag::note_constexpr_access_null) << AK; 215 216 return false; 217 } 218 219 if (!Ptr.isLive()) { 220 const auto &Src = S.Current->getSource(OpPC); 221 bool IsTemp = Ptr.isTemporary(); 222 223 S.FFDiag(Src, diag::note_constexpr_lifetime_ended, 1) << AK << !IsTemp; 224 225 if (IsTemp) 226 S.Note(Ptr.getDeclLoc(), diag::note_constexpr_temporary_here); 227 else 228 S.Note(Ptr.getDeclLoc(), diag::note_declared_at); 229 230 return false; 231 } 232 233 return true; 234 } 235 236 bool CheckConstant(InterpState &S, CodePtr OpPC, const Descriptor *Desc) { 237 assert(Desc); 238 239 auto IsConstType = [&S](const VarDecl *VD) -> bool { 240 if (VD->isConstexpr()) 241 return true; 242 243 if (S.getLangOpts().CPlusPlus && !S.getLangOpts().CPlusPlus11) 244 return false; 245 246 QualType T = VD->getType(); 247 if (T.isConstQualified()) 248 return true; 249 250 if (const auto *RT = T->getAs<ReferenceType>()) 251 return RT->getPointeeType().isConstQualified(); 252 253 if (const auto *PT = T->getAs<PointerType>()) 254 return PT->getPointeeType().isConstQualified(); 255 256 return false; 257 }; 258 259 if (const auto *D = Desc->asValueDecl()) { 260 if (const auto *VD = dyn_cast<VarDecl>(D); 261 VD && VD->hasGlobalStorage() && !IsConstType(VD)) { 262 diagnoseNonConstVariable(S, OpPC, VD); 263 return S.inConstantContext(); 264 } 265 } 266 267 return true; 268 } 269 270 static bool CheckConstant(InterpState &S, CodePtr OpPC, const Pointer &Ptr) { 271 return CheckConstant(S, OpPC, Ptr.getDeclDesc()); 272 } 273 274 bool CheckDummy(InterpState &S, CodePtr OpPC, const Pointer &Ptr) { 275 return !Ptr.isZero() && !Ptr.isDummy(); 276 } 277 278 bool CheckNull(InterpState &S, CodePtr OpPC, const Pointer &Ptr, 279 CheckSubobjectKind CSK) { 280 if (!Ptr.isZero()) 281 return true; 282 const SourceInfo &Loc = S.Current->getSource(OpPC); 283 S.FFDiag(Loc, diag::note_constexpr_null_subobject) << CSK; 284 return false; 285 } 286 287 bool CheckRange(InterpState &S, CodePtr OpPC, const Pointer &Ptr, 288 AccessKinds AK) { 289 if (!Ptr.isOnePastEnd()) 290 return true; 291 const SourceInfo &Loc = S.Current->getSource(OpPC); 292 S.FFDiag(Loc, diag::note_constexpr_access_past_end) << AK; 293 return false; 294 } 295 296 bool CheckRange(InterpState &S, CodePtr OpPC, const Pointer &Ptr, 297 CheckSubobjectKind CSK) { 298 if (!Ptr.isElementPastEnd()) 299 return true; 300 const SourceInfo &Loc = S.Current->getSource(OpPC); 301 S.FFDiag(Loc, diag::note_constexpr_past_end_subobject) << CSK; 302 return false; 303 } 304 305 bool CheckSubobject(InterpState &S, CodePtr OpPC, const Pointer &Ptr, 306 CheckSubobjectKind CSK) { 307 if (!Ptr.isOnePastEnd()) 308 return true; 309 310 const SourceInfo &Loc = S.Current->getSource(OpPC); 311 S.FFDiag(Loc, diag::note_constexpr_past_end_subobject) << CSK; 312 return false; 313 } 314 315 bool CheckConst(InterpState &S, CodePtr OpPC, const Pointer &Ptr) { 316 assert(Ptr.isLive() && "Pointer is not live"); 317 if (!Ptr.isConst()) 318 return true; 319 320 // The This pointer is writable in constructors and destructors, 321 // even if isConst() returns true. 322 if (const Function *Func = S.Current->getFunction(); 323 Func && (Func->isConstructor() || Func->isDestructor()) && 324 Ptr.block() == S.Current->getThis().block()) { 325 return true; 326 } 327 328 const QualType Ty = Ptr.getType(); 329 const SourceInfo &Loc = S.Current->getSource(OpPC); 330 S.FFDiag(Loc, diag::note_constexpr_modify_const_type) << Ty; 331 return false; 332 } 333 334 bool CheckMutable(InterpState &S, CodePtr OpPC, const Pointer &Ptr) { 335 assert(Ptr.isLive() && "Pointer is not live"); 336 if (!Ptr.isMutable()) { 337 return true; 338 } 339 340 const SourceInfo &Loc = S.Current->getSource(OpPC); 341 const FieldDecl *Field = Ptr.getField(); 342 S.FFDiag(Loc, diag::note_constexpr_access_mutable, 1) << AK_Read << Field; 343 S.Note(Field->getLocation(), diag::note_declared_at); 344 return false; 345 } 346 347 bool CheckInitialized(InterpState &S, CodePtr OpPC, const Pointer &Ptr, 348 AccessKinds AK) { 349 if (Ptr.isInitialized()) 350 return true; 351 352 if (!S.checkingPotentialConstantExpression()) { 353 S.FFDiag(S.Current->getSource(OpPC), diag::note_constexpr_access_uninit) 354 << AK << /*uninitialized=*/true << S.Current->getRange(OpPC); 355 } 356 return false; 357 } 358 359 bool CheckLoad(InterpState &S, CodePtr OpPC, const Pointer &Ptr) { 360 if (!CheckLive(S, OpPC, Ptr, AK_Read)) 361 return false; 362 if (!CheckConstant(S, OpPC, Ptr)) 363 return false; 364 365 if (!CheckDummy(S, OpPC, Ptr)) 366 return false; 367 if (!CheckExtern(S, OpPC, Ptr)) 368 return false; 369 if (!CheckRange(S, OpPC, Ptr, AK_Read)) 370 return false; 371 if (!CheckInitialized(S, OpPC, Ptr, AK_Read)) 372 return false; 373 if (!CheckActive(S, OpPC, Ptr, AK_Read)) 374 return false; 375 if (!CheckTemporary(S, OpPC, Ptr, AK_Read)) 376 return false; 377 if (!CheckMutable(S, OpPC, Ptr)) 378 return false; 379 return true; 380 } 381 382 bool CheckStore(InterpState &S, CodePtr OpPC, const Pointer &Ptr) { 383 if (!CheckLive(S, OpPC, Ptr, AK_Assign)) 384 return false; 385 if (!CheckExtern(S, OpPC, Ptr)) 386 return false; 387 if (!CheckRange(S, OpPC, Ptr, AK_Assign)) 388 return false; 389 if (!CheckGlobal(S, OpPC, Ptr)) 390 return false; 391 if (!CheckConst(S, OpPC, Ptr)) 392 return false; 393 return true; 394 } 395 396 bool CheckInvoke(InterpState &S, CodePtr OpPC, const Pointer &Ptr) { 397 if (!CheckLive(S, OpPC, Ptr, AK_MemberCall)) 398 return false; 399 if (!CheckExtern(S, OpPC, Ptr)) 400 return false; 401 if (!CheckRange(S, OpPC, Ptr, AK_MemberCall)) 402 return false; 403 return true; 404 } 405 406 bool CheckInit(InterpState &S, CodePtr OpPC, const Pointer &Ptr) { 407 if (!CheckLive(S, OpPC, Ptr, AK_Assign)) 408 return false; 409 if (!CheckRange(S, OpPC, Ptr, AK_Assign)) 410 return false; 411 return true; 412 } 413 414 bool CheckCallable(InterpState &S, CodePtr OpPC, const Function *F) { 415 416 if (F->isVirtual() && !S.getLangOpts().CPlusPlus20) { 417 const SourceLocation &Loc = S.Current->getLocation(OpPC); 418 S.CCEDiag(Loc, diag::note_constexpr_virtual_call); 419 return false; 420 } 421 422 if (!F->isConstexpr()) { 423 const SourceLocation &Loc = S.Current->getLocation(OpPC); 424 if (S.getLangOpts().CPlusPlus11) { 425 const FunctionDecl *DiagDecl = F->getDecl(); 426 427 // If this function is not constexpr because it is an inherited 428 // non-constexpr constructor, diagnose that directly. 429 const auto *CD = dyn_cast<CXXConstructorDecl>(DiagDecl); 430 if (CD && CD->isInheritingConstructor()) { 431 const auto *Inherited = CD->getInheritedConstructor().getConstructor(); 432 if (!Inherited->isConstexpr()) 433 DiagDecl = CD = Inherited; 434 } 435 436 // FIXME: If DiagDecl is an implicitly-declared special member function 437 // or an inheriting constructor, we should be much more explicit about why 438 // it's not constexpr. 439 if (CD && CD->isInheritingConstructor()) { 440 S.FFDiag(Loc, diag::note_constexpr_invalid_inhctor, 1) 441 << CD->getInheritedConstructor().getConstructor()->getParent(); 442 S.Note(DiagDecl->getLocation(), diag::note_declared_at); 443 } else { 444 // Don't emit anything if the function isn't defined and we're checking 445 // for a constant expression. It might be defined at the point we're 446 // actually calling it. 447 if (!DiagDecl->isDefined() && S.checkingPotentialConstantExpression()) 448 return false; 449 450 S.FFDiag(Loc, diag::note_constexpr_invalid_function, 1) 451 << DiagDecl->isConstexpr() << (bool)CD << DiagDecl; 452 S.Note(DiagDecl->getLocation(), diag::note_declared_at); 453 } 454 } else { 455 S.FFDiag(Loc, diag::note_invalid_subexpr_in_const_expr); 456 } 457 return false; 458 } 459 460 return true; 461 } 462 463 bool CheckCallDepth(InterpState &S, CodePtr OpPC) { 464 if ((S.Current->getDepth() + 1) > S.getLangOpts().ConstexprCallDepth) { 465 S.FFDiag(S.Current->getSource(OpPC), 466 diag::note_constexpr_depth_limit_exceeded) 467 << S.getLangOpts().ConstexprCallDepth; 468 return false; 469 } 470 471 return true; 472 } 473 474 bool CheckThis(InterpState &S, CodePtr OpPC, const Pointer &This) { 475 if (!This.isZero()) 476 return true; 477 478 const SourceInfo &Loc = S.Current->getSource(OpPC); 479 480 bool IsImplicit = false; 481 if (const auto *E = dyn_cast_if_present<CXXThisExpr>(Loc.asExpr())) 482 IsImplicit = E->isImplicit(); 483 484 if (S.getLangOpts().CPlusPlus11) 485 S.FFDiag(Loc, diag::note_constexpr_this) << IsImplicit; 486 else 487 S.FFDiag(Loc); 488 489 return false; 490 } 491 492 bool CheckPure(InterpState &S, CodePtr OpPC, const CXXMethodDecl *MD) { 493 if (!MD->isPureVirtual()) 494 return true; 495 const SourceInfo &E = S.Current->getSource(OpPC); 496 S.FFDiag(E, diag::note_constexpr_pure_virtual_call, 1) << MD; 497 S.Note(MD->getLocation(), diag::note_declared_at); 498 return false; 499 } 500 501 bool CheckPotentialReinterpretCast(InterpState &S, CodePtr OpPC, 502 const Pointer &Ptr) { 503 if (!S.inConstantContext()) 504 return true; 505 506 const SourceInfo &E = S.Current->getSource(OpPC); 507 S.CCEDiag(E, diag::note_constexpr_invalid_cast) 508 << 2 << S.getLangOpts().CPlusPlus << S.Current->getRange(OpPC); 509 return false; 510 } 511 512 bool CheckFloatResult(InterpState &S, CodePtr OpPC, const Floating &Result, 513 APFloat::opStatus Status) { 514 const SourceInfo &E = S.Current->getSource(OpPC); 515 516 // [expr.pre]p4: 517 // If during the evaluation of an expression, the result is not 518 // mathematically defined [...], the behavior is undefined. 519 // FIXME: C++ rules require us to not conform to IEEE 754 here. 520 if (Result.isNan()) { 521 S.CCEDiag(E, diag::note_constexpr_float_arithmetic) 522 << /*NaN=*/true << S.Current->getRange(OpPC); 523 return S.noteUndefinedBehavior(); 524 } 525 526 // In a constant context, assume that any dynamic rounding mode or FP 527 // exception state matches the default floating-point environment. 528 if (S.inConstantContext()) 529 return true; 530 531 FPOptions FPO = E.asExpr()->getFPFeaturesInEffect(S.Ctx.getLangOpts()); 532 533 if ((Status & APFloat::opInexact) && 534 FPO.getRoundingMode() == llvm::RoundingMode::Dynamic) { 535 // Inexact result means that it depends on rounding mode. If the requested 536 // mode is dynamic, the evaluation cannot be made in compile time. 537 S.FFDiag(E, diag::note_constexpr_dynamic_rounding); 538 return false; 539 } 540 541 if ((Status != APFloat::opOK) && 542 (FPO.getRoundingMode() == llvm::RoundingMode::Dynamic || 543 FPO.getExceptionMode() != LangOptions::FPE_Ignore || 544 FPO.getAllowFEnvAccess())) { 545 S.FFDiag(E, diag::note_constexpr_float_arithmetic_strict); 546 return false; 547 } 548 549 if ((Status & APFloat::opStatus::opInvalidOp) && 550 FPO.getExceptionMode() != LangOptions::FPE_Ignore) { 551 // There is no usefully definable result. 552 S.FFDiag(E); 553 return false; 554 } 555 556 return true; 557 } 558 559 /// We aleady know the given DeclRefExpr is invalid for some reason, 560 /// now figure out why and print appropriate diagnostics. 561 bool CheckDeclRef(InterpState &S, CodePtr OpPC, const DeclRefExpr *DR) { 562 const ValueDecl *D = DR->getDecl(); 563 const SourceInfo &E = S.Current->getSource(OpPC); 564 565 if (isa<ParmVarDecl>(D)) { 566 if (S.getLangOpts().CPlusPlus11) { 567 S.FFDiag(E, diag::note_constexpr_function_param_value_unknown) << D; 568 S.Note(D->getLocation(), diag::note_declared_at) << D->getSourceRange(); 569 } else { 570 S.FFDiag(E); 571 } 572 } else if (const auto *VD = dyn_cast<VarDecl>(D)) { 573 if (!VD->getType().isConstQualified()) { 574 diagnoseNonConstVariable(S, OpPC, VD); 575 return false; 576 } 577 578 // const, but no initializer. 579 if (!VD->getAnyInitializer()) { 580 S.FFDiag(E, diag::note_constexpr_var_init_unknown, 1) << VD; 581 S.Note(VD->getLocation(), diag::note_declared_at) << VD->getSourceRange(); 582 return false; 583 } 584 } 585 586 return false; 587 } 588 589 bool Interpret(InterpState &S, APValue &Result) { 590 // The current stack frame when we started Interpret(). 591 // This is being used by the ops to determine wheter 592 // to return from this function and thus terminate 593 // interpretation. 594 const InterpFrame *StartFrame = S.Current; 595 assert(!S.Current->isRoot()); 596 CodePtr PC = S.Current->getPC(); 597 598 // Empty program. 599 if (!PC) 600 return true; 601 602 for (;;) { 603 auto Op = PC.read<Opcode>(); 604 CodePtr OpPC = PC; 605 606 switch (Op) { 607 #define GET_INTERP 608 #include "Opcodes.inc" 609 #undef GET_INTERP 610 } 611 } 612 } 613 614 } // namespace interp 615 } // namespace clang 616