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