1 //===--- SemaExceptionSpec.cpp - C++ Exception Specifications ---*- C++ -*-===// 2 // 3 // The LLVM Compiler Infrastructure 4 // 5 // This file is distributed under the University of Illinois Open Source 6 // License. See LICENSE.TXT for details. 7 // 8 //===----------------------------------------------------------------------===// 9 // 10 // This file provides Sema routines for C++ exception specification testing. 11 // 12 //===----------------------------------------------------------------------===// 13 14 #include "clang/Sema/SemaInternal.h" 15 #include "clang/AST/ASTMutationListener.h" 16 #include "clang/AST/CXXInheritance.h" 17 #include "clang/AST/Expr.h" 18 #include "clang/AST/ExprCXX.h" 19 #include "clang/AST/TypeLoc.h" 20 #include "clang/Basic/Diagnostic.h" 21 #include "clang/Basic/SourceManager.h" 22 #include "llvm/ADT/SmallPtrSet.h" 23 #include "llvm/ADT/SmallString.h" 24 25 namespace clang { 26 27 static const FunctionProtoType *GetUnderlyingFunction(QualType T) 28 { 29 if (const PointerType *PtrTy = T->getAs<PointerType>()) 30 T = PtrTy->getPointeeType(); 31 else if (const ReferenceType *RefTy = T->getAs<ReferenceType>()) 32 T = RefTy->getPointeeType(); 33 else if (const MemberPointerType *MPTy = T->getAs<MemberPointerType>()) 34 T = MPTy->getPointeeType(); 35 return T->getAs<FunctionProtoType>(); 36 } 37 38 /// CheckSpecifiedExceptionType - Check if the given type is valid in an 39 /// exception specification. Incomplete types, or pointers to incomplete types 40 /// other than void are not allowed. 41 /// 42 /// \param[in,out] T The exception type. This will be decayed to a pointer type 43 /// when the input is an array or a function type. 44 bool Sema::CheckSpecifiedExceptionType(QualType &T, const SourceRange &Range) { 45 // C++11 [except.spec]p2: 46 // A type cv T, "array of T", or "function returning T" denoted 47 // in an exception-specification is adjusted to type T, "pointer to T", or 48 // "pointer to function returning T", respectively. 49 // 50 // We also apply this rule in C++98. 51 if (T->isArrayType()) 52 T = Context.getArrayDecayedType(T); 53 else if (T->isFunctionType()) 54 T = Context.getPointerType(T); 55 56 int Kind = 0; 57 QualType PointeeT = T; 58 if (const PointerType *PT = T->getAs<PointerType>()) { 59 PointeeT = PT->getPointeeType(); 60 Kind = 1; 61 62 // cv void* is explicitly permitted, despite being a pointer to an 63 // incomplete type. 64 if (PointeeT->isVoidType()) 65 return false; 66 } else if (const ReferenceType *RT = T->getAs<ReferenceType>()) { 67 PointeeT = RT->getPointeeType(); 68 Kind = 2; 69 70 if (RT->isRValueReferenceType()) { 71 // C++11 [except.spec]p2: 72 // A type denoted in an exception-specification shall not denote [...] 73 // an rvalue reference type. 74 Diag(Range.getBegin(), diag::err_rref_in_exception_spec) 75 << T << Range; 76 return true; 77 } 78 } 79 80 // C++11 [except.spec]p2: 81 // A type denoted in an exception-specification shall not denote an 82 // incomplete type other than a class currently being defined [...]. 83 // A type denoted in an exception-specification shall not denote a 84 // pointer or reference to an incomplete type, other than (cv) void* or a 85 // pointer or reference to a class currently being defined. 86 if (!(PointeeT->isRecordType() && 87 PointeeT->getAs<RecordType>()->isBeingDefined()) && 88 RequireCompleteType(Range.getBegin(), PointeeT, 89 diag::err_incomplete_in_exception_spec, Kind, Range)) 90 return true; 91 92 return false; 93 } 94 95 /// CheckDistantExceptionSpec - Check if the given type is a pointer or pointer 96 /// to member to a function with an exception specification. This means that 97 /// it is invalid to add another level of indirection. 98 bool Sema::CheckDistantExceptionSpec(QualType T) { 99 if (const PointerType *PT = T->getAs<PointerType>()) 100 T = PT->getPointeeType(); 101 else if (const MemberPointerType *PT = T->getAs<MemberPointerType>()) 102 T = PT->getPointeeType(); 103 else 104 return false; 105 106 const FunctionProtoType *FnT = T->getAs<FunctionProtoType>(); 107 if (!FnT) 108 return false; 109 110 return FnT->hasExceptionSpec(); 111 } 112 113 const FunctionProtoType * 114 Sema::ResolveExceptionSpec(SourceLocation Loc, const FunctionProtoType *FPT) { 115 if (!isUnresolvedExceptionSpec(FPT->getExceptionSpecType())) 116 return FPT; 117 118 FunctionDecl *SourceDecl = FPT->getExceptionSpecDecl(); 119 const FunctionProtoType *SourceFPT = 120 SourceDecl->getType()->castAs<FunctionProtoType>(); 121 122 // If the exception specification has already been resolved, just return it. 123 if (!isUnresolvedExceptionSpec(SourceFPT->getExceptionSpecType())) 124 return SourceFPT; 125 126 // Compute or instantiate the exception specification now. 127 if (SourceFPT->getExceptionSpecType() == EST_Unevaluated) 128 EvaluateImplicitExceptionSpec(Loc, cast<CXXMethodDecl>(SourceDecl)); 129 else 130 InstantiateExceptionSpec(Loc, SourceDecl); 131 132 return SourceDecl->getType()->castAs<FunctionProtoType>(); 133 } 134 135 void Sema::UpdateExceptionSpec(FunctionDecl *FD, 136 const FunctionProtoType::ExtProtoInfo &EPI) { 137 const FunctionProtoType *Proto = FD->getType()->castAs<FunctionProtoType>(); 138 139 // Overwrite the exception spec and rebuild the function type. 140 FunctionProtoType::ExtProtoInfo NewEPI = Proto->getExtProtoInfo(); 141 NewEPI.ExceptionSpecType = EPI.ExceptionSpecType; 142 NewEPI.NumExceptions = EPI.NumExceptions; 143 NewEPI.Exceptions = EPI.Exceptions; 144 NewEPI.NoexceptExpr = EPI.NoexceptExpr; 145 FD->setType(Context.getFunctionType(Proto->getReturnType(), 146 Proto->getParamTypes(), NewEPI)); 147 148 // If we've fully resolved the exception specification, notify listeners. 149 if (!isUnresolvedExceptionSpec(EPI.ExceptionSpecType)) 150 if (auto *Listener = getASTMutationListener()) 151 Listener->ResolvedExceptionSpec(FD); 152 } 153 154 /// Determine whether a function has an implicitly-generated exception 155 /// specification. 156 static bool hasImplicitExceptionSpec(FunctionDecl *Decl) { 157 if (!isa<CXXDestructorDecl>(Decl) && 158 Decl->getDeclName().getCXXOverloadedOperator() != OO_Delete && 159 Decl->getDeclName().getCXXOverloadedOperator() != OO_Array_Delete) 160 return false; 161 162 // For a function that the user didn't declare: 163 // - if this is a destructor, its exception specification is implicit. 164 // - if this is 'operator delete' or 'operator delete[]', the exception 165 // specification is as-if an explicit exception specification was given 166 // (per [basic.stc.dynamic]p2). 167 if (!Decl->getTypeSourceInfo()) 168 return isa<CXXDestructorDecl>(Decl); 169 170 const FunctionProtoType *Ty = 171 Decl->getTypeSourceInfo()->getType()->getAs<FunctionProtoType>(); 172 return !Ty->hasExceptionSpec(); 173 } 174 175 bool Sema::CheckEquivalentExceptionSpec(FunctionDecl *Old, FunctionDecl *New) { 176 OverloadedOperatorKind OO = New->getDeclName().getCXXOverloadedOperator(); 177 bool IsOperatorNew = OO == OO_New || OO == OO_Array_New; 178 bool MissingExceptionSpecification = false; 179 bool MissingEmptyExceptionSpecification = false; 180 181 unsigned DiagID = diag::err_mismatched_exception_spec; 182 bool ReturnValueOnError = true; 183 if (getLangOpts().MicrosoftExt) { 184 DiagID = diag::warn_mismatched_exception_spec; 185 ReturnValueOnError = false; 186 } 187 188 // Check the types as written: they must match before any exception 189 // specification adjustment is applied. 190 if (!CheckEquivalentExceptionSpec( 191 PDiag(DiagID), PDiag(diag::note_previous_declaration), 192 Old->getType()->getAs<FunctionProtoType>(), Old->getLocation(), 193 New->getType()->getAs<FunctionProtoType>(), New->getLocation(), 194 &MissingExceptionSpecification, &MissingEmptyExceptionSpecification, 195 /*AllowNoexceptAllMatchWithNoSpec=*/true, IsOperatorNew)) { 196 // C++11 [except.spec]p4 [DR1492]: 197 // If a declaration of a function has an implicit 198 // exception-specification, other declarations of the function shall 199 // not specify an exception-specification. 200 if (getLangOpts().CPlusPlus11 && 201 hasImplicitExceptionSpec(Old) != hasImplicitExceptionSpec(New)) { 202 Diag(New->getLocation(), diag::ext_implicit_exception_spec_mismatch) 203 << hasImplicitExceptionSpec(Old); 204 if (!Old->getLocation().isInvalid()) 205 Diag(Old->getLocation(), diag::note_previous_declaration); 206 } 207 return false; 208 } 209 210 // The failure was something other than an missing exception 211 // specification; return an error, except in MS mode where this is a warning. 212 if (!MissingExceptionSpecification) 213 return ReturnValueOnError; 214 215 const FunctionProtoType *NewProto = 216 New->getType()->castAs<FunctionProtoType>(); 217 218 // The new function declaration is only missing an empty exception 219 // specification "throw()". If the throw() specification came from a 220 // function in a system header that has C linkage, just add an empty 221 // exception specification to the "new" declaration. This is an 222 // egregious workaround for glibc, which adds throw() specifications 223 // to many libc functions as an optimization. Unfortunately, that 224 // optimization isn't permitted by the C++ standard, so we're forced 225 // to work around it here. 226 if (MissingEmptyExceptionSpecification && NewProto && 227 (Old->getLocation().isInvalid() || 228 Context.getSourceManager().isInSystemHeader(Old->getLocation())) && 229 Old->isExternC()) { 230 FunctionProtoType::ExtProtoInfo EPI = NewProto->getExtProtoInfo(); 231 EPI.ExceptionSpecType = EST_DynamicNone; 232 QualType NewType = Context.getFunctionType(NewProto->getReturnType(), 233 NewProto->getParamTypes(), EPI); 234 New->setType(NewType); 235 return false; 236 } 237 238 const FunctionProtoType *OldProto = 239 Old->getType()->castAs<FunctionProtoType>(); 240 241 FunctionProtoType::ExtProtoInfo EPI = NewProto->getExtProtoInfo(); 242 EPI.ExceptionSpecType = OldProto->getExceptionSpecType(); 243 if (EPI.ExceptionSpecType == EST_Dynamic) { 244 EPI.NumExceptions = OldProto->getNumExceptions(); 245 EPI.Exceptions = OldProto->exception_begin(); 246 } else if (EPI.ExceptionSpecType == EST_ComputedNoexcept) { 247 // FIXME: We can't just take the expression from the old prototype. It 248 // likely contains references to the old prototype's parameters. 249 } 250 251 // Update the type of the function with the appropriate exception 252 // specification. 253 QualType NewType = Context.getFunctionType(NewProto->getReturnType(), 254 NewProto->getParamTypes(), EPI); 255 New->setType(NewType); 256 257 // Warn about the lack of exception specification. 258 SmallString<128> ExceptionSpecString; 259 llvm::raw_svector_ostream OS(ExceptionSpecString); 260 switch (OldProto->getExceptionSpecType()) { 261 case EST_DynamicNone: 262 OS << "throw()"; 263 break; 264 265 case EST_Dynamic: { 266 OS << "throw("; 267 bool OnFirstException = true; 268 for (const auto &E : OldProto->exceptions()) { 269 if (OnFirstException) 270 OnFirstException = false; 271 else 272 OS << ", "; 273 274 OS << E.getAsString(getPrintingPolicy()); 275 } 276 OS << ")"; 277 break; 278 } 279 280 case EST_BasicNoexcept: 281 OS << "noexcept"; 282 break; 283 284 case EST_ComputedNoexcept: 285 OS << "noexcept("; 286 OldProto->getNoexceptExpr()->printPretty(OS, nullptr, getPrintingPolicy()); 287 OS << ")"; 288 break; 289 290 default: 291 llvm_unreachable("This spec type is compatible with none."); 292 } 293 OS.flush(); 294 295 SourceLocation FixItLoc; 296 if (TypeSourceInfo *TSInfo = New->getTypeSourceInfo()) { 297 TypeLoc TL = TSInfo->getTypeLoc().IgnoreParens(); 298 if (FunctionTypeLoc FTLoc = TL.getAs<FunctionTypeLoc>()) 299 FixItLoc = getLocForEndOfToken(FTLoc.getLocalRangeEnd()); 300 } 301 302 if (FixItLoc.isInvalid()) 303 Diag(New->getLocation(), diag::warn_missing_exception_specification) 304 << New << OS.str(); 305 else { 306 // FIXME: This will get more complicated with C++0x 307 // late-specified return types. 308 Diag(New->getLocation(), diag::warn_missing_exception_specification) 309 << New << OS.str() 310 << FixItHint::CreateInsertion(FixItLoc, " " + OS.str().str()); 311 } 312 313 if (!Old->getLocation().isInvalid()) 314 Diag(Old->getLocation(), diag::note_previous_declaration); 315 316 return false; 317 } 318 319 /// CheckEquivalentExceptionSpec - Check if the two types have equivalent 320 /// exception specifications. Exception specifications are equivalent if 321 /// they allow exactly the same set of exception types. It does not matter how 322 /// that is achieved. See C++ [except.spec]p2. 323 bool Sema::CheckEquivalentExceptionSpec( 324 const FunctionProtoType *Old, SourceLocation OldLoc, 325 const FunctionProtoType *New, SourceLocation NewLoc) { 326 unsigned DiagID = diag::err_mismatched_exception_spec; 327 if (getLangOpts().MicrosoftExt) 328 DiagID = diag::warn_mismatched_exception_spec; 329 bool Result = CheckEquivalentExceptionSpec(PDiag(DiagID), 330 PDiag(diag::note_previous_declaration), Old, OldLoc, New, NewLoc); 331 332 // In Microsoft mode, mismatching exception specifications just cause a warning. 333 if (getLangOpts().MicrosoftExt) 334 return false; 335 return Result; 336 } 337 338 /// CheckEquivalentExceptionSpec - Check if the two types have compatible 339 /// exception specifications. See C++ [except.spec]p3. 340 /// 341 /// \return \c false if the exception specifications match, \c true if there is 342 /// a problem. If \c true is returned, either a diagnostic has already been 343 /// produced or \c *MissingExceptionSpecification is set to \c true. 344 bool Sema::CheckEquivalentExceptionSpec(const PartialDiagnostic &DiagID, 345 const PartialDiagnostic & NoteID, 346 const FunctionProtoType *Old, 347 SourceLocation OldLoc, 348 const FunctionProtoType *New, 349 SourceLocation NewLoc, 350 bool *MissingExceptionSpecification, 351 bool*MissingEmptyExceptionSpecification, 352 bool AllowNoexceptAllMatchWithNoSpec, 353 bool IsOperatorNew) { 354 // Just completely ignore this under -fno-exceptions. 355 if (!getLangOpts().CXXExceptions) 356 return false; 357 358 if (MissingExceptionSpecification) 359 *MissingExceptionSpecification = false; 360 361 if (MissingEmptyExceptionSpecification) 362 *MissingEmptyExceptionSpecification = false; 363 364 Old = ResolveExceptionSpec(NewLoc, Old); 365 if (!Old) 366 return false; 367 New = ResolveExceptionSpec(NewLoc, New); 368 if (!New) 369 return false; 370 371 // C++0x [except.spec]p3: Two exception-specifications are compatible if: 372 // - both are non-throwing, regardless of their form, 373 // - both have the form noexcept(constant-expression) and the constant- 374 // expressions are equivalent, 375 // - both are dynamic-exception-specifications that have the same set of 376 // adjusted types. 377 // 378 // C++0x [except.spec]p12: An exception-specifcation is non-throwing if it is 379 // of the form throw(), noexcept, or noexcept(constant-expression) where the 380 // constant-expression yields true. 381 // 382 // C++0x [except.spec]p4: If any declaration of a function has an exception- 383 // specifier that is not a noexcept-specification allowing all exceptions, 384 // all declarations [...] of that function shall have a compatible 385 // exception-specification. 386 // 387 // That last point basically means that noexcept(false) matches no spec. 388 // It's considered when AllowNoexceptAllMatchWithNoSpec is true. 389 390 ExceptionSpecificationType OldEST = Old->getExceptionSpecType(); 391 ExceptionSpecificationType NewEST = New->getExceptionSpecType(); 392 393 assert(!isUnresolvedExceptionSpec(OldEST) && 394 !isUnresolvedExceptionSpec(NewEST) && 395 "Shouldn't see unknown exception specifications here"); 396 397 // Shortcut the case where both have no spec. 398 if (OldEST == EST_None && NewEST == EST_None) 399 return false; 400 401 FunctionProtoType::NoexceptResult OldNR = Old->getNoexceptSpec(Context); 402 FunctionProtoType::NoexceptResult NewNR = New->getNoexceptSpec(Context); 403 if (OldNR == FunctionProtoType::NR_BadNoexcept || 404 NewNR == FunctionProtoType::NR_BadNoexcept) 405 return false; 406 407 // Dependent noexcept specifiers are compatible with each other, but nothing 408 // else. 409 // One noexcept is compatible with another if the argument is the same 410 if (OldNR == NewNR && 411 OldNR != FunctionProtoType::NR_NoNoexcept && 412 NewNR != FunctionProtoType::NR_NoNoexcept) 413 return false; 414 if (OldNR != NewNR && 415 OldNR != FunctionProtoType::NR_NoNoexcept && 416 NewNR != FunctionProtoType::NR_NoNoexcept) { 417 Diag(NewLoc, DiagID); 418 if (NoteID.getDiagID() != 0) 419 Diag(OldLoc, NoteID); 420 return true; 421 } 422 423 // The MS extension throw(...) is compatible with itself. 424 if (OldEST == EST_MSAny && NewEST == EST_MSAny) 425 return false; 426 427 // It's also compatible with no spec. 428 if ((OldEST == EST_None && NewEST == EST_MSAny) || 429 (OldEST == EST_MSAny && NewEST == EST_None)) 430 return false; 431 432 // It's also compatible with noexcept(false). 433 if (OldEST == EST_MSAny && NewNR == FunctionProtoType::NR_Throw) 434 return false; 435 if (NewEST == EST_MSAny && OldNR == FunctionProtoType::NR_Throw) 436 return false; 437 438 // As described above, noexcept(false) matches no spec only for functions. 439 if (AllowNoexceptAllMatchWithNoSpec) { 440 if (OldEST == EST_None && NewNR == FunctionProtoType::NR_Throw) 441 return false; 442 if (NewEST == EST_None && OldNR == FunctionProtoType::NR_Throw) 443 return false; 444 } 445 446 // Any non-throwing specifications are compatible. 447 bool OldNonThrowing = OldNR == FunctionProtoType::NR_Nothrow || 448 OldEST == EST_DynamicNone; 449 bool NewNonThrowing = NewNR == FunctionProtoType::NR_Nothrow || 450 NewEST == EST_DynamicNone; 451 if (OldNonThrowing && NewNonThrowing) 452 return false; 453 454 // As a special compatibility feature, under C++0x we accept no spec and 455 // throw(std::bad_alloc) as equivalent for operator new and operator new[]. 456 // This is because the implicit declaration changed, but old code would break. 457 if (getLangOpts().CPlusPlus11 && IsOperatorNew) { 458 const FunctionProtoType *WithExceptions = nullptr; 459 if (OldEST == EST_None && NewEST == EST_Dynamic) 460 WithExceptions = New; 461 else if (OldEST == EST_Dynamic && NewEST == EST_None) 462 WithExceptions = Old; 463 if (WithExceptions && WithExceptions->getNumExceptions() == 1) { 464 // One has no spec, the other throw(something). If that something is 465 // std::bad_alloc, all conditions are met. 466 QualType Exception = *WithExceptions->exception_begin(); 467 if (CXXRecordDecl *ExRecord = Exception->getAsCXXRecordDecl()) { 468 IdentifierInfo* Name = ExRecord->getIdentifier(); 469 if (Name && Name->getName() == "bad_alloc") { 470 // It's called bad_alloc, but is it in std? 471 if (ExRecord->isInStdNamespace()) { 472 return false; 473 } 474 } 475 } 476 } 477 } 478 479 // At this point, the only remaining valid case is two matching dynamic 480 // specifications. We return here unless both specifications are dynamic. 481 if (OldEST != EST_Dynamic || NewEST != EST_Dynamic) { 482 if (MissingExceptionSpecification && Old->hasExceptionSpec() && 483 !New->hasExceptionSpec()) { 484 // The old type has an exception specification of some sort, but 485 // the new type does not. 486 *MissingExceptionSpecification = true; 487 488 if (MissingEmptyExceptionSpecification && OldNonThrowing) { 489 // The old type has a throw() or noexcept(true) exception specification 490 // and the new type has no exception specification, and the caller asked 491 // to handle this itself. 492 *MissingEmptyExceptionSpecification = true; 493 } 494 495 return true; 496 } 497 498 Diag(NewLoc, DiagID); 499 if (NoteID.getDiagID() != 0) 500 Diag(OldLoc, NoteID); 501 return true; 502 } 503 504 assert(OldEST == EST_Dynamic && NewEST == EST_Dynamic && 505 "Exception compatibility logic error: non-dynamic spec slipped through."); 506 507 bool Success = true; 508 // Both have a dynamic exception spec. Collect the first set, then compare 509 // to the second. 510 llvm::SmallPtrSet<CanQualType, 8> OldTypes, NewTypes; 511 for (const auto &I : Old->exceptions()) 512 OldTypes.insert(Context.getCanonicalType(I).getUnqualifiedType()); 513 514 for (const auto &I : New->exceptions()) { 515 CanQualType TypePtr = Context.getCanonicalType(I).getUnqualifiedType(); 516 if(OldTypes.count(TypePtr)) 517 NewTypes.insert(TypePtr); 518 else 519 Success = false; 520 } 521 522 Success = Success && OldTypes.size() == NewTypes.size(); 523 524 if (Success) { 525 return false; 526 } 527 Diag(NewLoc, DiagID); 528 if (NoteID.getDiagID() != 0) 529 Diag(OldLoc, NoteID); 530 return true; 531 } 532 533 /// CheckExceptionSpecSubset - Check whether the second function type's 534 /// exception specification is a subset (or equivalent) of the first function 535 /// type. This is used by override and pointer assignment checks. 536 bool Sema::CheckExceptionSpecSubset( 537 const PartialDiagnostic &DiagID, const PartialDiagnostic & NoteID, 538 const FunctionProtoType *Superset, SourceLocation SuperLoc, 539 const FunctionProtoType *Subset, SourceLocation SubLoc) { 540 541 // Just auto-succeed under -fno-exceptions. 542 if (!getLangOpts().CXXExceptions) 543 return false; 544 545 // FIXME: As usual, we could be more specific in our error messages, but 546 // that better waits until we've got types with source locations. 547 548 if (!SubLoc.isValid()) 549 SubLoc = SuperLoc; 550 551 // Resolve the exception specifications, if needed. 552 Superset = ResolveExceptionSpec(SuperLoc, Superset); 553 if (!Superset) 554 return false; 555 Subset = ResolveExceptionSpec(SubLoc, Subset); 556 if (!Subset) 557 return false; 558 559 ExceptionSpecificationType SuperEST = Superset->getExceptionSpecType(); 560 561 // If superset contains everything, we're done. 562 if (SuperEST == EST_None || SuperEST == EST_MSAny) 563 return CheckParamExceptionSpec(NoteID, Superset, SuperLoc, Subset, SubLoc); 564 565 // If there are dependent noexcept specs, assume everything is fine. Unlike 566 // with the equivalency check, this is safe in this case, because we don't 567 // want to merge declarations. Checks after instantiation will catch any 568 // omissions we make here. 569 // We also shortcut checking if a noexcept expression was bad. 570 571 FunctionProtoType::NoexceptResult SuperNR =Superset->getNoexceptSpec(Context); 572 if (SuperNR == FunctionProtoType::NR_BadNoexcept || 573 SuperNR == FunctionProtoType::NR_Dependent) 574 return false; 575 576 // Another case of the superset containing everything. 577 if (SuperNR == FunctionProtoType::NR_Throw) 578 return CheckParamExceptionSpec(NoteID, Superset, SuperLoc, Subset, SubLoc); 579 580 ExceptionSpecificationType SubEST = Subset->getExceptionSpecType(); 581 582 assert(!isUnresolvedExceptionSpec(SuperEST) && 583 !isUnresolvedExceptionSpec(SubEST) && 584 "Shouldn't see unknown exception specifications here"); 585 586 // It does not. If the subset contains everything, we've failed. 587 if (SubEST == EST_None || SubEST == EST_MSAny) { 588 Diag(SubLoc, DiagID); 589 if (NoteID.getDiagID() != 0) 590 Diag(SuperLoc, NoteID); 591 return true; 592 } 593 594 FunctionProtoType::NoexceptResult SubNR = Subset->getNoexceptSpec(Context); 595 if (SubNR == FunctionProtoType::NR_BadNoexcept || 596 SubNR == FunctionProtoType::NR_Dependent) 597 return false; 598 599 // Another case of the subset containing everything. 600 if (SubNR == FunctionProtoType::NR_Throw) { 601 Diag(SubLoc, DiagID); 602 if (NoteID.getDiagID() != 0) 603 Diag(SuperLoc, NoteID); 604 return true; 605 } 606 607 // If the subset contains nothing, we're done. 608 if (SubEST == EST_DynamicNone || SubNR == FunctionProtoType::NR_Nothrow) 609 return CheckParamExceptionSpec(NoteID, Superset, SuperLoc, Subset, SubLoc); 610 611 // Otherwise, if the superset contains nothing, we've failed. 612 if (SuperEST == EST_DynamicNone || SuperNR == FunctionProtoType::NR_Nothrow) { 613 Diag(SubLoc, DiagID); 614 if (NoteID.getDiagID() != 0) 615 Diag(SuperLoc, NoteID); 616 return true; 617 } 618 619 assert(SuperEST == EST_Dynamic && SubEST == EST_Dynamic && 620 "Exception spec subset: non-dynamic case slipped through."); 621 622 // Neither contains everything or nothing. Do a proper comparison. 623 for (const auto &SubI : Subset->exceptions()) { 624 // Take one type from the subset. 625 QualType CanonicalSubT = Context.getCanonicalType(SubI); 626 // Unwrap pointers and references so that we can do checks within a class 627 // hierarchy. Don't unwrap member pointers; they don't have hierarchy 628 // conversions on the pointee. 629 bool SubIsPointer = false; 630 if (const ReferenceType *RefTy = CanonicalSubT->getAs<ReferenceType>()) 631 CanonicalSubT = RefTy->getPointeeType(); 632 if (const PointerType *PtrTy = CanonicalSubT->getAs<PointerType>()) { 633 CanonicalSubT = PtrTy->getPointeeType(); 634 SubIsPointer = true; 635 } 636 bool SubIsClass = CanonicalSubT->isRecordType(); 637 CanonicalSubT = CanonicalSubT.getLocalUnqualifiedType(); 638 639 CXXBasePaths Paths(/*FindAmbiguities=*/true, /*RecordPaths=*/true, 640 /*DetectVirtual=*/false); 641 642 bool Contained = false; 643 // Make sure it's in the superset. 644 for (const auto &SuperI : Superset->exceptions()) { 645 QualType CanonicalSuperT = Context.getCanonicalType(SuperI); 646 // SubT must be SuperT or derived from it, or pointer or reference to 647 // such types. 648 if (const ReferenceType *RefTy = CanonicalSuperT->getAs<ReferenceType>()) 649 CanonicalSuperT = RefTy->getPointeeType(); 650 if (SubIsPointer) { 651 if (const PointerType *PtrTy = CanonicalSuperT->getAs<PointerType>()) 652 CanonicalSuperT = PtrTy->getPointeeType(); 653 else { 654 continue; 655 } 656 } 657 CanonicalSuperT = CanonicalSuperT.getLocalUnqualifiedType(); 658 // If the types are the same, move on to the next type in the subset. 659 if (CanonicalSubT == CanonicalSuperT) { 660 Contained = true; 661 break; 662 } 663 664 // Otherwise we need to check the inheritance. 665 if (!SubIsClass || !CanonicalSuperT->isRecordType()) 666 continue; 667 668 Paths.clear(); 669 if (!IsDerivedFrom(CanonicalSubT, CanonicalSuperT, Paths)) 670 continue; 671 672 if (Paths.isAmbiguous(Context.getCanonicalType(CanonicalSuperT))) 673 continue; 674 675 // Do this check from a context without privileges. 676 switch (CheckBaseClassAccess(SourceLocation(), 677 CanonicalSuperT, CanonicalSubT, 678 Paths.front(), 679 /*Diagnostic*/ 0, 680 /*ForceCheck*/ true, 681 /*ForceUnprivileged*/ true)) { 682 case AR_accessible: break; 683 case AR_inaccessible: continue; 684 case AR_dependent: 685 llvm_unreachable("access check dependent for unprivileged context"); 686 case AR_delayed: 687 llvm_unreachable("access check delayed in non-declaration"); 688 } 689 690 Contained = true; 691 break; 692 } 693 if (!Contained) { 694 Diag(SubLoc, DiagID); 695 if (NoteID.getDiagID() != 0) 696 Diag(SuperLoc, NoteID); 697 return true; 698 } 699 } 700 // We've run half the gauntlet. 701 return CheckParamExceptionSpec(NoteID, Superset, SuperLoc, Subset, SubLoc); 702 } 703 704 static bool CheckSpecForTypesEquivalent(Sema &S, 705 const PartialDiagnostic &DiagID, const PartialDiagnostic & NoteID, 706 QualType Target, SourceLocation TargetLoc, 707 QualType Source, SourceLocation SourceLoc) 708 { 709 const FunctionProtoType *TFunc = GetUnderlyingFunction(Target); 710 if (!TFunc) 711 return false; 712 const FunctionProtoType *SFunc = GetUnderlyingFunction(Source); 713 if (!SFunc) 714 return false; 715 716 return S.CheckEquivalentExceptionSpec(DiagID, NoteID, TFunc, TargetLoc, 717 SFunc, SourceLoc); 718 } 719 720 /// CheckParamExceptionSpec - Check if the parameter and return types of the 721 /// two functions have equivalent exception specs. This is part of the 722 /// assignment and override compatibility check. We do not check the parameters 723 /// of parameter function pointers recursively, as no sane programmer would 724 /// even be able to write such a function type. 725 bool Sema::CheckParamExceptionSpec(const PartialDiagnostic & NoteID, 726 const FunctionProtoType *Target, SourceLocation TargetLoc, 727 const FunctionProtoType *Source, SourceLocation SourceLoc) 728 { 729 if (CheckSpecForTypesEquivalent( 730 *this, PDiag(diag::err_deep_exception_specs_differ) << 0, PDiag(), 731 Target->getReturnType(), TargetLoc, Source->getReturnType(), 732 SourceLoc)) 733 return true; 734 735 // We shouldn't even be testing this unless the arguments are otherwise 736 // compatible. 737 assert(Target->getNumParams() == Source->getNumParams() && 738 "Functions have different argument counts."); 739 for (unsigned i = 0, E = Target->getNumParams(); i != E; ++i) { 740 if (CheckSpecForTypesEquivalent( 741 *this, PDiag(diag::err_deep_exception_specs_differ) << 1, PDiag(), 742 Target->getParamType(i), TargetLoc, Source->getParamType(i), 743 SourceLoc)) 744 return true; 745 } 746 return false; 747 } 748 749 bool Sema::CheckExceptionSpecCompatibility(Expr *From, QualType ToType) 750 { 751 // First we check for applicability. 752 // Target type must be a function, function pointer or function reference. 753 const FunctionProtoType *ToFunc = GetUnderlyingFunction(ToType); 754 if (!ToFunc) 755 return false; 756 757 // SourceType must be a function or function pointer. 758 const FunctionProtoType *FromFunc = GetUnderlyingFunction(From->getType()); 759 if (!FromFunc) 760 return false; 761 762 // Now we've got the correct types on both sides, check their compatibility. 763 // This means that the source of the conversion can only throw a subset of 764 // the exceptions of the target, and any exception specs on arguments or 765 // return types must be equivalent. 766 return CheckExceptionSpecSubset(PDiag(diag::err_incompatible_exception_specs), 767 PDiag(), ToFunc, 768 From->getSourceRange().getBegin(), 769 FromFunc, SourceLocation()); 770 } 771 772 bool Sema::CheckOverridingFunctionExceptionSpec(const CXXMethodDecl *New, 773 const CXXMethodDecl *Old) { 774 if (getLangOpts().CPlusPlus11 && isa<CXXDestructorDecl>(New)) { 775 // Don't check uninstantiated template destructors at all. We can only 776 // synthesize correct specs after the template is instantiated. 777 if (New->getParent()->isDependentType()) 778 return false; 779 if (New->getParent()->isBeingDefined()) { 780 // The destructor might be updated once the definition is finished. So 781 // remember it and check later. 782 DelayedDestructorExceptionSpecChecks.push_back(std::make_pair( 783 cast<CXXDestructorDecl>(New), cast<CXXDestructorDecl>(Old))); 784 return false; 785 } 786 } 787 unsigned DiagID = diag::err_override_exception_spec; 788 if (getLangOpts().MicrosoftExt) 789 DiagID = diag::warn_override_exception_spec; 790 return CheckExceptionSpecSubset(PDiag(DiagID), 791 PDiag(diag::note_overridden_virtual_function), 792 Old->getType()->getAs<FunctionProtoType>(), 793 Old->getLocation(), 794 New->getType()->getAs<FunctionProtoType>(), 795 New->getLocation()); 796 } 797 798 static CanThrowResult canSubExprsThrow(Sema &S, const Expr *CE) { 799 Expr *E = const_cast<Expr*>(CE); 800 CanThrowResult R = CT_Cannot; 801 for (Expr::child_range I = E->children(); I && R != CT_Can; ++I) 802 R = mergeCanThrow(R, S.canThrow(cast<Expr>(*I))); 803 return R; 804 } 805 806 static CanThrowResult canCalleeThrow(Sema &S, const Expr *E, const Decl *D) { 807 assert(D && "Expected decl"); 808 809 // See if we can get a function type from the decl somehow. 810 const ValueDecl *VD = dyn_cast<ValueDecl>(D); 811 if (!VD) // If we have no clue what we're calling, assume the worst. 812 return CT_Can; 813 814 // As an extension, we assume that __attribute__((nothrow)) functions don't 815 // throw. 816 if (isa<FunctionDecl>(D) && D->hasAttr<NoThrowAttr>()) 817 return CT_Cannot; 818 819 QualType T = VD->getType(); 820 const FunctionProtoType *FT; 821 if ((FT = T->getAs<FunctionProtoType>())) { 822 } else if (const PointerType *PT = T->getAs<PointerType>()) 823 FT = PT->getPointeeType()->getAs<FunctionProtoType>(); 824 else if (const ReferenceType *RT = T->getAs<ReferenceType>()) 825 FT = RT->getPointeeType()->getAs<FunctionProtoType>(); 826 else if (const MemberPointerType *MT = T->getAs<MemberPointerType>()) 827 FT = MT->getPointeeType()->getAs<FunctionProtoType>(); 828 else if (const BlockPointerType *BT = T->getAs<BlockPointerType>()) 829 FT = BT->getPointeeType()->getAs<FunctionProtoType>(); 830 831 if (!FT) 832 return CT_Can; 833 834 FT = S.ResolveExceptionSpec(E->getLocStart(), FT); 835 if (!FT) 836 return CT_Can; 837 838 return FT->isNothrow(S.Context) ? CT_Cannot : CT_Can; 839 } 840 841 static CanThrowResult canDynamicCastThrow(const CXXDynamicCastExpr *DC) { 842 if (DC->isTypeDependent()) 843 return CT_Dependent; 844 845 if (!DC->getTypeAsWritten()->isReferenceType()) 846 return CT_Cannot; 847 848 if (DC->getSubExpr()->isTypeDependent()) 849 return CT_Dependent; 850 851 return DC->getCastKind() == clang::CK_Dynamic? CT_Can : CT_Cannot; 852 } 853 854 static CanThrowResult canTypeidThrow(Sema &S, const CXXTypeidExpr *DC) { 855 if (DC->isTypeOperand()) 856 return CT_Cannot; 857 858 Expr *Op = DC->getExprOperand(); 859 if (Op->isTypeDependent()) 860 return CT_Dependent; 861 862 const RecordType *RT = Op->getType()->getAs<RecordType>(); 863 if (!RT) 864 return CT_Cannot; 865 866 if (!cast<CXXRecordDecl>(RT->getDecl())->isPolymorphic()) 867 return CT_Cannot; 868 869 if (Op->Classify(S.Context).isPRValue()) 870 return CT_Cannot; 871 872 return CT_Can; 873 } 874 875 CanThrowResult Sema::canThrow(const Expr *E) { 876 // C++ [expr.unary.noexcept]p3: 877 // [Can throw] if in a potentially-evaluated context the expression would 878 // contain: 879 switch (E->getStmtClass()) { 880 case Expr::CXXThrowExprClass: 881 // - a potentially evaluated throw-expression 882 return CT_Can; 883 884 case Expr::CXXDynamicCastExprClass: { 885 // - a potentially evaluated dynamic_cast expression dynamic_cast<T>(v), 886 // where T is a reference type, that requires a run-time check 887 CanThrowResult CT = canDynamicCastThrow(cast<CXXDynamicCastExpr>(E)); 888 if (CT == CT_Can) 889 return CT; 890 return mergeCanThrow(CT, canSubExprsThrow(*this, E)); 891 } 892 893 case Expr::CXXTypeidExprClass: 894 // - a potentially evaluated typeid expression applied to a glvalue 895 // expression whose type is a polymorphic class type 896 return canTypeidThrow(*this, cast<CXXTypeidExpr>(E)); 897 898 // - a potentially evaluated call to a function, member function, function 899 // pointer, or member function pointer that does not have a non-throwing 900 // exception-specification 901 case Expr::CallExprClass: 902 case Expr::CXXMemberCallExprClass: 903 case Expr::CXXOperatorCallExprClass: 904 case Expr::UserDefinedLiteralClass: { 905 const CallExpr *CE = cast<CallExpr>(E); 906 CanThrowResult CT; 907 if (E->isTypeDependent()) 908 CT = CT_Dependent; 909 else if (isa<CXXPseudoDestructorExpr>(CE->getCallee()->IgnoreParens())) 910 CT = CT_Cannot; 911 else if (CE->getCalleeDecl()) 912 CT = canCalleeThrow(*this, E, CE->getCalleeDecl()); 913 else 914 CT = CT_Can; 915 if (CT == CT_Can) 916 return CT; 917 return mergeCanThrow(CT, canSubExprsThrow(*this, E)); 918 } 919 920 case Expr::CXXConstructExprClass: 921 case Expr::CXXTemporaryObjectExprClass: { 922 CanThrowResult CT = canCalleeThrow(*this, E, 923 cast<CXXConstructExpr>(E)->getConstructor()); 924 if (CT == CT_Can) 925 return CT; 926 return mergeCanThrow(CT, canSubExprsThrow(*this, E)); 927 } 928 929 case Expr::LambdaExprClass: { 930 const LambdaExpr *Lambda = cast<LambdaExpr>(E); 931 CanThrowResult CT = CT_Cannot; 932 for (LambdaExpr::capture_init_iterator Cap = Lambda->capture_init_begin(), 933 CapEnd = Lambda->capture_init_end(); 934 Cap != CapEnd; ++Cap) 935 CT = mergeCanThrow(CT, canThrow(*Cap)); 936 return CT; 937 } 938 939 case Expr::CXXNewExprClass: { 940 CanThrowResult CT; 941 if (E->isTypeDependent()) 942 CT = CT_Dependent; 943 else 944 CT = canCalleeThrow(*this, E, cast<CXXNewExpr>(E)->getOperatorNew()); 945 if (CT == CT_Can) 946 return CT; 947 return mergeCanThrow(CT, canSubExprsThrow(*this, E)); 948 } 949 950 case Expr::CXXDeleteExprClass: { 951 CanThrowResult CT; 952 QualType DTy = cast<CXXDeleteExpr>(E)->getDestroyedType(); 953 if (DTy.isNull() || DTy->isDependentType()) { 954 CT = CT_Dependent; 955 } else { 956 CT = canCalleeThrow(*this, E, 957 cast<CXXDeleteExpr>(E)->getOperatorDelete()); 958 if (const RecordType *RT = DTy->getAs<RecordType>()) { 959 const CXXRecordDecl *RD = cast<CXXRecordDecl>(RT->getDecl()); 960 const CXXDestructorDecl *DD = RD->getDestructor(); 961 if (DD) 962 CT = mergeCanThrow(CT, canCalleeThrow(*this, E, DD)); 963 } 964 if (CT == CT_Can) 965 return CT; 966 } 967 return mergeCanThrow(CT, canSubExprsThrow(*this, E)); 968 } 969 970 case Expr::CXXBindTemporaryExprClass: { 971 // The bound temporary has to be destroyed again, which might throw. 972 CanThrowResult CT = canCalleeThrow(*this, E, 973 cast<CXXBindTemporaryExpr>(E)->getTemporary()->getDestructor()); 974 if (CT == CT_Can) 975 return CT; 976 return mergeCanThrow(CT, canSubExprsThrow(*this, E)); 977 } 978 979 // ObjC message sends are like function calls, but never have exception 980 // specs. 981 case Expr::ObjCMessageExprClass: 982 case Expr::ObjCPropertyRefExprClass: 983 case Expr::ObjCSubscriptRefExprClass: 984 return CT_Can; 985 986 // All the ObjC literals that are implemented as calls are 987 // potentially throwing unless we decide to close off that 988 // possibility. 989 case Expr::ObjCArrayLiteralClass: 990 case Expr::ObjCDictionaryLiteralClass: 991 case Expr::ObjCBoxedExprClass: 992 return CT_Can; 993 994 // Many other things have subexpressions, so we have to test those. 995 // Some are simple: 996 case Expr::ConditionalOperatorClass: 997 case Expr::CompoundLiteralExprClass: 998 case Expr::CXXConstCastExprClass: 999 case Expr::CXXReinterpretCastExprClass: 1000 case Expr::CXXStdInitializerListExprClass: 1001 case Expr::DesignatedInitExprClass: 1002 case Expr::ExprWithCleanupsClass: 1003 case Expr::ExtVectorElementExprClass: 1004 case Expr::InitListExprClass: 1005 case Expr::MemberExprClass: 1006 case Expr::ObjCIsaExprClass: 1007 case Expr::ObjCIvarRefExprClass: 1008 case Expr::ParenExprClass: 1009 case Expr::ParenListExprClass: 1010 case Expr::ShuffleVectorExprClass: 1011 case Expr::ConvertVectorExprClass: 1012 case Expr::VAArgExprClass: 1013 return canSubExprsThrow(*this, E); 1014 1015 // Some might be dependent for other reasons. 1016 case Expr::ArraySubscriptExprClass: 1017 case Expr::BinaryOperatorClass: 1018 case Expr::CompoundAssignOperatorClass: 1019 case Expr::CStyleCastExprClass: 1020 case Expr::CXXStaticCastExprClass: 1021 case Expr::CXXFunctionalCastExprClass: 1022 case Expr::ImplicitCastExprClass: 1023 case Expr::MaterializeTemporaryExprClass: 1024 case Expr::UnaryOperatorClass: { 1025 CanThrowResult CT = E->isTypeDependent() ? CT_Dependent : CT_Cannot; 1026 return mergeCanThrow(CT, canSubExprsThrow(*this, E)); 1027 } 1028 1029 // FIXME: We should handle StmtExpr, but that opens a MASSIVE can of worms. 1030 case Expr::StmtExprClass: 1031 return CT_Can; 1032 1033 case Expr::CXXDefaultArgExprClass: 1034 return canThrow(cast<CXXDefaultArgExpr>(E)->getExpr()); 1035 1036 case Expr::CXXDefaultInitExprClass: 1037 return canThrow(cast<CXXDefaultInitExpr>(E)->getExpr()); 1038 1039 case Expr::ChooseExprClass: 1040 if (E->isTypeDependent() || E->isValueDependent()) 1041 return CT_Dependent; 1042 return canThrow(cast<ChooseExpr>(E)->getChosenSubExpr()); 1043 1044 case Expr::GenericSelectionExprClass: 1045 if (cast<GenericSelectionExpr>(E)->isResultDependent()) 1046 return CT_Dependent; 1047 return canThrow(cast<GenericSelectionExpr>(E)->getResultExpr()); 1048 1049 // Some expressions are always dependent. 1050 case Expr::CXXDependentScopeMemberExprClass: 1051 case Expr::CXXUnresolvedConstructExprClass: 1052 case Expr::DependentScopeDeclRefExprClass: 1053 return CT_Dependent; 1054 1055 case Expr::AsTypeExprClass: 1056 case Expr::BinaryConditionalOperatorClass: 1057 case Expr::BlockExprClass: 1058 case Expr::CUDAKernelCallExprClass: 1059 case Expr::DeclRefExprClass: 1060 case Expr::ObjCBridgedCastExprClass: 1061 case Expr::ObjCIndirectCopyRestoreExprClass: 1062 case Expr::ObjCProtocolExprClass: 1063 case Expr::ObjCSelectorExprClass: 1064 case Expr::OffsetOfExprClass: 1065 case Expr::PackExpansionExprClass: 1066 case Expr::PseudoObjectExprClass: 1067 case Expr::SubstNonTypeTemplateParmExprClass: 1068 case Expr::SubstNonTypeTemplateParmPackExprClass: 1069 case Expr::FunctionParmPackExprClass: 1070 case Expr::UnaryExprOrTypeTraitExprClass: 1071 case Expr::UnresolvedLookupExprClass: 1072 case Expr::UnresolvedMemberExprClass: 1073 // FIXME: Can any of the above throw? If so, when? 1074 return CT_Cannot; 1075 1076 case Expr::AddrLabelExprClass: 1077 case Expr::ArrayTypeTraitExprClass: 1078 case Expr::AtomicExprClass: 1079 case Expr::TypeTraitExprClass: 1080 case Expr::CXXBoolLiteralExprClass: 1081 case Expr::CXXNoexceptExprClass: 1082 case Expr::CXXNullPtrLiteralExprClass: 1083 case Expr::CXXPseudoDestructorExprClass: 1084 case Expr::CXXScalarValueInitExprClass: 1085 case Expr::CXXThisExprClass: 1086 case Expr::CXXUuidofExprClass: 1087 case Expr::CharacterLiteralClass: 1088 case Expr::ExpressionTraitExprClass: 1089 case Expr::FloatingLiteralClass: 1090 case Expr::GNUNullExprClass: 1091 case Expr::ImaginaryLiteralClass: 1092 case Expr::ImplicitValueInitExprClass: 1093 case Expr::IntegerLiteralClass: 1094 case Expr::ObjCEncodeExprClass: 1095 case Expr::ObjCStringLiteralClass: 1096 case Expr::ObjCBoolLiteralExprClass: 1097 case Expr::OpaqueValueExprClass: 1098 case Expr::PredefinedExprClass: 1099 case Expr::SizeOfPackExprClass: 1100 case Expr::StringLiteralClass: 1101 // These expressions can never throw. 1102 return CT_Cannot; 1103 1104 case Expr::MSPropertyRefExprClass: 1105 llvm_unreachable("Invalid class for expression"); 1106 1107 #define STMT(CLASS, PARENT) case Expr::CLASS##Class: 1108 #define STMT_RANGE(Base, First, Last) 1109 #define LAST_STMT_RANGE(BASE, FIRST, LAST) 1110 #define EXPR(CLASS, PARENT) 1111 #define ABSTRACT_STMT(STMT) 1112 #include "clang/AST/StmtNodes.inc" 1113 case Expr::NoStmtClass: 1114 llvm_unreachable("Invalid class for expression"); 1115 } 1116 llvm_unreachable("Bogus StmtClass"); 1117 } 1118 1119 } // end namespace clang 1120