1 //===- Stmt.cpp - Statement AST Node Implementation -----------------------===// 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 // This file implements the Stmt class and statement subclasses. 10 // 11 //===----------------------------------------------------------------------===// 12 13 #include "clang/AST/Stmt.h" 14 #include "clang/AST/ASTContext.h" 15 #include "clang/AST/ASTDiagnostic.h" 16 #include "clang/AST/Decl.h" 17 #include "clang/AST/DeclGroup.h" 18 #include "clang/AST/Expr.h" 19 #include "clang/AST/ExprConcepts.h" 20 #include "clang/AST/ExprCXX.h" 21 #include "clang/AST/ExprObjC.h" 22 #include "clang/AST/ExprOpenMP.h" 23 #include "clang/AST/StmtCXX.h" 24 #include "clang/AST/StmtObjC.h" 25 #include "clang/AST/StmtOpenMP.h" 26 #include "clang/AST/Type.h" 27 #include "clang/Basic/CharInfo.h" 28 #include "clang/Basic/LLVM.h" 29 #include "clang/Basic/SourceLocation.h" 30 #include "clang/Basic/TargetInfo.h" 31 #include "clang/Lex/Token.h" 32 #include "llvm/ADT/SmallVector.h" 33 #include "llvm/ADT/StringExtras.h" 34 #include "llvm/ADT/StringRef.h" 35 #include "llvm/Support/Casting.h" 36 #include "llvm/Support/Compiler.h" 37 #include "llvm/Support/ErrorHandling.h" 38 #include "llvm/Support/MathExtras.h" 39 #include "llvm/Support/raw_ostream.h" 40 #include <algorithm> 41 #include <cassert> 42 #include <cstring> 43 #include <string> 44 #include <utility> 45 #include <type_traits> 46 47 using namespace clang; 48 49 static struct StmtClassNameTable { 50 const char *Name; 51 unsigned Counter; 52 unsigned Size; 53 } StmtClassInfo[Stmt::lastStmtConstant+1]; 54 55 static StmtClassNameTable &getStmtInfoTableEntry(Stmt::StmtClass E) { 56 static bool Initialized = false; 57 if (Initialized) 58 return StmtClassInfo[E]; 59 60 // Initialize the table on the first use. 61 Initialized = true; 62 #define ABSTRACT_STMT(STMT) 63 #define STMT(CLASS, PARENT) \ 64 StmtClassInfo[(unsigned)Stmt::CLASS##Class].Name = #CLASS; \ 65 StmtClassInfo[(unsigned)Stmt::CLASS##Class].Size = sizeof(CLASS); 66 #include "clang/AST/StmtNodes.inc" 67 68 return StmtClassInfo[E]; 69 } 70 71 void *Stmt::operator new(size_t bytes, const ASTContext& C, 72 unsigned alignment) { 73 return ::operator new(bytes, C, alignment); 74 } 75 76 const char *Stmt::getStmtClassName() const { 77 return getStmtInfoTableEntry((StmtClass) StmtBits.sClass).Name; 78 } 79 80 // Check that no statement / expression class is polymorphic. LLVM style RTTI 81 // should be used instead. If absolutely needed an exception can still be added 82 // here by defining the appropriate macro (but please don't do this). 83 #define STMT(CLASS, PARENT) \ 84 static_assert(!std::is_polymorphic<CLASS>::value, \ 85 #CLASS " should not be polymorphic!"); 86 #include "clang/AST/StmtNodes.inc" 87 88 // Check that no statement / expression class has a non-trival destructor. 89 // Statements and expressions are allocated with the BumpPtrAllocator from 90 // ASTContext and therefore their destructor is not executed. 91 #define STMT(CLASS, PARENT) \ 92 static_assert(std::is_trivially_destructible<CLASS>::value, \ 93 #CLASS " should be trivially destructible!"); 94 // FIXME: InitListExpr is not trivially destructible due to its ASTVector. 95 #define INITLISTEXPR(CLASS, PARENT) 96 #include "clang/AST/StmtNodes.inc" 97 98 void Stmt::PrintStats() { 99 // Ensure the table is primed. 100 getStmtInfoTableEntry(Stmt::NullStmtClass); 101 102 unsigned sum = 0; 103 llvm::errs() << "\n*** Stmt/Expr Stats:\n"; 104 for (int i = 0; i != Stmt::lastStmtConstant+1; i++) { 105 if (StmtClassInfo[i].Name == nullptr) continue; 106 sum += StmtClassInfo[i].Counter; 107 } 108 llvm::errs() << " " << sum << " stmts/exprs total.\n"; 109 sum = 0; 110 for (int i = 0; i != Stmt::lastStmtConstant+1; i++) { 111 if (StmtClassInfo[i].Name == nullptr) continue; 112 if (StmtClassInfo[i].Counter == 0) continue; 113 llvm::errs() << " " << StmtClassInfo[i].Counter << " " 114 << StmtClassInfo[i].Name << ", " << StmtClassInfo[i].Size 115 << " each (" << StmtClassInfo[i].Counter*StmtClassInfo[i].Size 116 << " bytes)\n"; 117 sum += StmtClassInfo[i].Counter*StmtClassInfo[i].Size; 118 } 119 120 llvm::errs() << "Total bytes = " << sum << "\n"; 121 } 122 123 void Stmt::addStmtClass(StmtClass s) { 124 ++getStmtInfoTableEntry(s).Counter; 125 } 126 127 bool Stmt::StatisticsEnabled = false; 128 void Stmt::EnableStatistics() { 129 StatisticsEnabled = true; 130 } 131 132 /// Skip no-op (attributed, compound) container stmts and skip captured 133 /// stmt at the top, if \a IgnoreCaptured is true. 134 Stmt *Stmt::IgnoreContainers(bool IgnoreCaptured) { 135 Stmt *S = this; 136 if (IgnoreCaptured) 137 if (auto CapS = dyn_cast_or_null<CapturedStmt>(S)) 138 S = CapS->getCapturedStmt(); 139 while (true) { 140 if (auto AS = dyn_cast_or_null<AttributedStmt>(S)) 141 S = AS->getSubStmt(); 142 else if (auto CS = dyn_cast_or_null<CompoundStmt>(S)) { 143 if (CS->size() != 1) 144 break; 145 S = CS->body_back(); 146 } else 147 break; 148 } 149 return S; 150 } 151 152 /// Strip off all label-like statements. 153 /// 154 /// This will strip off label statements, case statements, attributed 155 /// statements and default statements recursively. 156 const Stmt *Stmt::stripLabelLikeStatements() const { 157 const Stmt *S = this; 158 while (true) { 159 if (const auto *LS = dyn_cast<LabelStmt>(S)) 160 S = LS->getSubStmt(); 161 else if (const auto *SC = dyn_cast<SwitchCase>(S)) 162 S = SC->getSubStmt(); 163 else if (const auto *AS = dyn_cast<AttributedStmt>(S)) 164 S = AS->getSubStmt(); 165 else 166 return S; 167 } 168 } 169 170 namespace { 171 172 struct good {}; 173 struct bad {}; 174 175 // These silly little functions have to be static inline to suppress 176 // unused warnings, and they have to be defined to suppress other 177 // warnings. 178 static good is_good(good) { return good(); } 179 180 typedef Stmt::child_range children_t(); 181 template <class T> good implements_children(children_t T::*) { 182 return good(); 183 } 184 LLVM_ATTRIBUTE_UNUSED 185 static bad implements_children(children_t Stmt::*) { 186 return bad(); 187 } 188 189 typedef SourceLocation getBeginLoc_t() const; 190 template <class T> good implements_getBeginLoc(getBeginLoc_t T::*) { 191 return good(); 192 } 193 LLVM_ATTRIBUTE_UNUSED 194 static bad implements_getBeginLoc(getBeginLoc_t Stmt::*) { return bad(); } 195 196 typedef SourceLocation getLocEnd_t() const; 197 template <class T> good implements_getEndLoc(getLocEnd_t T::*) { 198 return good(); 199 } 200 LLVM_ATTRIBUTE_UNUSED 201 static bad implements_getEndLoc(getLocEnd_t Stmt::*) { return bad(); } 202 203 #define ASSERT_IMPLEMENTS_children(type) \ 204 (void) is_good(implements_children(&type::children)) 205 #define ASSERT_IMPLEMENTS_getBeginLoc(type) \ 206 (void)is_good(implements_getBeginLoc(&type::getBeginLoc)) 207 #define ASSERT_IMPLEMENTS_getEndLoc(type) \ 208 (void)is_good(implements_getEndLoc(&type::getEndLoc)) 209 210 } // namespace 211 212 /// Check whether the various Stmt classes implement their member 213 /// functions. 214 LLVM_ATTRIBUTE_UNUSED 215 static inline void check_implementations() { 216 #define ABSTRACT_STMT(type) 217 #define STMT(type, base) \ 218 ASSERT_IMPLEMENTS_children(type); \ 219 ASSERT_IMPLEMENTS_getBeginLoc(type); \ 220 ASSERT_IMPLEMENTS_getEndLoc(type); 221 #include "clang/AST/StmtNodes.inc" 222 } 223 224 Stmt::child_range Stmt::children() { 225 switch (getStmtClass()) { 226 case Stmt::NoStmtClass: llvm_unreachable("statement without class"); 227 #define ABSTRACT_STMT(type) 228 #define STMT(type, base) \ 229 case Stmt::type##Class: \ 230 return static_cast<type*>(this)->children(); 231 #include "clang/AST/StmtNodes.inc" 232 } 233 llvm_unreachable("unknown statement kind!"); 234 } 235 236 // Amusing macro metaprogramming hack: check whether a class provides 237 // a more specific implementation of getSourceRange. 238 // 239 // See also Expr.cpp:getExprLoc(). 240 namespace { 241 242 /// This implementation is used when a class provides a custom 243 /// implementation of getSourceRange. 244 template <class S, class T> 245 SourceRange getSourceRangeImpl(const Stmt *stmt, 246 SourceRange (T::*v)() const) { 247 return static_cast<const S*>(stmt)->getSourceRange(); 248 } 249 250 /// This implementation is used when a class doesn't provide a custom 251 /// implementation of getSourceRange. Overload resolution should pick it over 252 /// the implementation above because it's more specialized according to 253 /// function template partial ordering. 254 template <class S> 255 SourceRange getSourceRangeImpl(const Stmt *stmt, 256 SourceRange (Stmt::*v)() const) { 257 return SourceRange(static_cast<const S *>(stmt)->getBeginLoc(), 258 static_cast<const S *>(stmt)->getEndLoc()); 259 } 260 261 } // namespace 262 263 SourceRange Stmt::getSourceRange() const { 264 switch (getStmtClass()) { 265 case Stmt::NoStmtClass: llvm_unreachable("statement without class"); 266 #define ABSTRACT_STMT(type) 267 #define STMT(type, base) \ 268 case Stmt::type##Class: \ 269 return getSourceRangeImpl<type>(this, &type::getSourceRange); 270 #include "clang/AST/StmtNodes.inc" 271 } 272 llvm_unreachable("unknown statement kind!"); 273 } 274 275 SourceLocation Stmt::getBeginLoc() const { 276 // llvm::errs() << "getBeginLoc() for " << getStmtClassName() << "\n"; 277 switch (getStmtClass()) { 278 case Stmt::NoStmtClass: llvm_unreachable("statement without class"); 279 #define ABSTRACT_STMT(type) 280 #define STMT(type, base) \ 281 case Stmt::type##Class: \ 282 return static_cast<const type *>(this)->getBeginLoc(); 283 #include "clang/AST/StmtNodes.inc" 284 } 285 llvm_unreachable("unknown statement kind"); 286 } 287 288 SourceLocation Stmt::getEndLoc() const { 289 switch (getStmtClass()) { 290 case Stmt::NoStmtClass: llvm_unreachable("statement without class"); 291 #define ABSTRACT_STMT(type) 292 #define STMT(type, base) \ 293 case Stmt::type##Class: \ 294 return static_cast<const type *>(this)->getEndLoc(); 295 #include "clang/AST/StmtNodes.inc" 296 } 297 llvm_unreachable("unknown statement kind"); 298 } 299 300 int64_t Stmt::getID(const ASTContext &Context) const { 301 return Context.getAllocator().identifyKnownAlignedObject<Stmt>(this); 302 } 303 304 CompoundStmt::CompoundStmt(ArrayRef<Stmt *> Stmts, SourceLocation LB, 305 SourceLocation RB) 306 : Stmt(CompoundStmtClass), RBraceLoc(RB) { 307 CompoundStmtBits.NumStmts = Stmts.size(); 308 setStmts(Stmts); 309 CompoundStmtBits.LBraceLoc = LB; 310 } 311 312 void CompoundStmt::setStmts(ArrayRef<Stmt *> Stmts) { 313 assert(CompoundStmtBits.NumStmts == Stmts.size() && 314 "NumStmts doesn't fit in bits of CompoundStmtBits.NumStmts!"); 315 316 std::copy(Stmts.begin(), Stmts.end(), body_begin()); 317 } 318 319 CompoundStmt *CompoundStmt::Create(const ASTContext &C, ArrayRef<Stmt *> Stmts, 320 SourceLocation LB, SourceLocation RB) { 321 void *Mem = 322 C.Allocate(totalSizeToAlloc<Stmt *>(Stmts.size()), alignof(CompoundStmt)); 323 return new (Mem) CompoundStmt(Stmts, LB, RB); 324 } 325 326 CompoundStmt *CompoundStmt::CreateEmpty(const ASTContext &C, 327 unsigned NumStmts) { 328 void *Mem = 329 C.Allocate(totalSizeToAlloc<Stmt *>(NumStmts), alignof(CompoundStmt)); 330 CompoundStmt *New = new (Mem) CompoundStmt(EmptyShell()); 331 New->CompoundStmtBits.NumStmts = NumStmts; 332 return New; 333 } 334 335 const Expr *ValueStmt::getExprStmt() const { 336 const Stmt *S = this; 337 do { 338 if (const auto *E = dyn_cast<Expr>(S)) 339 return E; 340 341 if (const auto *LS = dyn_cast<LabelStmt>(S)) 342 S = LS->getSubStmt(); 343 else if (const auto *AS = dyn_cast<AttributedStmt>(S)) 344 S = AS->getSubStmt(); 345 else 346 llvm_unreachable("unknown kind of ValueStmt"); 347 } while (isa<ValueStmt>(S)); 348 349 return nullptr; 350 } 351 352 const char *LabelStmt::getName() const { 353 return getDecl()->getIdentifier()->getNameStart(); 354 } 355 356 AttributedStmt *AttributedStmt::Create(const ASTContext &C, SourceLocation Loc, 357 ArrayRef<const Attr*> Attrs, 358 Stmt *SubStmt) { 359 assert(!Attrs.empty() && "Attrs should not be empty"); 360 void *Mem = C.Allocate(totalSizeToAlloc<const Attr *>(Attrs.size()), 361 alignof(AttributedStmt)); 362 return new (Mem) AttributedStmt(Loc, Attrs, SubStmt); 363 } 364 365 AttributedStmt *AttributedStmt::CreateEmpty(const ASTContext &C, 366 unsigned NumAttrs) { 367 assert(NumAttrs > 0 && "NumAttrs should be greater than zero"); 368 void *Mem = C.Allocate(totalSizeToAlloc<const Attr *>(NumAttrs), 369 alignof(AttributedStmt)); 370 return new (Mem) AttributedStmt(EmptyShell(), NumAttrs); 371 } 372 373 std::string AsmStmt::generateAsmString(const ASTContext &C) const { 374 if (const auto *gccAsmStmt = dyn_cast<GCCAsmStmt>(this)) 375 return gccAsmStmt->generateAsmString(C); 376 if (const auto *msAsmStmt = dyn_cast<MSAsmStmt>(this)) 377 return msAsmStmt->generateAsmString(C); 378 llvm_unreachable("unknown asm statement kind!"); 379 } 380 381 StringRef AsmStmt::getOutputConstraint(unsigned i) const { 382 if (const auto *gccAsmStmt = dyn_cast<GCCAsmStmt>(this)) 383 return gccAsmStmt->getOutputConstraint(i); 384 if (const auto *msAsmStmt = dyn_cast<MSAsmStmt>(this)) 385 return msAsmStmt->getOutputConstraint(i); 386 llvm_unreachable("unknown asm statement kind!"); 387 } 388 389 const Expr *AsmStmt::getOutputExpr(unsigned i) const { 390 if (const auto *gccAsmStmt = dyn_cast<GCCAsmStmt>(this)) 391 return gccAsmStmt->getOutputExpr(i); 392 if (const auto *msAsmStmt = dyn_cast<MSAsmStmt>(this)) 393 return msAsmStmt->getOutputExpr(i); 394 llvm_unreachable("unknown asm statement kind!"); 395 } 396 397 StringRef AsmStmt::getInputConstraint(unsigned i) const { 398 if (const auto *gccAsmStmt = dyn_cast<GCCAsmStmt>(this)) 399 return gccAsmStmt->getInputConstraint(i); 400 if (const auto *msAsmStmt = dyn_cast<MSAsmStmt>(this)) 401 return msAsmStmt->getInputConstraint(i); 402 llvm_unreachable("unknown asm statement kind!"); 403 } 404 405 const Expr *AsmStmt::getInputExpr(unsigned i) const { 406 if (const auto *gccAsmStmt = dyn_cast<GCCAsmStmt>(this)) 407 return gccAsmStmt->getInputExpr(i); 408 if (const auto *msAsmStmt = dyn_cast<MSAsmStmt>(this)) 409 return msAsmStmt->getInputExpr(i); 410 llvm_unreachable("unknown asm statement kind!"); 411 } 412 413 StringRef AsmStmt::getClobber(unsigned i) const { 414 if (const auto *gccAsmStmt = dyn_cast<GCCAsmStmt>(this)) 415 return gccAsmStmt->getClobber(i); 416 if (const auto *msAsmStmt = dyn_cast<MSAsmStmt>(this)) 417 return msAsmStmt->getClobber(i); 418 llvm_unreachable("unknown asm statement kind!"); 419 } 420 421 /// getNumPlusOperands - Return the number of output operands that have a "+" 422 /// constraint. 423 unsigned AsmStmt::getNumPlusOperands() const { 424 unsigned Res = 0; 425 for (unsigned i = 0, e = getNumOutputs(); i != e; ++i) 426 if (isOutputPlusConstraint(i)) 427 ++Res; 428 return Res; 429 } 430 431 char GCCAsmStmt::AsmStringPiece::getModifier() const { 432 assert(isOperand() && "Only Operands can have modifiers."); 433 return isLetter(Str[0]) ? Str[0] : '\0'; 434 } 435 436 StringRef GCCAsmStmt::getClobber(unsigned i) const { 437 return getClobberStringLiteral(i)->getString(); 438 } 439 440 Expr *GCCAsmStmt::getOutputExpr(unsigned i) { 441 return cast<Expr>(Exprs[i]); 442 } 443 444 /// getOutputConstraint - Return the constraint string for the specified 445 /// output operand. All output constraints are known to be non-empty (either 446 /// '=' or '+'). 447 StringRef GCCAsmStmt::getOutputConstraint(unsigned i) const { 448 return getOutputConstraintLiteral(i)->getString(); 449 } 450 451 Expr *GCCAsmStmt::getInputExpr(unsigned i) { 452 return cast<Expr>(Exprs[i + NumOutputs]); 453 } 454 455 void GCCAsmStmt::setInputExpr(unsigned i, Expr *E) { 456 Exprs[i + NumOutputs] = E; 457 } 458 459 AddrLabelExpr *GCCAsmStmt::getLabelExpr(unsigned i) const { 460 return cast<AddrLabelExpr>(Exprs[i + NumInputs]); 461 } 462 463 StringRef GCCAsmStmt::getLabelName(unsigned i) const { 464 return getLabelExpr(i)->getLabel()->getName(); 465 } 466 467 /// getInputConstraint - Return the specified input constraint. Unlike output 468 /// constraints, these can be empty. 469 StringRef GCCAsmStmt::getInputConstraint(unsigned i) const { 470 return getInputConstraintLiteral(i)->getString(); 471 } 472 473 void GCCAsmStmt::setOutputsAndInputsAndClobbers(const ASTContext &C, 474 IdentifierInfo **Names, 475 StringLiteral **Constraints, 476 Stmt **Exprs, 477 unsigned NumOutputs, 478 unsigned NumInputs, 479 unsigned NumLabels, 480 StringLiteral **Clobbers, 481 unsigned NumClobbers) { 482 this->NumOutputs = NumOutputs; 483 this->NumInputs = NumInputs; 484 this->NumClobbers = NumClobbers; 485 this->NumLabels = NumLabels; 486 assert(!(NumOutputs && NumLabels) && "asm goto cannot have outputs"); 487 488 unsigned NumExprs = NumOutputs + NumInputs + NumLabels; 489 490 C.Deallocate(this->Names); 491 this->Names = new (C) IdentifierInfo*[NumExprs]; 492 std::copy(Names, Names + NumExprs, this->Names); 493 494 C.Deallocate(this->Exprs); 495 this->Exprs = new (C) Stmt*[NumExprs]; 496 std::copy(Exprs, Exprs + NumExprs, this->Exprs); 497 498 unsigned NumConstraints = NumOutputs + NumInputs; 499 C.Deallocate(this->Constraints); 500 this->Constraints = new (C) StringLiteral*[NumConstraints]; 501 std::copy(Constraints, Constraints + NumConstraints, this->Constraints); 502 503 C.Deallocate(this->Clobbers); 504 this->Clobbers = new (C) StringLiteral*[NumClobbers]; 505 std::copy(Clobbers, Clobbers + NumClobbers, this->Clobbers); 506 } 507 508 /// getNamedOperand - Given a symbolic operand reference like %[foo], 509 /// translate this into a numeric value needed to reference the same operand. 510 /// This returns -1 if the operand name is invalid. 511 int GCCAsmStmt::getNamedOperand(StringRef SymbolicName) const { 512 unsigned NumPlusOperands = 0; 513 514 // Check if this is an output operand. 515 for (unsigned i = 0, e = getNumOutputs(); i != e; ++i) { 516 if (getOutputName(i) == SymbolicName) 517 return i; 518 } 519 520 for (unsigned i = 0, e = getNumInputs(); i != e; ++i) 521 if (getInputName(i) == SymbolicName) 522 return getNumOutputs() + NumPlusOperands + i; 523 524 for (unsigned i = 0, e = getNumLabels(); i != e; ++i) 525 if (getLabelName(i) == SymbolicName) 526 return i + getNumInputs(); 527 528 // Not found. 529 return -1; 530 } 531 532 /// AnalyzeAsmString - Analyze the asm string of the current asm, decomposing 533 /// it into pieces. If the asm string is erroneous, emit errors and return 534 /// true, otherwise return false. 535 unsigned GCCAsmStmt::AnalyzeAsmString(SmallVectorImpl<AsmStringPiece>&Pieces, 536 const ASTContext &C, unsigned &DiagOffs) const { 537 StringRef Str = getAsmString()->getString(); 538 const char *StrStart = Str.begin(); 539 const char *StrEnd = Str.end(); 540 const char *CurPtr = StrStart; 541 542 // "Simple" inline asms have no constraints or operands, just convert the asm 543 // string to escape $'s. 544 if (isSimple()) { 545 std::string Result; 546 for (; CurPtr != StrEnd; ++CurPtr) { 547 switch (*CurPtr) { 548 case '$': 549 Result += "$$"; 550 break; 551 default: 552 Result += *CurPtr; 553 break; 554 } 555 } 556 Pieces.push_back(AsmStringPiece(Result)); 557 return 0; 558 } 559 560 // CurStringPiece - The current string that we are building up as we scan the 561 // asm string. 562 std::string CurStringPiece; 563 564 bool HasVariants = !C.getTargetInfo().hasNoAsmVariants(); 565 566 unsigned LastAsmStringToken = 0; 567 unsigned LastAsmStringOffset = 0; 568 569 while (true) { 570 // Done with the string? 571 if (CurPtr == StrEnd) { 572 if (!CurStringPiece.empty()) 573 Pieces.push_back(AsmStringPiece(CurStringPiece)); 574 return 0; 575 } 576 577 char CurChar = *CurPtr++; 578 switch (CurChar) { 579 case '$': CurStringPiece += "$$"; continue; 580 case '{': CurStringPiece += (HasVariants ? "$(" : "{"); continue; 581 case '|': CurStringPiece += (HasVariants ? "$|" : "|"); continue; 582 case '}': CurStringPiece += (HasVariants ? "$)" : "}"); continue; 583 case '%': 584 break; 585 default: 586 CurStringPiece += CurChar; 587 continue; 588 } 589 590 // Escaped "%" character in asm string. 591 if (CurPtr == StrEnd) { 592 // % at end of string is invalid (no escape). 593 DiagOffs = CurPtr-StrStart-1; 594 return diag::err_asm_invalid_escape; 595 } 596 // Handle escaped char and continue looping over the asm string. 597 char EscapedChar = *CurPtr++; 598 switch (EscapedChar) { 599 default: 600 break; 601 case '%': // %% -> % 602 case '{': // %{ -> { 603 case '}': // %} -> } 604 CurStringPiece += EscapedChar; 605 continue; 606 case '=': // %= -> Generate a unique ID. 607 CurStringPiece += "${:uid}"; 608 continue; 609 } 610 611 // Otherwise, we have an operand. If we have accumulated a string so far, 612 // add it to the Pieces list. 613 if (!CurStringPiece.empty()) { 614 Pieces.push_back(AsmStringPiece(CurStringPiece)); 615 CurStringPiece.clear(); 616 } 617 618 // Handle operands that have asmSymbolicName (e.g., %x[foo]) and those that 619 // don't (e.g., %x4). 'x' following the '%' is the constraint modifier. 620 621 const char *Begin = CurPtr - 1; // Points to the character following '%'. 622 const char *Percent = Begin - 1; // Points to '%'. 623 624 if (isLetter(EscapedChar)) { 625 if (CurPtr == StrEnd) { // Premature end. 626 DiagOffs = CurPtr-StrStart-1; 627 return diag::err_asm_invalid_escape; 628 } 629 EscapedChar = *CurPtr++; 630 } 631 632 const TargetInfo &TI = C.getTargetInfo(); 633 const SourceManager &SM = C.getSourceManager(); 634 const LangOptions &LO = C.getLangOpts(); 635 636 // Handle operands that don't have asmSymbolicName (e.g., %x4). 637 if (isDigit(EscapedChar)) { 638 // %n - Assembler operand n 639 unsigned N = 0; 640 641 --CurPtr; 642 while (CurPtr != StrEnd && isDigit(*CurPtr)) 643 N = N*10 + ((*CurPtr++)-'0'); 644 645 unsigned NumOperands = getNumOutputs() + getNumPlusOperands() + 646 getNumInputs() + getNumLabels(); 647 if (N >= NumOperands) { 648 DiagOffs = CurPtr-StrStart-1; 649 return diag::err_asm_invalid_operand_number; 650 } 651 652 // Str contains "x4" (Operand without the leading %). 653 std::string Str(Begin, CurPtr - Begin); 654 655 // (BeginLoc, EndLoc) represents the range of the operand we are currently 656 // processing. Unlike Str, the range includes the leading '%'. 657 SourceLocation BeginLoc = getAsmString()->getLocationOfByte( 658 Percent - StrStart, SM, LO, TI, &LastAsmStringToken, 659 &LastAsmStringOffset); 660 SourceLocation EndLoc = getAsmString()->getLocationOfByte( 661 CurPtr - StrStart, SM, LO, TI, &LastAsmStringToken, 662 &LastAsmStringOffset); 663 664 Pieces.emplace_back(N, std::move(Str), BeginLoc, EndLoc); 665 continue; 666 } 667 668 // Handle operands that have asmSymbolicName (e.g., %x[foo]). 669 if (EscapedChar == '[') { 670 DiagOffs = CurPtr-StrStart-1; 671 672 // Find the ']'. 673 const char *NameEnd = (const char*)memchr(CurPtr, ']', StrEnd-CurPtr); 674 if (NameEnd == nullptr) 675 return diag::err_asm_unterminated_symbolic_operand_name; 676 if (NameEnd == CurPtr) 677 return diag::err_asm_empty_symbolic_operand_name; 678 679 StringRef SymbolicName(CurPtr, NameEnd - CurPtr); 680 681 int N = getNamedOperand(SymbolicName); 682 if (N == -1) { 683 // Verify that an operand with that name exists. 684 DiagOffs = CurPtr-StrStart; 685 return diag::err_asm_unknown_symbolic_operand_name; 686 } 687 688 // Str contains "x[foo]" (Operand without the leading %). 689 std::string Str(Begin, NameEnd + 1 - Begin); 690 691 // (BeginLoc, EndLoc) represents the range of the operand we are currently 692 // processing. Unlike Str, the range includes the leading '%'. 693 SourceLocation BeginLoc = getAsmString()->getLocationOfByte( 694 Percent - StrStart, SM, LO, TI, &LastAsmStringToken, 695 &LastAsmStringOffset); 696 SourceLocation EndLoc = getAsmString()->getLocationOfByte( 697 NameEnd + 1 - StrStart, SM, LO, TI, &LastAsmStringToken, 698 &LastAsmStringOffset); 699 700 Pieces.emplace_back(N, std::move(Str), BeginLoc, EndLoc); 701 702 CurPtr = NameEnd+1; 703 continue; 704 } 705 706 DiagOffs = CurPtr-StrStart-1; 707 return diag::err_asm_invalid_escape; 708 } 709 } 710 711 /// Assemble final IR asm string (GCC-style). 712 std::string GCCAsmStmt::generateAsmString(const ASTContext &C) const { 713 // Analyze the asm string to decompose it into its pieces. We know that Sema 714 // has already done this, so it is guaranteed to be successful. 715 SmallVector<GCCAsmStmt::AsmStringPiece, 4> Pieces; 716 unsigned DiagOffs; 717 AnalyzeAsmString(Pieces, C, DiagOffs); 718 719 std::string AsmString; 720 for (const auto &Piece : Pieces) { 721 if (Piece.isString()) 722 AsmString += Piece.getString(); 723 else if (Piece.getModifier() == '\0') 724 AsmString += '$' + llvm::utostr(Piece.getOperandNo()); 725 else 726 AsmString += "${" + llvm::utostr(Piece.getOperandNo()) + ':' + 727 Piece.getModifier() + '}'; 728 } 729 return AsmString; 730 } 731 732 /// Assemble final IR asm string (MS-style). 733 std::string MSAsmStmt::generateAsmString(const ASTContext &C) const { 734 // FIXME: This needs to be translated into the IR string representation. 735 return AsmStr; 736 } 737 738 Expr *MSAsmStmt::getOutputExpr(unsigned i) { 739 return cast<Expr>(Exprs[i]); 740 } 741 742 Expr *MSAsmStmt::getInputExpr(unsigned i) { 743 return cast<Expr>(Exprs[i + NumOutputs]); 744 } 745 746 void MSAsmStmt::setInputExpr(unsigned i, Expr *E) { 747 Exprs[i + NumOutputs] = E; 748 } 749 750 //===----------------------------------------------------------------------===// 751 // Constructors 752 //===----------------------------------------------------------------------===// 753 754 GCCAsmStmt::GCCAsmStmt(const ASTContext &C, SourceLocation asmloc, 755 bool issimple, bool isvolatile, unsigned numoutputs, 756 unsigned numinputs, IdentifierInfo **names, 757 StringLiteral **constraints, Expr **exprs, 758 StringLiteral *asmstr, unsigned numclobbers, 759 StringLiteral **clobbers, unsigned numlabels, 760 SourceLocation rparenloc) 761 : AsmStmt(GCCAsmStmtClass, asmloc, issimple, isvolatile, numoutputs, 762 numinputs, numclobbers), 763 RParenLoc(rparenloc), AsmStr(asmstr), NumLabels(numlabels) { 764 unsigned NumExprs = NumOutputs + NumInputs + NumLabels; 765 766 Names = new (C) IdentifierInfo*[NumExprs]; 767 std::copy(names, names + NumExprs, Names); 768 769 Exprs = new (C) Stmt*[NumExprs]; 770 std::copy(exprs, exprs + NumExprs, Exprs); 771 772 unsigned NumConstraints = NumOutputs + NumInputs; 773 Constraints = new (C) StringLiteral*[NumConstraints]; 774 std::copy(constraints, constraints + NumConstraints, Constraints); 775 776 Clobbers = new (C) StringLiteral*[NumClobbers]; 777 std::copy(clobbers, clobbers + NumClobbers, Clobbers); 778 } 779 780 MSAsmStmt::MSAsmStmt(const ASTContext &C, SourceLocation asmloc, 781 SourceLocation lbraceloc, bool issimple, bool isvolatile, 782 ArrayRef<Token> asmtoks, unsigned numoutputs, 783 unsigned numinputs, 784 ArrayRef<StringRef> constraints, ArrayRef<Expr*> exprs, 785 StringRef asmstr, ArrayRef<StringRef> clobbers, 786 SourceLocation endloc) 787 : AsmStmt(MSAsmStmtClass, asmloc, issimple, isvolatile, numoutputs, 788 numinputs, clobbers.size()), LBraceLoc(lbraceloc), 789 EndLoc(endloc), NumAsmToks(asmtoks.size()) { 790 initialize(C, asmstr, asmtoks, constraints, exprs, clobbers); 791 } 792 793 static StringRef copyIntoContext(const ASTContext &C, StringRef str) { 794 return str.copy(C); 795 } 796 797 void MSAsmStmt::initialize(const ASTContext &C, StringRef asmstr, 798 ArrayRef<Token> asmtoks, 799 ArrayRef<StringRef> constraints, 800 ArrayRef<Expr*> exprs, 801 ArrayRef<StringRef> clobbers) { 802 assert(NumAsmToks == asmtoks.size()); 803 assert(NumClobbers == clobbers.size()); 804 805 assert(exprs.size() == NumOutputs + NumInputs); 806 assert(exprs.size() == constraints.size()); 807 808 AsmStr = copyIntoContext(C, asmstr); 809 810 Exprs = new (C) Stmt*[exprs.size()]; 811 std::copy(exprs.begin(), exprs.end(), Exprs); 812 813 AsmToks = new (C) Token[asmtoks.size()]; 814 std::copy(asmtoks.begin(), asmtoks.end(), AsmToks); 815 816 Constraints = new (C) StringRef[exprs.size()]; 817 std::transform(constraints.begin(), constraints.end(), Constraints, 818 [&](StringRef Constraint) { 819 return copyIntoContext(C, Constraint); 820 }); 821 822 Clobbers = new (C) StringRef[NumClobbers]; 823 // FIXME: Avoid the allocation/copy if at all possible. 824 std::transform(clobbers.begin(), clobbers.end(), Clobbers, 825 [&](StringRef Clobber) { 826 return copyIntoContext(C, Clobber); 827 }); 828 } 829 830 IfStmt::IfStmt(const ASTContext &Ctx, SourceLocation IL, bool IsConstexpr, 831 Stmt *Init, VarDecl *Var, Expr *Cond, Stmt *Then, 832 SourceLocation EL, Stmt *Else) 833 : Stmt(IfStmtClass) { 834 bool HasElse = Else != nullptr; 835 bool HasVar = Var != nullptr; 836 bool HasInit = Init != nullptr; 837 IfStmtBits.HasElse = HasElse; 838 IfStmtBits.HasVar = HasVar; 839 IfStmtBits.HasInit = HasInit; 840 841 setConstexpr(IsConstexpr); 842 843 setCond(Cond); 844 setThen(Then); 845 if (HasElse) 846 setElse(Else); 847 if (HasVar) 848 setConditionVariable(Ctx, Var); 849 if (HasInit) 850 setInit(Init); 851 852 setIfLoc(IL); 853 if (HasElse) 854 setElseLoc(EL); 855 } 856 857 IfStmt::IfStmt(EmptyShell Empty, bool HasElse, bool HasVar, bool HasInit) 858 : Stmt(IfStmtClass, Empty) { 859 IfStmtBits.HasElse = HasElse; 860 IfStmtBits.HasVar = HasVar; 861 IfStmtBits.HasInit = HasInit; 862 } 863 864 IfStmt *IfStmt::Create(const ASTContext &Ctx, SourceLocation IL, 865 bool IsConstexpr, Stmt *Init, VarDecl *Var, Expr *Cond, 866 Stmt *Then, SourceLocation EL, Stmt *Else) { 867 bool HasElse = Else != nullptr; 868 bool HasVar = Var != nullptr; 869 bool HasInit = Init != nullptr; 870 void *Mem = Ctx.Allocate( 871 totalSizeToAlloc<Stmt *, SourceLocation>( 872 NumMandatoryStmtPtr + HasElse + HasVar + HasInit, HasElse), 873 alignof(IfStmt)); 874 return new (Mem) 875 IfStmt(Ctx, IL, IsConstexpr, Init, Var, Cond, Then, EL, Else); 876 } 877 878 IfStmt *IfStmt::CreateEmpty(const ASTContext &Ctx, bool HasElse, bool HasVar, 879 bool HasInit) { 880 void *Mem = Ctx.Allocate( 881 totalSizeToAlloc<Stmt *, SourceLocation>( 882 NumMandatoryStmtPtr + HasElse + HasVar + HasInit, HasElse), 883 alignof(IfStmt)); 884 return new (Mem) IfStmt(EmptyShell(), HasElse, HasVar, HasInit); 885 } 886 887 VarDecl *IfStmt::getConditionVariable() { 888 auto *DS = getConditionVariableDeclStmt(); 889 if (!DS) 890 return nullptr; 891 return cast<VarDecl>(DS->getSingleDecl()); 892 } 893 894 void IfStmt::setConditionVariable(const ASTContext &Ctx, VarDecl *V) { 895 assert(hasVarStorage() && 896 "This if statement has no storage for a condition variable!"); 897 898 if (!V) { 899 getTrailingObjects<Stmt *>()[varOffset()] = nullptr; 900 return; 901 } 902 903 SourceRange VarRange = V->getSourceRange(); 904 getTrailingObjects<Stmt *>()[varOffset()] = new (Ctx) 905 DeclStmt(DeclGroupRef(V), VarRange.getBegin(), VarRange.getEnd()); 906 } 907 908 bool IfStmt::isObjCAvailabilityCheck() const { 909 return isa<ObjCAvailabilityCheckExpr>(getCond()); 910 } 911 912 Optional<const Stmt*> IfStmt::getNondiscardedCase(const ASTContext &Ctx) const { 913 if (!isConstexpr() || getCond()->isValueDependent()) 914 return None; 915 return !getCond()->EvaluateKnownConstInt(Ctx) ? getElse() : getThen(); 916 } 917 918 ForStmt::ForStmt(const ASTContext &C, Stmt *Init, Expr *Cond, VarDecl *condVar, 919 Expr *Inc, Stmt *Body, SourceLocation FL, SourceLocation LP, 920 SourceLocation RP) 921 : Stmt(ForStmtClass), LParenLoc(LP), RParenLoc(RP) 922 { 923 SubExprs[INIT] = Init; 924 setConditionVariable(C, condVar); 925 SubExprs[COND] = Cond; 926 SubExprs[INC] = Inc; 927 SubExprs[BODY] = Body; 928 ForStmtBits.ForLoc = FL; 929 } 930 931 VarDecl *ForStmt::getConditionVariable() const { 932 if (!SubExprs[CONDVAR]) 933 return nullptr; 934 935 auto *DS = cast<DeclStmt>(SubExprs[CONDVAR]); 936 return cast<VarDecl>(DS->getSingleDecl()); 937 } 938 939 void ForStmt::setConditionVariable(const ASTContext &C, VarDecl *V) { 940 if (!V) { 941 SubExprs[CONDVAR] = nullptr; 942 return; 943 } 944 945 SourceRange VarRange = V->getSourceRange(); 946 SubExprs[CONDVAR] = new (C) DeclStmt(DeclGroupRef(V), VarRange.getBegin(), 947 VarRange.getEnd()); 948 } 949 950 SwitchStmt::SwitchStmt(const ASTContext &Ctx, Stmt *Init, VarDecl *Var, 951 Expr *Cond) 952 : Stmt(SwitchStmtClass), FirstCase(nullptr) { 953 bool HasInit = Init != nullptr; 954 bool HasVar = Var != nullptr; 955 SwitchStmtBits.HasInit = HasInit; 956 SwitchStmtBits.HasVar = HasVar; 957 SwitchStmtBits.AllEnumCasesCovered = false; 958 959 setCond(Cond); 960 setBody(nullptr); 961 if (HasInit) 962 setInit(Init); 963 if (HasVar) 964 setConditionVariable(Ctx, Var); 965 966 setSwitchLoc(SourceLocation{}); 967 } 968 969 SwitchStmt::SwitchStmt(EmptyShell Empty, bool HasInit, bool HasVar) 970 : Stmt(SwitchStmtClass, Empty) { 971 SwitchStmtBits.HasInit = HasInit; 972 SwitchStmtBits.HasVar = HasVar; 973 SwitchStmtBits.AllEnumCasesCovered = false; 974 } 975 976 SwitchStmt *SwitchStmt::Create(const ASTContext &Ctx, Stmt *Init, VarDecl *Var, 977 Expr *Cond) { 978 bool HasInit = Init != nullptr; 979 bool HasVar = Var != nullptr; 980 void *Mem = Ctx.Allocate( 981 totalSizeToAlloc<Stmt *>(NumMandatoryStmtPtr + HasInit + HasVar), 982 alignof(SwitchStmt)); 983 return new (Mem) SwitchStmt(Ctx, Init, Var, Cond); 984 } 985 986 SwitchStmt *SwitchStmt::CreateEmpty(const ASTContext &Ctx, bool HasInit, 987 bool HasVar) { 988 void *Mem = Ctx.Allocate( 989 totalSizeToAlloc<Stmt *>(NumMandatoryStmtPtr + HasInit + HasVar), 990 alignof(SwitchStmt)); 991 return new (Mem) SwitchStmt(EmptyShell(), HasInit, HasVar); 992 } 993 994 VarDecl *SwitchStmt::getConditionVariable() { 995 auto *DS = getConditionVariableDeclStmt(); 996 if (!DS) 997 return nullptr; 998 return cast<VarDecl>(DS->getSingleDecl()); 999 } 1000 1001 void SwitchStmt::setConditionVariable(const ASTContext &Ctx, VarDecl *V) { 1002 assert(hasVarStorage() && 1003 "This switch statement has no storage for a condition variable!"); 1004 1005 if (!V) { 1006 getTrailingObjects<Stmt *>()[varOffset()] = nullptr; 1007 return; 1008 } 1009 1010 SourceRange VarRange = V->getSourceRange(); 1011 getTrailingObjects<Stmt *>()[varOffset()] = new (Ctx) 1012 DeclStmt(DeclGroupRef(V), VarRange.getBegin(), VarRange.getEnd()); 1013 } 1014 1015 WhileStmt::WhileStmt(const ASTContext &Ctx, VarDecl *Var, Expr *Cond, 1016 Stmt *Body, SourceLocation WL) 1017 : Stmt(WhileStmtClass) { 1018 bool HasVar = Var != nullptr; 1019 WhileStmtBits.HasVar = HasVar; 1020 1021 setCond(Cond); 1022 setBody(Body); 1023 if (HasVar) 1024 setConditionVariable(Ctx, Var); 1025 1026 setWhileLoc(WL); 1027 } 1028 1029 WhileStmt::WhileStmt(EmptyShell Empty, bool HasVar) 1030 : Stmt(WhileStmtClass, Empty) { 1031 WhileStmtBits.HasVar = HasVar; 1032 } 1033 1034 WhileStmt *WhileStmt::Create(const ASTContext &Ctx, VarDecl *Var, Expr *Cond, 1035 Stmt *Body, SourceLocation WL) { 1036 bool HasVar = Var != nullptr; 1037 void *Mem = 1038 Ctx.Allocate(totalSizeToAlloc<Stmt *>(NumMandatoryStmtPtr + HasVar), 1039 alignof(WhileStmt)); 1040 return new (Mem) WhileStmt(Ctx, Var, Cond, Body, WL); 1041 } 1042 1043 WhileStmt *WhileStmt::CreateEmpty(const ASTContext &Ctx, bool HasVar) { 1044 void *Mem = 1045 Ctx.Allocate(totalSizeToAlloc<Stmt *>(NumMandatoryStmtPtr + HasVar), 1046 alignof(WhileStmt)); 1047 return new (Mem) WhileStmt(EmptyShell(), HasVar); 1048 } 1049 1050 VarDecl *WhileStmt::getConditionVariable() { 1051 auto *DS = getConditionVariableDeclStmt(); 1052 if (!DS) 1053 return nullptr; 1054 return cast<VarDecl>(DS->getSingleDecl()); 1055 } 1056 1057 void WhileStmt::setConditionVariable(const ASTContext &Ctx, VarDecl *V) { 1058 assert(hasVarStorage() && 1059 "This while statement has no storage for a condition variable!"); 1060 1061 if (!V) { 1062 getTrailingObjects<Stmt *>()[varOffset()] = nullptr; 1063 return; 1064 } 1065 1066 SourceRange VarRange = V->getSourceRange(); 1067 getTrailingObjects<Stmt *>()[varOffset()] = new (Ctx) 1068 DeclStmt(DeclGroupRef(V), VarRange.getBegin(), VarRange.getEnd()); 1069 } 1070 1071 // IndirectGotoStmt 1072 LabelDecl *IndirectGotoStmt::getConstantTarget() { 1073 if (auto *E = dyn_cast<AddrLabelExpr>(getTarget()->IgnoreParenImpCasts())) 1074 return E->getLabel(); 1075 return nullptr; 1076 } 1077 1078 // ReturnStmt 1079 ReturnStmt::ReturnStmt(SourceLocation RL, Expr *E, const VarDecl *NRVOCandidate) 1080 : Stmt(ReturnStmtClass), RetExpr(E) { 1081 bool HasNRVOCandidate = NRVOCandidate != nullptr; 1082 ReturnStmtBits.HasNRVOCandidate = HasNRVOCandidate; 1083 if (HasNRVOCandidate) 1084 setNRVOCandidate(NRVOCandidate); 1085 setReturnLoc(RL); 1086 } 1087 1088 ReturnStmt::ReturnStmt(EmptyShell Empty, bool HasNRVOCandidate) 1089 : Stmt(ReturnStmtClass, Empty) { 1090 ReturnStmtBits.HasNRVOCandidate = HasNRVOCandidate; 1091 } 1092 1093 ReturnStmt *ReturnStmt::Create(const ASTContext &Ctx, SourceLocation RL, 1094 Expr *E, const VarDecl *NRVOCandidate) { 1095 bool HasNRVOCandidate = NRVOCandidate != nullptr; 1096 void *Mem = Ctx.Allocate(totalSizeToAlloc<const VarDecl *>(HasNRVOCandidate), 1097 alignof(ReturnStmt)); 1098 return new (Mem) ReturnStmt(RL, E, NRVOCandidate); 1099 } 1100 1101 ReturnStmt *ReturnStmt::CreateEmpty(const ASTContext &Ctx, 1102 bool HasNRVOCandidate) { 1103 void *Mem = Ctx.Allocate(totalSizeToAlloc<const VarDecl *>(HasNRVOCandidate), 1104 alignof(ReturnStmt)); 1105 return new (Mem) ReturnStmt(EmptyShell(), HasNRVOCandidate); 1106 } 1107 1108 // CaseStmt 1109 CaseStmt *CaseStmt::Create(const ASTContext &Ctx, Expr *lhs, Expr *rhs, 1110 SourceLocation caseLoc, SourceLocation ellipsisLoc, 1111 SourceLocation colonLoc) { 1112 bool CaseStmtIsGNURange = rhs != nullptr; 1113 void *Mem = Ctx.Allocate( 1114 totalSizeToAlloc<Stmt *, SourceLocation>( 1115 NumMandatoryStmtPtr + CaseStmtIsGNURange, CaseStmtIsGNURange), 1116 alignof(CaseStmt)); 1117 return new (Mem) CaseStmt(lhs, rhs, caseLoc, ellipsisLoc, colonLoc); 1118 } 1119 1120 CaseStmt *CaseStmt::CreateEmpty(const ASTContext &Ctx, 1121 bool CaseStmtIsGNURange) { 1122 void *Mem = Ctx.Allocate( 1123 totalSizeToAlloc<Stmt *, SourceLocation>( 1124 NumMandatoryStmtPtr + CaseStmtIsGNURange, CaseStmtIsGNURange), 1125 alignof(CaseStmt)); 1126 return new (Mem) CaseStmt(EmptyShell(), CaseStmtIsGNURange); 1127 } 1128 1129 SEHTryStmt::SEHTryStmt(bool IsCXXTry, SourceLocation TryLoc, Stmt *TryBlock, 1130 Stmt *Handler) 1131 : Stmt(SEHTryStmtClass), IsCXXTry(IsCXXTry), TryLoc(TryLoc) { 1132 Children[TRY] = TryBlock; 1133 Children[HANDLER] = Handler; 1134 } 1135 1136 SEHTryStmt* SEHTryStmt::Create(const ASTContext &C, bool IsCXXTry, 1137 SourceLocation TryLoc, Stmt *TryBlock, 1138 Stmt *Handler) { 1139 return new(C) SEHTryStmt(IsCXXTry,TryLoc,TryBlock,Handler); 1140 } 1141 1142 SEHExceptStmt* SEHTryStmt::getExceptHandler() const { 1143 return dyn_cast<SEHExceptStmt>(getHandler()); 1144 } 1145 1146 SEHFinallyStmt* SEHTryStmt::getFinallyHandler() const { 1147 return dyn_cast<SEHFinallyStmt>(getHandler()); 1148 } 1149 1150 SEHExceptStmt::SEHExceptStmt(SourceLocation Loc, Expr *FilterExpr, Stmt *Block) 1151 : Stmt(SEHExceptStmtClass), Loc(Loc) { 1152 Children[FILTER_EXPR] = FilterExpr; 1153 Children[BLOCK] = Block; 1154 } 1155 1156 SEHExceptStmt* SEHExceptStmt::Create(const ASTContext &C, SourceLocation Loc, 1157 Expr *FilterExpr, Stmt *Block) { 1158 return new(C) SEHExceptStmt(Loc,FilterExpr,Block); 1159 } 1160 1161 SEHFinallyStmt::SEHFinallyStmt(SourceLocation Loc, Stmt *Block) 1162 : Stmt(SEHFinallyStmtClass), Loc(Loc), Block(Block) {} 1163 1164 SEHFinallyStmt* SEHFinallyStmt::Create(const ASTContext &C, SourceLocation Loc, 1165 Stmt *Block) { 1166 return new(C)SEHFinallyStmt(Loc,Block); 1167 } 1168 1169 CapturedStmt::Capture::Capture(SourceLocation Loc, VariableCaptureKind Kind, 1170 VarDecl *Var) 1171 : VarAndKind(Var, Kind), Loc(Loc) { 1172 switch (Kind) { 1173 case VCK_This: 1174 assert(!Var && "'this' capture cannot have a variable!"); 1175 break; 1176 case VCK_ByRef: 1177 assert(Var && "capturing by reference must have a variable!"); 1178 break; 1179 case VCK_ByCopy: 1180 assert(Var && "capturing by copy must have a variable!"); 1181 assert( 1182 (Var->getType()->isScalarType() || (Var->getType()->isReferenceType() && 1183 Var->getType() 1184 ->castAs<ReferenceType>() 1185 ->getPointeeType() 1186 ->isScalarType())) && 1187 "captures by copy are expected to have a scalar type!"); 1188 break; 1189 case VCK_VLAType: 1190 assert(!Var && 1191 "Variable-length array type capture cannot have a variable!"); 1192 break; 1193 } 1194 } 1195 1196 CapturedStmt::VariableCaptureKind 1197 CapturedStmt::Capture::getCaptureKind() const { 1198 return VarAndKind.getInt(); 1199 } 1200 1201 VarDecl *CapturedStmt::Capture::getCapturedVar() const { 1202 assert((capturesVariable() || capturesVariableByCopy()) && 1203 "No variable available for 'this' or VAT capture"); 1204 return VarAndKind.getPointer(); 1205 } 1206 1207 CapturedStmt::Capture *CapturedStmt::getStoredCaptures() const { 1208 unsigned Size = sizeof(CapturedStmt) + sizeof(Stmt *) * (NumCaptures + 1); 1209 1210 // Offset of the first Capture object. 1211 unsigned FirstCaptureOffset = llvm::alignTo(Size, alignof(Capture)); 1212 1213 return reinterpret_cast<Capture *>( 1214 reinterpret_cast<char *>(const_cast<CapturedStmt *>(this)) 1215 + FirstCaptureOffset); 1216 } 1217 1218 CapturedStmt::CapturedStmt(Stmt *S, CapturedRegionKind Kind, 1219 ArrayRef<Capture> Captures, 1220 ArrayRef<Expr *> CaptureInits, 1221 CapturedDecl *CD, 1222 RecordDecl *RD) 1223 : Stmt(CapturedStmtClass), NumCaptures(Captures.size()), 1224 CapDeclAndKind(CD, Kind), TheRecordDecl(RD) { 1225 assert( S && "null captured statement"); 1226 assert(CD && "null captured declaration for captured statement"); 1227 assert(RD && "null record declaration for captured statement"); 1228 1229 // Copy initialization expressions. 1230 Stmt **Stored = getStoredStmts(); 1231 for (unsigned I = 0, N = NumCaptures; I != N; ++I) 1232 *Stored++ = CaptureInits[I]; 1233 1234 // Copy the statement being captured. 1235 *Stored = S; 1236 1237 // Copy all Capture objects. 1238 Capture *Buffer = getStoredCaptures(); 1239 std::copy(Captures.begin(), Captures.end(), Buffer); 1240 } 1241 1242 CapturedStmt::CapturedStmt(EmptyShell Empty, unsigned NumCaptures) 1243 : Stmt(CapturedStmtClass, Empty), NumCaptures(NumCaptures), 1244 CapDeclAndKind(nullptr, CR_Default) { 1245 getStoredStmts()[NumCaptures] = nullptr; 1246 } 1247 1248 CapturedStmt *CapturedStmt::Create(const ASTContext &Context, Stmt *S, 1249 CapturedRegionKind Kind, 1250 ArrayRef<Capture> Captures, 1251 ArrayRef<Expr *> CaptureInits, 1252 CapturedDecl *CD, 1253 RecordDecl *RD) { 1254 // The layout is 1255 // 1256 // ----------------------------------------------------------- 1257 // | CapturedStmt, Init, ..., Init, S, Capture, ..., Capture | 1258 // ----------------^-------------------^---------------------- 1259 // getStoredStmts() getStoredCaptures() 1260 // 1261 // where S is the statement being captured. 1262 // 1263 assert(CaptureInits.size() == Captures.size() && "wrong number of arguments"); 1264 1265 unsigned Size = sizeof(CapturedStmt) + sizeof(Stmt *) * (Captures.size() + 1); 1266 if (!Captures.empty()) { 1267 // Realign for the following Capture array. 1268 Size = llvm::alignTo(Size, alignof(Capture)); 1269 Size += sizeof(Capture) * Captures.size(); 1270 } 1271 1272 void *Mem = Context.Allocate(Size); 1273 return new (Mem) CapturedStmt(S, Kind, Captures, CaptureInits, CD, RD); 1274 } 1275 1276 CapturedStmt *CapturedStmt::CreateDeserialized(const ASTContext &Context, 1277 unsigned NumCaptures) { 1278 unsigned Size = sizeof(CapturedStmt) + sizeof(Stmt *) * (NumCaptures + 1); 1279 if (NumCaptures > 0) { 1280 // Realign for the following Capture array. 1281 Size = llvm::alignTo(Size, alignof(Capture)); 1282 Size += sizeof(Capture) * NumCaptures; 1283 } 1284 1285 void *Mem = Context.Allocate(Size); 1286 return new (Mem) CapturedStmt(EmptyShell(), NumCaptures); 1287 } 1288 1289 Stmt::child_range CapturedStmt::children() { 1290 // Children are captured field initializers. 1291 return child_range(getStoredStmts(), getStoredStmts() + NumCaptures); 1292 } 1293 1294 Stmt::const_child_range CapturedStmt::children() const { 1295 return const_child_range(getStoredStmts(), getStoredStmts() + NumCaptures); 1296 } 1297 1298 CapturedDecl *CapturedStmt::getCapturedDecl() { 1299 return CapDeclAndKind.getPointer(); 1300 } 1301 1302 const CapturedDecl *CapturedStmt::getCapturedDecl() const { 1303 return CapDeclAndKind.getPointer(); 1304 } 1305 1306 /// Set the outlined function declaration. 1307 void CapturedStmt::setCapturedDecl(CapturedDecl *D) { 1308 assert(D && "null CapturedDecl"); 1309 CapDeclAndKind.setPointer(D); 1310 } 1311 1312 /// Retrieve the captured region kind. 1313 CapturedRegionKind CapturedStmt::getCapturedRegionKind() const { 1314 return CapDeclAndKind.getInt(); 1315 } 1316 1317 /// Set the captured region kind. 1318 void CapturedStmt::setCapturedRegionKind(CapturedRegionKind Kind) { 1319 CapDeclAndKind.setInt(Kind); 1320 } 1321 1322 bool CapturedStmt::capturesVariable(const VarDecl *Var) const { 1323 for (const auto &I : captures()) { 1324 if (!I.capturesVariable() && !I.capturesVariableByCopy()) 1325 continue; 1326 if (I.getCapturedVar()->getCanonicalDecl() == Var->getCanonicalDecl()) 1327 return true; 1328 } 1329 1330 return false; 1331 } 1332