File: | tools/clang/lib/Sema/SemaExceptionSpec.cpp |
Warning: | line 189, column 7 Called C++ object pointer is null |
Press '?' to see keyboard shortcuts
Keyboard shortcuts:
1 | //===--- SemaExceptionSpec.cpp - C++ Exception Specifications ---*- C++ -*-===// | ||||
2 | // | ||||
3 | // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. | ||||
4 | // See https://llvm.org/LICENSE.txt for license information. | ||||
5 | // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception | ||||
6 | // | ||||
7 | //===----------------------------------------------------------------------===// | ||||
8 | // | ||||
9 | // This file provides Sema routines for C++ exception specification testing. | ||||
10 | // | ||||
11 | //===----------------------------------------------------------------------===// | ||||
12 | |||||
13 | #include "clang/Sema/SemaInternal.h" | ||||
14 | #include "clang/AST/ASTMutationListener.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/Basic/Diagnostic.h" | ||||
20 | #include "clang/Basic/SourceManager.h" | ||||
21 | #include "llvm/ADT/SmallPtrSet.h" | ||||
22 | #include "llvm/ADT/SmallString.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 | /// HACK: libstdc++ has a bug where it shadows std::swap with a member | ||||
38 | /// swap function then tries to call std::swap unqualified from the exception | ||||
39 | /// specification of that function. This function detects whether we're in | ||||
40 | /// such a case and turns off delay-parsing of exception specifications. | ||||
41 | bool Sema::isLibstdcxxEagerExceptionSpecHack(const Declarator &D) { | ||||
42 | auto *RD = dyn_cast<CXXRecordDecl>(CurContext); | ||||
43 | |||||
44 | // All the problem cases are member functions named "swap" within class | ||||
45 | // templates declared directly within namespace std or std::__debug or | ||||
46 | // std::__profile. | ||||
47 | if (!RD || !RD->getIdentifier() || !RD->getDescribedClassTemplate() || | ||||
48 | !D.getIdentifier() || !D.getIdentifier()->isStr("swap")) | ||||
49 | return false; | ||||
50 | |||||
51 | auto *ND = dyn_cast<NamespaceDecl>(RD->getDeclContext()); | ||||
52 | if (!ND) | ||||
53 | return false; | ||||
54 | |||||
55 | bool IsInStd = ND->isStdNamespace(); | ||||
56 | if (!IsInStd) { | ||||
57 | // This isn't a direct member of namespace std, but it might still be | ||||
58 | // libstdc++'s std::__debug::array or std::__profile::array. | ||||
59 | IdentifierInfo *II = ND->getIdentifier(); | ||||
60 | if (!II || !(II->isStr("__debug") || II->isStr("__profile")) || | ||||
61 | !ND->isInStdNamespace()) | ||||
62 | return false; | ||||
63 | } | ||||
64 | |||||
65 | // Only apply this hack within a system header. | ||||
66 | if (!Context.getSourceManager().isInSystemHeader(D.getBeginLoc())) | ||||
67 | return false; | ||||
68 | |||||
69 | return llvm::StringSwitch<bool>(RD->getIdentifier()->getName()) | ||||
70 | .Case("array", true) | ||||
71 | .Case("pair", IsInStd) | ||||
72 | .Case("priority_queue", IsInStd) | ||||
73 | .Case("stack", IsInStd) | ||||
74 | .Case("queue", IsInStd) | ||||
75 | .Default(false); | ||||
76 | } | ||||
77 | |||||
78 | ExprResult Sema::ActOnNoexceptSpec(SourceLocation NoexceptLoc, | ||||
79 | Expr *NoexceptExpr, | ||||
80 | ExceptionSpecificationType &EST) { | ||||
81 | // FIXME: This is bogus, a noexcept expression is not a condition. | ||||
82 | ExprResult Converted = CheckBooleanCondition(NoexceptLoc, NoexceptExpr); | ||||
83 | if (Converted.isInvalid()) | ||||
84 | return Converted; | ||||
85 | |||||
86 | if (Converted.get()->isValueDependent()) { | ||||
87 | EST = EST_DependentNoexcept; | ||||
88 | return Converted; | ||||
89 | } | ||||
90 | |||||
91 | llvm::APSInt Result; | ||||
92 | Converted = VerifyIntegerConstantExpression( | ||||
93 | Converted.get(), &Result, | ||||
94 | diag::err_noexcept_needs_constant_expression, | ||||
95 | /*AllowFold*/ false); | ||||
96 | if (!Converted.isInvalid()) | ||||
97 | EST = !Result ? EST_NoexceptFalse : EST_NoexceptTrue; | ||||
98 | return Converted; | ||||
99 | } | ||||
100 | |||||
101 | /// CheckSpecifiedExceptionType - Check if the given type is valid in an | ||||
102 | /// exception specification. Incomplete types, or pointers to incomplete types | ||||
103 | /// other than void are not allowed. | ||||
104 | /// | ||||
105 | /// \param[in,out] T The exception type. This will be decayed to a pointer type | ||||
106 | /// when the input is an array or a function type. | ||||
107 | bool Sema::CheckSpecifiedExceptionType(QualType &T, SourceRange Range) { | ||||
108 | // C++11 [except.spec]p2: | ||||
109 | // A type cv T, "array of T", or "function returning T" denoted | ||||
110 | // in an exception-specification is adjusted to type T, "pointer to T", or | ||||
111 | // "pointer to function returning T", respectively. | ||||
112 | // | ||||
113 | // We also apply this rule in C++98. | ||||
114 | if (T->isArrayType()) | ||||
115 | T = Context.getArrayDecayedType(T); | ||||
116 | else if (T->isFunctionType()) | ||||
117 | T = Context.getPointerType(T); | ||||
118 | |||||
119 | int Kind = 0; | ||||
120 | QualType PointeeT = T; | ||||
121 | if (const PointerType *PT = T->getAs<PointerType>()) { | ||||
122 | PointeeT = PT->getPointeeType(); | ||||
123 | Kind = 1; | ||||
124 | |||||
125 | // cv void* is explicitly permitted, despite being a pointer to an | ||||
126 | // incomplete type. | ||||
127 | if (PointeeT->isVoidType()) | ||||
128 | return false; | ||||
129 | } else if (const ReferenceType *RT = T->getAs<ReferenceType>()) { | ||||
130 | PointeeT = RT->getPointeeType(); | ||||
131 | Kind = 2; | ||||
132 | |||||
133 | if (RT->isRValueReferenceType()) { | ||||
134 | // C++11 [except.spec]p2: | ||||
135 | // A type denoted in an exception-specification shall not denote [...] | ||||
136 | // an rvalue reference type. | ||||
137 | Diag(Range.getBegin(), diag::err_rref_in_exception_spec) | ||||
138 | << T << Range; | ||||
139 | return true; | ||||
140 | } | ||||
141 | } | ||||
142 | |||||
143 | // C++11 [except.spec]p2: | ||||
144 | // A type denoted in an exception-specification shall not denote an | ||||
145 | // incomplete type other than a class currently being defined [...]. | ||||
146 | // A type denoted in an exception-specification shall not denote a | ||||
147 | // pointer or reference to an incomplete type, other than (cv) void* or a | ||||
148 | // pointer or reference to a class currently being defined. | ||||
149 | // In Microsoft mode, downgrade this to a warning. | ||||
150 | unsigned DiagID = diag::err_incomplete_in_exception_spec; | ||||
151 | bool ReturnValueOnError = true; | ||||
152 | if (getLangOpts().MSVCCompat) { | ||||
153 | DiagID = diag::ext_incomplete_in_exception_spec; | ||||
154 | ReturnValueOnError = false; | ||||
155 | } | ||||
156 | if (!(PointeeT->isRecordType() && | ||||
157 | PointeeT->castAs<RecordType>()->isBeingDefined()) && | ||||
158 | RequireCompleteType(Range.getBegin(), PointeeT, DiagID, Kind, Range)) | ||||
159 | return ReturnValueOnError; | ||||
160 | |||||
161 | return false; | ||||
162 | } | ||||
163 | |||||
164 | /// CheckDistantExceptionSpec - Check if the given type is a pointer or pointer | ||||
165 | /// to member to a function with an exception specification. This means that | ||||
166 | /// it is invalid to add another level of indirection. | ||||
167 | bool Sema::CheckDistantExceptionSpec(QualType T) { | ||||
168 | // C++17 removes this rule in favor of putting exception specifications into | ||||
169 | // the type system. | ||||
170 | if (getLangOpts().CPlusPlus17) | ||||
171 | return false; | ||||
172 | |||||
173 | if (const PointerType *PT = T->getAs<PointerType>()) | ||||
174 | T = PT->getPointeeType(); | ||||
175 | else if (const MemberPointerType *PT = T->getAs<MemberPointerType>()) | ||||
176 | T = PT->getPointeeType(); | ||||
177 | else | ||||
178 | return false; | ||||
179 | |||||
180 | const FunctionProtoType *FnT = T->getAs<FunctionProtoType>(); | ||||
181 | if (!FnT) | ||||
182 | return false; | ||||
183 | |||||
184 | return FnT->hasExceptionSpec(); | ||||
185 | } | ||||
186 | |||||
187 | const FunctionProtoType * | ||||
188 | Sema::ResolveExceptionSpec(SourceLocation Loc, const FunctionProtoType *FPT) { | ||||
189 | if (FPT->getExceptionSpecType() == EST_Unparsed) { | ||||
| |||||
190 | Diag(Loc, diag::err_exception_spec_not_parsed); | ||||
191 | return nullptr; | ||||
192 | } | ||||
193 | |||||
194 | if (!isUnresolvedExceptionSpec(FPT->getExceptionSpecType())) | ||||
195 | return FPT; | ||||
196 | |||||
197 | FunctionDecl *SourceDecl = FPT->getExceptionSpecDecl(); | ||||
198 | const FunctionProtoType *SourceFPT = | ||||
199 | SourceDecl->getType()->castAs<FunctionProtoType>(); | ||||
200 | |||||
201 | // If the exception specification has already been resolved, just return it. | ||||
202 | if (!isUnresolvedExceptionSpec(SourceFPT->getExceptionSpecType())) | ||||
203 | return SourceFPT; | ||||
204 | |||||
205 | // Compute or instantiate the exception specification now. | ||||
206 | if (SourceFPT->getExceptionSpecType() == EST_Unevaluated) | ||||
207 | EvaluateImplicitExceptionSpec(Loc, cast<CXXMethodDecl>(SourceDecl)); | ||||
208 | else | ||||
209 | InstantiateExceptionSpec(Loc, SourceDecl); | ||||
210 | |||||
211 | const FunctionProtoType *Proto = | ||||
212 | SourceDecl->getType()->castAs<FunctionProtoType>(); | ||||
213 | if (Proto->getExceptionSpecType() == clang::EST_Unparsed) { | ||||
214 | Diag(Loc, diag::err_exception_spec_not_parsed); | ||||
215 | Proto = nullptr; | ||||
216 | } | ||||
217 | return Proto; | ||||
218 | } | ||||
219 | |||||
220 | void | ||||
221 | Sema::UpdateExceptionSpec(FunctionDecl *FD, | ||||
222 | const FunctionProtoType::ExceptionSpecInfo &ESI) { | ||||
223 | // If we've fully resolved the exception specification, notify listeners. | ||||
224 | if (!isUnresolvedExceptionSpec(ESI.Type)) | ||||
225 | if (auto *Listener = getASTMutationListener()) | ||||
226 | Listener->ResolvedExceptionSpec(FD); | ||||
227 | |||||
228 | for (FunctionDecl *Redecl : FD->redecls()) | ||||
229 | Context.adjustExceptionSpec(Redecl, ESI); | ||||
230 | } | ||||
231 | |||||
232 | static bool exceptionSpecNotKnownYet(const FunctionDecl *FD) { | ||||
233 | auto *MD = dyn_cast<CXXMethodDecl>(FD); | ||||
234 | if (!MD
| ||||
235 | return false; | ||||
236 | |||||
237 | auto EST = MD->getType()->castAs<FunctionProtoType>()->getExceptionSpecType(); | ||||
238 | return EST == EST_Unparsed || | ||||
239 | (EST == EST_Unevaluated && MD->getParent()->isBeingDefined()); | ||||
240 | } | ||||
241 | |||||
242 | static bool CheckEquivalentExceptionSpecImpl( | ||||
243 | Sema &S, const PartialDiagnostic &DiagID, const PartialDiagnostic &NoteID, | ||||
244 | const FunctionProtoType *Old, SourceLocation OldLoc, | ||||
245 | const FunctionProtoType *New, SourceLocation NewLoc, | ||||
246 | bool *MissingExceptionSpecification = nullptr, | ||||
247 | bool *MissingEmptyExceptionSpecification = nullptr, | ||||
248 | bool AllowNoexceptAllMatchWithNoSpec = false, bool IsOperatorNew = false); | ||||
249 | |||||
250 | /// Determine whether a function has an implicitly-generated exception | ||||
251 | /// specification. | ||||
252 | static bool hasImplicitExceptionSpec(FunctionDecl *Decl) { | ||||
253 | if (!isa<CXXDestructorDecl>(Decl) && | ||||
254 | Decl->getDeclName().getCXXOverloadedOperator() != OO_Delete && | ||||
255 | Decl->getDeclName().getCXXOverloadedOperator() != OO_Array_Delete) | ||||
256 | return false; | ||||
257 | |||||
258 | // For a function that the user didn't declare: | ||||
259 | // - if this is a destructor, its exception specification is implicit. | ||||
260 | // - if this is 'operator delete' or 'operator delete[]', the exception | ||||
261 | // specification is as-if an explicit exception specification was given | ||||
262 | // (per [basic.stc.dynamic]p2). | ||||
263 | if (!Decl->getTypeSourceInfo()) | ||||
264 | return isa<CXXDestructorDecl>(Decl); | ||||
265 | |||||
266 | const FunctionProtoType *Ty = | ||||
267 | Decl->getTypeSourceInfo()->getType()->getAs<FunctionProtoType>(); | ||||
268 | return !Ty->hasExceptionSpec(); | ||||
269 | } | ||||
270 | |||||
271 | bool Sema::CheckEquivalentExceptionSpec(FunctionDecl *Old, FunctionDecl *New) { | ||||
272 | // Just completely ignore this under -fno-exceptions prior to C++17. | ||||
273 | // In C++17 onwards, the exception specification is part of the type and | ||||
274 | // we will diagnose mismatches anyway, so it's better to check for them here. | ||||
275 | if (!getLangOpts().CXXExceptions && !getLangOpts().CPlusPlus17) | ||||
276 | return false; | ||||
277 | |||||
278 | OverloadedOperatorKind OO = New->getDeclName().getCXXOverloadedOperator(); | ||||
279 | bool IsOperatorNew = OO == OO_New || OO == OO_Array_New; | ||||
280 | bool MissingExceptionSpecification = false; | ||||
281 | bool MissingEmptyExceptionSpecification = false; | ||||
282 | |||||
283 | unsigned DiagID = diag::err_mismatched_exception_spec; | ||||
284 | bool ReturnValueOnError = true; | ||||
285 | if (getLangOpts().MSVCCompat) { | ||||
286 | DiagID = diag::ext_mismatched_exception_spec; | ||||
287 | ReturnValueOnError = false; | ||||
288 | } | ||||
289 | |||||
290 | // If we're befriending a member function of a class that's currently being | ||||
291 | // defined, we might not be able to work out its exception specification yet. | ||||
292 | // If not, defer the check until later. | ||||
293 | if (exceptionSpecNotKnownYet(Old) || exceptionSpecNotKnownYet(New)) { | ||||
294 | DelayedEquivalentExceptionSpecChecks.push_back({New, Old}); | ||||
295 | return false; | ||||
296 | } | ||||
297 | |||||
298 | // Check the types as written: they must match before any exception | ||||
299 | // specification adjustment is applied. | ||||
300 | if (!CheckEquivalentExceptionSpecImpl( | ||||
301 | *this, PDiag(DiagID), PDiag(diag::note_previous_declaration), | ||||
302 | Old->getType()->getAs<FunctionProtoType>(), Old->getLocation(), | ||||
303 | New->getType()->getAs<FunctionProtoType>(), New->getLocation(), | ||||
304 | &MissingExceptionSpecification, &MissingEmptyExceptionSpecification, | ||||
305 | /*AllowNoexceptAllMatchWithNoSpec=*/true, IsOperatorNew)) { | ||||
306 | // C++11 [except.spec]p4 [DR1492]: | ||||
307 | // If a declaration of a function has an implicit | ||||
308 | // exception-specification, other declarations of the function shall | ||||
309 | // not specify an exception-specification. | ||||
310 | if (getLangOpts().CPlusPlus11 && getLangOpts().CXXExceptions && | ||||
311 | hasImplicitExceptionSpec(Old) != hasImplicitExceptionSpec(New)) { | ||||
312 | Diag(New->getLocation(), diag::ext_implicit_exception_spec_mismatch) | ||||
313 | << hasImplicitExceptionSpec(Old); | ||||
314 | if (Old->getLocation().isValid()) | ||||
315 | Diag(Old->getLocation(), diag::note_previous_declaration); | ||||
316 | } | ||||
317 | return false; | ||||
318 | } | ||||
319 | |||||
320 | // The failure was something other than an missing exception | ||||
321 | // specification; return an error, except in MS mode where this is a warning. | ||||
322 | if (!MissingExceptionSpecification) | ||||
323 | return ReturnValueOnError; | ||||
324 | |||||
325 | const FunctionProtoType *NewProto = | ||||
326 | New->getType()->castAs<FunctionProtoType>(); | ||||
327 | |||||
328 | // The new function declaration is only missing an empty exception | ||||
329 | // specification "throw()". If the throw() specification came from a | ||||
330 | // function in a system header that has C linkage, just add an empty | ||||
331 | // exception specification to the "new" declaration. Note that C library | ||||
332 | // implementations are permitted to add these nothrow exception | ||||
333 | // specifications. | ||||
334 | // | ||||
335 | // Likewise if the old function is a builtin. | ||||
336 | if (MissingEmptyExceptionSpecification && NewProto && | ||||
337 | (Old->getLocation().isInvalid() || | ||||
338 | Context.getSourceManager().isInSystemHeader(Old->getLocation()) || | ||||
339 | Old->getBuiltinID()) && | ||||
340 | Old->isExternC()) { | ||||
341 | New->setType(Context.getFunctionType( | ||||
342 | NewProto->getReturnType(), NewProto->getParamTypes(), | ||||
343 | NewProto->getExtProtoInfo().withExceptionSpec(EST_DynamicNone))); | ||||
344 | return false; | ||||
345 | } | ||||
346 | |||||
347 | const FunctionProtoType *OldProto = | ||||
348 | Old->getType()->castAs<FunctionProtoType>(); | ||||
349 | |||||
350 | FunctionProtoType::ExceptionSpecInfo ESI = OldProto->getExceptionSpecType(); | ||||
351 | if (ESI.Type == EST_Dynamic) { | ||||
352 | // FIXME: What if the exceptions are described in terms of the old | ||||
353 | // prototype's parameters? | ||||
354 | ESI.Exceptions = OldProto->exceptions(); | ||||
355 | } | ||||
356 | |||||
357 | if (ESI.Type == EST_NoexceptFalse) | ||||
358 | ESI.Type = EST_None; | ||||
359 | if (ESI.Type == EST_NoexceptTrue) | ||||
360 | ESI.Type = EST_BasicNoexcept; | ||||
361 | |||||
362 | // For dependent noexcept, we can't just take the expression from the old | ||||
363 | // prototype. It likely contains references to the old prototype's parameters. | ||||
364 | if (ESI.Type == EST_DependentNoexcept) { | ||||
365 | New->setInvalidDecl(); | ||||
366 | } else { | ||||
367 | // Update the type of the function with the appropriate exception | ||||
368 | // specification. | ||||
369 | New->setType(Context.getFunctionType( | ||||
370 | NewProto->getReturnType(), NewProto->getParamTypes(), | ||||
371 | NewProto->getExtProtoInfo().withExceptionSpec(ESI))); | ||||
372 | } | ||||
373 | |||||
374 | if (getLangOpts().MSVCCompat && ESI.Type != EST_DependentNoexcept) { | ||||
375 | // Allow missing exception specifications in redeclarations as an extension. | ||||
376 | DiagID = diag::ext_ms_missing_exception_specification; | ||||
377 | ReturnValueOnError = false; | ||||
378 | } else if (New->isReplaceableGlobalAllocationFunction() && | ||||
379 | ESI.Type != EST_DependentNoexcept) { | ||||
380 | // Allow missing exception specifications in redeclarations as an extension, | ||||
381 | // when declaring a replaceable global allocation function. | ||||
382 | DiagID = diag::ext_missing_exception_specification; | ||||
383 | ReturnValueOnError = false; | ||||
384 | } else if (ESI.Type == EST_NoThrow) { | ||||
385 | // Allow missing attribute 'nothrow' in redeclarations, since this is a very | ||||
386 | // common omission. | ||||
387 | DiagID = diag::ext_missing_exception_specification; | ||||
388 | ReturnValueOnError = false; | ||||
389 | } else { | ||||
390 | DiagID = diag::err_missing_exception_specification; | ||||
391 | ReturnValueOnError = true; | ||||
392 | } | ||||
393 | |||||
394 | // Warn about the lack of exception specification. | ||||
395 | SmallString<128> ExceptionSpecString; | ||||
396 | llvm::raw_svector_ostream OS(ExceptionSpecString); | ||||
397 | switch (OldProto->getExceptionSpecType()) { | ||||
398 | case EST_DynamicNone: | ||||
399 | OS << "throw()"; | ||||
400 | break; | ||||
401 | |||||
402 | case EST_Dynamic: { | ||||
403 | OS << "throw("; | ||||
404 | bool OnFirstException = true; | ||||
405 | for (const auto &E : OldProto->exceptions()) { | ||||
406 | if (OnFirstException) | ||||
407 | OnFirstException = false; | ||||
408 | else | ||||
409 | OS << ", "; | ||||
410 | |||||
411 | OS << E.getAsString(getPrintingPolicy()); | ||||
412 | } | ||||
413 | OS << ")"; | ||||
414 | break; | ||||
415 | } | ||||
416 | |||||
417 | case EST_BasicNoexcept: | ||||
418 | OS << "noexcept"; | ||||
419 | break; | ||||
420 | |||||
421 | case EST_DependentNoexcept: | ||||
422 | case EST_NoexceptFalse: | ||||
423 | case EST_NoexceptTrue: | ||||
424 | OS << "noexcept("; | ||||
425 | assert(OldProto->getNoexceptExpr() != nullptr && "Expected non-null Expr")((OldProto->getNoexceptExpr() != nullptr && "Expected non-null Expr" ) ? static_cast<void> (0) : __assert_fail ("OldProto->getNoexceptExpr() != nullptr && \"Expected non-null Expr\"" , "/build/llvm-toolchain-snapshot-10~svn374877/tools/clang/lib/Sema/SemaExceptionSpec.cpp" , 425, __PRETTY_FUNCTION__)); | ||||
426 | OldProto->getNoexceptExpr()->printPretty(OS, nullptr, getPrintingPolicy()); | ||||
427 | OS << ")"; | ||||
428 | break; | ||||
429 | case EST_NoThrow: | ||||
430 | OS <<"__attribute__((nothrow))"; | ||||
431 | break; | ||||
432 | case EST_None: | ||||
433 | case EST_MSAny: | ||||
434 | case EST_Unevaluated: | ||||
435 | case EST_Uninstantiated: | ||||
436 | case EST_Unparsed: | ||||
437 | llvm_unreachable("This spec type is compatible with none.")::llvm::llvm_unreachable_internal("This spec type is compatible with none." , "/build/llvm-toolchain-snapshot-10~svn374877/tools/clang/lib/Sema/SemaExceptionSpec.cpp" , 437); | ||||
438 | } | ||||
439 | |||||
440 | SourceLocation FixItLoc; | ||||
441 | if (TypeSourceInfo *TSInfo = New->getTypeSourceInfo()) { | ||||
442 | TypeLoc TL = TSInfo->getTypeLoc().IgnoreParens(); | ||||
443 | // FIXME: Preserve enough information so that we can produce a correct fixit | ||||
444 | // location when there is a trailing return type. | ||||
445 | if (auto FTLoc = TL.getAs<FunctionProtoTypeLoc>()) | ||||
446 | if (!FTLoc.getTypePtr()->hasTrailingReturn()) | ||||
447 | FixItLoc = getLocForEndOfToken(FTLoc.getLocalRangeEnd()); | ||||
448 | } | ||||
449 | |||||
450 | if (FixItLoc.isInvalid()) | ||||
451 | Diag(New->getLocation(), DiagID) | ||||
452 | << New << OS.str(); | ||||
453 | else { | ||||
454 | Diag(New->getLocation(), DiagID) | ||||
455 | << New << OS.str() | ||||
456 | << FixItHint::CreateInsertion(FixItLoc, " " + OS.str().str()); | ||||
457 | } | ||||
458 | |||||
459 | if (Old->getLocation().isValid()) | ||||
460 | Diag(Old->getLocation(), diag::note_previous_declaration); | ||||
461 | |||||
462 | return ReturnValueOnError; | ||||
463 | } | ||||
464 | |||||
465 | /// CheckEquivalentExceptionSpec - Check if the two types have equivalent | ||||
466 | /// exception specifications. Exception specifications are equivalent if | ||||
467 | /// they allow exactly the same set of exception types. It does not matter how | ||||
468 | /// that is achieved. See C++ [except.spec]p2. | ||||
469 | bool Sema::CheckEquivalentExceptionSpec( | ||||
470 | const FunctionProtoType *Old, SourceLocation OldLoc, | ||||
471 | const FunctionProtoType *New, SourceLocation NewLoc) { | ||||
472 | if (!getLangOpts().CXXExceptions) | ||||
473 | return false; | ||||
474 | |||||
475 | unsigned DiagID = diag::err_mismatched_exception_spec; | ||||
476 | if (getLangOpts().MSVCCompat) | ||||
477 | DiagID = diag::ext_mismatched_exception_spec; | ||||
478 | bool Result = CheckEquivalentExceptionSpecImpl( | ||||
479 | *this, PDiag(DiagID), PDiag(diag::note_previous_declaration), | ||||
480 | Old, OldLoc, New, NewLoc); | ||||
481 | |||||
482 | // In Microsoft mode, mismatching exception specifications just cause a warning. | ||||
483 | if (getLangOpts().MSVCCompat) | ||||
484 | return false; | ||||
485 | return Result; | ||||
486 | } | ||||
487 | |||||
488 | /// CheckEquivalentExceptionSpec - Check if the two types have compatible | ||||
489 | /// exception specifications. See C++ [except.spec]p3. | ||||
490 | /// | ||||
491 | /// \return \c false if the exception specifications match, \c true if there is | ||||
492 | /// a problem. If \c true is returned, either a diagnostic has already been | ||||
493 | /// produced or \c *MissingExceptionSpecification is set to \c true. | ||||
494 | static bool CheckEquivalentExceptionSpecImpl( | ||||
495 | Sema &S, const PartialDiagnostic &DiagID, const PartialDiagnostic &NoteID, | ||||
496 | const FunctionProtoType *Old, SourceLocation OldLoc, | ||||
497 | const FunctionProtoType *New, SourceLocation NewLoc, | ||||
498 | bool *MissingExceptionSpecification, | ||||
499 | bool *MissingEmptyExceptionSpecification, | ||||
500 | bool AllowNoexceptAllMatchWithNoSpec, bool IsOperatorNew) { | ||||
501 | if (MissingExceptionSpecification) | ||||
502 | *MissingExceptionSpecification = false; | ||||
503 | |||||
504 | if (MissingEmptyExceptionSpecification) | ||||
505 | *MissingEmptyExceptionSpecification = false; | ||||
506 | |||||
507 | Old = S.ResolveExceptionSpec(NewLoc, Old); | ||||
508 | if (!Old) | ||||
509 | return false; | ||||
510 | New = S.ResolveExceptionSpec(NewLoc, New); | ||||
511 | if (!New) | ||||
512 | return false; | ||||
513 | |||||
514 | // C++0x [except.spec]p3: Two exception-specifications are compatible if: | ||||
515 | // - both are non-throwing, regardless of their form, | ||||
516 | // - both have the form noexcept(constant-expression) and the constant- | ||||
517 | // expressions are equivalent, | ||||
518 | // - both are dynamic-exception-specifications that have the same set of | ||||
519 | // adjusted types. | ||||
520 | // | ||||
521 | // C++0x [except.spec]p12: An exception-specification is non-throwing if it is | ||||
522 | // of the form throw(), noexcept, or noexcept(constant-expression) where the | ||||
523 | // constant-expression yields true. | ||||
524 | // | ||||
525 | // C++0x [except.spec]p4: If any declaration of a function has an exception- | ||||
526 | // specifier that is not a noexcept-specification allowing all exceptions, | ||||
527 | // all declarations [...] of that function shall have a compatible | ||||
528 | // exception-specification. | ||||
529 | // | ||||
530 | // That last point basically means that noexcept(false) matches no spec. | ||||
531 | // It's considered when AllowNoexceptAllMatchWithNoSpec is true. | ||||
532 | |||||
533 | ExceptionSpecificationType OldEST = Old->getExceptionSpecType(); | ||||
534 | ExceptionSpecificationType NewEST = New->getExceptionSpecType(); | ||||
535 | |||||
536 | assert(!isUnresolvedExceptionSpec(OldEST) &&((!isUnresolvedExceptionSpec(OldEST) && !isUnresolvedExceptionSpec (NewEST) && "Shouldn't see unknown exception specifications here" ) ? static_cast<void> (0) : __assert_fail ("!isUnresolvedExceptionSpec(OldEST) && !isUnresolvedExceptionSpec(NewEST) && \"Shouldn't see unknown exception specifications here\"" , "/build/llvm-toolchain-snapshot-10~svn374877/tools/clang/lib/Sema/SemaExceptionSpec.cpp" , 538, __PRETTY_FUNCTION__)) | ||||
537 | !isUnresolvedExceptionSpec(NewEST) &&((!isUnresolvedExceptionSpec(OldEST) && !isUnresolvedExceptionSpec (NewEST) && "Shouldn't see unknown exception specifications here" ) ? static_cast<void> (0) : __assert_fail ("!isUnresolvedExceptionSpec(OldEST) && !isUnresolvedExceptionSpec(NewEST) && \"Shouldn't see unknown exception specifications here\"" , "/build/llvm-toolchain-snapshot-10~svn374877/tools/clang/lib/Sema/SemaExceptionSpec.cpp" , 538, __PRETTY_FUNCTION__)) | ||||
538 | "Shouldn't see unknown exception specifications here")((!isUnresolvedExceptionSpec(OldEST) && !isUnresolvedExceptionSpec (NewEST) && "Shouldn't see unknown exception specifications here" ) ? static_cast<void> (0) : __assert_fail ("!isUnresolvedExceptionSpec(OldEST) && !isUnresolvedExceptionSpec(NewEST) && \"Shouldn't see unknown exception specifications here\"" , "/build/llvm-toolchain-snapshot-10~svn374877/tools/clang/lib/Sema/SemaExceptionSpec.cpp" , 538, __PRETTY_FUNCTION__)); | ||||
539 | |||||
540 | CanThrowResult OldCanThrow = Old->canThrow(); | ||||
541 | CanThrowResult NewCanThrow = New->canThrow(); | ||||
542 | |||||
543 | // Any non-throwing specifications are compatible. | ||||
544 | if (OldCanThrow == CT_Cannot && NewCanThrow == CT_Cannot) | ||||
545 | return false; | ||||
546 | |||||
547 | // Any throws-anything specifications are usually compatible. | ||||
548 | if (OldCanThrow == CT_Can && OldEST != EST_Dynamic && | ||||
549 | NewCanThrow == CT_Can && NewEST != EST_Dynamic) { | ||||
550 | // The exception is that the absence of an exception specification only | ||||
551 | // matches noexcept(false) for functions, as described above. | ||||
552 | if (!AllowNoexceptAllMatchWithNoSpec && | ||||
553 | ((OldEST == EST_None && NewEST == EST_NoexceptFalse) || | ||||
554 | (OldEST == EST_NoexceptFalse && NewEST == EST_None))) { | ||||
555 | // This is the disallowed case. | ||||
556 | } else { | ||||
557 | return false; | ||||
558 | } | ||||
559 | } | ||||
560 | |||||
561 | // C++14 [except.spec]p3: | ||||
562 | // Two exception-specifications are compatible if [...] both have the form | ||||
563 | // noexcept(constant-expression) and the constant-expressions are equivalent | ||||
564 | if (OldEST == EST_DependentNoexcept && NewEST == EST_DependentNoexcept) { | ||||
565 | llvm::FoldingSetNodeID OldFSN, NewFSN; | ||||
566 | Old->getNoexceptExpr()->Profile(OldFSN, S.Context, true); | ||||
567 | New->getNoexceptExpr()->Profile(NewFSN, S.Context, true); | ||||
568 | if (OldFSN == NewFSN) | ||||
569 | return false; | ||||
570 | } | ||||
571 | |||||
572 | // Dynamic exception specifications with the same set of adjusted types | ||||
573 | // are compatible. | ||||
574 | if (OldEST == EST_Dynamic && NewEST == EST_Dynamic) { | ||||
575 | bool Success = true; | ||||
576 | // Both have a dynamic exception spec. Collect the first set, then compare | ||||
577 | // to the second. | ||||
578 | llvm::SmallPtrSet<CanQualType, 8> OldTypes, NewTypes; | ||||
579 | for (const auto &I : Old->exceptions()) | ||||
580 | OldTypes.insert(S.Context.getCanonicalType(I).getUnqualifiedType()); | ||||
581 | |||||
582 | for (const auto &I : New->exceptions()) { | ||||
583 | CanQualType TypePtr = S.Context.getCanonicalType(I).getUnqualifiedType(); | ||||
584 | if (OldTypes.count(TypePtr)) | ||||
585 | NewTypes.insert(TypePtr); | ||||
586 | else { | ||||
587 | Success = false; | ||||
588 | break; | ||||
589 | } | ||||
590 | } | ||||
591 | |||||
592 | if (Success && OldTypes.size() == NewTypes.size()) | ||||
593 | return false; | ||||
594 | } | ||||
595 | |||||
596 | // As a special compatibility feature, under C++0x we accept no spec and | ||||
597 | // throw(std::bad_alloc) as equivalent for operator new and operator new[]. | ||||
598 | // This is because the implicit declaration changed, but old code would break. | ||||
599 | if (S.getLangOpts().CPlusPlus11 && IsOperatorNew) { | ||||
600 | const FunctionProtoType *WithExceptions = nullptr; | ||||
601 | if (OldEST == EST_None && NewEST == EST_Dynamic) | ||||
602 | WithExceptions = New; | ||||
603 | else if (OldEST == EST_Dynamic && NewEST == EST_None) | ||||
604 | WithExceptions = Old; | ||||
605 | if (WithExceptions && WithExceptions->getNumExceptions() == 1) { | ||||
606 | // One has no spec, the other throw(something). If that something is | ||||
607 | // std::bad_alloc, all conditions are met. | ||||
608 | QualType Exception = *WithExceptions->exception_begin(); | ||||
609 | if (CXXRecordDecl *ExRecord = Exception->getAsCXXRecordDecl()) { | ||||
610 | IdentifierInfo* Name = ExRecord->getIdentifier(); | ||||
611 | if (Name && Name->getName() == "bad_alloc") { | ||||
612 | // It's called bad_alloc, but is it in std? | ||||
613 | if (ExRecord->isInStdNamespace()) { | ||||
614 | return false; | ||||
615 | } | ||||
616 | } | ||||
617 | } | ||||
618 | } | ||||
619 | } | ||||
620 | |||||
621 | // If the caller wants to handle the case that the new function is | ||||
622 | // incompatible due to a missing exception specification, let it. | ||||
623 | if (MissingExceptionSpecification && OldEST != EST_None && | ||||
624 | NewEST == EST_None) { | ||||
625 | // The old type has an exception specification of some sort, but | ||||
626 | // the new type does not. | ||||
627 | *MissingExceptionSpecification = true; | ||||
628 | |||||
629 | if (MissingEmptyExceptionSpecification && OldCanThrow == CT_Cannot) { | ||||
630 | // The old type has a throw() or noexcept(true) exception specification | ||||
631 | // and the new type has no exception specification, and the caller asked | ||||
632 | // to handle this itself. | ||||
633 | *MissingEmptyExceptionSpecification = true; | ||||
634 | } | ||||
635 | |||||
636 | return true; | ||||
637 | } | ||||
638 | |||||
639 | S.Diag(NewLoc, DiagID); | ||||
640 | if (NoteID.getDiagID() != 0 && OldLoc.isValid()) | ||||
641 | S.Diag(OldLoc, NoteID); | ||||
642 | return true; | ||||
643 | } | ||||
644 | |||||
645 | bool Sema::CheckEquivalentExceptionSpec(const PartialDiagnostic &DiagID, | ||||
646 | const PartialDiagnostic &NoteID, | ||||
647 | const FunctionProtoType *Old, | ||||
648 | SourceLocation OldLoc, | ||||
649 | const FunctionProtoType *New, | ||||
650 | SourceLocation NewLoc) { | ||||
651 | if (!getLangOpts().CXXExceptions) | ||||
652 | return false; | ||||
653 | return CheckEquivalentExceptionSpecImpl(*this, DiagID, NoteID, Old, OldLoc, | ||||
654 | New, NewLoc); | ||||
655 | } | ||||
656 | |||||
657 | bool Sema::handlerCanCatch(QualType HandlerType, QualType ExceptionType) { | ||||
658 | // [except.handle]p3: | ||||
659 | // A handler is a match for an exception object of type E if: | ||||
660 | |||||
661 | // HandlerType must be ExceptionType or derived from it, or pointer or | ||||
662 | // reference to such types. | ||||
663 | const ReferenceType *RefTy = HandlerType->getAs<ReferenceType>(); | ||||
664 | if (RefTy) | ||||
665 | HandlerType = RefTy->getPointeeType(); | ||||
666 | |||||
667 | // -- the handler is of type cv T or cv T& and E and T are the same type | ||||
668 | if (Context.hasSameUnqualifiedType(ExceptionType, HandlerType)) | ||||
669 | return true; | ||||
670 | |||||
671 | // FIXME: ObjC pointer types? | ||||
672 | if (HandlerType->isPointerType() || HandlerType->isMemberPointerType()) { | ||||
673 | if (RefTy && (!HandlerType.isConstQualified() || | ||||
674 | HandlerType.isVolatileQualified())) | ||||
675 | return false; | ||||
676 | |||||
677 | // -- the handler is of type cv T or const T& where T is a pointer or | ||||
678 | // pointer to member type and E is std::nullptr_t | ||||
679 | if (ExceptionType->isNullPtrType()) | ||||
680 | return true; | ||||
681 | |||||
682 | // -- the handler is of type cv T or const T& where T is a pointer or | ||||
683 | // pointer to member type and E is a pointer or pointer to member type | ||||
684 | // that can be converted to T by one or more of | ||||
685 | // -- a qualification conversion | ||||
686 | // -- a function pointer conversion | ||||
687 | bool LifetimeConv; | ||||
688 | QualType Result; | ||||
689 | // FIXME: Should we treat the exception as catchable if a lifetime | ||||
690 | // conversion is required? | ||||
691 | if (IsQualificationConversion(ExceptionType, HandlerType, false, | ||||
692 | LifetimeConv) || | ||||
693 | IsFunctionConversion(ExceptionType, HandlerType, Result)) | ||||
694 | return true; | ||||
695 | |||||
696 | // -- a standard pointer conversion [...] | ||||
697 | if (!ExceptionType->isPointerType() || !HandlerType->isPointerType()) | ||||
698 | return false; | ||||
699 | |||||
700 | // Handle the "qualification conversion" portion. | ||||
701 | Qualifiers EQuals, HQuals; | ||||
702 | ExceptionType = Context.getUnqualifiedArrayType( | ||||
703 | ExceptionType->getPointeeType(), EQuals); | ||||
704 | HandlerType = Context.getUnqualifiedArrayType( | ||||
705 | HandlerType->getPointeeType(), HQuals); | ||||
706 | if (!HQuals.compatiblyIncludes(EQuals)) | ||||
707 | return false; | ||||
708 | |||||
709 | if (HandlerType->isVoidType() && ExceptionType->isObjectType()) | ||||
710 | return true; | ||||
711 | |||||
712 | // The only remaining case is a derived-to-base conversion. | ||||
713 | } | ||||
714 | |||||
715 | // -- the handler is of type cg T or cv T& and T is an unambiguous public | ||||
716 | // base class of E | ||||
717 | if (!ExceptionType->isRecordType() || !HandlerType->isRecordType()) | ||||
718 | return false; | ||||
719 | CXXBasePaths Paths(/*FindAmbiguities=*/true, /*RecordPaths=*/true, | ||||
720 | /*DetectVirtual=*/false); | ||||
721 | if (!IsDerivedFrom(SourceLocation(), ExceptionType, HandlerType, Paths) || | ||||
722 | Paths.isAmbiguous(Context.getCanonicalType(HandlerType))) | ||||
723 | return false; | ||||
724 | |||||
725 | // Do this check from a context without privileges. | ||||
726 | switch (CheckBaseClassAccess(SourceLocation(), HandlerType, ExceptionType, | ||||
727 | Paths.front(), | ||||
728 | /*Diagnostic*/ 0, | ||||
729 | /*ForceCheck*/ true, | ||||
730 | /*ForceUnprivileged*/ true)) { | ||||
731 | case AR_accessible: return true; | ||||
732 | case AR_inaccessible: return false; | ||||
733 | case AR_dependent: | ||||
734 | llvm_unreachable("access check dependent for unprivileged context")::llvm::llvm_unreachable_internal("access check dependent for unprivileged context" , "/build/llvm-toolchain-snapshot-10~svn374877/tools/clang/lib/Sema/SemaExceptionSpec.cpp" , 734); | ||||
735 | case AR_delayed: | ||||
736 | llvm_unreachable("access check delayed in non-declaration")::llvm::llvm_unreachable_internal("access check delayed in non-declaration" , "/build/llvm-toolchain-snapshot-10~svn374877/tools/clang/lib/Sema/SemaExceptionSpec.cpp" , 736); | ||||
737 | } | ||||
738 | llvm_unreachable("unexpected access check result")::llvm::llvm_unreachable_internal("unexpected access check result" , "/build/llvm-toolchain-snapshot-10~svn374877/tools/clang/lib/Sema/SemaExceptionSpec.cpp" , 738); | ||||
739 | } | ||||
740 | |||||
741 | /// CheckExceptionSpecSubset - Check whether the second function type's | ||||
742 | /// exception specification is a subset (or equivalent) of the first function | ||||
743 | /// type. This is used by override and pointer assignment checks. | ||||
744 | bool Sema::CheckExceptionSpecSubset(const PartialDiagnostic &DiagID, | ||||
745 | const PartialDiagnostic &NestedDiagID, | ||||
746 | const PartialDiagnostic &NoteID, | ||||
747 | const PartialDiagnostic &NoThrowDiagID, | ||||
748 | const FunctionProtoType *Superset, | ||||
749 | SourceLocation SuperLoc, | ||||
750 | const FunctionProtoType *Subset, | ||||
751 | SourceLocation SubLoc) { | ||||
752 | |||||
753 | // Just auto-succeed under -fno-exceptions. | ||||
754 | if (!getLangOpts().CXXExceptions) | ||||
755 | return false; | ||||
756 | |||||
757 | // FIXME: As usual, we could be more specific in our error messages, but | ||||
758 | // that better waits until we've got types with source locations. | ||||
759 | |||||
760 | if (!SubLoc.isValid()) | ||||
761 | SubLoc = SuperLoc; | ||||
762 | |||||
763 | // Resolve the exception specifications, if needed. | ||||
764 | Superset = ResolveExceptionSpec(SuperLoc, Superset); | ||||
765 | if (!Superset) | ||||
766 | return false; | ||||
767 | Subset = ResolveExceptionSpec(SubLoc, Subset); | ||||
768 | if (!Subset) | ||||
769 | return false; | ||||
770 | |||||
771 | ExceptionSpecificationType SuperEST = Superset->getExceptionSpecType(); | ||||
772 | ExceptionSpecificationType SubEST = Subset->getExceptionSpecType(); | ||||
773 | assert(!isUnresolvedExceptionSpec(SuperEST) &&((!isUnresolvedExceptionSpec(SuperEST) && !isUnresolvedExceptionSpec (SubEST) && "Shouldn't see unknown exception specifications here" ) ? static_cast<void> (0) : __assert_fail ("!isUnresolvedExceptionSpec(SuperEST) && !isUnresolvedExceptionSpec(SubEST) && \"Shouldn't see unknown exception specifications here\"" , "/build/llvm-toolchain-snapshot-10~svn374877/tools/clang/lib/Sema/SemaExceptionSpec.cpp" , 775, __PRETTY_FUNCTION__)) | ||||
774 | !isUnresolvedExceptionSpec(SubEST) &&((!isUnresolvedExceptionSpec(SuperEST) && !isUnresolvedExceptionSpec (SubEST) && "Shouldn't see unknown exception specifications here" ) ? static_cast<void> (0) : __assert_fail ("!isUnresolvedExceptionSpec(SuperEST) && !isUnresolvedExceptionSpec(SubEST) && \"Shouldn't see unknown exception specifications here\"" , "/build/llvm-toolchain-snapshot-10~svn374877/tools/clang/lib/Sema/SemaExceptionSpec.cpp" , 775, __PRETTY_FUNCTION__)) | ||||
775 | "Shouldn't see unknown exception specifications here")((!isUnresolvedExceptionSpec(SuperEST) && !isUnresolvedExceptionSpec (SubEST) && "Shouldn't see unknown exception specifications here" ) ? static_cast<void> (0) : __assert_fail ("!isUnresolvedExceptionSpec(SuperEST) && !isUnresolvedExceptionSpec(SubEST) && \"Shouldn't see unknown exception specifications here\"" , "/build/llvm-toolchain-snapshot-10~svn374877/tools/clang/lib/Sema/SemaExceptionSpec.cpp" , 775, __PRETTY_FUNCTION__)); | ||||
776 | |||||
777 | // If there are dependent noexcept specs, assume everything is fine. Unlike | ||||
778 | // with the equivalency check, this is safe in this case, because we don't | ||||
779 | // want to merge declarations. Checks after instantiation will catch any | ||||
780 | // omissions we make here. | ||||
781 | if (SuperEST == EST_DependentNoexcept || SubEST == EST_DependentNoexcept) | ||||
782 | return false; | ||||
783 | |||||
784 | CanThrowResult SuperCanThrow = Superset->canThrow(); | ||||
785 | CanThrowResult SubCanThrow = Subset->canThrow(); | ||||
786 | |||||
787 | // If the superset contains everything or the subset contains nothing, we're | ||||
788 | // done. | ||||
789 | if ((SuperCanThrow == CT_Can && SuperEST != EST_Dynamic) || | ||||
790 | SubCanThrow == CT_Cannot) | ||||
791 | return CheckParamExceptionSpec(NestedDiagID, NoteID, Superset, SuperLoc, | ||||
792 | Subset, SubLoc); | ||||
793 | |||||
794 | // Allow __declspec(nothrow) to be missing on redeclaration as an extension in | ||||
795 | // some cases. | ||||
796 | if (NoThrowDiagID.getDiagID() != 0 && SubCanThrow == CT_Can && | ||||
797 | SuperCanThrow == CT_Cannot && SuperEST == EST_NoThrow) { | ||||
798 | Diag(SubLoc, NoThrowDiagID); | ||||
799 | if (NoteID.getDiagID() != 0) | ||||
800 | Diag(SuperLoc, NoteID); | ||||
801 | return true; | ||||
802 | } | ||||
803 | |||||
804 | // If the subset contains everything or the superset contains nothing, we've | ||||
805 | // failed. | ||||
806 | if ((SubCanThrow == CT_Can && SubEST != EST_Dynamic) || | ||||
807 | SuperCanThrow == CT_Cannot) { | ||||
808 | Diag(SubLoc, DiagID); | ||||
809 | if (NoteID.getDiagID() != 0) | ||||
810 | Diag(SuperLoc, NoteID); | ||||
811 | return true; | ||||
812 | } | ||||
813 | |||||
814 | assert(SuperEST == EST_Dynamic && SubEST == EST_Dynamic &&((SuperEST == EST_Dynamic && SubEST == EST_Dynamic && "Exception spec subset: non-dynamic case slipped through.") ? static_cast<void> (0) : __assert_fail ("SuperEST == EST_Dynamic && SubEST == EST_Dynamic && \"Exception spec subset: non-dynamic case slipped through.\"" , "/build/llvm-toolchain-snapshot-10~svn374877/tools/clang/lib/Sema/SemaExceptionSpec.cpp" , 815, __PRETTY_FUNCTION__)) | ||||
815 | "Exception spec subset: non-dynamic case slipped through.")((SuperEST == EST_Dynamic && SubEST == EST_Dynamic && "Exception spec subset: non-dynamic case slipped through.") ? static_cast<void> (0) : __assert_fail ("SuperEST == EST_Dynamic && SubEST == EST_Dynamic && \"Exception spec subset: non-dynamic case slipped through.\"" , "/build/llvm-toolchain-snapshot-10~svn374877/tools/clang/lib/Sema/SemaExceptionSpec.cpp" , 815, __PRETTY_FUNCTION__)); | ||||
816 | |||||
817 | // Neither contains everything or nothing. Do a proper comparison. | ||||
818 | for (QualType SubI : Subset->exceptions()) { | ||||
819 | if (const ReferenceType *RefTy = SubI->getAs<ReferenceType>()) | ||||
820 | SubI = RefTy->getPointeeType(); | ||||
821 | |||||
822 | // Make sure it's in the superset. | ||||
823 | bool Contained = false; | ||||
824 | for (QualType SuperI : Superset->exceptions()) { | ||||
825 | // [except.spec]p5: | ||||
826 | // the target entity shall allow at least the exceptions allowed by the | ||||
827 | // source | ||||
828 | // | ||||
829 | // We interpret this as meaning that a handler for some target type would | ||||
830 | // catch an exception of each source type. | ||||
831 | if (handlerCanCatch(SuperI, SubI)) { | ||||
832 | Contained = true; | ||||
833 | break; | ||||
834 | } | ||||
835 | } | ||||
836 | if (!Contained) { | ||||
837 | Diag(SubLoc, DiagID); | ||||
838 | if (NoteID.getDiagID() != 0) | ||||
839 | Diag(SuperLoc, NoteID); | ||||
840 | return true; | ||||
841 | } | ||||
842 | } | ||||
843 | // We've run half the gauntlet. | ||||
844 | return CheckParamExceptionSpec(NestedDiagID, NoteID, Superset, SuperLoc, | ||||
845 | Subset, SubLoc); | ||||
846 | } | ||||
847 | |||||
848 | static bool | ||||
849 | CheckSpecForTypesEquivalent(Sema &S, const PartialDiagnostic &DiagID, | ||||
850 | const PartialDiagnostic &NoteID, QualType Target, | ||||
851 | SourceLocation TargetLoc, QualType Source, | ||||
852 | SourceLocation SourceLoc) { | ||||
853 | const FunctionProtoType *TFunc = GetUnderlyingFunction(Target); | ||||
854 | if (!TFunc) | ||||
855 | return false; | ||||
856 | const FunctionProtoType *SFunc = GetUnderlyingFunction(Source); | ||||
857 | if (!SFunc) | ||||
858 | return false; | ||||
859 | |||||
860 | return S.CheckEquivalentExceptionSpec(DiagID, NoteID, TFunc, TargetLoc, | ||||
861 | SFunc, SourceLoc); | ||||
862 | } | ||||
863 | |||||
864 | /// CheckParamExceptionSpec - Check if the parameter and return types of the | ||||
865 | /// two functions have equivalent exception specs. This is part of the | ||||
866 | /// assignment and override compatibility check. We do not check the parameters | ||||
867 | /// of parameter function pointers recursively, as no sane programmer would | ||||
868 | /// even be able to write such a function type. | ||||
869 | bool Sema::CheckParamExceptionSpec(const PartialDiagnostic &DiagID, | ||||
870 | const PartialDiagnostic &NoteID, | ||||
871 | const FunctionProtoType *Target, | ||||
872 | SourceLocation TargetLoc, | ||||
873 | const FunctionProtoType *Source, | ||||
874 | SourceLocation SourceLoc) { | ||||
875 | auto RetDiag = DiagID; | ||||
876 | RetDiag << 0; | ||||
877 | if (CheckSpecForTypesEquivalent( | ||||
878 | *this, RetDiag, PDiag(), | ||||
879 | Target->getReturnType(), TargetLoc, Source->getReturnType(), | ||||
880 | SourceLoc)) | ||||
881 | return true; | ||||
882 | |||||
883 | // We shouldn't even be testing this unless the arguments are otherwise | ||||
884 | // compatible. | ||||
885 | assert(Target->getNumParams() == Source->getNumParams() &&((Target->getNumParams() == Source->getNumParams() && "Functions have different argument counts.") ? static_cast< void> (0) : __assert_fail ("Target->getNumParams() == Source->getNumParams() && \"Functions have different argument counts.\"" , "/build/llvm-toolchain-snapshot-10~svn374877/tools/clang/lib/Sema/SemaExceptionSpec.cpp" , 886, __PRETTY_FUNCTION__)) | ||||
886 | "Functions have different argument counts.")((Target->getNumParams() == Source->getNumParams() && "Functions have different argument counts.") ? static_cast< void> (0) : __assert_fail ("Target->getNumParams() == Source->getNumParams() && \"Functions have different argument counts.\"" , "/build/llvm-toolchain-snapshot-10~svn374877/tools/clang/lib/Sema/SemaExceptionSpec.cpp" , 886, __PRETTY_FUNCTION__)); | ||||
887 | for (unsigned i = 0, E = Target->getNumParams(); i != E; ++i) { | ||||
888 | auto ParamDiag = DiagID; | ||||
889 | ParamDiag << 1; | ||||
890 | if (CheckSpecForTypesEquivalent( | ||||
891 | *this, ParamDiag, PDiag(), | ||||
892 | Target->getParamType(i), TargetLoc, Source->getParamType(i), | ||||
893 | SourceLoc)) | ||||
894 | return true; | ||||
895 | } | ||||
896 | return false; | ||||
897 | } | ||||
898 | |||||
899 | bool Sema::CheckExceptionSpecCompatibility(Expr *From, QualType ToType) { | ||||
900 | // First we check for applicability. | ||||
901 | // Target type must be a function, function pointer or function reference. | ||||
902 | const FunctionProtoType *ToFunc = GetUnderlyingFunction(ToType); | ||||
903 | if (!ToFunc || ToFunc->hasDependentExceptionSpec()) | ||||
904 | return false; | ||||
905 | |||||
906 | // SourceType must be a function or function pointer. | ||||
907 | const FunctionProtoType *FromFunc = GetUnderlyingFunction(From->getType()); | ||||
908 | if (!FromFunc || FromFunc->hasDependentExceptionSpec()) | ||||
909 | return false; | ||||
910 | |||||
911 | unsigned DiagID = diag::err_incompatible_exception_specs; | ||||
912 | unsigned NestedDiagID = diag::err_deep_exception_specs_differ; | ||||
913 | // This is not an error in C++17 onwards, unless the noexceptness doesn't | ||||
914 | // match, but in that case we have a full-on type mismatch, not just a | ||||
915 | // type sugar mismatch. | ||||
916 | if (getLangOpts().CPlusPlus17) { | ||||
917 | DiagID = diag::warn_incompatible_exception_specs; | ||||
918 | NestedDiagID = diag::warn_deep_exception_specs_differ; | ||||
919 | } | ||||
920 | |||||
921 | // Now we've got the correct types on both sides, check their compatibility. | ||||
922 | // This means that the source of the conversion can only throw a subset of | ||||
923 | // the exceptions of the target, and any exception specs on arguments or | ||||
924 | // return types must be equivalent. | ||||
925 | // | ||||
926 | // FIXME: If there is a nested dependent exception specification, we should | ||||
927 | // not be checking it here. This is fine: | ||||
928 | // template<typename T> void f() { | ||||
929 | // void (*p)(void (*) throw(T)); | ||||
930 | // void (*q)(void (*) throw(int)) = p; | ||||
931 | // } | ||||
932 | // ... because it might be instantiated with T=int. | ||||
933 | return CheckExceptionSpecSubset( | ||||
934 | PDiag(DiagID), PDiag(NestedDiagID), PDiag(), PDiag(), ToFunc, | ||||
935 | From->getSourceRange().getBegin(), FromFunc, SourceLocation()) && | ||||
936 | !getLangOpts().CPlusPlus17; | ||||
937 | } | ||||
938 | |||||
939 | bool Sema::CheckOverridingFunctionExceptionSpec(const CXXMethodDecl *New, | ||||
940 | const CXXMethodDecl *Old) { | ||||
941 | // If the new exception specification hasn't been parsed yet, skip the check. | ||||
942 | // We'll get called again once it's been parsed. | ||||
943 | if (New->getType()->castAs<FunctionProtoType>()->getExceptionSpecType() == | ||||
| |||||
944 | EST_Unparsed) | ||||
945 | return false; | ||||
946 | |||||
947 | // Don't check uninstantiated template destructors at all. We can only | ||||
948 | // synthesize correct specs after the template is instantiated. | ||||
949 | if (isa<CXXDestructorDecl>(New) && New->getParent()->isDependentType()) | ||||
950 | return false; | ||||
951 | |||||
952 | // If the old exception specification hasn't been parsed yet, or the new | ||||
953 | // exception specification can't be computed yet, remember that we need to | ||||
954 | // perform this check when we get to the end of the outermost | ||||
955 | // lexically-surrounding class. | ||||
956 | if (exceptionSpecNotKnownYet(Old) || exceptionSpecNotKnownYet(New)) { | ||||
957 | DelayedOverridingExceptionSpecChecks.push_back({New, Old}); | ||||
958 | return false; | ||||
959 | } | ||||
960 | |||||
961 | unsigned DiagID = diag::err_override_exception_spec; | ||||
962 | if (getLangOpts().MSVCCompat) | ||||
963 | DiagID = diag::ext_override_exception_spec; | ||||
964 | return CheckExceptionSpecSubset(PDiag(DiagID), | ||||
965 | PDiag(diag::err_deep_exception_specs_differ), | ||||
966 | PDiag(diag::note_overridden_virtual_function), | ||||
967 | PDiag(diag::ext_override_exception_spec), | ||||
968 | Old->getType()->getAs<FunctionProtoType>(), | ||||
969 | Old->getLocation(), | ||||
970 | New->getType()->getAs<FunctionProtoType>(), | ||||
971 | New->getLocation()); | ||||
972 | } | ||||
973 | |||||
974 | static CanThrowResult canSubExprsThrow(Sema &S, const Expr *E) { | ||||
975 | CanThrowResult R = CT_Cannot; | ||||
976 | for (const Stmt *SubStmt : E->children()) { | ||||
977 | R = mergeCanThrow(R, S.canThrow(cast<Expr>(SubStmt))); | ||||
978 | if (R == CT_Can) | ||||
979 | break; | ||||
980 | } | ||||
981 | return R; | ||||
982 | } | ||||
983 | |||||
984 | static CanThrowResult canCalleeThrow(Sema &S, const Expr *E, const Decl *D) { | ||||
985 | // As an extension, we assume that __attribute__((nothrow)) functions don't | ||||
986 | // throw. | ||||
987 | if (D && isa<FunctionDecl>(D) && D->hasAttr<NoThrowAttr>()) | ||||
988 | return CT_Cannot; | ||||
989 | |||||
990 | QualType T; | ||||
991 | |||||
992 | // In C++1z, just look at the function type of the callee. | ||||
993 | if (S.getLangOpts().CPlusPlus17 && isa<CallExpr>(E)) { | ||||
994 | E = cast<CallExpr>(E)->getCallee(); | ||||
995 | T = E->getType(); | ||||
996 | if (T->isSpecificPlaceholderType(BuiltinType::BoundMember)) { | ||||
997 | // Sadly we don't preserve the actual type as part of the "bound member" | ||||
998 | // placeholder, so we need to reconstruct it. | ||||
999 | E = E->IgnoreParenImpCasts(); | ||||
1000 | |||||
1001 | // Could be a call to a pointer-to-member or a plain member access. | ||||
1002 | if (auto *Op = dyn_cast<BinaryOperator>(E)) { | ||||
1003 | assert(Op->getOpcode() == BO_PtrMemD || Op->getOpcode() == BO_PtrMemI)((Op->getOpcode() == BO_PtrMemD || Op->getOpcode() == BO_PtrMemI ) ? static_cast<void> (0) : __assert_fail ("Op->getOpcode() == BO_PtrMemD || Op->getOpcode() == BO_PtrMemI" , "/build/llvm-toolchain-snapshot-10~svn374877/tools/clang/lib/Sema/SemaExceptionSpec.cpp" , 1003, __PRETTY_FUNCTION__)); | ||||
1004 | T = Op->getRHS()->getType() | ||||
1005 | ->castAs<MemberPointerType>()->getPointeeType(); | ||||
1006 | } else { | ||||
1007 | T = cast<MemberExpr>(E)->getMemberDecl()->getType(); | ||||
1008 | } | ||||
1009 | } | ||||
1010 | } else if (const ValueDecl *VD = dyn_cast_or_null<ValueDecl>(D)) | ||||
1011 | T = VD->getType(); | ||||
1012 | else | ||||
1013 | // If we have no clue what we're calling, assume the worst. | ||||
1014 | return CT_Can; | ||||
1015 | |||||
1016 | const FunctionProtoType *FT; | ||||
1017 | if ((FT = T->getAs<FunctionProtoType>())) { | ||||
1018 | } else if (const PointerType *PT = T->getAs<PointerType>()) | ||||
1019 | FT = PT->getPointeeType()->getAs<FunctionProtoType>(); | ||||
1020 | else if (const ReferenceType *RT = T->getAs<ReferenceType>()) | ||||
1021 | FT = RT->getPointeeType()->getAs<FunctionProtoType>(); | ||||
1022 | else if (const MemberPointerType *MT = T->getAs<MemberPointerType>()) | ||||
1023 | FT = MT->getPointeeType()->getAs<FunctionProtoType>(); | ||||
1024 | else if (const BlockPointerType *BT = T->getAs<BlockPointerType>()) | ||||
1025 | FT = BT->getPointeeType()->getAs<FunctionProtoType>(); | ||||
1026 | |||||
1027 | if (!FT) | ||||
1028 | return CT_Can; | ||||
1029 | |||||
1030 | FT = S.ResolveExceptionSpec(E->getBeginLoc(), FT); | ||||
1031 | if (!FT) | ||||
1032 | return CT_Can; | ||||
1033 | |||||
1034 | return FT->canThrow(); | ||||
1035 | } | ||||
1036 | |||||
1037 | static CanThrowResult canDynamicCastThrow(const CXXDynamicCastExpr *DC) { | ||||
1038 | if (DC->isTypeDependent()) | ||||
1039 | return CT_Dependent; | ||||
1040 | |||||
1041 | if (!DC->getTypeAsWritten()->isReferenceType()) | ||||
1042 | return CT_Cannot; | ||||
1043 | |||||
1044 | if (DC->getSubExpr()->isTypeDependent()) | ||||
1045 | return CT_Dependent; | ||||
1046 | |||||
1047 | return DC->getCastKind() == clang::CK_Dynamic? CT_Can : CT_Cannot; | ||||
1048 | } | ||||
1049 | |||||
1050 | static CanThrowResult canTypeidThrow(Sema &S, const CXXTypeidExpr *DC) { | ||||
1051 | if (DC->isTypeOperand()) | ||||
1052 | return CT_Cannot; | ||||
1053 | |||||
1054 | Expr *Op = DC->getExprOperand(); | ||||
1055 | if (Op->isTypeDependent()) | ||||
1056 | return CT_Dependent; | ||||
1057 | |||||
1058 | const RecordType *RT = Op->getType()->getAs<RecordType>(); | ||||
1059 | if (!RT) | ||||
1060 | return CT_Cannot; | ||||
1061 | |||||
1062 | if (!cast<CXXRecordDecl>(RT->getDecl())->isPolymorphic()) | ||||
1063 | return CT_Cannot; | ||||
1064 | |||||
1065 | if (Op->Classify(S.Context).isPRValue()) | ||||
1066 | return CT_Cannot; | ||||
1067 | |||||
1068 | return CT_Can; | ||||
1069 | } | ||||
1070 | |||||
1071 | CanThrowResult Sema::canThrow(const Expr *E) { | ||||
1072 | // C++ [expr.unary.noexcept]p3: | ||||
1073 | // [Can throw] if in a potentially-evaluated context the expression would | ||||
1074 | // contain: | ||||
1075 | switch (E->getStmtClass()) { | ||||
1076 | case Expr::ConstantExprClass: | ||||
1077 | return canThrow(cast<ConstantExpr>(E)->getSubExpr()); | ||||
1078 | |||||
1079 | case Expr::CXXThrowExprClass: | ||||
1080 | // - a potentially evaluated throw-expression | ||||
1081 | return CT_Can; | ||||
1082 | |||||
1083 | case Expr::CXXDynamicCastExprClass: { | ||||
1084 | // - a potentially evaluated dynamic_cast expression dynamic_cast<T>(v), | ||||
1085 | // where T is a reference type, that requires a run-time check | ||||
1086 | CanThrowResult CT = canDynamicCastThrow(cast<CXXDynamicCastExpr>(E)); | ||||
1087 | if (CT == CT_Can) | ||||
1088 | return CT; | ||||
1089 | return mergeCanThrow(CT, canSubExprsThrow(*this, E)); | ||||
1090 | } | ||||
1091 | |||||
1092 | case Expr::CXXTypeidExprClass: | ||||
1093 | // - a potentially evaluated typeid expression applied to a glvalue | ||||
1094 | // expression whose type is a polymorphic class type | ||||
1095 | return canTypeidThrow(*this, cast<CXXTypeidExpr>(E)); | ||||
1096 | |||||
1097 | // - a potentially evaluated call to a function, member function, function | ||||
1098 | // pointer, or member function pointer that does not have a non-throwing | ||||
1099 | // exception-specification | ||||
1100 | case Expr::CallExprClass: | ||||
1101 | case Expr::CXXMemberCallExprClass: | ||||
1102 | case Expr::CXXOperatorCallExprClass: | ||||
1103 | case Expr::UserDefinedLiteralClass: { | ||||
1104 | const CallExpr *CE = cast<CallExpr>(E); | ||||
1105 | CanThrowResult CT; | ||||
1106 | if (E->isTypeDependent()) | ||||
1107 | CT = CT_Dependent; | ||||
1108 | else if (isa<CXXPseudoDestructorExpr>(CE->getCallee()->IgnoreParens())) | ||||
1109 | CT = CT_Cannot; | ||||
1110 | else | ||||
1111 | CT = canCalleeThrow(*this, E, CE->getCalleeDecl()); | ||||
1112 | if (CT == CT_Can) | ||||
1113 | return CT; | ||||
1114 | return mergeCanThrow(CT, canSubExprsThrow(*this, E)); | ||||
1115 | } | ||||
1116 | |||||
1117 | case Expr::CXXConstructExprClass: | ||||
1118 | case Expr::CXXTemporaryObjectExprClass: { | ||||
1119 | CanThrowResult CT = canCalleeThrow(*this, E, | ||||
1120 | cast<CXXConstructExpr>(E)->getConstructor()); | ||||
1121 | if (CT == CT_Can) | ||||
1122 | return CT; | ||||
1123 | return mergeCanThrow(CT, canSubExprsThrow(*this, E)); | ||||
1124 | } | ||||
1125 | |||||
1126 | case Expr::CXXInheritedCtorInitExprClass: | ||||
1127 | return canCalleeThrow(*this, E, | ||||
1128 | cast<CXXInheritedCtorInitExpr>(E)->getConstructor()); | ||||
1129 | |||||
1130 | case Expr::LambdaExprClass: { | ||||
1131 | const LambdaExpr *Lambda = cast<LambdaExpr>(E); | ||||
1132 | CanThrowResult CT = CT_Cannot; | ||||
1133 | for (LambdaExpr::const_capture_init_iterator | ||||
1134 | Cap = Lambda->capture_init_begin(), | ||||
1135 | CapEnd = Lambda->capture_init_end(); | ||||
1136 | Cap != CapEnd; ++Cap) | ||||
1137 | CT = mergeCanThrow(CT, canThrow(*Cap)); | ||||
1138 | return CT; | ||||
1139 | } | ||||
1140 | |||||
1141 | case Expr::CXXNewExprClass: { | ||||
1142 | CanThrowResult CT; | ||||
1143 | if (E->isTypeDependent()) | ||||
1144 | CT = CT_Dependent; | ||||
1145 | else | ||||
1146 | CT = canCalleeThrow(*this, E, cast<CXXNewExpr>(E)->getOperatorNew()); | ||||
1147 | if (CT == CT_Can) | ||||
1148 | return CT; | ||||
1149 | return mergeCanThrow(CT, canSubExprsThrow(*this, E)); | ||||
1150 | } | ||||
1151 | |||||
1152 | case Expr::CXXDeleteExprClass: { | ||||
1153 | CanThrowResult CT; | ||||
1154 | QualType DTy = cast<CXXDeleteExpr>(E)->getDestroyedType(); | ||||
1155 | if (DTy.isNull() || DTy->isDependentType()) { | ||||
1156 | CT = CT_Dependent; | ||||
1157 | } else { | ||||
1158 | CT = canCalleeThrow(*this, E, | ||||
1159 | cast<CXXDeleteExpr>(E)->getOperatorDelete()); | ||||
1160 | if (const RecordType *RT = DTy->getAs<RecordType>()) { | ||||
1161 | const CXXRecordDecl *RD = cast<CXXRecordDecl>(RT->getDecl()); | ||||
1162 | const CXXDestructorDecl *DD = RD->getDestructor(); | ||||
1163 | if (DD) | ||||
1164 | CT = mergeCanThrow(CT, canCalleeThrow(*this, E, DD)); | ||||
1165 | } | ||||
1166 | if (CT == CT_Can) | ||||
1167 | return CT; | ||||
1168 | } | ||||
1169 | return mergeCanThrow(CT, canSubExprsThrow(*this, E)); | ||||
1170 | } | ||||
1171 | |||||
1172 | case Expr::CXXBindTemporaryExprClass: { | ||||
1173 | // The bound temporary has to be destroyed again, which might throw. | ||||
1174 | CanThrowResult CT = canCalleeThrow(*this, E, | ||||
1175 | cast<CXXBindTemporaryExpr>(E)->getTemporary()->getDestructor()); | ||||
1176 | if (CT == CT_Can) | ||||
1177 | return CT; | ||||
1178 | return mergeCanThrow(CT, canSubExprsThrow(*this, E)); | ||||
1179 | } | ||||
1180 | |||||
1181 | // ObjC message sends are like function calls, but never have exception | ||||
1182 | // specs. | ||||
1183 | case Expr::ObjCMessageExprClass: | ||||
1184 | case Expr::ObjCPropertyRefExprClass: | ||||
1185 | case Expr::ObjCSubscriptRefExprClass: | ||||
1186 | return CT_Can; | ||||
1187 | |||||
1188 | // All the ObjC literals that are implemented as calls are | ||||
1189 | // potentially throwing unless we decide to close off that | ||||
1190 | // possibility. | ||||
1191 | case Expr::ObjCArrayLiteralClass: | ||||
1192 | case Expr::ObjCDictionaryLiteralClass: | ||||
1193 | case Expr::ObjCBoxedExprClass: | ||||
1194 | return CT_Can; | ||||
1195 | |||||
1196 | // Many other things have subexpressions, so we have to test those. | ||||
1197 | // Some are simple: | ||||
1198 | case Expr::CoawaitExprClass: | ||||
1199 | case Expr::ConditionalOperatorClass: | ||||
1200 | case Expr::CompoundLiteralExprClass: | ||||
1201 | case Expr::CoyieldExprClass: | ||||
1202 | case Expr::CXXConstCastExprClass: | ||||
1203 | case Expr::CXXReinterpretCastExprClass: | ||||
1204 | case Expr::BuiltinBitCastExprClass: | ||||
1205 | case Expr::CXXStdInitializerListExprClass: | ||||
1206 | case Expr::DesignatedInitExprClass: | ||||
1207 | case Expr::DesignatedInitUpdateExprClass: | ||||
1208 | case Expr::ExprWithCleanupsClass: | ||||
1209 | case Expr::ExtVectorElementExprClass: | ||||
1210 | case Expr::InitListExprClass: | ||||
1211 | case Expr::ArrayInitLoopExprClass: | ||||
1212 | case Expr::MemberExprClass: | ||||
1213 | case Expr::ObjCIsaExprClass: | ||||
1214 | case Expr::ObjCIvarRefExprClass: | ||||
1215 | case Expr::ParenExprClass: | ||||
1216 | case Expr::ParenListExprClass: | ||||
1217 | case Expr::ShuffleVectorExprClass: | ||||
1218 | case Expr::ConvertVectorExprClass: | ||||
1219 | case Expr::VAArgExprClass: | ||||
1220 | return canSubExprsThrow(*this, E); | ||||
1221 | |||||
1222 | // Some might be dependent for other reasons. | ||||
1223 | case Expr::ArraySubscriptExprClass: | ||||
1224 | case Expr::OMPArraySectionExprClass: | ||||
1225 | case Expr::BinaryOperatorClass: | ||||
1226 | case Expr::DependentCoawaitExprClass: | ||||
1227 | case Expr::CompoundAssignOperatorClass: | ||||
1228 | case Expr::CStyleCastExprClass: | ||||
1229 | case Expr::CXXStaticCastExprClass: | ||||
1230 | case Expr::CXXFunctionalCastExprClass: | ||||
1231 | case Expr::ImplicitCastExprClass: | ||||
1232 | case Expr::MaterializeTemporaryExprClass: | ||||
1233 | case Expr::UnaryOperatorClass: { | ||||
1234 | CanThrowResult CT = E->isTypeDependent() ? CT_Dependent : CT_Cannot; | ||||
1235 | return mergeCanThrow(CT, canSubExprsThrow(*this, E)); | ||||
1236 | } | ||||
1237 | |||||
1238 | // FIXME: We should handle StmtExpr, but that opens a MASSIVE can of worms. | ||||
1239 | case Expr::StmtExprClass: | ||||
1240 | return CT_Can; | ||||
1241 | |||||
1242 | case Expr::CXXDefaultArgExprClass: | ||||
1243 | return canThrow(cast<CXXDefaultArgExpr>(E)->getExpr()); | ||||
1244 | |||||
1245 | case Expr::CXXDefaultInitExprClass: | ||||
1246 | return canThrow(cast<CXXDefaultInitExpr>(E)->getExpr()); | ||||
1247 | |||||
1248 | case Expr::ChooseExprClass: | ||||
1249 | if (E->isTypeDependent() || E->isValueDependent()) | ||||
1250 | return CT_Dependent; | ||||
1251 | return canThrow(cast<ChooseExpr>(E)->getChosenSubExpr()); | ||||
1252 | |||||
1253 | case Expr::GenericSelectionExprClass: | ||||
1254 | if (cast<GenericSelectionExpr>(E)->isResultDependent()) | ||||
1255 | return CT_Dependent; | ||||
1256 | return canThrow(cast<GenericSelectionExpr>(E)->getResultExpr()); | ||||
1257 | |||||
1258 | // Some expressions are always dependent. | ||||
1259 | case Expr::CXXDependentScopeMemberExprClass: | ||||
1260 | case Expr::CXXUnresolvedConstructExprClass: | ||||
1261 | case Expr::DependentScopeDeclRefExprClass: | ||||
1262 | case Expr::CXXFoldExprClass: | ||||
1263 | return CT_Dependent; | ||||
1264 | |||||
1265 | case Expr::AsTypeExprClass: | ||||
1266 | case Expr::BinaryConditionalOperatorClass: | ||||
1267 | case Expr::BlockExprClass: | ||||
1268 | case Expr::CUDAKernelCallExprClass: | ||||
1269 | case Expr::DeclRefExprClass: | ||||
1270 | case Expr::ObjCBridgedCastExprClass: | ||||
1271 | case Expr::ObjCIndirectCopyRestoreExprClass: | ||||
1272 | case Expr::ObjCProtocolExprClass: | ||||
1273 | case Expr::ObjCSelectorExprClass: | ||||
1274 | case Expr::ObjCAvailabilityCheckExprClass: | ||||
1275 | case Expr::OffsetOfExprClass: | ||||
1276 | case Expr::PackExpansionExprClass: | ||||
1277 | case Expr::PseudoObjectExprClass: | ||||
1278 | case Expr::SubstNonTypeTemplateParmExprClass: | ||||
1279 | case Expr::SubstNonTypeTemplateParmPackExprClass: | ||||
1280 | case Expr::FunctionParmPackExprClass: | ||||
1281 | case Expr::UnaryExprOrTypeTraitExprClass: | ||||
1282 | case Expr::UnresolvedLookupExprClass: | ||||
1283 | case Expr::UnresolvedMemberExprClass: | ||||
1284 | case Expr::TypoExprClass: | ||||
1285 | // FIXME: Can any of the above throw? If so, when? | ||||
1286 | return CT_Cannot; | ||||
1287 | |||||
1288 | case Expr::AddrLabelExprClass: | ||||
1289 | case Expr::ArrayTypeTraitExprClass: | ||||
1290 | case Expr::AtomicExprClass: | ||||
1291 | case Expr::TypeTraitExprClass: | ||||
1292 | case Expr::CXXBoolLiteralExprClass: | ||||
1293 | case Expr::CXXNoexceptExprClass: | ||||
1294 | case Expr::CXXNullPtrLiteralExprClass: | ||||
1295 | case Expr::CXXPseudoDestructorExprClass: | ||||
1296 | case Expr::CXXScalarValueInitExprClass: | ||||
1297 | case Expr::CXXThisExprClass: | ||||
1298 | case Expr::CXXUuidofExprClass: | ||||
1299 | case Expr::CharacterLiteralClass: | ||||
1300 | case Expr::ExpressionTraitExprClass: | ||||
1301 | case Expr::FloatingLiteralClass: | ||||
1302 | case Expr::GNUNullExprClass: | ||||
1303 | case Expr::ImaginaryLiteralClass: | ||||
1304 | case Expr::ImplicitValueInitExprClass: | ||||
1305 | case Expr::IntegerLiteralClass: | ||||
1306 | case Expr::FixedPointLiteralClass: | ||||
1307 | case Expr::ArrayInitIndexExprClass: | ||||
1308 | case Expr::NoInitExprClass: | ||||
1309 | case Expr::ObjCEncodeExprClass: | ||||
1310 | case Expr::ObjCStringLiteralClass: | ||||
1311 | case Expr::ObjCBoolLiteralExprClass: | ||||
1312 | case Expr::OpaqueValueExprClass: | ||||
1313 | case Expr::PredefinedExprClass: | ||||
1314 | case Expr::SizeOfPackExprClass: | ||||
1315 | case Expr::StringLiteralClass: | ||||
1316 | case Expr::SourceLocExprClass: | ||||
1317 | // These expressions can never throw. | ||||
1318 | return CT_Cannot; | ||||
1319 | |||||
1320 | case Expr::MSPropertyRefExprClass: | ||||
1321 | case Expr::MSPropertySubscriptExprClass: | ||||
1322 | llvm_unreachable("Invalid class for expression")::llvm::llvm_unreachable_internal("Invalid class for expression" , "/build/llvm-toolchain-snapshot-10~svn374877/tools/clang/lib/Sema/SemaExceptionSpec.cpp" , 1322); | ||||
1323 | |||||
1324 | #define STMT(CLASS, PARENT) case Expr::CLASS##Class: | ||||
1325 | #define STMT_RANGE(Base, First, Last) | ||||
1326 | #define LAST_STMT_RANGE(BASE, FIRST, LAST) | ||||
1327 | #define EXPR(CLASS, PARENT) | ||||
1328 | #define ABSTRACT_STMT(STMT) | ||||
1329 | #include "clang/AST/StmtNodes.inc" | ||||
1330 | case Expr::NoStmtClass: | ||||
1331 | llvm_unreachable("Invalid class for expression")::llvm::llvm_unreachable_internal("Invalid class for expression" , "/build/llvm-toolchain-snapshot-10~svn374877/tools/clang/lib/Sema/SemaExceptionSpec.cpp" , 1331); | ||||
1332 | } | ||||
1333 | llvm_unreachable("Bogus StmtClass")::llvm::llvm_unreachable_internal("Bogus StmtClass", "/build/llvm-toolchain-snapshot-10~svn374877/tools/clang/lib/Sema/SemaExceptionSpec.cpp" , 1333); | ||||
1334 | } | ||||
1335 | |||||
1336 | } // end namespace clang |