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/CXXInheritance.h" 16 #include "clang/AST/Expr.h" 17 #include "clang/AST/ExprCXX.h" 18 #include "clang/AST/TypeLoc.h" 19 #include "clang/Lex/Preprocessor.h" 20 #include "clang/Basic/Diagnostic.h" 21 #include "clang/Basic/SourceManager.h" 22 #include "llvm/ADT/SmallPtrSet.h" 23 24 namespace clang { 25 26 static const FunctionProtoType *GetUnderlyingFunction(QualType T) 27 { 28 if (const PointerType *PtrTy = T->getAs<PointerType>()) 29 T = PtrTy->getPointeeType(); 30 else if (const ReferenceType *RefTy = T->getAs<ReferenceType>()) 31 T = RefTy->getPointeeType(); 32 else if (const MemberPointerType *MPTy = T->getAs<MemberPointerType>()) 33 T = MPTy->getPointeeType(); 34 return T->getAs<FunctionProtoType>(); 35 } 36 37 /// CheckSpecifiedExceptionType - Check if the given type is valid in an 38 /// exception specification. Incomplete types, or pointers to incomplete types 39 /// other than void are not allowed. 40 bool Sema::CheckSpecifiedExceptionType(QualType T, const SourceRange &Range) { 41 42 // This check (and the similar one below) deals with issue 437, that changes 43 // C++ 9.2p2 this way: 44 // Within the class member-specification, the class is regarded as complete 45 // within function bodies, default arguments, exception-specifications, and 46 // constructor ctor-initializers (including such things in nested classes). 47 if (T->isRecordType() && T->getAs<RecordType>()->isBeingDefined()) 48 return false; 49 50 // C++ 15.4p2: A type denoted in an exception-specification shall not denote 51 // an incomplete type. 52 if (RequireCompleteType(Range.getBegin(), T, 53 PDiag(diag::err_incomplete_in_exception_spec) << /*direct*/0 << Range)) 54 return true; 55 56 // C++ 15.4p2: A type denoted in an exception-specification shall not denote 57 // an incomplete type a pointer or reference to an incomplete type, other 58 // than (cv) void*. 59 int kind; 60 if (const PointerType* IT = T->getAs<PointerType>()) { 61 T = IT->getPointeeType(); 62 kind = 1; 63 } else if (const ReferenceType* IT = T->getAs<ReferenceType>()) { 64 T = IT->getPointeeType(); 65 kind = 2; 66 } else 67 return false; 68 69 // Again as before 70 if (T->isRecordType() && T->getAs<RecordType>()->isBeingDefined()) 71 return false; 72 73 if (!T->isVoidType() && RequireCompleteType(Range.getBegin(), T, 74 PDiag(diag::err_incomplete_in_exception_spec) << kind << Range)) 75 return true; 76 77 return false; 78 } 79 80 /// CheckDistantExceptionSpec - Check if the given type is a pointer or pointer 81 /// to member to a function with an exception specification. This means that 82 /// it is invalid to add another level of indirection. 83 bool Sema::CheckDistantExceptionSpec(QualType T) { 84 if (const PointerType *PT = T->getAs<PointerType>()) 85 T = PT->getPointeeType(); 86 else if (const MemberPointerType *PT = T->getAs<MemberPointerType>()) 87 T = PT->getPointeeType(); 88 else 89 return false; 90 91 const FunctionProtoType *FnT = T->getAs<FunctionProtoType>(); 92 if (!FnT) 93 return false; 94 95 return FnT->hasExceptionSpec(); 96 } 97 98 bool Sema::CheckEquivalentExceptionSpec(FunctionDecl *Old, FunctionDecl *New) { 99 OverloadedOperatorKind OO = New->getDeclName().getCXXOverloadedOperator(); 100 bool IsOperatorNew = OO == OO_New || OO == OO_Array_New; 101 bool MissingExceptionSpecification = false; 102 bool MissingEmptyExceptionSpecification = false; 103 unsigned DiagID = diag::err_mismatched_exception_spec; 104 if (getLangOptions().Microsoft) 105 DiagID = diag::war_mismatched_exception_spec; 106 107 if (!CheckEquivalentExceptionSpec(PDiag(DiagID), 108 PDiag(diag::note_previous_declaration), 109 Old->getType()->getAs<FunctionProtoType>(), 110 Old->getLocation(), 111 New->getType()->getAs<FunctionProtoType>(), 112 New->getLocation(), 113 &MissingExceptionSpecification, 114 &MissingEmptyExceptionSpecification, 115 /*AllowNoexceptAllMatchWithNoSpec=*/true, 116 IsOperatorNew)) 117 return false; 118 119 // The failure was something other than an empty exception 120 // specification; return an error. 121 if (!MissingExceptionSpecification && !MissingEmptyExceptionSpecification) 122 return true; 123 124 const FunctionProtoType *NewProto 125 = New->getType()->getAs<FunctionProtoType>(); 126 127 // The new function declaration is only missing an empty exception 128 // specification "throw()". If the throw() specification came from a 129 // function in a system header that has C linkage, just add an empty 130 // exception specification to the "new" declaration. This is an 131 // egregious workaround for glibc, which adds throw() specifications 132 // to many libc functions as an optimization. Unfortunately, that 133 // optimization isn't permitted by the C++ standard, so we're forced 134 // to work around it here. 135 if (MissingEmptyExceptionSpecification && NewProto && 136 (Old->getLocation().isInvalid() || 137 Context.getSourceManager().isInSystemHeader(Old->getLocation())) && 138 Old->isExternC()) { 139 FunctionProtoType::ExtProtoInfo EPI = NewProto->getExtProtoInfo(); 140 EPI.ExceptionSpecType = EST_DynamicNone; 141 QualType NewType = Context.getFunctionType(NewProto->getResultType(), 142 NewProto->arg_type_begin(), 143 NewProto->getNumArgs(), 144 EPI); 145 New->setType(NewType); 146 return false; 147 } 148 149 if (MissingExceptionSpecification && NewProto) { 150 const FunctionProtoType *OldProto 151 = Old->getType()->getAs<FunctionProtoType>(); 152 153 FunctionProtoType::ExtProtoInfo EPI = NewProto->getExtProtoInfo(); 154 EPI.ExceptionSpecType = OldProto->getExceptionSpecType(); 155 if (EPI.ExceptionSpecType == EST_Dynamic) { 156 EPI.NumExceptions = OldProto->getNumExceptions(); 157 EPI.Exceptions = OldProto->exception_begin(); 158 } else if (EPI.ExceptionSpecType == EST_ComputedNoexcept) { 159 // FIXME: We can't just take the expression from the old prototype. It 160 // likely contains references to the old prototype's parameters. 161 } 162 163 // Update the type of the function with the appropriate exception 164 // specification. 165 QualType NewType = Context.getFunctionType(NewProto->getResultType(), 166 NewProto->arg_type_begin(), 167 NewProto->getNumArgs(), 168 EPI); 169 New->setType(NewType); 170 171 // If exceptions are disabled, suppress the warning about missing 172 // exception specifications for new and delete operators. 173 if (!getLangOptions().CXXExceptions) { 174 switch (New->getDeclName().getCXXOverloadedOperator()) { 175 case OO_New: 176 case OO_Array_New: 177 case OO_Delete: 178 case OO_Array_Delete: 179 if (New->getDeclContext()->isTranslationUnit()) 180 return false; 181 break; 182 183 default: 184 break; 185 } 186 } 187 188 // Warn about the lack of exception specification. 189 llvm::SmallString<128> ExceptionSpecString; 190 llvm::raw_svector_ostream OS(ExceptionSpecString); 191 switch (OldProto->getExceptionSpecType()) { 192 case EST_DynamicNone: 193 OS << "throw()"; 194 break; 195 196 case EST_Dynamic: { 197 OS << "throw("; 198 bool OnFirstException = true; 199 for (FunctionProtoType::exception_iterator E = OldProto->exception_begin(), 200 EEnd = OldProto->exception_end(); 201 E != EEnd; 202 ++E) { 203 if (OnFirstException) 204 OnFirstException = false; 205 else 206 OS << ", "; 207 208 OS << E->getAsString(Context.PrintingPolicy); 209 } 210 OS << ")"; 211 break; 212 } 213 214 case EST_BasicNoexcept: 215 OS << "noexcept"; 216 break; 217 218 case EST_ComputedNoexcept: 219 OS << "noexcept("; 220 OldProto->getNoexceptExpr()->printPretty(OS, Context, 0, 221 Context.PrintingPolicy); 222 OS << ")"; 223 break; 224 225 default: 226 assert(false && "This spec type is compatible with none."); 227 } 228 OS.flush(); 229 230 SourceLocation FixItLoc; 231 if (TypeSourceInfo *TSInfo = New->getTypeSourceInfo()) { 232 TypeLoc TL = TSInfo->getTypeLoc().IgnoreParens(); 233 if (const FunctionTypeLoc *FTLoc = dyn_cast<FunctionTypeLoc>(&TL)) 234 FixItLoc = PP.getLocForEndOfToken(FTLoc->getLocalRangeEnd()); 235 } 236 237 if (FixItLoc.isInvalid()) 238 Diag(New->getLocation(), diag::warn_missing_exception_specification) 239 << New << OS.str(); 240 else { 241 // FIXME: This will get more complicated with C++0x 242 // late-specified return types. 243 Diag(New->getLocation(), diag::warn_missing_exception_specification) 244 << New << OS.str() 245 << FixItHint::CreateInsertion(FixItLoc, " " + OS.str().str()); 246 } 247 248 if (!Old->getLocation().isInvalid()) 249 Diag(Old->getLocation(), diag::note_previous_declaration); 250 251 return false; 252 } 253 254 Diag(New->getLocation(), DiagID); 255 Diag(Old->getLocation(), diag::note_previous_declaration); 256 return true; 257 } 258 259 /// CheckEquivalentExceptionSpec - Check if the two types have equivalent 260 /// exception specifications. Exception specifications are equivalent if 261 /// they allow exactly the same set of exception types. It does not matter how 262 /// that is achieved. See C++ [except.spec]p2. 263 bool Sema::CheckEquivalentExceptionSpec( 264 const FunctionProtoType *Old, SourceLocation OldLoc, 265 const FunctionProtoType *New, SourceLocation NewLoc) { 266 unsigned DiagID = diag::err_mismatched_exception_spec; 267 if (getLangOptions().Microsoft) 268 DiagID = diag::war_mismatched_exception_spec; 269 return CheckEquivalentExceptionSpec( 270 PDiag(DiagID), 271 PDiag(diag::note_previous_declaration), 272 Old, OldLoc, New, NewLoc); 273 } 274 275 /// CheckEquivalentExceptionSpec - Check if the two types have compatible 276 /// exception specifications. See C++ [except.spec]p3. 277 bool Sema::CheckEquivalentExceptionSpec(const PartialDiagnostic &DiagID, 278 const PartialDiagnostic & NoteID, 279 const FunctionProtoType *Old, 280 SourceLocation OldLoc, 281 const FunctionProtoType *New, 282 SourceLocation NewLoc, 283 bool *MissingExceptionSpecification, 284 bool*MissingEmptyExceptionSpecification, 285 bool AllowNoexceptAllMatchWithNoSpec, 286 bool IsOperatorNew) { 287 // Just completely ignore this under -fno-exceptions. 288 if (!getLangOptions().CXXExceptions) 289 return false; 290 291 if (MissingExceptionSpecification) 292 *MissingExceptionSpecification = false; 293 294 if (MissingEmptyExceptionSpecification) 295 *MissingEmptyExceptionSpecification = false; 296 297 // C++0x [except.spec]p3: Two exception-specifications are compatible if: 298 // - both are non-throwing, regardless of their form, 299 // - both have the form noexcept(constant-expression) and the constant- 300 // expressions are equivalent, 301 // - one exception-specification is a noexcept-specification allowing all 302 // exceptions and the other is of the form throw(type-id-list), or 303 // - both are dynamic-exception-specifications that have the same set of 304 // adjusted types. 305 // 306 // C++0x [except.spec]p12: An exception-specifcation is non-throwing if it is 307 // of the form throw(), noexcept, or noexcept(constant-expression) where the 308 // constant-expression yields true. 309 // 310 // CWG 1073 Proposed resolution: Strike the third bullet above. 311 // 312 // C++0x [except.spec]p4: If any declaration of a function has an exception- 313 // specifier that is not a noexcept-specification allowing all exceptions, 314 // all declarations [...] of that function shall have a compatible 315 // exception-specification. 316 // 317 // That last point basically means that noexcept(false) matches no spec. 318 // It's considered when AllowNoexceptAllMatchWithNoSpec is true. 319 320 ExceptionSpecificationType OldEST = Old->getExceptionSpecType(); 321 ExceptionSpecificationType NewEST = New->getExceptionSpecType(); 322 323 // Shortcut the case where both have no spec. 324 if (OldEST == EST_None && NewEST == EST_None) 325 return false; 326 327 FunctionProtoType::NoexceptResult OldNR = Old->getNoexceptSpec(Context); 328 FunctionProtoType::NoexceptResult NewNR = New->getNoexceptSpec(Context); 329 if (OldNR == FunctionProtoType::NR_BadNoexcept || 330 NewNR == FunctionProtoType::NR_BadNoexcept) 331 return false; 332 333 // Dependent noexcept specifiers are compatible with each other, but nothing 334 // else. 335 // One noexcept is compatible with another if the argument is the same 336 if (OldNR == NewNR && 337 OldNR != FunctionProtoType::NR_NoNoexcept && 338 NewNR != FunctionProtoType::NR_NoNoexcept) 339 return false; 340 if (OldNR != NewNR && 341 OldNR != FunctionProtoType::NR_NoNoexcept && 342 NewNR != FunctionProtoType::NR_NoNoexcept) { 343 Diag(NewLoc, DiagID); 344 if (NoteID.getDiagID() != 0) 345 Diag(OldLoc, NoteID); 346 return true; 347 } 348 349 // The MS extension throw(...) is compatible with itself. 350 if (OldEST == EST_MSAny && NewEST == EST_MSAny) 351 return false; 352 353 // It's also compatible with no spec. 354 if ((OldEST == EST_None && NewEST == EST_MSAny) || 355 (OldEST == EST_MSAny && NewEST == EST_None)) 356 return false; 357 358 // It's also compatible with noexcept(false). 359 if (OldEST == EST_MSAny && NewNR == FunctionProtoType::NR_Throw) 360 return false; 361 if (NewEST == EST_MSAny && OldNR == FunctionProtoType::NR_Throw) 362 return false; 363 364 // As described above, noexcept(false) matches no spec only for functions. 365 if (AllowNoexceptAllMatchWithNoSpec) { 366 if (OldEST == EST_None && NewNR == FunctionProtoType::NR_Throw) 367 return false; 368 if (NewEST == EST_None && OldNR == FunctionProtoType::NR_Throw) 369 return false; 370 } 371 372 // Any non-throwing specifications are compatible. 373 bool OldNonThrowing = OldNR == FunctionProtoType::NR_Nothrow || 374 OldEST == EST_DynamicNone; 375 bool NewNonThrowing = NewNR == FunctionProtoType::NR_Nothrow || 376 NewEST == EST_DynamicNone; 377 if (OldNonThrowing && NewNonThrowing) 378 return false; 379 380 // As a special compatibility feature, under C++0x we accept no spec and 381 // throw(std::bad_alloc) as equivalent for operator new and operator new[]. 382 // This is because the implicit declaration changed, but old code would break. 383 if (getLangOptions().CPlusPlus0x && IsOperatorNew) { 384 const FunctionProtoType *WithExceptions = 0; 385 if (OldEST == EST_None && NewEST == EST_Dynamic) 386 WithExceptions = New; 387 else if (OldEST == EST_Dynamic && NewEST == EST_None) 388 WithExceptions = Old; 389 if (WithExceptions && WithExceptions->getNumExceptions() == 1) { 390 // One has no spec, the other throw(something). If that something is 391 // std::bad_alloc, all conditions are met. 392 QualType Exception = *WithExceptions->exception_begin(); 393 if (CXXRecordDecl *ExRecord = Exception->getAsCXXRecordDecl()) { 394 IdentifierInfo* Name = ExRecord->getIdentifier(); 395 if (Name && Name->getName() == "bad_alloc") { 396 // It's called bad_alloc, but is it in std? 397 DeclContext* DC = ExRecord->getDeclContext(); 398 DC = DC->getEnclosingNamespaceContext(); 399 if (NamespaceDecl* NS = dyn_cast<NamespaceDecl>(DC)) { 400 IdentifierInfo* NSName = NS->getIdentifier(); 401 DC = DC->getParent(); 402 if (NSName && NSName->getName() == "std" && 403 DC->getEnclosingNamespaceContext()->isTranslationUnit()) { 404 return false; 405 } 406 } 407 } 408 } 409 } 410 } 411 412 // At this point, the only remaining valid case is two matching dynamic 413 // specifications. We return here unless both specifications are dynamic. 414 if (OldEST != EST_Dynamic || NewEST != EST_Dynamic) { 415 if (MissingExceptionSpecification && Old->hasExceptionSpec() && 416 !New->hasExceptionSpec()) { 417 // The old type has an exception specification of some sort, but 418 // the new type does not. 419 *MissingExceptionSpecification = true; 420 421 if (MissingEmptyExceptionSpecification && OldNonThrowing) { 422 // The old type has a throw() or noexcept(true) exception specification 423 // and the new type has no exception specification, and the caller asked 424 // to handle this itself. 425 *MissingEmptyExceptionSpecification = true; 426 } 427 428 return true; 429 } 430 431 Diag(NewLoc, DiagID); 432 if (NoteID.getDiagID() != 0) 433 Diag(OldLoc, NoteID); 434 return true; 435 } 436 437 assert(OldEST == EST_Dynamic && NewEST == EST_Dynamic && 438 "Exception compatibility logic error: non-dynamic spec slipped through."); 439 440 bool Success = true; 441 // Both have a dynamic exception spec. Collect the first set, then compare 442 // to the second. 443 llvm::SmallPtrSet<CanQualType, 8> OldTypes, NewTypes; 444 for (FunctionProtoType::exception_iterator I = Old->exception_begin(), 445 E = Old->exception_end(); I != E; ++I) 446 OldTypes.insert(Context.getCanonicalType(*I).getUnqualifiedType()); 447 448 for (FunctionProtoType::exception_iterator I = New->exception_begin(), 449 E = New->exception_end(); I != E && Success; ++I) { 450 CanQualType TypePtr = Context.getCanonicalType(*I).getUnqualifiedType(); 451 if(OldTypes.count(TypePtr)) 452 NewTypes.insert(TypePtr); 453 else 454 Success = false; 455 } 456 457 Success = Success && OldTypes.size() == NewTypes.size(); 458 459 if (Success) { 460 return false; 461 } 462 Diag(NewLoc, DiagID); 463 if (NoteID.getDiagID() != 0) 464 Diag(OldLoc, NoteID); 465 return true; 466 } 467 468 /// CheckExceptionSpecSubset - Check whether the second function type's 469 /// exception specification is a subset (or equivalent) of the first function 470 /// type. This is used by override and pointer assignment checks. 471 bool Sema::CheckExceptionSpecSubset( 472 const PartialDiagnostic &DiagID, const PartialDiagnostic & NoteID, 473 const FunctionProtoType *Superset, SourceLocation SuperLoc, 474 const FunctionProtoType *Subset, SourceLocation SubLoc) { 475 476 // Just auto-succeed under -fno-exceptions. 477 if (!getLangOptions().CXXExceptions) 478 return false; 479 480 // FIXME: As usual, we could be more specific in our error messages, but 481 // that better waits until we've got types with source locations. 482 483 if (!SubLoc.isValid()) 484 SubLoc = SuperLoc; 485 486 ExceptionSpecificationType SuperEST = Superset->getExceptionSpecType(); 487 488 // If superset contains everything, we're done. 489 if (SuperEST == EST_None || SuperEST == EST_MSAny) 490 return CheckParamExceptionSpec(NoteID, Superset, SuperLoc, Subset, SubLoc); 491 492 // If there are dependent noexcept specs, assume everything is fine. Unlike 493 // with the equivalency check, this is safe in this case, because we don't 494 // want to merge declarations. Checks after instantiation will catch any 495 // omissions we make here. 496 // We also shortcut checking if a noexcept expression was bad. 497 498 FunctionProtoType::NoexceptResult SuperNR =Superset->getNoexceptSpec(Context); 499 if (SuperNR == FunctionProtoType::NR_BadNoexcept || 500 SuperNR == FunctionProtoType::NR_Dependent) 501 return false; 502 503 // Another case of the superset containing everything. 504 if (SuperNR == FunctionProtoType::NR_Throw) 505 return CheckParamExceptionSpec(NoteID, Superset, SuperLoc, Subset, SubLoc); 506 507 ExceptionSpecificationType SubEST = Subset->getExceptionSpecType(); 508 509 // It does not. If the subset contains everything, we've failed. 510 if (SubEST == EST_None || SubEST == EST_MSAny) { 511 Diag(SubLoc, DiagID); 512 if (NoteID.getDiagID() != 0) 513 Diag(SuperLoc, NoteID); 514 return true; 515 } 516 517 FunctionProtoType::NoexceptResult SubNR = Subset->getNoexceptSpec(Context); 518 if (SubNR == FunctionProtoType::NR_BadNoexcept || 519 SubNR == FunctionProtoType::NR_Dependent) 520 return false; 521 522 // Another case of the subset containing everything. 523 if (SubNR == FunctionProtoType::NR_Throw) { 524 Diag(SubLoc, DiagID); 525 if (NoteID.getDiagID() != 0) 526 Diag(SuperLoc, NoteID); 527 return true; 528 } 529 530 // If the subset contains nothing, we're done. 531 if (SubEST == EST_DynamicNone || SubNR == FunctionProtoType::NR_Nothrow) 532 return CheckParamExceptionSpec(NoteID, Superset, SuperLoc, Subset, SubLoc); 533 534 // Otherwise, if the superset contains nothing, we've failed. 535 if (SuperEST == EST_DynamicNone || SuperNR == FunctionProtoType::NR_Nothrow) { 536 Diag(SubLoc, DiagID); 537 if (NoteID.getDiagID() != 0) 538 Diag(SuperLoc, NoteID); 539 return true; 540 } 541 542 assert(SuperEST == EST_Dynamic && SubEST == EST_Dynamic && 543 "Exception spec subset: non-dynamic case slipped through."); 544 545 // Neither contains everything or nothing. Do a proper comparison. 546 for (FunctionProtoType::exception_iterator SubI = Subset->exception_begin(), 547 SubE = Subset->exception_end(); SubI != SubE; ++SubI) { 548 // Take one type from the subset. 549 QualType CanonicalSubT = Context.getCanonicalType(*SubI); 550 // Unwrap pointers and references so that we can do checks within a class 551 // hierarchy. Don't unwrap member pointers; they don't have hierarchy 552 // conversions on the pointee. 553 bool SubIsPointer = false; 554 if (const ReferenceType *RefTy = CanonicalSubT->getAs<ReferenceType>()) 555 CanonicalSubT = RefTy->getPointeeType(); 556 if (const PointerType *PtrTy = CanonicalSubT->getAs<PointerType>()) { 557 CanonicalSubT = PtrTy->getPointeeType(); 558 SubIsPointer = true; 559 } 560 bool SubIsClass = CanonicalSubT->isRecordType(); 561 CanonicalSubT = CanonicalSubT.getLocalUnqualifiedType(); 562 563 CXXBasePaths Paths(/*FindAmbiguities=*/true, /*RecordPaths=*/true, 564 /*DetectVirtual=*/false); 565 566 bool Contained = false; 567 // Make sure it's in the superset. 568 for (FunctionProtoType::exception_iterator SuperI = 569 Superset->exception_begin(), SuperE = Superset->exception_end(); 570 SuperI != SuperE; ++SuperI) { 571 QualType CanonicalSuperT = Context.getCanonicalType(*SuperI); 572 // SubT must be SuperT or derived from it, or pointer or reference to 573 // such types. 574 if (const ReferenceType *RefTy = CanonicalSuperT->getAs<ReferenceType>()) 575 CanonicalSuperT = RefTy->getPointeeType(); 576 if (SubIsPointer) { 577 if (const PointerType *PtrTy = CanonicalSuperT->getAs<PointerType>()) 578 CanonicalSuperT = PtrTy->getPointeeType(); 579 else { 580 continue; 581 } 582 } 583 CanonicalSuperT = CanonicalSuperT.getLocalUnqualifiedType(); 584 // If the types are the same, move on to the next type in the subset. 585 if (CanonicalSubT == CanonicalSuperT) { 586 Contained = true; 587 break; 588 } 589 590 // Otherwise we need to check the inheritance. 591 if (!SubIsClass || !CanonicalSuperT->isRecordType()) 592 continue; 593 594 Paths.clear(); 595 if (!IsDerivedFrom(CanonicalSubT, CanonicalSuperT, Paths)) 596 continue; 597 598 if (Paths.isAmbiguous(Context.getCanonicalType(CanonicalSuperT))) 599 continue; 600 601 // Do this check from a context without privileges. 602 switch (CheckBaseClassAccess(SourceLocation(), 603 CanonicalSuperT, CanonicalSubT, 604 Paths.front(), 605 /*Diagnostic*/ 0, 606 /*ForceCheck*/ true, 607 /*ForceUnprivileged*/ true)) { 608 case AR_accessible: break; 609 case AR_inaccessible: continue; 610 case AR_dependent: 611 llvm_unreachable("access check dependent for unprivileged context"); 612 break; 613 case AR_delayed: 614 llvm_unreachable("access check delayed in non-declaration"); 615 break; 616 } 617 618 Contained = true; 619 break; 620 } 621 if (!Contained) { 622 Diag(SubLoc, DiagID); 623 if (NoteID.getDiagID() != 0) 624 Diag(SuperLoc, NoteID); 625 return true; 626 } 627 } 628 // We've run half the gauntlet. 629 return CheckParamExceptionSpec(NoteID, Superset, SuperLoc, Subset, SubLoc); 630 } 631 632 static bool CheckSpecForTypesEquivalent(Sema &S, 633 const PartialDiagnostic &DiagID, const PartialDiagnostic & NoteID, 634 QualType Target, SourceLocation TargetLoc, 635 QualType Source, SourceLocation SourceLoc) 636 { 637 const FunctionProtoType *TFunc = GetUnderlyingFunction(Target); 638 if (!TFunc) 639 return false; 640 const FunctionProtoType *SFunc = GetUnderlyingFunction(Source); 641 if (!SFunc) 642 return false; 643 644 return S.CheckEquivalentExceptionSpec(DiagID, NoteID, TFunc, TargetLoc, 645 SFunc, SourceLoc); 646 } 647 648 /// CheckParamExceptionSpec - Check if the parameter and return types of the 649 /// two functions have equivalent exception specs. This is part of the 650 /// assignment and override compatibility check. We do not check the parameters 651 /// of parameter function pointers recursively, as no sane programmer would 652 /// even be able to write such a function type. 653 bool Sema::CheckParamExceptionSpec(const PartialDiagnostic & NoteID, 654 const FunctionProtoType *Target, SourceLocation TargetLoc, 655 const FunctionProtoType *Source, SourceLocation SourceLoc) 656 { 657 if (CheckSpecForTypesEquivalent(*this, 658 PDiag(diag::err_deep_exception_specs_differ) << 0, 659 PDiag(), 660 Target->getResultType(), TargetLoc, 661 Source->getResultType(), SourceLoc)) 662 return true; 663 664 // We shouldn't even be testing this unless the arguments are otherwise 665 // compatible. 666 assert(Target->getNumArgs() == Source->getNumArgs() && 667 "Functions have different argument counts."); 668 for (unsigned i = 0, E = Target->getNumArgs(); i != E; ++i) { 669 if (CheckSpecForTypesEquivalent(*this, 670 PDiag(diag::err_deep_exception_specs_differ) << 1, 671 PDiag(), 672 Target->getArgType(i), TargetLoc, 673 Source->getArgType(i), SourceLoc)) 674 return true; 675 } 676 return false; 677 } 678 679 bool Sema::CheckExceptionSpecCompatibility(Expr *From, QualType ToType) 680 { 681 // First we check for applicability. 682 // Target type must be a function, function pointer or function reference. 683 const FunctionProtoType *ToFunc = GetUnderlyingFunction(ToType); 684 if (!ToFunc) 685 return false; 686 687 // SourceType must be a function or function pointer. 688 const FunctionProtoType *FromFunc = GetUnderlyingFunction(From->getType()); 689 if (!FromFunc) 690 return false; 691 692 // Now we've got the correct types on both sides, check their compatibility. 693 // This means that the source of the conversion can only throw a subset of 694 // the exceptions of the target, and any exception specs on arguments or 695 // return types must be equivalent. 696 return CheckExceptionSpecSubset(PDiag(diag::err_incompatible_exception_specs), 697 PDiag(), ToFunc, 698 From->getSourceRange().getBegin(), 699 FromFunc, SourceLocation()); 700 } 701 702 bool Sema::CheckOverridingFunctionExceptionSpec(const CXXMethodDecl *New, 703 const CXXMethodDecl *Old) { 704 return CheckExceptionSpecSubset(PDiag(diag::err_override_exception_spec), 705 PDiag(diag::note_overridden_virtual_function), 706 Old->getType()->getAs<FunctionProtoType>(), 707 Old->getLocation(), 708 New->getType()->getAs<FunctionProtoType>(), 709 New->getLocation()); 710 } 711 712 } // end namespace clang 713