Bug Summary

File:clang/lib/Sema/SemaExceptionSpec.cpp
Warning:line 1035, column 49
Called C++ object pointer is null

Annotated Source Code

Press '?' to see keyboard shortcuts

clang -cc1 -triple x86_64-pc-linux-gnu -analyze -disable-free -disable-llvm-verifier -discard-value-names -main-file-name SemaExceptionSpec.cpp -analyzer-store=region -analyzer-opt-analyze-nested-blocks -analyzer-checker=core -analyzer-checker=apiModeling -analyzer-checker=unix -analyzer-checker=deadcode -analyzer-checker=cplusplus -analyzer-checker=security.insecureAPI.UncheckedReturn -analyzer-checker=security.insecureAPI.getpw -analyzer-checker=security.insecureAPI.gets -analyzer-checker=security.insecureAPI.mktemp -analyzer-checker=security.insecureAPI.mkstemp -analyzer-checker=security.insecureAPI.vfork -analyzer-checker=nullability.NullPassedToNonnull -analyzer-checker=nullability.NullReturnedFromNonnull -analyzer-output plist -w -setup-static-analyzer -analyzer-config-compatibility-mode=true -mrelocation-model pic -pic-level 2 -mthread-model posix -mframe-pointer=none -relaxed-aliasing -fmath-errno -fno-rounding-math -masm-verbose -mconstructor-aliases -munwind-tables -target-cpu x86-64 -dwarf-column-info -fno-split-dwarf-inlining -debugger-tuning=gdb -ffunction-sections -fdata-sections -resource-dir /usr/lib/llvm-10/lib/clang/10.0.0 -D CLANG_VENDOR="Debian " -D _DEBUG -D _GNU_SOURCE -D __STDC_CONSTANT_MACROS -D __STDC_FORMAT_MACROS -D __STDC_LIMIT_MACROS -I /build/llvm-toolchain-snapshot-10~++20200112100611+7fa5290d5bd/build-llvm/tools/clang/lib/Sema -I /build/llvm-toolchain-snapshot-10~++20200112100611+7fa5290d5bd/clang/lib/Sema -I /build/llvm-toolchain-snapshot-10~++20200112100611+7fa5290d5bd/clang/include -I /build/llvm-toolchain-snapshot-10~++20200112100611+7fa5290d5bd/build-llvm/tools/clang/include -I /build/llvm-toolchain-snapshot-10~++20200112100611+7fa5290d5bd/build-llvm/include -I /build/llvm-toolchain-snapshot-10~++20200112100611+7fa5290d5bd/llvm/include -U NDEBUG -internal-isystem /usr/lib/gcc/x86_64-linux-gnu/6.3.0/../../../../include/c++/6.3.0 -internal-isystem /usr/lib/gcc/x86_64-linux-gnu/6.3.0/../../../../include/x86_64-linux-gnu/c++/6.3.0 -internal-isystem /usr/lib/gcc/x86_64-linux-gnu/6.3.0/../../../../include/x86_64-linux-gnu/c++/6.3.0 -internal-isystem /usr/lib/gcc/x86_64-linux-gnu/6.3.0/../../../../include/c++/6.3.0/backward -internal-isystem /usr/local/include -internal-isystem /usr/lib/llvm-10/lib/clang/10.0.0/include -internal-externc-isystem /usr/include/x86_64-linux-gnu -internal-externc-isystem /include -internal-externc-isystem /usr/include -O2 -Wno-unused-parameter -Wwrite-strings -Wno-missing-field-initializers -Wno-long-long -Wno-maybe-uninitialized -Wno-comment -std=c++14 -fdeprecated-macro -fdebug-compilation-dir /build/llvm-toolchain-snapshot-10~++20200112100611+7fa5290d5bd/build-llvm/tools/clang/lib/Sema -fdebug-prefix-map=/build/llvm-toolchain-snapshot-10~++20200112100611+7fa5290d5bd=. -ferror-limit 19 -fmessage-length 0 -fvisibility-inlines-hidden -stack-protector 2 -fgnuc-version=4.2.1 -fobjc-runtime=gcc -fno-common -fdiagnostics-show-option -vectorize-loops -vectorize-slp -analyzer-output=html -analyzer-config stable-report-filename=true -faddrsig -o /tmp/scan-build-2020-01-13-084841-49055-1 -x c++ /build/llvm-toolchain-snapshot-10~++20200112100611+7fa5290d5bd/clang/lib/Sema/SemaExceptionSpec.cpp

