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 25namespace clang { 26 27static 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. 44bool 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. 98bool 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 113const FunctionProtoType * 114Sema::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 135void 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. 156static 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 175bool 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 assert(OldProto->getNoexceptExpr() != nullptr && "Expected non-null Expr"); 287 OldProto->getNoexceptExpr()->printPretty(OS, nullptr, getPrintingPolicy()); 288 OS << ")"; 289 break; 290 291 default: 292 llvm_unreachable("This spec type is compatible with none."); 293 } 294 OS.flush(); 295 296 SourceLocation FixItLoc; 297 if (TypeSourceInfo *TSInfo = New->getTypeSourceInfo()) { 298 TypeLoc TL = TSInfo->getTypeLoc().IgnoreParens(); 299 if (FunctionTypeLoc FTLoc = TL.getAs<FunctionTypeLoc>()) 300 FixItLoc = getLocForEndOfToken(FTLoc.getLocalRangeEnd()); 301 } 302 303 if (FixItLoc.isInvalid()) 304 Diag(New->getLocation(), diag::warn_missing_exception_specification) 305 << New << OS.str(); 306 else { 307 // FIXME: This will get more complicated with C++0x 308 // late-specified return types. 309 Diag(New->getLocation(), diag::warn_missing_exception_specification) 310 << New << OS.str() 311 << FixItHint::CreateInsertion(FixItLoc, " " + OS.str().str()); 312 } 313 314 if (!Old->getLocation().isInvalid()) 315 Diag(Old->getLocation(), diag::note_previous_declaration); 316 317 return false; 318} 319 320/// CheckEquivalentExceptionSpec - Check if the two types have equivalent 321/// exception specifications. Exception specifications are equivalent if 322/// they allow exactly the same set of exception types. It does not matter how 323/// that is achieved. See C++ [except.spec]p2. 324bool Sema::CheckEquivalentExceptionSpec( 325 const FunctionProtoType *Old, SourceLocation OldLoc, 326 const FunctionProtoType *New, SourceLocation NewLoc) { 327 unsigned DiagID = diag::err_mismatched_exception_spec; 328 if (getLangOpts().MicrosoftExt) 329 DiagID = diag::warn_mismatched_exception_spec; 330 bool Result = CheckEquivalentExceptionSpec(PDiag(DiagID), 331 PDiag(diag::note_previous_declaration), Old, OldLoc, New, NewLoc); 332 333 // In Microsoft mode, mismatching exception specifications just cause a warning. 334 if (getLangOpts().MicrosoftExt) 335 return false; 336 return Result; 337} 338 339/// CheckEquivalentExceptionSpec - Check if the two types have compatible 340/// exception specifications. See C++ [except.spec]p3. 341/// 342/// \return \c false if the exception specifications match, \c true if there is 343/// a problem. If \c true is returned, either a diagnostic has already been 344/// produced or \c *MissingExceptionSpecification is set to \c true. 345bool Sema::CheckEquivalentExceptionSpec(const PartialDiagnostic &DiagID, 346 const PartialDiagnostic & NoteID, 347 const FunctionProtoType *Old, 348 SourceLocation OldLoc, 349 const FunctionProtoType *New, 350 SourceLocation NewLoc, 351 bool *MissingExceptionSpecification, 352 bool*MissingEmptyExceptionSpecification, 353 bool AllowNoexceptAllMatchWithNoSpec, 354 bool IsOperatorNew) { 355 // Just completely ignore this under -fno-exceptions. 356 if (!getLangOpts().CXXExceptions) 357 return false; 358 359 if (MissingExceptionSpecification) 360 *MissingExceptionSpecification = false; 361 362 if (MissingEmptyExceptionSpecification) 363 *MissingEmptyExceptionSpecification = false; 364 365 Old = ResolveExceptionSpec(NewLoc, Old); 366 if (!Old) 367 return false; 368 New = ResolveExceptionSpec(NewLoc, New); 369 if (!New) 370 return false; 371 372 // C++0x [except.spec]p3: Two exception-specifications are compatible if: 373 // - both are non-throwing, regardless of their form, 374 // - both have the form noexcept(constant-expression) and the constant- 375 // expressions are equivalent, 376 // - both are dynamic-exception-specifications that have the same set of 377 // adjusted types. 378 // 379 // C++0x [except.spec]p12: An exception-specifcation is non-throwing if it is 380 // of the form throw(), noexcept, or noexcept(constant-expression) where the 381 // constant-expression yields true. 382 // 383 // C++0x [except.spec]p4: If any declaration of a function has an exception- 384 // specifier that is not a noexcept-specification allowing all exceptions, 385 // all declarations [...] of that function shall have a compatible 386 // exception-specification. 387 // 388 // That last point basically means that noexcept(false) matches no spec. 389 // It's considered when AllowNoexceptAllMatchWithNoSpec is true. 390 391 ExceptionSpecificationType OldEST = Old->getExceptionSpecType(); 392 ExceptionSpecificationType NewEST = New->getExceptionSpecType(); 393 394 assert(!isUnresolvedExceptionSpec(OldEST) && 395 !isUnresolvedExceptionSpec(NewEST) && 396 "Shouldn't see unknown exception specifications here"); 397 398 // Shortcut the case where both have no spec. 399 if (OldEST == EST_None && NewEST == EST_None) 400 return false; 401 402 FunctionProtoType::NoexceptResult OldNR = Old->getNoexceptSpec(Context); 403 FunctionProtoType::NoexceptResult NewNR = New->getNoexceptSpec(Context); 404 if (OldNR == FunctionProtoType::NR_BadNoexcept || 405 NewNR == FunctionProtoType::NR_BadNoexcept) 406 return false; 407 408 // Dependent noexcept specifiers are compatible with each other, but nothing 409 // else. 410 // One noexcept is compatible with another if the argument is the same 411 if (OldNR == NewNR && 412 OldNR != FunctionProtoType::NR_NoNoexcept && 413 NewNR != FunctionProtoType::NR_NoNoexcept) 414 return false; 415 if (OldNR != NewNR && 416 OldNR != FunctionProtoType::NR_NoNoexcept && 417 NewNR != FunctionProtoType::NR_NoNoexcept) { 418 Diag(NewLoc, DiagID); 419 if (NoteID.getDiagID() != 0) 420 Diag(OldLoc, NoteID); 421 return true; 422 } 423 424 // The MS extension throw(...) is compatible with itself. 425 if (OldEST == EST_MSAny && NewEST == EST_MSAny) 426 return false; 427 428 // It's also compatible with no spec. 429 if ((OldEST == EST_None && NewEST == EST_MSAny) || 430 (OldEST == EST_MSAny && NewEST == EST_None)) 431 return false; 432 433 // It's also compatible with noexcept(false). 434 if (OldEST == EST_MSAny && NewNR == FunctionProtoType::NR_Throw) 435 return false; 436 if (NewEST == EST_MSAny && OldNR == FunctionProtoType::NR_Throw) 437 return false; 438 439 // As described above, noexcept(false) matches no spec only for functions. 440 if (AllowNoexceptAllMatchWithNoSpec) { 441 if (OldEST == EST_None && NewNR == FunctionProtoType::NR_Throw) 442 return false; 443 if (NewEST == EST_None && OldNR == FunctionProtoType::NR_Throw) 444 return false; 445 } 446 447 // Any non-throwing specifications are compatible. 448 bool OldNonThrowing = OldNR == FunctionProtoType::NR_Nothrow || 449 OldEST == EST_DynamicNone; 450 bool NewNonThrowing = NewNR == FunctionProtoType::NR_Nothrow || 451 NewEST == EST_DynamicNone; 452 if (OldNonThrowing && NewNonThrowing) 453 return false; 454 455 // As a special compatibility feature, under C++0x we accept no spec and 456 // throw(std::bad_alloc) as equivalent for operator new and operator new[]. 457 // This is because the implicit declaration changed, but old code would break. 458 if (getLangOpts().CPlusPlus11 && IsOperatorNew) { 459 const FunctionProtoType *WithExceptions = nullptr; 460 if (OldEST == EST_None && NewEST == EST_Dynamic) 461 WithExceptions = New; 462 else if (OldEST == EST_Dynamic && NewEST == EST_None) 463 WithExceptions = Old; 464 if (WithExceptions && WithExceptions->getNumExceptions() == 1) { 465 // One has no spec, the other throw(something). If that something is 466 // std::bad_alloc, all conditions are met. 467 QualType Exception = *WithExceptions->exception_begin(); 468 if (CXXRecordDecl *ExRecord = Exception->getAsCXXRecordDecl()) { 469 IdentifierInfo* Name = ExRecord->getIdentifier(); 470 if (Name && Name->getName() == "bad_alloc") { 471 // It's called bad_alloc, but is it in std? 472 if (ExRecord->isInStdNamespace()) { 473 return false; 474 } 475 } 476 } 477 } 478 } 479 480 // At this point, the only remaining valid case is two matching dynamic 481 // specifications. We return here unless both specifications are dynamic. 482 if (OldEST != EST_Dynamic || NewEST != EST_Dynamic) { 483 if (MissingExceptionSpecification && Old->hasExceptionSpec() && 484 !New->hasExceptionSpec()) { 485 // The old type has an exception specification of some sort, but 486 // the new type does not. 487 *MissingExceptionSpecification = true; 488 489 if (MissingEmptyExceptionSpecification && OldNonThrowing) { 490 // The old type has a throw() or noexcept(true) exception specification 491 // and the new type has no exception specification, and the caller asked 492 // to handle this itself. 493 *MissingEmptyExceptionSpecification = true; 494 } 495 496 return true; 497 } 498 499 Diag(NewLoc, DiagID); 500 if (NoteID.getDiagID() != 0) 501 Diag(OldLoc, NoteID); 502 return true; 503 } 504 505 assert(OldEST == EST_Dynamic && NewEST == EST_Dynamic && 506 "Exception compatibility logic error: non-dynamic spec slipped through."); 507 508 bool Success = true; 509 // Both have a dynamic exception spec. Collect the first set, then compare 510 // to the second. 511 llvm::SmallPtrSet<CanQualType, 8> OldTypes, NewTypes; 512 for (const auto &I : Old->exceptions()) 513 OldTypes.insert(Context.getCanonicalType(I).getUnqualifiedType()); 514 515 for (const auto &I : New->exceptions()) { 516 CanQualType TypePtr = Context.getCanonicalType(I).getUnqualifiedType(); 517 if(OldTypes.count(TypePtr)) 518 NewTypes.insert(TypePtr); 519 else 520 Success = false; 521 } 522 523 Success = Success && OldTypes.size() == NewTypes.size(); 524 525 if (Success) { 526 return false; 527 } 528 Diag(NewLoc, DiagID); 529 if (NoteID.getDiagID() != 0) 530 Diag(OldLoc, NoteID); 531 return true; 532} 533 534/// CheckExceptionSpecSubset - Check whether the second function type's 535/// exception specification is a subset (or equivalent) of the first function 536/// type. This is used by override and pointer assignment checks. 537bool Sema::CheckExceptionSpecSubset( 538 const PartialDiagnostic &DiagID, const PartialDiagnostic & NoteID, 539 const FunctionProtoType *Superset, SourceLocation SuperLoc, 540 const FunctionProtoType *Subset, SourceLocation SubLoc) { 541 542 // Just auto-succeed under -fno-exceptions. 543 if (!getLangOpts().CXXExceptions) 544 return false; 545 546 // FIXME: As usual, we could be more specific in our error messages, but 547 // that better waits until we've got types with source locations. 548 549 if (!SubLoc.isValid()) 550 SubLoc = SuperLoc; 551 552 // Resolve the exception specifications, if needed. 553 Superset = ResolveExceptionSpec(SuperLoc, Superset); 554 if (!Superset) 555 return false; 556 Subset = ResolveExceptionSpec(SubLoc, Subset); 557 if (!Subset) 558 return false; 559 560 ExceptionSpecificationType SuperEST = Superset->getExceptionSpecType(); 561 562 // If superset contains everything, we're done. 563 if (SuperEST == EST_None || SuperEST == EST_MSAny) 564 return CheckParamExceptionSpec(NoteID, Superset, SuperLoc, Subset, SubLoc); 565 566 // If there are dependent noexcept specs, assume everything is fine. Unlike 567 // with the equivalency check, this is safe in this case, because we don't 568 // want to merge declarations. Checks after instantiation will catch any 569 // omissions we make here. 570 // We also shortcut checking if a noexcept expression was bad. 571 572 FunctionProtoType::NoexceptResult SuperNR =Superset->getNoexceptSpec(Context); 573 if (SuperNR == FunctionProtoType::NR_BadNoexcept || 574 SuperNR == FunctionProtoType::NR_Dependent) 575 return false; 576 577 // Another case of the superset containing everything. 578 if (SuperNR == FunctionProtoType::NR_Throw) 579 return CheckParamExceptionSpec(NoteID, Superset, SuperLoc, Subset, SubLoc); 580 581 ExceptionSpecificationType SubEST = Subset->getExceptionSpecType(); 582 583 assert(!isUnresolvedExceptionSpec(SuperEST) && 584 !isUnresolvedExceptionSpec(SubEST) && 585 "Shouldn't see unknown exception specifications here"); 586 587 // It does not. If the subset contains everything, we've failed. 588 if (SubEST == EST_None || SubEST == EST_MSAny) { 589 Diag(SubLoc, DiagID); 590 if (NoteID.getDiagID() != 0) 591 Diag(SuperLoc, NoteID); 592 return true; 593 } 594 595 FunctionProtoType::NoexceptResult SubNR = Subset->getNoexceptSpec(Context); 596 if (SubNR == FunctionProtoType::NR_BadNoexcept || 597 SubNR == FunctionProtoType::NR_Dependent) 598 return false; 599 600 // Another case of the subset containing everything. 601 if (SubNR == FunctionProtoType::NR_Throw) { 602 Diag(SubLoc, DiagID); 603 if (NoteID.getDiagID() != 0) 604 Diag(SuperLoc, NoteID); 605 return true; 606 } 607 608 // If the subset contains nothing, we're done. 609 if (SubEST == EST_DynamicNone || SubNR == FunctionProtoType::NR_Nothrow) 610 return CheckParamExceptionSpec(NoteID, Superset, SuperLoc, Subset, SubLoc); 611 612 // Otherwise, if the superset contains nothing, we've failed. 613 if (SuperEST == EST_DynamicNone || SuperNR == FunctionProtoType::NR_Nothrow) { 614 Diag(SubLoc, DiagID); 615 if (NoteID.getDiagID() != 0) 616 Diag(SuperLoc, NoteID); 617 return true; 618 } 619 620 assert(SuperEST == EST_Dynamic && SubEST == EST_Dynamic && 621 "Exception spec subset: non-dynamic case slipped through."); 622 623 // Neither contains everything or nothing. Do a proper comparison. 624 for (const auto &SubI : Subset->exceptions()) { 625 // Take one type from the subset. 626 QualType CanonicalSubT = Context.getCanonicalType(SubI); 627 // Unwrap pointers and references so that we can do checks within a class 628 // hierarchy. Don't unwrap member pointers; they don't have hierarchy 629 // conversions on the pointee. 630 bool SubIsPointer = false; 631 if (const ReferenceType *RefTy = CanonicalSubT->getAs<ReferenceType>()) 632 CanonicalSubT = RefTy->getPointeeType(); 633 if (const PointerType *PtrTy = CanonicalSubT->getAs<PointerType>()) { 634 CanonicalSubT = PtrTy->getPointeeType(); 635 SubIsPointer = true; 636 } 637 bool SubIsClass = CanonicalSubT->isRecordType(); 638 CanonicalSubT = CanonicalSubT.getLocalUnqualifiedType(); 639 640 CXXBasePaths Paths(/*FindAmbiguities=*/true, /*RecordPaths=*/true, 641 /*DetectVirtual=*/false); 642 643 bool Contained = false; 644 // Make sure it's in the superset. 645 for (const auto &SuperI : Superset->exceptions()) { 646 QualType CanonicalSuperT = Context.getCanonicalType(SuperI); 647 // SubT must be SuperT or derived from it, or pointer or reference to 648 // such types. 649 if (const ReferenceType *RefTy = CanonicalSuperT->getAs<ReferenceType>()) 650 CanonicalSuperT = RefTy->getPointeeType(); 651 if (SubIsPointer) { 652 if (const PointerType *PtrTy = CanonicalSuperT->getAs<PointerType>()) 653 CanonicalSuperT = PtrTy->getPointeeType(); 654 else { 655 continue; 656 } 657 } 658 CanonicalSuperT = CanonicalSuperT.getLocalUnqualifiedType(); 659 // If the types are the same, move on to the next type in the subset. 660 if (CanonicalSubT == CanonicalSuperT) { 661 Contained = true; 662 break; 663 } 664 665 // Otherwise we need to check the inheritance. 666 if (!SubIsClass || !CanonicalSuperT->isRecordType()) 667 continue; 668 669 Paths.clear(); 670 if (!IsDerivedFrom(CanonicalSubT, CanonicalSuperT, Paths)) 671 continue; 672 673 if (Paths.isAmbiguous(Context.getCanonicalType(CanonicalSuperT))) 674 continue; 675 676 // Do this check from a context without privileges. 677 switch (CheckBaseClassAccess(SourceLocation(), 678 CanonicalSuperT, CanonicalSubT, 679 Paths.front(), 680 /*Diagnostic*/ 0, 681 /*ForceCheck*/ true, 682 /*ForceUnprivileged*/ true)) { 683 case AR_accessible: break; 684 case AR_inaccessible: continue; 685 case AR_dependent: 686 llvm_unreachable("access check dependent for unprivileged context"); 687 case AR_delayed: 688 llvm_unreachable("access check delayed in non-declaration"); 689 } 690 691 Contained = true; 692 break; 693 } 694 if (!Contained) { 695 Diag(SubLoc, DiagID); 696 if (NoteID.getDiagID() != 0) 697 Diag(SuperLoc, NoteID); 698 return true; 699 } 700 } 701 // We've run half the gauntlet. 702 return CheckParamExceptionSpec(NoteID, Superset, SuperLoc, Subset, SubLoc); 703} 704 705static bool CheckSpecForTypesEquivalent(Sema &S, 706 const PartialDiagnostic &DiagID, const PartialDiagnostic & NoteID, 707 QualType Target, SourceLocation TargetLoc, 708 QualType Source, SourceLocation SourceLoc) 709{ 710 const FunctionProtoType *TFunc = GetUnderlyingFunction(Target); 711 if (!TFunc) 712 return false; 713 const FunctionProtoType *SFunc = GetUnderlyingFunction(Source); 714 if (!SFunc) 715 return false; 716 717 return S.CheckEquivalentExceptionSpec(DiagID, NoteID, TFunc, TargetLoc, 718 SFunc, SourceLoc); 719} 720 721/// CheckParamExceptionSpec - Check if the parameter and return types of the 722/// two functions have equivalent exception specs. This is part of the 723/// assignment and override compatibility check. We do not check the parameters 724/// of parameter function pointers recursively, as no sane programmer would 725/// even be able to write such a function type. 726bool Sema::CheckParamExceptionSpec(const PartialDiagnostic & NoteID, 727 const FunctionProtoType *Target, SourceLocation TargetLoc, 728 const FunctionProtoType *Source, SourceLocation SourceLoc) 729{ 730 if (CheckSpecForTypesEquivalent( 731 *this, PDiag(diag::err_deep_exception_specs_differ) << 0, PDiag(), 732 Target->getReturnType(), TargetLoc, Source->getReturnType(), 733 SourceLoc)) 734 return true; 735 736 // We shouldn't even be testing this unless the arguments are otherwise 737 // compatible. 738 assert(Target->getNumParams() == Source->getNumParams() && 739 "Functions have different argument counts."); 740 for (unsigned i = 0, E = Target->getNumParams(); i != E; ++i) { 741 if (CheckSpecForTypesEquivalent( 742 *this, PDiag(diag::err_deep_exception_specs_differ) << 1, PDiag(), 743 Target->getParamType(i), TargetLoc, Source->getParamType(i), 744 SourceLoc)) 745 return true; 746 } 747 return false; 748} 749 750bool Sema::CheckExceptionSpecCompatibility(Expr *From, QualType ToType) 751{ 752 // First we check for applicability. 753 // Target type must be a function, function pointer or function reference. 754 const FunctionProtoType *ToFunc = GetUnderlyingFunction(ToType); 755 if (!ToFunc) 756 return false; 757 758 // SourceType must be a function or function pointer. 759 const FunctionProtoType *FromFunc = GetUnderlyingFunction(From->getType()); 760 if (!FromFunc) 761 return false; 762 763 // Now we've got the correct types on both sides, check their compatibility. 764 // This means that the source of the conversion can only throw a subset of 765 // the exceptions of the target, and any exception specs on arguments or 766 // return types must be equivalent. 767 return CheckExceptionSpecSubset(PDiag(diag::err_incompatible_exception_specs), 768 PDiag(), ToFunc, 769 From->getSourceRange().getBegin(), 770 FromFunc, SourceLocation()); 771} 772 773bool Sema::CheckOverridingFunctionExceptionSpec(const CXXMethodDecl *New, 774 const CXXMethodDecl *Old) { 775 if (getLangOpts().CPlusPlus11 && isa<CXXDestructorDecl>(New)) { 776 // Don't check uninstantiated template destructors at all. We can only 777 // synthesize correct specs after the template is instantiated. 778 if (New->getParent()->isDependentType()) 779 return false; 780 if (New->getParent()->isBeingDefined()) { 781 // The destructor might be updated once the definition is finished. So 782 // remember it and check later. 783 DelayedDestructorExceptionSpecChecks.push_back(std::make_pair( 784 cast<CXXDestructorDecl>(New), cast<CXXDestructorDecl>(Old))); 785 return false; 786 } 787 } 788 unsigned DiagID = diag::err_override_exception_spec; 789 if (getLangOpts().MicrosoftExt) 790 DiagID = diag::warn_override_exception_spec; 791 return CheckExceptionSpecSubset(PDiag(DiagID), 792 PDiag(diag::note_overridden_virtual_function), 793 Old->getType()->getAs<FunctionProtoType>(), 794 Old->getLocation(), 795 New->getType()->getAs<FunctionProtoType>(), 796 New->getLocation()); 797} 798 799static CanThrowResult canSubExprsThrow(Sema &S, const Expr *CE) { 800 Expr *E = const_cast<Expr*>(CE); 801 CanThrowResult R = CT_Cannot; 802 for (Expr::child_range I = E->children(); I && R != CT_Can; ++I) 803 R = mergeCanThrow(R, S.canThrow(cast<Expr>(*I))); 804 return R; 805} 806 807static CanThrowResult canCalleeThrow(Sema &S, const Expr *E, const Decl *D) { 808 assert(D && "Expected decl"); 809 810 // See if we can get a function type from the decl somehow. 811 const ValueDecl *VD = dyn_cast<ValueDecl>(D); 812 if (!VD) // If we have no clue what we're calling, assume the worst. 813 return CT_Can; 814 815 // As an extension, we assume that __attribute__((nothrow)) functions don't 816 // throw. 817 if (isa<FunctionDecl>(D) && D->hasAttr<NoThrowAttr>()) 818 return CT_Cannot; 819 820 QualType T = VD->getType(); 821 const FunctionProtoType *FT; 822 if ((FT = T->getAs<FunctionProtoType>())) { 823 } else if (const PointerType *PT = T->getAs<PointerType>()) 824 FT = PT->getPointeeType()->getAs<FunctionProtoType>(); 825 else if (const ReferenceType *RT = T->getAs<ReferenceType>()) 826 FT = RT->getPointeeType()->getAs<FunctionProtoType>(); 827 else if (const MemberPointerType *MT = T->getAs<MemberPointerType>()) 828 FT = MT->getPointeeType()->getAs<FunctionProtoType>(); 829 else if (const BlockPointerType *BT = T->getAs<BlockPointerType>()) 830 FT = BT->getPointeeType()->getAs<FunctionProtoType>(); 831 832 if (!FT) 833 return CT_Can; 834 835 FT = S.ResolveExceptionSpec(E->getLocStart(), FT); 836 if (!FT) 837 return CT_Can; 838 839 return FT->isNothrow(S.Context) ? CT_Cannot : CT_Can; 840} 841 842static CanThrowResult canDynamicCastThrow(const CXXDynamicCastExpr *DC) { 843 if (DC->isTypeDependent()) 844 return CT_Dependent; 845 846 if (!DC->getTypeAsWritten()->isReferenceType()) 847 return CT_Cannot; 848 849 if (DC->getSubExpr()->isTypeDependent()) 850 return CT_Dependent; 851 852 return DC->getCastKind() == clang::CK_Dynamic? CT_Can : CT_Cannot; 853} 854 855static CanThrowResult canTypeidThrow(Sema &S, const CXXTypeidExpr *DC) { 856 if (DC->isTypeOperand()) 857 return CT_Cannot; 858 859 Expr *Op = DC->getExprOperand(); 860 if (Op->isTypeDependent()) 861 return CT_Dependent; 862 863 const RecordType *RT = Op->getType()->getAs<RecordType>(); 864 if (!RT) 865 return CT_Cannot; 866 867 if (!cast<CXXRecordDecl>(RT->getDecl())->isPolymorphic()) 868 return CT_Cannot; 869 870 if (Op->Classify(S.Context).isPRValue()) 871 return CT_Cannot; 872 873 return CT_Can; 874} 875 876CanThrowResult Sema::canThrow(const Expr *E) { 877 // C++ [expr.unary.noexcept]p3: 878 // [Can throw] if in a potentially-evaluated context the expression would 879 // contain: 880 switch (E->getStmtClass()) { 881 case Expr::CXXThrowExprClass: 882 // - a potentially evaluated throw-expression 883 return CT_Can; 884 885 case Expr::CXXDynamicCastExprClass: { 886 // - a potentially evaluated dynamic_cast expression dynamic_cast<T>(v), 887 // where T is a reference type, that requires a run-time check 888 CanThrowResult CT = canDynamicCastThrow(cast<CXXDynamicCastExpr>(E)); 889 if (CT == CT_Can) 890 return CT; 891 return mergeCanThrow(CT, canSubExprsThrow(*this, E)); 892 } 893 894 case Expr::CXXTypeidExprClass: 895 // - a potentially evaluated typeid expression applied to a glvalue 896 // expression whose type is a polymorphic class type 897 return canTypeidThrow(*this, cast<CXXTypeidExpr>(E)); 898 899 // - a potentially evaluated call to a function, member function, function 900 // pointer, or member function pointer that does not have a non-throwing 901 // exception-specification 902 case Expr::CallExprClass: 903 case Expr::CXXMemberCallExprClass: 904 case Expr::CXXOperatorCallExprClass: 905 case Expr::UserDefinedLiteralClass: { 906 const CallExpr *CE = cast<CallExpr>(E); 907 CanThrowResult CT; 908 if (E->isTypeDependent()) 909 CT = CT_Dependent; 910 else if (isa<CXXPseudoDestructorExpr>(CE->getCallee()->IgnoreParens())) 911 CT = CT_Cannot; 912 else if (CE->getCalleeDecl()) 913 CT = canCalleeThrow(*this, E, CE->getCalleeDecl()); 914 else 915 CT = CT_Can; 916 if (CT == CT_Can) 917 return CT; 918 return mergeCanThrow(CT, canSubExprsThrow(*this, E)); 919 } 920 921 case Expr::CXXConstructExprClass: 922 case Expr::CXXTemporaryObjectExprClass: { 923 CanThrowResult CT = canCalleeThrow(*this, E, 924 cast<CXXConstructExpr>(E)->getConstructor()); 925 if (CT == CT_Can) 926 return CT; 927 return mergeCanThrow(CT, canSubExprsThrow(*this, E)); 928 } 929 930 case Expr::LambdaExprClass: { 931 const LambdaExpr *Lambda = cast<LambdaExpr>(E); 932 CanThrowResult CT = CT_Cannot; 933 for (LambdaExpr::capture_init_iterator Cap = Lambda->capture_init_begin(), 934 CapEnd = Lambda->capture_init_end(); 935 Cap != CapEnd; ++Cap) 936 CT = mergeCanThrow(CT, canThrow(*Cap)); 937 return CT; 938 } 939 940 case Expr::CXXNewExprClass: { 941 CanThrowResult CT; 942 if (E->isTypeDependent()) 943 CT = CT_Dependent; 944 else 945 CT = canCalleeThrow(*this, E, cast<CXXNewExpr>(E)->getOperatorNew()); 946 if (CT == CT_Can) 947 return CT; 948 return mergeCanThrow(CT, canSubExprsThrow(*this, E)); 949 } 950 951 case Expr::CXXDeleteExprClass: { 952 CanThrowResult CT; 953 QualType DTy = cast<CXXDeleteExpr>(E)->getDestroyedType(); 954 if (DTy.isNull() || DTy->isDependentType()) { 955 CT = CT_Dependent; 956 } else { 957 CT = canCalleeThrow(*this, E, 958 cast<CXXDeleteExpr>(E)->getOperatorDelete()); 959 if (const RecordType *RT = DTy->getAs<RecordType>()) { 960 const CXXRecordDecl *RD = cast<CXXRecordDecl>(RT->getDecl()); 961 const CXXDestructorDecl *DD = RD->getDestructor(); 962 if (DD) 963 CT = mergeCanThrow(CT, canCalleeThrow(*this, E, DD)); 964 } 965 if (CT == CT_Can) 966 return CT; 967 } 968 return mergeCanThrow(CT, canSubExprsThrow(*this, E)); 969 } 970 971 case Expr::CXXBindTemporaryExprClass: { 972 // The bound temporary has to be destroyed again, which might throw. 973 CanThrowResult CT = canCalleeThrow(*this, E, 974 cast<CXXBindTemporaryExpr>(E)->getTemporary()->getDestructor()); 975 if (CT == CT_Can) 976 return CT; 977 return mergeCanThrow(CT, canSubExprsThrow(*this, E)); 978 } 979 980 // ObjC message sends are like function calls, but never have exception 981 // specs. 982 case Expr::ObjCMessageExprClass: 983 case Expr::ObjCPropertyRefExprClass: 984 case Expr::ObjCSubscriptRefExprClass: 985 return CT_Can; 986 987 // All the ObjC literals that are implemented as calls are 988 // potentially throwing unless we decide to close off that 989 // possibility. 990 case Expr::ObjCArrayLiteralClass: 991 case Expr::ObjCDictionaryLiteralClass: 992 case Expr::ObjCBoxedExprClass: 993 return CT_Can; 994 995 // Many other things have subexpressions, so we have to test those. 996 // Some are simple: 997 case Expr::ConditionalOperatorClass: 998 case Expr::CompoundLiteralExprClass: 999 case Expr::CXXConstCastExprClass: 1000 case Expr::CXXReinterpretCastExprClass: 1001 case Expr::CXXStdInitializerListExprClass: 1002 case Expr::DesignatedInitExprClass: 1003 case Expr::ExprWithCleanupsClass: 1004 case Expr::ExtVectorElementExprClass: 1005 case Expr::InitListExprClass: 1006 case Expr::MemberExprClass: 1007 case Expr::ObjCIsaExprClass: 1008 case Expr::ObjCIvarRefExprClass: 1009 case Expr::ParenExprClass: 1010 case Expr::ParenListExprClass: 1011 case Expr::ShuffleVectorExprClass: 1012 case Expr::ConvertVectorExprClass: 1013 case Expr::VAArgExprClass: 1014 return canSubExprsThrow(*this, E); 1015 1016 // Some might be dependent for other reasons. 1017 case Expr::ArraySubscriptExprClass: 1018 case Expr::BinaryOperatorClass: 1019 case Expr::CompoundAssignOperatorClass: 1020 case Expr::CStyleCastExprClass: 1021 case Expr::CXXStaticCastExprClass: 1022 case Expr::CXXFunctionalCastExprClass: 1023 case Expr::ImplicitCastExprClass: 1024 case Expr::MaterializeTemporaryExprClass: 1025 case Expr::UnaryOperatorClass: { 1026 CanThrowResult CT = E->isTypeDependent() ? CT_Dependent : CT_Cannot; 1027 return mergeCanThrow(CT, canSubExprsThrow(*this, E)); 1028 } 1029 1030 // FIXME: We should handle StmtExpr, but that opens a MASSIVE can of worms. 1031 case Expr::StmtExprClass: 1032 return CT_Can; 1033 1034 case Expr::CXXDefaultArgExprClass: 1035 return canThrow(cast<CXXDefaultArgExpr>(E)->getExpr()); 1036 1037 case Expr::CXXDefaultInitExprClass: 1038 return canThrow(cast<CXXDefaultInitExpr>(E)->getExpr()); 1039 1040 case Expr::ChooseExprClass: 1041 if (E->isTypeDependent() || E->isValueDependent()) 1042 return CT_Dependent; 1043 return canThrow(cast<ChooseExpr>(E)->getChosenSubExpr()); 1044 1045 case Expr::GenericSelectionExprClass: 1046 if (cast<GenericSelectionExpr>(E)->isResultDependent()) 1047 return CT_Dependent; 1048 return canThrow(cast<GenericSelectionExpr>(E)->getResultExpr()); 1049 1050 // Some expressions are always dependent. 1051 case Expr::CXXDependentScopeMemberExprClass: 1052 case Expr::CXXUnresolvedConstructExprClass: 1053 case Expr::DependentScopeDeclRefExprClass: 1054 return CT_Dependent; 1055 1056 case Expr::AsTypeExprClass: 1057 case Expr::BinaryConditionalOperatorClass: 1058 case Expr::BlockExprClass: 1059 case Expr::CUDAKernelCallExprClass: 1060 case Expr::DeclRefExprClass: 1061 case Expr::ObjCBridgedCastExprClass: 1062 case Expr::ObjCIndirectCopyRestoreExprClass: 1063 case Expr::ObjCProtocolExprClass: 1064 case Expr::ObjCSelectorExprClass: 1065 case Expr::OffsetOfExprClass: 1066 case Expr::PackExpansionExprClass: 1067 case Expr::PseudoObjectExprClass: 1068 case Expr::SubstNonTypeTemplateParmExprClass: 1069 case Expr::SubstNonTypeTemplateParmPackExprClass: 1070 case Expr::FunctionParmPackExprClass: 1071 case Expr::UnaryExprOrTypeTraitExprClass: 1072 case Expr::UnresolvedLookupExprClass: 1073 case Expr::UnresolvedMemberExprClass: 1074 // FIXME: Can any of the above throw? If so, when? 1075 return CT_Cannot; 1076 1077 case Expr::AddrLabelExprClass: 1078 case Expr::ArrayTypeTraitExprClass: 1079 case Expr::AtomicExprClass: 1080 case Expr::TypeTraitExprClass: 1081 case Expr::CXXBoolLiteralExprClass: 1082 case Expr::CXXNoexceptExprClass: 1083 case Expr::CXXNullPtrLiteralExprClass: 1084 case Expr::CXXPseudoDestructorExprClass: 1085 case Expr::CXXScalarValueInitExprClass: 1086 case Expr::CXXThisExprClass: 1087 case Expr::CXXUuidofExprClass: 1088 case Expr::CharacterLiteralClass: 1089 case Expr::ExpressionTraitExprClass: 1090 case Expr::FloatingLiteralClass: 1091 case Expr::GNUNullExprClass: 1092 case Expr::ImaginaryLiteralClass: 1093 case Expr::ImplicitValueInitExprClass: 1094 case Expr::IntegerLiteralClass: 1095 case Expr::ObjCEncodeExprClass: 1096 case Expr::ObjCStringLiteralClass: 1097 case Expr::ObjCBoolLiteralExprClass: 1098 case Expr::OpaqueValueExprClass: 1099 case Expr::PredefinedExprClass: 1100 case Expr::SizeOfPackExprClass: 1101 case Expr::StringLiteralClass: 1102 // These expressions can never throw. 1103 return CT_Cannot; 1104 1105 case Expr::MSPropertyRefExprClass: 1106 llvm_unreachable("Invalid class for expression"); 1107 1108#define STMT(CLASS, PARENT) case Expr::CLASS##Class: 1109#define STMT_RANGE(Base, First, Last) 1110#define LAST_STMT_RANGE(BASE, FIRST, LAST) 1111#define EXPR(CLASS, PARENT) 1112#define ABSTRACT_STMT(STMT) 1113#include "clang/AST/StmtNodes.inc" 1114 case Expr::NoStmtClass: 1115 llvm_unreachable("Invalid class for expression"); 1116 } 1117 llvm_unreachable("Bogus StmtClass"); 1118} 1119 1120} // end namespace clang 1121