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::warn_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::warn_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 // - both are dynamic-exception-specifications that have the same set of 302 // adjusted types. 303 // 304 // C++0x [except.spec]p12: An exception-specifcation is non-throwing if it is 305 // of the form throw(), noexcept, or noexcept(constant-expression) where the 306 // constant-expression yields true. 307 // 308 // C++0x [except.spec]p4: If any declaration of a function has an exception- 309 // specifier that is not a noexcept-specification allowing all exceptions, 310 // all declarations [...] of that function shall have a compatible 311 // exception-specification. 312 // 313 // That last point basically means that noexcept(false) matches no spec. 314 // It's considered when AllowNoexceptAllMatchWithNoSpec is true. 315 316 ExceptionSpecificationType OldEST = Old->getExceptionSpecType(); 317 ExceptionSpecificationType NewEST = New->getExceptionSpecType(); 318 319 assert(OldEST != EST_Delayed && NewEST != EST_Delayed && 320 "Shouldn't see unknown exception specifications here"); 321 322 // Shortcut the case where both have no spec. 323 if (OldEST == EST_None && NewEST == EST_None) 324 return false; 325 326 FunctionProtoType::NoexceptResult OldNR = Old->getNoexceptSpec(Context); 327 FunctionProtoType::NoexceptResult NewNR = New->getNoexceptSpec(Context); 328 if (OldNR == FunctionProtoType::NR_BadNoexcept || 329 NewNR == FunctionProtoType::NR_BadNoexcept) 330 return false; 331 332 // Dependent noexcept specifiers are compatible with each other, but nothing 333 // else. 334 // One noexcept is compatible with another if the argument is the same 335 if (OldNR == NewNR && 336 OldNR != FunctionProtoType::NR_NoNoexcept && 337 NewNR != FunctionProtoType::NR_NoNoexcept) 338 return false; 339 if (OldNR != NewNR && 340 OldNR != FunctionProtoType::NR_NoNoexcept && 341 NewNR != FunctionProtoType::NR_NoNoexcept) { 342 Diag(NewLoc, DiagID); 343 if (NoteID.getDiagID() != 0) 344 Diag(OldLoc, NoteID); 345 return true; 346 } 347 348 // The MS extension throw(...) is compatible with itself. 349 if (OldEST == EST_MSAny && NewEST == EST_MSAny) 350 return false; 351 352 // It's also compatible with no spec. 353 if ((OldEST == EST_None && NewEST == EST_MSAny) || 354 (OldEST == EST_MSAny && NewEST == EST_None)) 355 return false; 356 357 // It's also compatible with noexcept(false). 358 if (OldEST == EST_MSAny && NewNR == FunctionProtoType::NR_Throw) 359 return false; 360 if (NewEST == EST_MSAny && OldNR == FunctionProtoType::NR_Throw) 361 return false; 362 363 // As described above, noexcept(false) matches no spec only for functions. 364 if (AllowNoexceptAllMatchWithNoSpec) { 365 if (OldEST == EST_None && NewNR == FunctionProtoType::NR_Throw) 366 return false; 367 if (NewEST == EST_None && OldNR == FunctionProtoType::NR_Throw) 368 return false; 369 } 370 371 // Any non-throwing specifications are compatible. 372 bool OldNonThrowing = OldNR == FunctionProtoType::NR_Nothrow || 373 OldEST == EST_DynamicNone; 374 bool NewNonThrowing = NewNR == FunctionProtoType::NR_Nothrow || 375 NewEST == EST_DynamicNone; 376 if (OldNonThrowing && NewNonThrowing) 377 return false; 378 379 // As a special compatibility feature, under C++0x we accept no spec and 380 // throw(std::bad_alloc) as equivalent for operator new and operator new[]. 381 // This is because the implicit declaration changed, but old code would break. 382 if (getLangOptions().CPlusPlus0x && IsOperatorNew) { 383 const FunctionProtoType *WithExceptions = 0; 384 if (OldEST == EST_None && NewEST == EST_Dynamic) 385 WithExceptions = New; 386 else if (OldEST == EST_Dynamic && NewEST == EST_None) 387 WithExceptions = Old; 388 if (WithExceptions && WithExceptions->getNumExceptions() == 1) { 389 // One has no spec, the other throw(something). If that something is 390 // std::bad_alloc, all conditions are met. 391 QualType Exception = *WithExceptions->exception_begin(); 392 if (CXXRecordDecl *ExRecord = Exception->getAsCXXRecordDecl()) { 393 IdentifierInfo* Name = ExRecord->getIdentifier(); 394 if (Name && Name->getName() == "bad_alloc") { 395 // It's called bad_alloc, but is it in std? 396 DeclContext* DC = ExRecord->getDeclContext(); 397 DC = DC->getEnclosingNamespaceContext(); 398 if (NamespaceDecl* NS = dyn_cast<NamespaceDecl>(DC)) { 399 IdentifierInfo* NSName = NS->getIdentifier(); 400 DC = DC->getParent(); 401 if (NSName && NSName->getName() == "std" && 402 DC->getEnclosingNamespaceContext()->isTranslationUnit()) { 403 return false; 404 } 405 } 406 } 407 } 408 } 409 } 410 411 // At this point, the only remaining valid case is two matching dynamic 412 // specifications. We return here unless both specifications are dynamic. 413 if (OldEST != EST_Dynamic || NewEST != EST_Dynamic) { 414 if (MissingExceptionSpecification && Old->hasExceptionSpec() && 415 !New->hasExceptionSpec()) { 416 // The old type has an exception specification of some sort, but 417 // the new type does not. 418 *MissingExceptionSpecification = true; 419 420 if (MissingEmptyExceptionSpecification && OldNonThrowing) { 421 // The old type has a throw() or noexcept(true) exception specification 422 // and the new type has no exception specification, and the caller asked 423 // to handle this itself. 424 *MissingEmptyExceptionSpecification = true; 425 } 426 427 return true; 428 } 429 430 Diag(NewLoc, DiagID); 431 if (NoteID.getDiagID() != 0) 432 Diag(OldLoc, NoteID); 433 return true; 434 } 435 436 assert(OldEST == EST_Dynamic && NewEST == EST_Dynamic && 437 "Exception compatibility logic error: non-dynamic spec slipped through."); 438 439 bool Success = true; 440 // Both have a dynamic exception spec. Collect the first set, then compare 441 // to the second. 442 llvm::SmallPtrSet<CanQualType, 8> OldTypes, NewTypes; 443 for (FunctionProtoType::exception_iterator I = Old->exception_begin(), 444 E = Old->exception_end(); I != E; ++I) 445 OldTypes.insert(Context.getCanonicalType(*I).getUnqualifiedType()); 446 447 for (FunctionProtoType::exception_iterator I = New->exception_begin(), 448 E = New->exception_end(); I != E && Success; ++I) { 449 CanQualType TypePtr = Context.getCanonicalType(*I).getUnqualifiedType(); 450 if(OldTypes.count(TypePtr)) 451 NewTypes.insert(TypePtr); 452 else 453 Success = false; 454 } 455 456 Success = Success && OldTypes.size() == NewTypes.size(); 457 458 if (Success) { 459 return false; 460 } 461 Diag(NewLoc, DiagID); 462 if (NoteID.getDiagID() != 0) 463 Diag(OldLoc, NoteID); 464 return true; 465 } 466 467 /// CheckExceptionSpecSubset - Check whether the second function type's 468 /// exception specification is a subset (or equivalent) of the first function 469 /// type. This is used by override and pointer assignment checks. 470 bool Sema::CheckExceptionSpecSubset( 471 const PartialDiagnostic &DiagID, const PartialDiagnostic & NoteID, 472 const FunctionProtoType *Superset, SourceLocation SuperLoc, 473 const FunctionProtoType *Subset, SourceLocation SubLoc) { 474 475 // Just auto-succeed under -fno-exceptions. 476 if (!getLangOptions().CXXExceptions) 477 return false; 478 479 // FIXME: As usual, we could be more specific in our error messages, but 480 // that better waits until we've got types with source locations. 481 482 if (!SubLoc.isValid()) 483 SubLoc = SuperLoc; 484 485 ExceptionSpecificationType SuperEST = Superset->getExceptionSpecType(); 486 487 // If superset contains everything, we're done. 488 if (SuperEST == EST_None || SuperEST == EST_MSAny) 489 return CheckParamExceptionSpec(NoteID, Superset, SuperLoc, Subset, SubLoc); 490 491 // If there are dependent noexcept specs, assume everything is fine. Unlike 492 // with the equivalency check, this is safe in this case, because we don't 493 // want to merge declarations. Checks after instantiation will catch any 494 // omissions we make here. 495 // We also shortcut checking if a noexcept expression was bad. 496 497 FunctionProtoType::NoexceptResult SuperNR =Superset->getNoexceptSpec(Context); 498 if (SuperNR == FunctionProtoType::NR_BadNoexcept || 499 SuperNR == FunctionProtoType::NR_Dependent) 500 return false; 501 502 // Another case of the superset containing everything. 503 if (SuperNR == FunctionProtoType::NR_Throw) 504 return CheckParamExceptionSpec(NoteID, Superset, SuperLoc, Subset, SubLoc); 505 506 ExceptionSpecificationType SubEST = Subset->getExceptionSpecType(); 507 508 assert(SuperEST != EST_Delayed && SubEST != EST_Delayed && 509 "Shouldn't see unknown exception specifications here"); 510 511 // It does not. If the subset contains everything, we've failed. 512 if (SubEST == EST_None || SubEST == EST_MSAny) { 513 Diag(SubLoc, DiagID); 514 if (NoteID.getDiagID() != 0) 515 Diag(SuperLoc, NoteID); 516 return true; 517 } 518 519 FunctionProtoType::NoexceptResult SubNR = Subset->getNoexceptSpec(Context); 520 if (SubNR == FunctionProtoType::NR_BadNoexcept || 521 SubNR == FunctionProtoType::NR_Dependent) 522 return false; 523 524 // Another case of the subset containing everything. 525 if (SubNR == FunctionProtoType::NR_Throw) { 526 Diag(SubLoc, DiagID); 527 if (NoteID.getDiagID() != 0) 528 Diag(SuperLoc, NoteID); 529 return true; 530 } 531 532 // If the subset contains nothing, we're done. 533 if (SubEST == EST_DynamicNone || SubNR == FunctionProtoType::NR_Nothrow) 534 return CheckParamExceptionSpec(NoteID, Superset, SuperLoc, Subset, SubLoc); 535 536 // Otherwise, if the superset contains nothing, we've failed. 537 if (SuperEST == EST_DynamicNone || SuperNR == FunctionProtoType::NR_Nothrow) { 538 Diag(SubLoc, DiagID); 539 if (NoteID.getDiagID() != 0) 540 Diag(SuperLoc, NoteID); 541 return true; 542 } 543 544 assert(SuperEST == EST_Dynamic && SubEST == EST_Dynamic && 545 "Exception spec subset: non-dynamic case slipped through."); 546 547 // Neither contains everything or nothing. Do a proper comparison. 548 for (FunctionProtoType::exception_iterator SubI = Subset->exception_begin(), 549 SubE = Subset->exception_end(); SubI != SubE; ++SubI) { 550 // Take one type from the subset. 551 QualType CanonicalSubT = Context.getCanonicalType(*SubI); 552 // Unwrap pointers and references so that we can do checks within a class 553 // hierarchy. Don't unwrap member pointers; they don't have hierarchy 554 // conversions on the pointee. 555 bool SubIsPointer = false; 556 if (const ReferenceType *RefTy = CanonicalSubT->getAs<ReferenceType>()) 557 CanonicalSubT = RefTy->getPointeeType(); 558 if (const PointerType *PtrTy = CanonicalSubT->getAs<PointerType>()) { 559 CanonicalSubT = PtrTy->getPointeeType(); 560 SubIsPointer = true; 561 } 562 bool SubIsClass = CanonicalSubT->isRecordType(); 563 CanonicalSubT = CanonicalSubT.getLocalUnqualifiedType(); 564 565 CXXBasePaths Paths(/*FindAmbiguities=*/true, /*RecordPaths=*/true, 566 /*DetectVirtual=*/false); 567 568 bool Contained = false; 569 // Make sure it's in the superset. 570 for (FunctionProtoType::exception_iterator SuperI = 571 Superset->exception_begin(), SuperE = Superset->exception_end(); 572 SuperI != SuperE; ++SuperI) { 573 QualType CanonicalSuperT = Context.getCanonicalType(*SuperI); 574 // SubT must be SuperT or derived from it, or pointer or reference to 575 // such types. 576 if (const ReferenceType *RefTy = CanonicalSuperT->getAs<ReferenceType>()) 577 CanonicalSuperT = RefTy->getPointeeType(); 578 if (SubIsPointer) { 579 if (const PointerType *PtrTy = CanonicalSuperT->getAs<PointerType>()) 580 CanonicalSuperT = PtrTy->getPointeeType(); 581 else { 582 continue; 583 } 584 } 585 CanonicalSuperT = CanonicalSuperT.getLocalUnqualifiedType(); 586 // If the types are the same, move on to the next type in the subset. 587 if (CanonicalSubT == CanonicalSuperT) { 588 Contained = true; 589 break; 590 } 591 592 // Otherwise we need to check the inheritance. 593 if (!SubIsClass || !CanonicalSuperT->isRecordType()) 594 continue; 595 596 Paths.clear(); 597 if (!IsDerivedFrom(CanonicalSubT, CanonicalSuperT, Paths)) 598 continue; 599 600 if (Paths.isAmbiguous(Context.getCanonicalType(CanonicalSuperT))) 601 continue; 602 603 // Do this check from a context without privileges. 604 switch (CheckBaseClassAccess(SourceLocation(), 605 CanonicalSuperT, CanonicalSubT, 606 Paths.front(), 607 /*Diagnostic*/ 0, 608 /*ForceCheck*/ true, 609 /*ForceUnprivileged*/ true)) { 610 case AR_accessible: break; 611 case AR_inaccessible: continue; 612 case AR_dependent: 613 llvm_unreachable("access check dependent for unprivileged context"); 614 break; 615 case AR_delayed: 616 llvm_unreachable("access check delayed in non-declaration"); 617 break; 618 } 619 620 Contained = true; 621 break; 622 } 623 if (!Contained) { 624 Diag(SubLoc, DiagID); 625 if (NoteID.getDiagID() != 0) 626 Diag(SuperLoc, NoteID); 627 return true; 628 } 629 } 630 // We've run half the gauntlet. 631 return CheckParamExceptionSpec(NoteID, Superset, SuperLoc, Subset, SubLoc); 632 } 633 634 static bool CheckSpecForTypesEquivalent(Sema &S, 635 const PartialDiagnostic &DiagID, const PartialDiagnostic & NoteID, 636 QualType Target, SourceLocation TargetLoc, 637 QualType Source, SourceLocation SourceLoc) 638 { 639 const FunctionProtoType *TFunc = GetUnderlyingFunction(Target); 640 if (!TFunc) 641 return false; 642 const FunctionProtoType *SFunc = GetUnderlyingFunction(Source); 643 if (!SFunc) 644 return false; 645 646 return S.CheckEquivalentExceptionSpec(DiagID, NoteID, TFunc, TargetLoc, 647 SFunc, SourceLoc); 648 } 649 650 /// CheckParamExceptionSpec - Check if the parameter and return types of the 651 /// two functions have equivalent exception specs. This is part of the 652 /// assignment and override compatibility check. We do not check the parameters 653 /// of parameter function pointers recursively, as no sane programmer would 654 /// even be able to write such a function type. 655 bool Sema::CheckParamExceptionSpec(const PartialDiagnostic & NoteID, 656 const FunctionProtoType *Target, SourceLocation TargetLoc, 657 const FunctionProtoType *Source, SourceLocation SourceLoc) 658 { 659 if (CheckSpecForTypesEquivalent(*this, 660 PDiag(diag::err_deep_exception_specs_differ) << 0, 661 PDiag(), 662 Target->getResultType(), TargetLoc, 663 Source->getResultType(), SourceLoc)) 664 return true; 665 666 // We shouldn't even be testing this unless the arguments are otherwise 667 // compatible. 668 assert(Target->getNumArgs() == Source->getNumArgs() && 669 "Functions have different argument counts."); 670 for (unsigned i = 0, E = Target->getNumArgs(); i != E; ++i) { 671 if (CheckSpecForTypesEquivalent(*this, 672 PDiag(diag::err_deep_exception_specs_differ) << 1, 673 PDiag(), 674 Target->getArgType(i), TargetLoc, 675 Source->getArgType(i), SourceLoc)) 676 return true; 677 } 678 return false; 679 } 680 681 bool Sema::CheckExceptionSpecCompatibility(Expr *From, QualType ToType) 682 { 683 // First we check for applicability. 684 // Target type must be a function, function pointer or function reference. 685 const FunctionProtoType *ToFunc = GetUnderlyingFunction(ToType); 686 if (!ToFunc) 687 return false; 688 689 // SourceType must be a function or function pointer. 690 const FunctionProtoType *FromFunc = GetUnderlyingFunction(From->getType()); 691 if (!FromFunc) 692 return false; 693 694 // Now we've got the correct types on both sides, check their compatibility. 695 // This means that the source of the conversion can only throw a subset of 696 // the exceptions of the target, and any exception specs on arguments or 697 // return types must be equivalent. 698 return CheckExceptionSpecSubset(PDiag(diag::err_incompatible_exception_specs), 699 PDiag(), ToFunc, 700 From->getSourceRange().getBegin(), 701 FromFunc, SourceLocation()); 702 } 703 704 bool Sema::CheckOverridingFunctionExceptionSpec(const CXXMethodDecl *New, 705 const CXXMethodDecl *Old) { 706 if (getLangOptions().CPlusPlus0x && isa<CXXDestructorDecl>(New)) { 707 // Don't check uninstantiated template destructors at all. We can only 708 // synthesize correct specs after the template is instantiated. 709 if (New->getParent()->isDependentType()) 710 return false; 711 if (New->getParent()->isBeingDefined()) { 712 // The destructor might be updated once the definition is finished. So 713 // remember it and check later. 714 DelayedDestructorExceptionSpecChecks.push_back(std::make_pair( 715 cast<CXXDestructorDecl>(New), cast<CXXDestructorDecl>(Old))); 716 return false; 717 } 718 } 719 unsigned DiagID = diag::err_override_exception_spec; 720 if (getLangOptions().Microsoft) 721 DiagID = diag::warn_override_exception_spec; 722 return CheckExceptionSpecSubset(PDiag(DiagID), 723 PDiag(diag::note_overridden_virtual_function), 724 Old->getType()->getAs<FunctionProtoType>(), 725 Old->getLocation(), 726 New->getType()->getAs<FunctionProtoType>(), 727 New->getLocation()); 728 } 729 730 } // end namespace clang 731