/build/llvm-toolchain-snapshot-10~++20200112100611+7fa5290d5bd/clang/lib/Sema/SemaExceptionSpec.cpp

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/StmtObjC.h"
19#include "clang/AST/TypeLoc.h"
20#include "clang/Basic/Diagnostic.h"
21#include "clang/Basic/SourceManager.h"
22#include "llvm/ADT/SmallPtrSet.h"
23#include "llvm/ADT/SmallString.h"
24
25namespace clang {
26
27static const FunctionProtoType *GetUnderlyingFunction(QualType T)
28{
29 if (const PointerType *PtrTy = T->getAs<PointerType>())
30 T = PtrTy->getPointeeType();
31 else if (const ReferenceType *RefTy = T->getAs<ReferenceType>())
32 T = RefTy->getPointeeType();
33 else if (const MemberPointerType *MPTy = T->getAs<MemberPointerType>())
34 T = MPTy->getPointeeType();
35 return T->getAs<FunctionProtoType>();
36}
37
38/// HACK: libstdc++ has a bug where it shadows std::swap with a member
39/// swap function then tries to call std::swap unqualified from the exception
40/// specification of that function. This function detects whether we're in
41/// such a case and turns off delay-parsing of exception specifications.
42bool Sema::isLibstdcxxEagerExceptionSpecHack(const Declarator &D) {
43 auto *RD = dyn_cast<CXXRecordDecl>(CurContext);
44
45 // All the problem cases are member functions named "swap" within class
46 // templates declared directly within namespace std or std::__debug or
47 // std::__profile.
48 if (!RD || !RD->getIdentifier() || !RD->getDescribedClassTemplate() ||
49 !D.getIdentifier() || !D.getIdentifier()->isStr("swap"))
50 return false;
51
52 auto *ND = dyn_cast<NamespaceDecl>(RD->getDeclContext());
53 if (!ND)
54 return false;
55
56 bool IsInStd = ND->isStdNamespace();
57 if (!IsInStd) {
58 // This isn't a direct member of namespace std, but it might still be
59 // libstdc++'s std::__debug::array or std::__profile::array.
60 IdentifierInfo *II = ND->getIdentifier();
61 if (!II || !(II->isStr("__debug") || II->isStr("__profile")) ||
62 !ND->isInStdNamespace())
63 return false;
64 }
65
66 // Only apply this hack within a system header.
67 if (!Context.getSourceManager().isInSystemHeader(D.getBeginLoc()))
68 return false;
69
70 return llvm::StringSwitch<bool>(RD->getIdentifier()->getName())
71 .Case("array", true)
72 .Case("pair", IsInStd)
73 .Case("priority_queue", IsInStd)
74 .Case("stack", IsInStd)
75 .Case("queue", IsInStd)
76 .Default(false);
77}
78
79ExprResult Sema::ActOnNoexceptSpec(SourceLocation NoexceptLoc,
80 Expr *NoexceptExpr,
81 ExceptionSpecificationType &EST) {
82 // FIXME: This is bogus, a noexcept expression is not a condition.
83 ExprResult Converted = CheckBooleanCondition(NoexceptLoc, NoexceptExpr);
84 if (Converted.isInvalid())
85 return Converted;
86
87 if (Converted.get()->isValueDependent()) {
88 EST = EST_DependentNoexcept;
89 return Converted;
90 }
91
92 llvm::APSInt Result;
93 Converted = VerifyIntegerConstantExpression(
94 Converted.get(), &Result,
95 diag::err_noexcept_needs_constant_expression,
96 /*AllowFold*/ false);
97 if (!Converted.isInvalid())
98 EST = !Result ? EST_NoexceptFalse : EST_NoexceptTrue;
99 return Converted;
100}
101
102/// CheckSpecifiedExceptionType - Check if the given type is valid in an
103/// exception specification. Incomplete types, or pointers to incomplete types
104/// other than void are not allowed.
105///
106/// \param[in,out] T The exception type. This will be decayed to a pointer type
107/// when the input is an array or a function type.
108bool Sema::CheckSpecifiedExceptionType(QualType &T, SourceRange Range) {
109 // C++11 [except.spec]p2:
110 // A type cv T, "array of T", or "function returning T" denoted
111 // in an exception-specification is adjusted to type T, "pointer to T", or
112 // "pointer to function returning T", respectively.
113 //
114 // We also apply this rule in C++98.
115 if (T->isArrayType())
116 T = Context.getArrayDecayedType(T);
117 else if (T->isFunctionType())
118 T = Context.getPointerType(T);
119
120 int Kind = 0;
121 QualType PointeeT = T;
122 if (const PointerType *PT = T->getAs<PointerType>()) {
123 PointeeT = PT->getPointeeType();
124 Kind = 1;
125
126 // cv void* is explicitly permitted, despite being a pointer to an
127 // incomplete type.
128 if (PointeeT->isVoidType())
129 return false;
130 } else if (const ReferenceType *RT = T->getAs<ReferenceType>()) {
131 PointeeT = RT->getPointeeType();
132 Kind = 2;
133
134 if (RT->isRValueReferenceType()) {
135 // C++11 [except.spec]p2:
136 // A type denoted in an exception-specification shall not denote [...]
137 // an rvalue reference type.
138 Diag(Range.getBegin(), diag::err_rref_in_exception_spec)
139 << T << Range;
140 return true;
141 }
142 }
143
144 // C++11 [except.spec]p2:
145 // A type denoted in an exception-specification shall not denote an
146 // incomplete type other than a class currently being defined [...].
147 // A type denoted in an exception-specification shall not denote a
148 // pointer or reference to an incomplete type, other than (cv) void* or a
149 // pointer or reference to a class currently being defined.
150 // In Microsoft mode, downgrade this to a warning.
151 unsigned DiagID = diag::err_incomplete_in_exception_spec;
152 bool ReturnValueOnError = true;
153 if (getLangOpts().MSVCCompat) {
154 DiagID = diag::ext_incomplete_in_exception_spec;
155 ReturnValueOnError = false;
156 }
157 if (!(PointeeT->isRecordType() &&
158 PointeeT->castAs<RecordType>()->isBeingDefined()) &&
159 RequireCompleteType(Range.getBegin(), PointeeT, DiagID, Kind, Range))
160 return ReturnValueOnError;
161
162 return false;
163}
164
165/// CheckDistantExceptionSpec - Check if the given type is a pointer or pointer
166/// to member to a function with an exception specification. This means that
167/// it is invalid to add another level of indirection.
168bool Sema::CheckDistantExceptionSpec(QualType T) {
169 // C++17 removes this rule in favor of putting exception specifications into
170 // the type system.
171 if (getLangOpts().CPlusPlus17)
172 return false;
173
174 if (const PointerType *PT = T->getAs<PointerType>())
175 T = PT->getPointeeType();
176 else if (const MemberPointerType *PT = T->getAs<MemberPointerType>())
177 T = PT->getPointeeType();
178 else
179 return false;
180
181 const FunctionProtoType *FnT = T->getAs<FunctionProtoType>();
182 if (!FnT)
183 return false;
184
185 return FnT->hasExceptionSpec();
186}
187
188const FunctionProtoType *
189Sema::ResolveExceptionSpec(SourceLocation Loc, const FunctionProtoType *FPT) {
190 if (FPT->getExceptionSpecType() == EST_Unparsed) {
191 Diag(Loc, diag::err_exception_spec_not_parsed);
192 return nullptr;
193 }
194
195 if (!isUnresolvedExceptionSpec(FPT->getExceptionSpecType()))
196 return FPT;
197
198 FunctionDecl *SourceDecl = FPT->getExceptionSpecDecl();
199 const FunctionProtoType *SourceFPT =
200 SourceDecl->getType()->castAs<FunctionProtoType>();
201
202 // If the exception specification has already been resolved, just return it.
203 if (!isUnresolvedExceptionSpec(SourceFPT->getExceptionSpecType()))
204 return SourceFPT;
205
206 // Compute or instantiate the exception specification now.
207 if (SourceFPT->getExceptionSpecType() == EST_Unevaluated)
208 EvaluateImplicitExceptionSpec(Loc, SourceDecl);
209 else
210 InstantiateExceptionSpec(Loc, SourceDecl);
211
212 const FunctionProtoType *Proto =
213 SourceDecl->getType()->castAs<FunctionProtoType>();
214 if (Proto->getExceptionSpecType() == clang::EST_Unparsed) {
215 Diag(Loc, diag::err_exception_spec_not_parsed);
216 Proto = nullptr;
217 }
218 return Proto;
219}
220
221void
222Sema::UpdateExceptionSpec(FunctionDecl *FD,
223 const FunctionProtoType::ExceptionSpecInfo &ESI) {
224 // If we've fully resolved the exception specification, notify listeners.
225 if (!isUnresolvedExceptionSpec(ESI.Type))
226 if (auto *Listener = getASTMutationListener())
227 Listener->ResolvedExceptionSpec(FD);
228
229 for (FunctionDecl *Redecl : FD->redecls())
230 Context.adjustExceptionSpec(Redecl, ESI);
231}
232
233static bool exceptionSpecNotKnownYet(const FunctionDecl *FD) {
234 auto *MD = dyn_cast<CXXMethodDecl>(FD);
235 if (!MD)
236 return false;
237
238 auto EST = MD->getType()->castAs<FunctionProtoType>()->getExceptionSpecType();
239 return EST == EST_Unparsed ||
240 (EST == EST_Unevaluated && MD->getParent()->isBeingDefined());
241}
242
243static bool CheckEquivalentExceptionSpecImpl(
244 Sema &S, const PartialDiagnostic &DiagID, const PartialDiagnostic &NoteID,
245 const FunctionProtoType *Old, SourceLocation OldLoc,
246 const FunctionProtoType *New, SourceLocation NewLoc,
247 bool *MissingExceptionSpecification = nullptr,
248 bool *MissingEmptyExceptionSpecification = nullptr,
249 bool AllowNoexceptAllMatchWithNoSpec = false, bool IsOperatorNew = false);
250
251/// Determine whether a function has an implicitly-generated exception
252/// specification.
253static bool hasImplicitExceptionSpec(FunctionDecl *Decl) {
254 if (!isa<CXXDestructorDecl>(Decl) &&
255 Decl->getDeclName().getCXXOverloadedOperator() != OO_Delete &&
256 Decl->getDeclName().getCXXOverloadedOperator() != OO_Array_Delete)
257 return false;
258
259 // For a function that the user didn't declare:
260 // - if this is a destructor, its exception specification is implicit.
261 // - if this is 'operator delete' or 'operator delete[]', the exception
262 // specification is as-if an explicit exception specification was given
263 // (per [basic.stc.dynamic]p2).
264 if (!Decl->getTypeSourceInfo())
265 return isa<CXXDestructorDecl>(Decl);
266
267 auto *Ty = Decl->getTypeSourceInfo()->getType()->castAs<FunctionProtoType>();
268 return !Ty->hasExceptionSpec();
269}
270
271bool 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~++20200112100611+7fa5290d5bd/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~++20200112100611+7fa5290d5bd/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.
469bool 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.
494static 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~++20200112100611+7fa5290d5bd/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~++20200112100611+7fa5290d5bd/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~++20200112100611+7fa5290d5bd/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
645bool 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
657bool 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~++20200112100611+7fa5290d5bd/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~++20200112100611+7fa5290d5bd/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~++20200112100611+7fa5290d5bd/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.
744bool 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~++20200112100611+7fa5290d5bd/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~++20200112100611+7fa5290d5bd/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~++20200112100611+7fa5290d5bd/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~++20200112100611+7fa5290d5bd/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~++20200112100611+7fa5290d5bd/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
848static bool
849CheckSpecForTypesEquivalent(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.
869bool 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~++20200112100611+7fa5290d5bd/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~++20200112100611+7fa5290d5bd/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
899bool 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
939bool 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()->castAs<FunctionProtoType>(),
969 Old->getLocation(),
970 New->getType()->castAs<FunctionProtoType>(),
971 New->getLocation());
972}
973
974static CanThrowResult canSubStmtsThrow(Sema &Self, const Stmt *S) {
975 CanThrowResult R = CT_Cannot;
976 for (const Stmt *SubStmt : S->children()) {
977 if (!SubStmt)
978 continue;
979 R = mergeCanThrow(R, Self.canThrow(SubStmt));
980 if (R == CT_Can)
981 break;
982 }
983 return R;
984}
985
986/// Determine whether the callee of a particular function call can throw.
987/// E and D are both optional, but at least one of E and Loc must be specified.
988static CanThrowResult canCalleeThrow(Sema &S, const Expr *E, const Decl *D,
989 SourceLocation Loc = SourceLocation()) {
990 // As an extension, we assume that __attribute__((nothrow)) functions don't
991 // throw.
992 if (D
36.1
'D' is non-null
36.1
'D' is non-null
&& isa<FunctionDecl>(D) && D->hasAttr<NoThrowAttr>())
37
Assuming 'D' is not a 'FunctionDecl'
993 return CT_Cannot;
994
995 QualType T;
996
997 // In C++1z, just look at the function type of the callee.
998 if (S.getLangOpts().CPlusPlus17 && E && isa<CallExpr>(E)) {
38
Assuming field 'CPlusPlus17' is 0
999 E = cast<CallExpr>(E)->getCallee();
1000 T = E->getType();
1001 if (T->isSpecificPlaceholderType(BuiltinType::BoundMember)) {
1002 // Sadly we don't preserve the actual type as part of the "bound member"
1003 // placeholder, so we need to reconstruct it.
1004 E = E->IgnoreParenImpCasts();
1005
1006 // Could be a call to a pointer-to-member or a plain member access.
1007 if (auto *Op = dyn_cast<BinaryOperator>(E)) {
1008 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~++20200112100611+7fa5290d5bd/clang/lib/Sema/SemaExceptionSpec.cpp"
, 1008, __PRETTY_FUNCTION__))
;
1009 T = Op->getRHS()->getType()
1010 ->castAs<MemberPointerType>()->getPointeeType();
1011 } else {
1012 T = cast<MemberExpr>(E)->getMemberDecl()->getType();
1013 }
1014 }
1015 } else if (const ValueDecl *VD
39.1
'VD' is non-null
39.1
'VD' is non-null
= dyn_cast_or_null<ValueDecl>(D))
39
Assuming 'D' is a 'ValueDecl'
40
Taking true branch
1016 T = VD->getType();
1017 else
1018 // If we have no clue what we're calling, assume the worst.
1019 return CT_Can;
1020
1021 const FunctionProtoType *FT;
1022 if ((FT = T->getAs<FunctionProtoType>())) {
41
Assuming the object is not a 'FunctionProtoType'
42
Assuming 'FT' is null
43
Taking false branch
1023 } else if (const PointerType *PT
44.1
'PT' is null
44.1
'PT' is null
= T->getAs<PointerType>())
44
Assuming the object is not a 'PointerType'
45
Taking false branch
1024 FT = PT->getPointeeType()->getAs<FunctionProtoType>();
1025 else if (const ReferenceType *RT
46.1
'RT' is null
46.1
'RT' is null
= T->getAs<ReferenceType>())
46
Assuming the object is not a 'ReferenceType'
47
Taking false branch
1026 FT = RT->getPointeeType()->getAs<FunctionProtoType>();
1027 else if (const MemberPointerType *MT
48.1
'MT' is null
48.1
'MT' is null
= T->getAs<MemberPointerType>())
48
Assuming the object is not a 'MemberPointerType'
49
Taking false branch
1028 FT = MT->getPointeeType()->getAs<FunctionProtoType>();
1029 else if (const BlockPointerType *BT
50.1
'BT' is non-null
50.1
'BT' is non-null
= T->getAs<BlockPointerType>())
50
Assuming the object is a 'BlockPointerType'
51
Taking true branch
1030 FT = BT->getPointeeType()->getAs<FunctionProtoType>();
52
Assuming the object is a 'FunctionProtoType'
1031
1032 if (!FT
52.1
'FT' is non-null
52.1
'FT' is non-null
)
53
Taking false branch
1033 return CT_Can;
1034
1035 FT = S.ResolveExceptionSpec(Loc.isInvalid() ? E->getBeginLoc() : Loc, FT);
54
Calling 'SourceLocation::isInvalid'
57
Returning from 'SourceLocation::isInvalid'
58
'?' condition is true
59
Called C++ object pointer is null
1036 if (!FT)
1037 return CT_Can;
1038
1039 return FT->canThrow();
1040}
1041
1042static CanThrowResult canVarDeclThrow(Sema &Self, const VarDecl *VD) {
1043 CanThrowResult CT = CT_Cannot;
1044
1045 // Initialization might throw.
1046 if (!VD->isUsableInConstantExpressions(Self.Context))
7
Assuming the condition is false
8
Taking false branch
17
Assuming the condition is false
18
Taking false branch
27
Assuming the condition is false
28
Taking false branch
1047 if (const Expr *Init = VD->getInit())
1048 CT = mergeCanThrow(CT, Self.canThrow(Init));
1049
1050 // Destructor might throw.
1051 if (VD->needsDestruction(Self.Context) == QualType::DK_cxx_destructor) {
9
Assuming the condition is false
10
Taking false branch
19
Assuming the condition is false
20
Taking false branch
29
Assuming the condition is true
30
Taking true branch
1052 if (auto *RD =
31
Assuming 'RD' is non-null
32
Taking true branch
1053 VD->getType()->getBaseElementTypeUnsafe()->getAsCXXRecordDecl()) {
1054 if (auto *Dtor = RD->getDestructor()) {
33
Assuming 'Dtor' is non-null
34
Taking true branch
1055 CT = mergeCanThrow(
1056 CT, canCalleeThrow(Self, nullptr, Dtor, VD->getLocation()));
35
Passing null pointer value via 2nd parameter 'E'
36
Calling 'canCalleeThrow'
1057 }
1058 }
1059 }
1060
1061 // If this is a decomposition declaration, bindings might throw.
1062 if (auto *DD
11.1
'DD' is non-null
21.1
'DD' is non-null
11.1
'DD' is non-null
21.1
'DD' is non-null
= dyn_cast<DecompositionDecl>(VD))
11
Assuming 'VD' is a 'DecompositionDecl'
12
Taking true branch
21
Assuming 'VD' is a 'DecompositionDecl'
22
Taking true branch
1063 for (auto *B : DD->bindings())
13
Assuming '__begin2' is not equal to '__end2'
23
Assuming '__begin2' is not equal to '__end2'
1064 if (auto *HD = B->getHoldingVar())
14
Assuming 'HD' is non-null
15
Taking true branch
24
Assuming 'HD' is non-null
25
Taking true branch
1065 CT = mergeCanThrow(CT, canVarDeclThrow(Self, HD));
16
Calling 'canVarDeclThrow'
26
Calling 'canVarDeclThrow'
1066
1067 return CT;
1068}
1069
1070static CanThrowResult canDynamicCastThrow(const CXXDynamicCastExpr *DC) {
1071 if (DC->isTypeDependent())
1072 return CT_Dependent;
1073
1074 if (!DC->getTypeAsWritten()->isReferenceType())
1075 return CT_Cannot;
1076
1077 if (DC->getSubExpr()->isTypeDependent())
1078 return CT_Dependent;
1079
1080 return DC->getCastKind() == clang::CK_Dynamic? CT_Can : CT_Cannot;
1081}
1082
1083static CanThrowResult canTypeidThrow(Sema &S, const CXXTypeidExpr *DC) {
1084 if (DC->isTypeOperand())
1085 return CT_Cannot;
1086
1087 Expr *Op = DC->getExprOperand();
1088 if (Op->isTypeDependent())
1089 return CT_Dependent;
1090
1091 const RecordType *RT = Op->getType()->getAs<RecordType>();
1092 if (!RT)
1093 return CT_Cannot;
1094
1095 if (!cast<CXXRecordDecl>(RT->getDecl())->isPolymorphic())
1096 return CT_Cannot;
1097
1098 if (Op->Classify(S.Context).isPRValue())
1099 return CT_Cannot;
1100
1101 return CT_Can;
1102}
1103
1104CanThrowResult Sema::canThrow(const Stmt *S) {
1105 // C++ [expr.unary.noexcept]p3:
1106 // [Can throw] if in a potentially-evaluated context the expression would
1107 // contain:
1108 switch (S->getStmtClass()) {
1
Control jumps to 'case DeclStmtClass:' at line 1475
1109 case Expr::ConstantExprClass:
1110 return canThrow(cast<ConstantExpr>(S)->getSubExpr());
1111
1112 case Expr::CXXThrowExprClass:
1113 // - a potentially evaluated throw-expression
1114 return CT_Can;
1115
1116 case Expr::CXXDynamicCastExprClass: {
1117 // - a potentially evaluated dynamic_cast expression dynamic_cast<T>(v),
1118 // where T is a reference type, that requires a run-time check
1119 auto *CE = cast<CXXDynamicCastExpr>(S);
1120 // FIXME: Properly determine whether a variably-modified type can throw.
1121 if (CE->getType()->isVariablyModifiedType())
1122 return CT_Can;
1123 CanThrowResult CT = canDynamicCastThrow(CE);
1124 if (CT == CT_Can)
1125 return CT;
1126 return mergeCanThrow(CT, canSubStmtsThrow(*this, CE));
1127 }
1128
1129 case Expr::CXXTypeidExprClass:
1130 // - a potentially evaluated typeid expression applied to a glvalue
1131 // expression whose type is a polymorphic class type
1132 return canTypeidThrow(*this, cast<CXXTypeidExpr>(S));
1133
1134 // - a potentially evaluated call to a function, member function, function
1135 // pointer, or member function pointer that does not have a non-throwing
1136 // exception-specification
1137 case Expr::CallExprClass:
1138 case Expr::CXXMemberCallExprClass:
1139 case Expr::CXXOperatorCallExprClass:
1140 case Expr::UserDefinedLiteralClass: {
1141 const CallExpr *CE = cast<CallExpr>(S);
1142 CanThrowResult CT;
1143 if (CE->isTypeDependent())
1144 CT = CT_Dependent;
1145 else if (isa<CXXPseudoDestructorExpr>(CE->getCallee()->IgnoreParens()))
1146 CT = CT_Cannot;
1147 else
1148 CT = canCalleeThrow(*this, CE, CE->getCalleeDecl());
1149 if (CT == CT_Can)
1150 return CT;
1151 return mergeCanThrow(CT, canSubStmtsThrow(*this, CE));
1152 }
1153
1154 case Expr::CXXConstructExprClass:
1155 case Expr::CXXTemporaryObjectExprClass: {
1156 auto *CE = cast<CXXConstructExpr>(S);
1157 // FIXME: Properly determine whether a variably-modified type can throw.
1158 if (CE->getType()->isVariablyModifiedType())
1159 return CT_Can;
1160 CanThrowResult CT = canCalleeThrow(*this, CE, CE->getConstructor());
1161 if (CT == CT_Can)
1162 return CT;
1163 return mergeCanThrow(CT, canSubStmtsThrow(*this, CE));
1164 }
1165
1166 case Expr::CXXInheritedCtorInitExprClass: {
1167 auto *ICIE = cast<CXXInheritedCtorInitExpr>(S);
1168 return canCalleeThrow(*this, ICIE, ICIE->getConstructor());
1169 }
1170
1171 case Expr::LambdaExprClass: {
1172 const LambdaExpr *Lambda = cast<LambdaExpr>(S);
1173 CanThrowResult CT = CT_Cannot;
1174 for (LambdaExpr::const_capture_init_iterator
1175 Cap = Lambda->capture_init_begin(),
1176 CapEnd = Lambda->capture_init_end();
1177 Cap != CapEnd; ++Cap)
1178 CT = mergeCanThrow(CT, canThrow(*Cap));
1179 return CT;
1180 }
1181
1182 case Expr::CXXNewExprClass: {
1183 auto *NE = cast<CXXNewExpr>(S);
1184 CanThrowResult CT;
1185 if (NE->isTypeDependent())
1186 CT = CT_Dependent;
1187 else
1188 CT = canCalleeThrow(*this, NE, NE->getOperatorNew());
1189 if (CT == CT_Can)
1190 return CT;
1191 return mergeCanThrow(CT, canSubStmtsThrow(*this, NE));
1192 }
1193
1194 case Expr::CXXDeleteExprClass: {
1195 auto *DE = cast<CXXDeleteExpr>(S);
1196 CanThrowResult CT;
1197 QualType DTy = DE->getDestroyedType();
1198 if (DTy.isNull() || DTy->isDependentType()) {
1199 CT = CT_Dependent;
1200 } else {
1201 CT = canCalleeThrow(*this, DE, DE->getOperatorDelete());
1202 if (const RecordType *RT = DTy->getAs<RecordType>()) {
1203 const CXXRecordDecl *RD = cast<CXXRecordDecl>(RT->getDecl());
1204 const CXXDestructorDecl *DD = RD->getDestructor();
1205 if (DD)
1206 CT = mergeCanThrow(CT, canCalleeThrow(*this, DE, DD));
1207 }
1208 if (CT == CT_Can)
1209 return CT;
1210 }
1211 return mergeCanThrow(CT, canSubStmtsThrow(*this, DE));
1212 }
1213
1214 case Expr::CXXBindTemporaryExprClass: {
1215 auto *BTE = cast<CXXBindTemporaryExpr>(S);
1216 // The bound temporary has to be destroyed again, which might throw.
1217 CanThrowResult CT =
1218 canCalleeThrow(*this, BTE, BTE->getTemporary()->getDestructor());
1219 if (CT == CT_Can)
1220 return CT;
1221 return mergeCanThrow(CT, canSubStmtsThrow(*this, BTE));
1222 }
1223
1224 case Expr::PseudoObjectExprClass: {
1225 auto *POE = cast<PseudoObjectExpr>(S);
1226 CanThrowResult CT = CT_Cannot;
1227 for (const Expr *E : POE->semantics()) {
1228 CT = mergeCanThrow(CT, canThrow(E));
1229 if (CT == CT_Can)
1230 break;
1231 }
1232 return CT;
1233 }
1234
1235 // ObjC message sends are like function calls, but never have exception
1236 // specs.
1237 case Expr::ObjCMessageExprClass:
1238 case Expr::ObjCPropertyRefExprClass:
1239 case Expr::ObjCSubscriptRefExprClass:
1240 return CT_Can;
1241
1242 // All the ObjC literals that are implemented as calls are
1243 // potentially throwing unless we decide to close off that
1244 // possibility.
1245 case Expr::ObjCArrayLiteralClass:
1246 case Expr::ObjCDictionaryLiteralClass:
1247 case Expr::ObjCBoxedExprClass:
1248 return CT_Can;
1249
1250 // Many other things have subexpressions, so we have to test those.
1251 // Some are simple:
1252 case Expr::CoawaitExprClass:
1253 case Expr::ConditionalOperatorClass:
1254 case Expr::CoyieldExprClass:
1255 case Expr::CXXRewrittenBinaryOperatorClass:
1256 case Expr::CXXStdInitializerListExprClass:
1257 case Expr::DesignatedInitExprClass:
1258 case Expr::DesignatedInitUpdateExprClass:
1259 case Expr::ExprWithCleanupsClass:
1260 case Expr::ExtVectorElementExprClass:
1261 case Expr::InitListExprClass:
1262 case Expr::ArrayInitLoopExprClass:
1263 case Expr::MemberExprClass:
1264 case Expr::ObjCIsaExprClass:
1265 case Expr::ObjCIvarRefExprClass:
1266 case Expr::ParenExprClass:
1267 case Expr::ParenListExprClass:
1268 case Expr::ShuffleVectorExprClass:
1269 case Expr::StmtExprClass:
1270 case Expr::ConvertVectorExprClass:
1271 case Expr::VAArgExprClass:
1272 return canSubStmtsThrow(*this, S);
1273
1274 case Expr::CompoundLiteralExprClass:
1275 case Expr::CXXConstCastExprClass:
1276 case Expr::CXXReinterpretCastExprClass:
1277 case Expr::BuiltinBitCastExprClass:
1278 // FIXME: Properly determine whether a variably-modified type can throw.
1279 if (cast<Expr>(S)->getType()->isVariablyModifiedType())
1280 return CT_Can;
1281 return canSubStmtsThrow(*this, S);
1282
1283 // Some might be dependent for other reasons.
1284 case Expr::ArraySubscriptExprClass:
1285 case Expr::OMPArraySectionExprClass:
1286 case Expr::BinaryOperatorClass:
1287 case Expr::DependentCoawaitExprClass:
1288 case Expr::CompoundAssignOperatorClass:
1289 case Expr::CStyleCastExprClass:
1290 case Expr::CXXStaticCastExprClass:
1291 case Expr::CXXFunctionalCastExprClass:
1292 case Expr::ImplicitCastExprClass:
1293 case Expr::MaterializeTemporaryExprClass:
1294 case Expr::UnaryOperatorClass: {
1295 // FIXME: Properly determine whether a variably-modified type can throw.
1296 if (auto *CE = dyn_cast<CastExpr>(S))
1297 if (CE->getType()->isVariablyModifiedType())
1298 return CT_Can;
1299 CanThrowResult CT =
1300 cast<Expr>(S)->isTypeDependent() ? CT_Dependent : CT_Cannot;
1301 return mergeCanThrow(CT, canSubStmtsThrow(*this, S));
1302 }
1303
1304 case Expr::CXXDefaultArgExprClass:
1305 return canThrow(cast<CXXDefaultArgExpr>(S)->getExpr());
1306
1307 case Expr::CXXDefaultInitExprClass:
1308 return canThrow(cast<CXXDefaultInitExpr>(S)->getExpr());
1309
1310 case Expr::ChooseExprClass: {
1311 auto *CE = cast<ChooseExpr>(S);
1312 if (CE->isTypeDependent() || CE->isValueDependent())
1313 return CT_Dependent;
1314 return canThrow(CE->getChosenSubExpr());
1315 }
1316
1317 case Expr::GenericSelectionExprClass:
1318 if (cast<GenericSelectionExpr>(S)->isResultDependent())
1319 return CT_Dependent;
1320 return canThrow(cast<GenericSelectionExpr>(S)->getResultExpr());
1321
1322 // Some expressions are always dependent.
1323 case Expr::CXXDependentScopeMemberExprClass:
1324 case Expr::CXXUnresolvedConstructExprClass:
1325 case Expr::DependentScopeDeclRefExprClass:
1326 case Expr::CXXFoldExprClass:
1327 return CT_Dependent;
1328
1329 case Expr::AsTypeExprClass:
1330 case Expr::BinaryConditionalOperatorClass:
1331 case Expr::BlockExprClass:
1332 case Expr::CUDAKernelCallExprClass:
1333 case Expr::DeclRefExprClass:
1334 case Expr::ObjCBridgedCastExprClass:
1335 case Expr::ObjCIndirectCopyRestoreExprClass:
1336 case Expr::ObjCProtocolExprClass:
1337 case Expr::ObjCSelectorExprClass:
1338 case Expr::ObjCAvailabilityCheckExprClass:
1339 case Expr::OffsetOfExprClass:
1340 case Expr::PackExpansionExprClass:
1341 case Expr::SubstNonTypeTemplateParmExprClass:
1342 case Expr::SubstNonTypeTemplateParmPackExprClass:
1343 case Expr::FunctionParmPackExprClass:
1344 case Expr::UnaryExprOrTypeTraitExprClass:
1345 case Expr::UnresolvedLookupExprClass:
1346 case Expr::UnresolvedMemberExprClass:
1347 case Expr::TypoExprClass:
1348 // FIXME: Many of the above can throw.
1349 return CT_Cannot;
1350
1351 case Expr::AddrLabelExprClass:
1352 case Expr::ArrayTypeTraitExprClass:
1353 case Expr::AtomicExprClass:
1354 case Expr::TypeTraitExprClass:
1355 case Expr::CXXBoolLiteralExprClass:
1356 case Expr::CXXNoexceptExprClass:
1357 case Expr::CXXNullPtrLiteralExprClass:
1358 case Expr::CXXPseudoDestructorExprClass:
1359 case Expr::CXXScalarValueInitExprClass:
1360 case Expr::CXXThisExprClass:
1361 case Expr::CXXUuidofExprClass:
1362 case Expr::CharacterLiteralClass:
1363 case Expr::ExpressionTraitExprClass:
1364 case Expr::FloatingLiteralClass:
1365 case Expr::GNUNullExprClass:
1366 case Expr::ImaginaryLiteralClass:
1367 case Expr::ImplicitValueInitExprClass:
1368 case Expr::IntegerLiteralClass:
1369 case Expr::FixedPointLiteralClass:
1370 case Expr::ArrayInitIndexExprClass:
1371 case Expr::NoInitExprClass:
1372 case Expr::ObjCEncodeExprClass:
1373 case Expr::ObjCStringLiteralClass:
1374 case Expr::ObjCBoolLiteralExprClass:
1375 case Expr::OpaqueValueExprClass:
1376 case Expr::PredefinedExprClass:
1377 case Expr::SizeOfPackExprClass:
1378 case Expr::StringLiteralClass:
1379 case Expr::SourceLocExprClass:
1380 case Expr::ConceptSpecializationExprClass:
1381 // These expressions can never throw.
1382 return CT_Cannot;
1383
1384 case Expr::MSPropertyRefExprClass:
1385 case Expr::MSPropertySubscriptExprClass:
1386 llvm_unreachable("Invalid class for expression")::llvm::llvm_unreachable_internal("Invalid class for expression"
, "/build/llvm-toolchain-snapshot-10~++20200112100611+7fa5290d5bd/clang/lib/Sema/SemaExceptionSpec.cpp"
, 1386)
;
1387
1388 // Most statements can throw if any substatement can throw.
1389 case Stmt::AttributedStmtClass:
1390 case Stmt::BreakStmtClass:
1391 case Stmt::CapturedStmtClass:
1392 case Stmt::CaseStmtClass:
1393 case Stmt::CompoundStmtClass:
1394 case Stmt::ContinueStmtClass:
1395 case Stmt::CoreturnStmtClass:
1396 case Stmt::CoroutineBodyStmtClass:
1397 case Stmt::CXXCatchStmtClass:
1398 case Stmt::CXXForRangeStmtClass:
1399 case Stmt::DefaultStmtClass:
1400 case Stmt::DoStmtClass:
1401 case Stmt::ForStmtClass:
1402 case Stmt::GCCAsmStmtClass:
1403 case Stmt::GotoStmtClass:
1404 case Stmt::IndirectGotoStmtClass:
1405 case Stmt::LabelStmtClass:
1406 case Stmt::MSAsmStmtClass:
1407 case Stmt::MSDependentExistsStmtClass:
1408 case Stmt::NullStmtClass:
1409 case Stmt::ObjCAtCatchStmtClass:
1410 case Stmt::ObjCAtFinallyStmtClass:
1411 case Stmt::ObjCAtSynchronizedStmtClass:
1412 case Stmt::ObjCAutoreleasePoolStmtClass:
1413 case Stmt::ObjCForCollectionStmtClass:
1414 case Stmt::OMPAtomicDirectiveClass:
1415 case Stmt::OMPBarrierDirectiveClass:
1416 case Stmt::OMPCancelDirectiveClass:
1417 case Stmt::OMPCancellationPointDirectiveClass:
1418 case Stmt::OMPCriticalDirectiveClass:
1419 case Stmt::OMPDistributeDirectiveClass:
1420 case Stmt::OMPDistributeParallelForDirectiveClass:
1421 case Stmt::OMPDistributeParallelForSimdDirectiveClass:
1422 case Stmt::OMPDistributeSimdDirectiveClass:
1423 case Stmt::OMPFlushDirectiveClass:
1424 case Stmt::OMPForDirectiveClass:
1425 case Stmt::OMPForSimdDirectiveClass:
1426 case Stmt::OMPMasterDirectiveClass:
1427 case Stmt::OMPMasterTaskLoopDirectiveClass:
1428 case Stmt::OMPMasterTaskLoopSimdDirectiveClass:
1429 case Stmt::OMPOrderedDirectiveClass:
1430 case Stmt::OMPParallelDirectiveClass:
1431 case Stmt::OMPParallelForDirectiveClass:
1432 case Stmt::OMPParallelForSimdDirectiveClass:
1433 case Stmt::OMPParallelMasterDirectiveClass:
1434 case Stmt::OMPParallelMasterTaskLoopDirectiveClass:
1435 case Stmt::OMPParallelMasterTaskLoopSimdDirectiveClass:
1436 case Stmt::OMPParallelSectionsDirectiveClass:
1437 case Stmt::OMPSectionDirectiveClass:
1438 case Stmt::OMPSectionsDirectiveClass:
1439 case Stmt::OMPSimdDirectiveClass:
1440 case Stmt::OMPSingleDirectiveClass:
1441 case Stmt::OMPTargetDataDirectiveClass:
1442 case Stmt::OMPTargetDirectiveClass:
1443 case Stmt::OMPTargetEnterDataDirectiveClass:
1444 case Stmt::OMPTargetExitDataDirectiveClass:
1445 case Stmt::OMPTargetParallelDirectiveClass:
1446 case Stmt::OMPTargetParallelForDirectiveClass:
1447 case Stmt::OMPTargetParallelForSimdDirectiveClass:
1448 case Stmt::OMPTargetSimdDirectiveClass:
1449 case Stmt::OMPTargetTeamsDirectiveClass:
1450 case Stmt::OMPTargetTeamsDistributeDirectiveClass:
1451 case Stmt::OMPTargetTeamsDistributeParallelForDirectiveClass:
1452 case Stmt::OMPTargetTeamsDistributeParallelForSimdDirectiveClass:
1453 case Stmt::OMPTargetTeamsDistributeSimdDirectiveClass:
1454 case Stmt::OMPTargetUpdateDirectiveClass:
1455 case Stmt::OMPTaskDirectiveClass:
1456 case Stmt::OMPTaskgroupDirectiveClass:
1457 case Stmt::OMPTaskLoopDirectiveClass:
1458 case Stmt::OMPTaskLoopSimdDirectiveClass:
1459 case Stmt::OMPTaskwaitDirectiveClass:
1460 case Stmt::OMPTaskyieldDirectiveClass:
1461 case Stmt::OMPTeamsDirectiveClass:
1462 case Stmt::OMPTeamsDistributeDirectiveClass:
1463 case Stmt::OMPTeamsDistributeParallelForDirectiveClass:
1464 case Stmt::OMPTeamsDistributeParallelForSimdDirectiveClass:
1465 case Stmt::OMPTeamsDistributeSimdDirectiveClass:
1466 case Stmt::ReturnStmtClass:
1467 case Stmt::SEHExceptStmtClass:
1468 case Stmt::SEHFinallyStmtClass:
1469 case Stmt::SEHLeaveStmtClass:
1470 case Stmt::SEHTryStmtClass:
1471 case Stmt::SwitchStmtClass:
1472 case Stmt::WhileStmtClass:
1473 return canSubStmtsThrow(*this, S);
1474
1475 case Stmt::DeclStmtClass: {
1476 CanThrowResult CT = CT_Cannot;
1477 for (const Decl *D : cast<DeclStmt>(S)->decls()) {
2
'S' is a 'DeclStmt'
3
Assuming '__begin3' is not equal to '__end3'
1478 if (auto *VD
4.1
'VD' is non-null
4.1
'VD' is non-null
= dyn_cast<VarDecl>(D))
4
Assuming 'D' is a 'VarDecl'
5
Taking true branch
1479 CT = mergeCanThrow(CT, canVarDeclThrow(*this, VD));
6
Calling 'canVarDeclThrow'
1480
1481 // FIXME: Properly determine whether a variably-modified type can throw.
1482 if (auto *TND = dyn_cast<TypedefNameDecl>(D))
1483 if (TND->getUnderlyingType()->isVariablyModifiedType())
1484 return CT_Can;
1485 if (auto *VD = dyn_cast<ValueDecl>(D))
1486 if (VD->getType()->isVariablyModifiedType())
1487 return CT_Can;
1488 }
1489 return CT;
1490 }
1491
1492 case Stmt::IfStmtClass: {
1493 auto *IS = cast<IfStmt>(S);
1494 CanThrowResult CT = CT_Cannot;
1495 if (const Stmt *Init = IS->getInit())
1496 CT = mergeCanThrow(CT, canThrow(Init));
1497 if (const Stmt *CondDS = IS->getConditionVariableDeclStmt())
1498 CT = mergeCanThrow(CT, canThrow(CondDS));
1499 CT = mergeCanThrow(CT, canThrow(IS->getCond()));
1500
1501 // For 'if constexpr', consider only the non-discarded case.
1502 // FIXME: We should add a DiscardedStmt marker to the AST.
1503 if (Optional<const Stmt *> Case = IS->getNondiscardedCase(Context))
1504 return *Case ? mergeCanThrow(CT, canThrow(*Case)) : CT;
1505
1506 CanThrowResult Then = canThrow(IS->getThen());
1507 CanThrowResult Else = IS->getElse() ? canThrow(IS->getElse()) : CT_Cannot;
1508 if (Then == Else)
1509 return mergeCanThrow(CT, Then);
1510
1511 // For a dependent 'if constexpr', the result is dependent if it depends on
1512 // the value of the condition.
1513 return mergeCanThrow(CT, IS->isConstexpr() ? CT_Dependent
1514 : mergeCanThrow(Then, Else));
1515 }
1516
1517 case Stmt::CXXTryStmtClass: {
1518 auto *TS = cast<CXXTryStmt>(S);
1519 // try /*...*/ catch (...) { H } can throw only if H can throw.
1520 // Any other try-catch can throw if any substatement can throw.
1521 const CXXCatchStmt *FinalHandler = TS->getHandler(TS->getNumHandlers() - 1);
1522 if (!FinalHandler->getExceptionDecl())
1523 return canThrow(FinalHandler->getHandlerBlock());
1524 return canSubStmtsThrow(*this, S);
1525 }
1526
1527 case Stmt::ObjCAtThrowStmtClass:
1528 return CT_Can;
1529
1530 case Stmt::ObjCAtTryStmtClass: {
1531 auto *TS = cast<ObjCAtTryStmt>(S);
1532
1533 // @catch(...) need not be last in Objective-C. Walk backwards until we
1534 // see one or hit the @try.
1535 CanThrowResult CT = CT_Cannot;
1536 if (const Stmt *Finally = TS->getFinallyStmt())
1537 CT = mergeCanThrow(CT, canThrow(Finally));
1538 for (unsigned I = TS->getNumCatchStmts(); I != 0; --I) {
1539 const ObjCAtCatchStmt *Catch = TS->getCatchStmt(I - 1);
1540 CT = mergeCanThrow(CT, canThrow(Catch));
1541 // If we reach a @catch(...), no earlier exceptions can escape.
1542 if (Catch->hasEllipsis())
1543 return CT;
1544 }
1545
1546 // Didn't find an @catch(...). Exceptions from the @try body can escape.
1547 return mergeCanThrow(CT, canThrow(TS->getTryBody()));
1548 }
1549
1550 case Stmt::NoStmtClass:
1551 llvm_unreachable("Invalid class for statement")::llvm::llvm_unreachable_internal("Invalid class for statement"
, "/build/llvm-toolchain-snapshot-10~++20200112100611+7fa5290d5bd/clang/lib/Sema/SemaExceptionSpec.cpp"
, 1551)
;
1552 }
1553 llvm_unreachable("Bogus StmtClass")::llvm::llvm_unreachable_internal("Bogus StmtClass", "/build/llvm-toolchain-snapshot-10~++20200112100611+7fa5290d5bd/clang/lib/Sema/SemaExceptionSpec.cpp"
, 1553)
;
1554}
1555
1556} // end namespace clang

/build/llvm-toolchain-snapshot-10~++20200112100611+7fa5290d5bd/clang/include/clang/Basic/SourceLocation.h

1//===- SourceLocation.h - Compact identifier for Source Files ---*- 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/// \file
10/// Defines the clang::SourceLocation class and associated facilities.
11//
12//===----------------------------------------------------------------------===//
13
14#ifndef LLVM_CLANG_BASIC_SOURCELOCATION_H
15#define LLVM_CLANG_BASIC_SOURCELOCATION_H
16
17#include "clang/Basic/LLVM.h"
18#include "llvm/ADT/StringRef.h"
19#include "llvm/Support/PointerLikeTypeTraits.h"
20#include <cassert>
21#include <cstdint>
22#include <string>
23#include <utility>
24
25namespace llvm {
26
27template <typename T> struct DenseMapInfo;
28
29} // namespace llvm
30
31namespace clang {
32
33class SourceManager;
34
35/// An opaque identifier used by SourceManager which refers to a
36/// source file (MemoryBuffer) along with its \#include path and \#line data.
37///
38class FileID {
39 /// A mostly-opaque identifier, where 0 is "invalid", >0 is
40 /// this module, and <-1 is something loaded from another module.
41 int ID = 0;
42
43public:
44 bool isValid() const { return ID != 0; }
45 bool isInvalid() const { return ID == 0; }
46
47 bool operator==(const FileID &RHS) const { return ID == RHS.ID; }
48 bool operator<(const FileID &RHS) const { return ID < RHS.ID; }
49 bool operator<=(const FileID &RHS) const { return ID <= RHS.ID; }
50 bool operator!=(const FileID &RHS) const { return !(*this == RHS); }
51 bool operator>(const FileID &RHS) const { return RHS < *this; }
52 bool operator>=(const FileID &RHS) const { return RHS <= *this; }
53
54 static FileID getSentinel() { return get(-1); }
55 unsigned getHashValue() const { return static_cast<unsigned>(ID); }
56
57private:
58 friend class ASTWriter;
59 friend class ASTReader;
60 friend class SourceManager;
61
62 static FileID get(int V) {
63 FileID F;
64 F.ID = V;
65 return F;
66 }
67
68 int getOpaqueValue() const { return ID; }
69};
70
71/// Encodes a location in the source. The SourceManager can decode this
72/// to get at the full include stack, line and column information.
73///
74/// Technically, a source location is simply an offset into the manager's view
75/// of the input source, which is all input buffers (including macro
76/// expansions) concatenated in an effectively arbitrary order. The manager
77/// actually maintains two blocks of input buffers. One, starting at offset
78/// 0 and growing upwards, contains all buffers from this module. The other,
79/// starting at the highest possible offset and growing downwards, contains
80/// buffers of loaded modules.
81///
82/// In addition, one bit of SourceLocation is used for quick access to the
83/// information whether the location is in a file or a macro expansion.
84///
85/// It is important that this type remains small. It is currently 32 bits wide.
86class SourceLocation {
87 friend class ASTReader;
88 friend class ASTWriter;
89 friend class SourceManager;
90
91 unsigned ID = 0;
92
93 enum : unsigned {
94 MacroIDBit = 1U << 31
95 };
96
97public:
98 bool isFileID() const { return (ID & MacroIDBit) == 0; }
99 bool isMacroID() const { return (ID & MacroIDBit) != 0; }
100
101 /// Return true if this is a valid SourceLocation object.
102 ///
103 /// Invalid SourceLocations are often used when events have no corresponding
104 /// location in the source (e.g. a diagnostic is required for a command line
105 /// option).
106 bool isValid() const { return ID != 0; }
107 bool isInvalid() const { return ID == 0; }
55
Assuming field 'ID' is equal to 0
56
Returning the value 1, which participates in a condition later
108
109private:
110 /// Return the offset into the manager's global input view.
111 unsigned getOffset() const {
112 return ID & ~MacroIDBit;
113 }
114
115 static SourceLocation getFileLoc(unsigned ID) {
116 assert((ID & MacroIDBit) == 0 && "Ran out of source locations!")(((ID & MacroIDBit) == 0 && "Ran out of source locations!"
) ? static_cast<void> (0) : __assert_fail ("(ID & MacroIDBit) == 0 && \"Ran out of source locations!\""
, "/build/llvm-toolchain-snapshot-10~++20200112100611+7fa5290d5bd/clang/include/clang/Basic/SourceLocation.h"
, 116, __PRETTY_FUNCTION__))
;
117 SourceLocation L;
118 L.ID = ID;
119 return L;
120 }
121
122 static SourceLocation getMacroLoc(unsigned ID) {
123 assert((ID & MacroIDBit) == 0 && "Ran out of source locations!")(((ID & MacroIDBit) == 0 && "Ran out of source locations!"
) ? static_cast<void> (0) : __assert_fail ("(ID & MacroIDBit) == 0 && \"Ran out of source locations!\""
, "/build/llvm-toolchain-snapshot-10~++20200112100611+7fa5290d5bd/clang/include/clang/Basic/SourceLocation.h"
, 123, __PRETTY_FUNCTION__))
;
124 SourceLocation L;
125 L.ID = MacroIDBit | ID;
126 return L;
127 }
128
129public:
130 /// Return a source location with the specified offset from this
131 /// SourceLocation.
132 SourceLocation getLocWithOffset(int Offset) const {
133 assert(((getOffset()+Offset) & MacroIDBit) == 0 && "offset overflow")((((getOffset()+Offset) & MacroIDBit) == 0 && "offset overflow"
) ? static_cast<void> (0) : __assert_fail ("((getOffset()+Offset) & MacroIDBit) == 0 && \"offset overflow\""
, "/build/llvm-toolchain-snapshot-10~++20200112100611+7fa5290d5bd/clang/include/clang/Basic/SourceLocation.h"
, 133, __PRETTY_FUNCTION__))
;
134 SourceLocation L;
135 L.ID = ID+Offset;
136 return L;
137 }
138
139 /// When a SourceLocation itself cannot be used, this returns
140 /// an (opaque) 32-bit integer encoding for it.
141 ///
142 /// This should only be passed to SourceLocation::getFromRawEncoding, it
143 /// should not be inspected directly.
144 unsigned getRawEncoding() const { return ID; }
145
146 /// Turn a raw encoding of a SourceLocation object into
147 /// a real SourceLocation.
148 ///
149 /// \see getRawEncoding.
150 static SourceLocation getFromRawEncoding(unsigned Encoding) {
151 SourceLocation X;
152 X.ID = Encoding;
153 return X;
154 }
155
156 /// When a SourceLocation itself cannot be used, this returns
157 /// an (opaque) pointer encoding for it.
158 ///
159 /// This should only be passed to SourceLocation::getFromPtrEncoding, it
160 /// should not be inspected directly.
161 void* getPtrEncoding() const {
162 // Double cast to avoid a warning "cast to pointer from integer of different
163 // size".
164 return (void*)(uintptr_t)getRawEncoding();
165 }
166
167 /// Turn a pointer encoding of a SourceLocation object back
168 /// into a real SourceLocation.
169 static SourceLocation getFromPtrEncoding(const void *Encoding) {
170 return getFromRawEncoding((unsigned)(uintptr_t)Encoding);
171 }
172
173 static bool isPairOfFileLocations(SourceLocation Start, SourceLocation End) {
174 return Start.isValid() && Start.isFileID() && End.isValid() &&
175 End.isFileID();
176 }
177
178 void print(raw_ostream &OS, const SourceManager &SM) const;
179 std::string printToString(const SourceManager &SM) const;
180 void dump(const SourceManager &SM) const;
181};
182
183inline bool operator==(const SourceLocation &LHS, const SourceLocation &RHS) {
184 return LHS.getRawEncoding() == RHS.getRawEncoding();
185}
186
187inline bool operator!=(const SourceLocation &LHS, const SourceLocation &RHS) {
188 return !(LHS == RHS);
189}
190
191// Ordering is meaningful only if LHS and RHS have the same FileID!
192// Otherwise use SourceManager::isBeforeInTranslationUnit().
193inline bool operator<(const SourceLocation &LHS, const SourceLocation &RHS) {
194 return LHS.getRawEncoding() < RHS.getRawEncoding();
195}
196inline bool operator>(const SourceLocation &LHS, const SourceLocation &RHS) {
197 return LHS.getRawEncoding() > RHS.getRawEncoding();
198}
199inline bool operator<=(const SourceLocation &LHS, const SourceLocation &RHS) {
200 return LHS.getRawEncoding() <= RHS.getRawEncoding();
201}
202inline bool operator>=(const SourceLocation &LHS, const SourceLocation &RHS) {
203 return LHS.getRawEncoding() >= RHS.getRawEncoding();
204}
205
206/// A trivial tuple used to represent a source range.
207class SourceRange {
208 SourceLocation B;
209 SourceLocation E;
210
211public:
212 SourceRange() = default;
213 SourceRange(SourceLocation loc) : B(loc), E(loc) {}
214 SourceRange(SourceLocation begin, SourceLocation end) : B(begin), E(end) {}
215
216 SourceLocation getBegin() const { return B; }
217 SourceLocation getEnd() const { return E; }
218
219 void setBegin(SourceLocation b) { B = b; }
220 void setEnd(SourceLocation e) { E = e; }
221
222 bool isValid() const { return B.isValid() && E.isValid(); }
223 bool isInvalid() const { return !isValid(); }
224
225 bool operator==(const SourceRange &X) const {
226 return B == X.B && E == X.E;
227 }
228
229 bool operator!=(const SourceRange &X) const {
230 return B != X.B || E != X.E;
231 }
232
233 // Returns true iff other is wholly contained within this range.
234 bool fullyContains(const SourceRange &other) const {
235 return B <= other.B && E >= other.E;
236 }
237
238 void print(raw_ostream &OS, const SourceManager &SM) const;
239 std::string printToString(const SourceManager &SM) const;
240 void dump(const SourceManager &SM) const;
241};
242
243/// Represents a character-granular source range.
244///
245/// The underlying SourceRange can either specify the starting/ending character
246/// of the range, or it can specify the start of the range and the start of the
247/// last token of the range (a "token range"). In the token range case, the
248/// size of the last token must be measured to determine the actual end of the
249/// range.
250class CharSourceRange {
251 SourceRange Range;
252 bool IsTokenRange = false;
253
254public:
255 CharSourceRange() = default;
256 CharSourceRange(SourceRange R, bool ITR) : Range(R), IsTokenRange(ITR) {}
257
258 static CharSourceRange getTokenRange(SourceRange R) {
259 return CharSourceRange(R, true);
260 }
261
262 static CharSourceRange getCharRange(SourceRange R) {
263 return CharSourceRange(R, false);
264 }
265
266 static CharSourceRange getTokenRange(SourceLocation B, SourceLocation E) {
267 return getTokenRange(SourceRange(B, E));
268 }
269
270 static CharSourceRange getCharRange(SourceLocation B, SourceLocation E) {
271 return getCharRange(SourceRange(B, E));
272 }
273
274 /// Return true if the end of this range specifies the start of
275 /// the last token. Return false if the end of this range specifies the last
276 /// character in the range.
277 bool isTokenRange() const { return IsTokenRange; }
278 bool isCharRange() const { return !IsTokenRange; }
279
280 SourceLocation getBegin() const { return Range.getBegin(); }
281 SourceLocation getEnd() const { return Range.getEnd(); }
282 SourceRange getAsRange() const { return Range; }
283
284 void setBegin(SourceLocation b) { Range.setBegin(b); }
285 void setEnd(SourceLocation e) { Range.setEnd(e); }
286 void setTokenRange(bool TR) { IsTokenRange = TR; }
287
288 bool isValid() const { return Range.isValid(); }
289 bool isInvalid() const { return !isValid(); }
290};
291
292/// Represents an unpacked "presumed" location which can be presented
293/// to the user.
294///
295/// A 'presumed' location can be modified by \#line and GNU line marker
296/// directives and is always the expansion point of a normal location.
297///
298/// You can get a PresumedLoc from a SourceLocation with SourceManager.
299class PresumedLoc {
300 const char *Filename = nullptr;
301 FileID ID;
302 unsigned Line, Col;
303 SourceLocation IncludeLoc;
304
305public:
306 PresumedLoc() = default;
307 PresumedLoc(const char *FN, FileID FID, unsigned Ln, unsigned Co,
308 SourceLocation IL)
309 : Filename(FN), ID(FID), Line(Ln), Col(Co), IncludeLoc(IL) {}
310
311 /// Return true if this object is invalid or uninitialized.
312 ///
313 /// This occurs when created with invalid source locations or when walking
314 /// off the top of a \#include stack.
315 bool isInvalid() const { return Filename == nullptr; }
316 bool isValid() const { return Filename != nullptr; }
317
318 /// Return the presumed filename of this location.
319 ///
320 /// This can be affected by \#line etc.
321 const char *getFilename() const {
322 assert(isValid())((isValid()) ? static_cast<void> (0) : __assert_fail ("isValid()"
, "/build/llvm-toolchain-snapshot-10~++20200112100611+7fa5290d5bd/clang/include/clang/Basic/SourceLocation.h"
, 322, __PRETTY_FUNCTION__))
;
323 return Filename;
324 }
325
326 FileID getFileID() const {
327 assert(isValid())((isValid()) ? static_cast<void> (0) : __assert_fail ("isValid()"
, "/build/llvm-toolchain-snapshot-10~++20200112100611+7fa5290d5bd/clang/include/clang/Basic/SourceLocation.h"
, 327, __PRETTY_FUNCTION__))
;
328 return ID;
329 }
330
331 /// Return the presumed line number of this location.
332 ///
333 /// This can be affected by \#line etc.
334 unsigned getLine() const {
335 assert(isValid())((isValid()) ? static_cast<void> (0) : __assert_fail ("isValid()"
, "/build/llvm-toolchain-snapshot-10~++20200112100611+7fa5290d5bd/clang/include/clang/Basic/SourceLocation.h"
, 335, __PRETTY_FUNCTION__))
;
336 return Line;
337 }
338
339 /// Return the presumed column number of this location.
340 ///
341 /// This cannot be affected by \#line, but is packaged here for convenience.
342 unsigned getColumn() const {
343 assert(isValid())((isValid()) ? static_cast<void> (0) : __assert_fail ("isValid()"
, "/build/llvm-toolchain-snapshot-10~++20200112100611+7fa5290d5bd/clang/include/clang/Basic/SourceLocation.h"
, 343, __PRETTY_FUNCTION__))
;
344 return Col;
345 }
346
347 /// Return the presumed include location of this location.
348 ///
349 /// This can be affected by GNU linemarker directives.
350 SourceLocation getIncludeLoc() const {
351 assert(isValid())((isValid()) ? static_cast<void> (0) : __assert_fail ("isValid()"
, "/build/llvm-toolchain-snapshot-10~++20200112100611+7fa5290d5bd/clang/include/clang/Basic/SourceLocation.h"
, 351, __PRETTY_FUNCTION__))
;
352 return IncludeLoc;
353 }
354};
355
356class FileEntry;
357
358/// A SourceLocation and its associated SourceManager.
359///
360/// This is useful for argument passing to functions that expect both objects.
361class FullSourceLoc : public SourceLocation {
362 const SourceManager *SrcMgr = nullptr;
363
364public:
365 /// Creates a FullSourceLoc where isValid() returns \c false.
366 FullSourceLoc() = default;
367
368 explicit FullSourceLoc(SourceLocation Loc, const SourceManager &SM)
369 : SourceLocation(Loc), SrcMgr(&SM) {}
370
371 bool hasManager() const {
372 bool hasSrcMgr = SrcMgr != nullptr;
373 assert(hasSrcMgr == isValid() && "FullSourceLoc has location but no manager")((hasSrcMgr == isValid() && "FullSourceLoc has location but no manager"
) ? static_cast<void> (0) : __assert_fail ("hasSrcMgr == isValid() && \"FullSourceLoc has location but no manager\""
, "/build/llvm-toolchain-snapshot-10~++20200112100611+7fa5290d5bd/clang/include/clang/Basic/SourceLocation.h"
, 373, __PRETTY_FUNCTION__))
;
374 return hasSrcMgr;
375 }
376
377 /// \pre This FullSourceLoc has an associated SourceManager.
378 const SourceManager &getManager() const {
379 assert(SrcMgr && "SourceManager is NULL.")((SrcMgr && "SourceManager is NULL.") ? static_cast<
void> (0) : __assert_fail ("SrcMgr && \"SourceManager is NULL.\""
, "/build/llvm-toolchain-snapshot-10~++20200112100611+7fa5290d5bd/clang/include/clang/Basic/SourceLocation.h"
, 379, __PRETTY_FUNCTION__))
;
380 return *SrcMgr;
381 }
382
383 FileID getFileID() const;
384
385 FullSourceLoc getExpansionLoc() const;
386 FullSourceLoc getSpellingLoc() const;
387 FullSourceLoc getFileLoc() const;
388 PresumedLoc getPresumedLoc(bool UseLineDirectives = true) const;
389 bool isMacroArgExpansion(FullSourceLoc *StartLoc = nullptr) const;
390 FullSourceLoc getImmediateMacroCallerLoc() const;
391 std::pair<FullSourceLoc, StringRef> getModuleImportLoc() const;
392 unsigned getFileOffset() const;
393
394 unsigned getExpansionLineNumber(bool *Invalid = nullptr) const;
395 unsigned getExpansionColumnNumber(bool *Invalid = nullptr) const;
396
397 unsigned getSpellingLineNumber(bool *Invalid = nullptr) const;
398 unsigned getSpellingColumnNumber(bool *Invalid = nullptr) const;
399
400 const char *getCharacterData(bool *Invalid = nullptr) const;
401
402 unsigned getLineNumber(bool *Invalid = nullptr) const;
403 unsigned getColumnNumber(bool *Invalid = nullptr) const;
404
405 const FileEntry *getFileEntry() const;
406
407 /// Return a StringRef to the source buffer data for the
408 /// specified FileID.
409 StringRef getBufferData(bool *Invalid = nullptr) const;
410
411 /// Decompose the specified location into a raw FileID + Offset pair.
412 ///
413 /// The first element is the FileID, the second is the offset from the
414 /// start of the buffer of the location.
415 std::pair<FileID, unsigned> getDecomposedLoc() const;
416
417 bool isInSystemHeader() const;
418
419 /// Determines the order of 2 source locations in the translation unit.
420 ///
421 /// \returns true if this source location comes before 'Loc', false otherwise.
422 bool isBeforeInTranslationUnitThan(SourceLocation Loc) const;
423
424 /// Determines the order of 2 source locations in the translation unit.
425 ///
426 /// \returns true if this source location comes before 'Loc', false otherwise.
427 bool isBeforeInTranslationUnitThan(FullSourceLoc Loc) const {
428 assert(Loc.isValid())((Loc.isValid()) ? static_cast<void> (0) : __assert_fail
("Loc.isValid()", "/build/llvm-toolchain-snapshot-10~++20200112100611+7fa5290d5bd/clang/include/clang/Basic/SourceLocation.h"
, 428, __PRETTY_FUNCTION__))
;
429 assert(SrcMgr == Loc.SrcMgr && "Loc comes from another SourceManager!")((SrcMgr == Loc.SrcMgr && "Loc comes from another SourceManager!"
) ? static_cast<void> (0) : __assert_fail ("SrcMgr == Loc.SrcMgr && \"Loc comes from another SourceManager!\""
, "/build/llvm-toolchain-snapshot-10~++20200112100611+7fa5290d5bd/clang/include/clang/Basic/SourceLocation.h"
, 429, __PRETTY_FUNCTION__))
;
430 return isBeforeInTranslationUnitThan((SourceLocation)Loc);
431 }
432
433 /// Comparison function class, useful for sorting FullSourceLocs.
434 struct BeforeThanCompare {
435 bool operator()(const FullSourceLoc& lhs, const FullSourceLoc& rhs) const {
436 return lhs.isBeforeInTranslationUnitThan(rhs);
437 }
438 };
439
440 /// Prints information about this FullSourceLoc to stderr.
441 ///
442 /// This is useful for debugging.
443 void dump() const;
444
445 friend bool
446 operator==(const FullSourceLoc &LHS, const FullSourceLoc &RHS) {
447 return LHS.getRawEncoding() == RHS.getRawEncoding() &&
448 LHS.SrcMgr == RHS.SrcMgr;
449 }
450
451 friend bool
452 operator!=(const FullSourceLoc &LHS, const FullSourceLoc &RHS) {
453 return !(LHS == RHS);
454 }
455};
456
457} // namespace clang
458
459namespace llvm {
460
461 /// Define DenseMapInfo so that FileID's can be used as keys in DenseMap and
462 /// DenseSets.
463 template <>
464 struct DenseMapInfo<clang::FileID> {
465 static clang::FileID getEmptyKey() {
466 return {};
467 }
468
469 static clang::FileID getTombstoneKey() {
470 return clang::FileID::getSentinel();
471 }
472
473 static unsigned getHashValue(clang::FileID S) {
474 return S.getHashValue();
475 }
476
477 static bool isEqual(clang::FileID LHS, clang::FileID RHS) {
478 return LHS == RHS;
479 }
480 };
481
482 // Teach SmallPtrSet how to handle SourceLocation.
483 template<>
484 struct PointerLikeTypeTraits<clang::SourceLocation> {
485 enum { NumLowBitsAvailable = 0 };
486
487 static void *getAsVoidPointer(clang::SourceLocation L) {
488 return L.getPtrEncoding();
489 }
490
491 static clang::SourceLocation getFromVoidPointer(void *P) {
492 return clang::SourceLocation::getFromRawEncoding((unsigned)(uintptr_t)P);
493 }
494 };
495
496} // namespace llvm
497
498#endif // LLVM_CLANG_BASIC_SOURCELOCATION_H