Bug Summary

File:build/source/flang/lib/Semantics/expression.cpp
Warning:line 3928, column 48
Method called on moved-from object 'actuals_' of type 'std::vector'

Annotated Source Code

Press '?' to see keyboard shortcuts

clang -cc1 -cc1 -triple x86_64-pc-linux-gnu -analyze -disable-free -clear-ast-before-backend -disable-llvm-verifier -discard-value-names -main-file-name expression.cpp -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 -mframe-pointer=none -relaxed-aliasing -fmath-errno -ffp-contract=on -fno-rounding-math -mconstructor-aliases -funwind-tables=2 -target-cpu x86-64 -tune-cpu generic -debugger-tuning=gdb -ffunction-sections -fdata-sections -fcoverage-compilation-dir=/build/source/build-llvm/tools/clang/stage2-bins -resource-dir /usr/lib/llvm-17/lib/clang/17 -isystem /build/source/llvm/../mlir/include -isystem tools/mlir/include -isystem tools/clang/include -isystem /build/source/llvm/../clang/include -D FLANG_INCLUDE_TESTS=1 -D FLANG_LITTLE_ENDIAN=1 -D FLANG_VENDOR="Debian " -D _DEBUG -D _GLIBCXX_ASSERTIONS -D _GNU_SOURCE -D _LIBCPP_ENABLE_ASSERTIONS -D __STDC_CONSTANT_MACROS -D __STDC_FORMAT_MACROS -D __STDC_LIMIT_MACROS -I tools/flang/lib/Semantics -I /build/source/flang/lib/Semantics -I /build/source/flang/include -I tools/flang/include -I include -I /build/source/llvm/include -D _FORTIFY_SOURCE=2 -D NDEBUG -U NDEBUG -internal-isystem /usr/lib/gcc/x86_64-linux-gnu/10/../../../../include/c++/10 -internal-isystem /usr/lib/gcc/x86_64-linux-gnu/10/../../../../include/x86_64-linux-gnu/c++/10 -internal-isystem /usr/lib/gcc/x86_64-linux-gnu/10/../../../../include/c++/10/backward -internal-isystem /usr/lib/llvm-17/lib/clang/17/include -internal-isystem /usr/local/include -internal-isystem /usr/lib/gcc/x86_64-linux-gnu/10/../../../../x86_64-linux-gnu/include -internal-externc-isystem /usr/include/x86_64-linux-gnu -internal-externc-isystem /include -internal-externc-isystem /usr/include -fmacro-prefix-map=/build/source/build-llvm/tools/clang/stage2-bins=build-llvm/tools/clang/stage2-bins -fmacro-prefix-map=/build/source/= -fcoverage-prefix-map=/build/source/build-llvm/tools/clang/stage2-bins=build-llvm/tools/clang/stage2-bins -fcoverage-prefix-map=/build/source/= -source-date-epoch 1683717183 -O2 -Wno-unused-command-line-argument -Wno-unused-parameter -Wwrite-strings -Wno-missing-field-initializers -Wno-long-long -Wno-maybe-uninitialized -Wno-class-memaccess -Wno-redundant-move -Wno-pessimizing-move -Wno-noexcept-type -Wno-comment -Wno-misleading-indentation -Wno-deprecated-copy -Wno-ctad-maybe-unsupported -std=c++17 -fdeprecated-macro -fdebug-compilation-dir=/build/source/build-llvm/tools/clang/stage2-bins -fdebug-prefix-map=/build/source/build-llvm/tools/clang/stage2-bins=build-llvm/tools/clang/stage2-bins -fdebug-prefix-map=/build/source/= -ferror-limit 19 -fvisibility-inlines-hidden -stack-protector 2 -fgnuc-version=4.2.1 -fcolor-diagnostics -vectorize-loops -vectorize-slp -analyzer-output=html -analyzer-config stable-report-filename=true -faddrsig -D__GCC_HAVE_DWARF2_CFI_ASM=1 -o /tmp/scan-build-2023-05-10-133810-16478-1 -x c++ /build/source/flang/lib/Semantics/expression.cpp

/build/source/flang/lib/Semantics/expression.cpp

1//===-- lib/Semantics/expression.cpp --------------------------------------===//
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#include "flang/Semantics/expression.h"
10#include "check-call.h"
11#include "pointer-assignment.h"
12#include "resolve-names-utils.h"
13#include "resolve-names.h"
14#include "flang/Common/Fortran.h"
15#include "flang/Common/idioms.h"
16#include "flang/Evaluate/common.h"
17#include "flang/Evaluate/fold.h"
18#include "flang/Evaluate/tools.h"
19#include "flang/Parser/characters.h"
20#include "flang/Parser/dump-parse-tree.h"
21#include "flang/Parser/parse-tree-visitor.h"
22#include "flang/Parser/parse-tree.h"
23#include "flang/Semantics/scope.h"
24#include "flang/Semantics/semantics.h"
25#include "flang/Semantics/symbol.h"
26#include "flang/Semantics/tools.h"
27#include "llvm/Support/raw_ostream.h"
28#include <algorithm>
29#include <functional>
30#include <optional>
31#include <set>
32#include <vector>
33
34// Typedef for optional generic expressions (ubiquitous in this file)
35using MaybeExpr =
36 std::optional<Fortran::evaluate::Expr<Fortran::evaluate::SomeType>>;
37
38// Much of the code that implements semantic analysis of expressions is
39// tightly coupled with their typed representations in lib/Evaluate,
40// and appears here in namespace Fortran::evaluate for convenience.
41namespace Fortran::evaluate {
42
43using common::LanguageFeature;
44using common::NumericOperator;
45using common::TypeCategory;
46
47static inline std::string ToUpperCase(std::string_view str) {
48 return parser::ToUpperCaseLetters(str);
49}
50
51struct DynamicTypeWithLength : public DynamicType {
52 explicit DynamicTypeWithLength(const DynamicType &t) : DynamicType{t} {}
53 std::optional<Expr<SubscriptInteger>> LEN() const;
54 std::optional<Expr<SubscriptInteger>> length;
55};
56
57std::optional<Expr<SubscriptInteger>> DynamicTypeWithLength::LEN() const {
58 if (length) {
59 return length;
60 } else {
61 return GetCharLength();
62 }
63}
64
65static std::optional<DynamicTypeWithLength> AnalyzeTypeSpec(
66 const std::optional<parser::TypeSpec> &spec) {
67 if (spec) {
68 if (const semantics::DeclTypeSpec *typeSpec{spec->declTypeSpec}) {
69 // Name resolution sets TypeSpec::declTypeSpec only when it's valid
70 // (viz., an intrinsic type with valid known kind or a non-polymorphic
71 // & non-ABSTRACT derived type).
72 if (const semantics::IntrinsicTypeSpec *intrinsic{
73 typeSpec->AsIntrinsic()}) {
74 TypeCategory category{intrinsic->category()};
75 if (auto optKind{ToInt64(intrinsic->kind())}) {
76 int kind{static_cast<int>(*optKind)};
77 if (category == TypeCategory::Character) {
78 const semantics::CharacterTypeSpec &cts{
79 typeSpec->characterTypeSpec()};
80 const semantics::ParamValue &len{cts.length()};
81 // N.B. CHARACTER(LEN=*) is allowed in type-specs in ALLOCATE() &
82 // type guards, but not in array constructors.
83 return DynamicTypeWithLength{DynamicType{kind, len}};
84 } else {
85 return DynamicTypeWithLength{DynamicType{category, kind}};
86 }
87 }
88 } else if (const semantics::DerivedTypeSpec *derived{
89 typeSpec->AsDerived()}) {
90 return DynamicTypeWithLength{DynamicType{*derived}};
91 }
92 }
93 }
94 return std::nullopt;
95}
96
97// Utilities to set a source location, if we have one, on an actual argument,
98// when it is statically present.
99static void SetArgSourceLocation(ActualArgument &x, parser::CharBlock at) {
100 x.set_sourceLocation(at);
101}
102static void SetArgSourceLocation(
103 std::optional<ActualArgument> &x, parser::CharBlock at) {
104 if (x) {
105 x->set_sourceLocation(at);
106 }
107}
108static void SetArgSourceLocation(
109 std::optional<ActualArgument> &x, std::optional<parser::CharBlock> at) {
110 if (x && at) {
111 x->set_sourceLocation(*at);
112 }
113}
114
115class ArgumentAnalyzer {
116public:
117 explicit ArgumentAnalyzer(ExpressionAnalyzer &context)
118 : context_{context}, source_{context.GetContextualMessages().at()},
119 isProcedureCall_{false} {}
120 ArgumentAnalyzer(ExpressionAnalyzer &context, parser::CharBlock source,
121 bool isProcedureCall = false)
122 : context_{context}, source_{source}, isProcedureCall_{isProcedureCall} {}
123 bool fatalErrors() const { return fatalErrors_; }
124 ActualArguments &&GetActuals() {
125 CHECK(!fatalErrors_)((!fatalErrors_) || (Fortran::common::die("CHECK(" "!fatalErrors_"
") failed" " at " "flang/lib/Semantics/expression.cpp" "(%d)"
, 125), false))
;
126 return std::move(actuals_);
127 }
128 const Expr<SomeType> &GetExpr(std::size_t i) const {
129 return DEREF(actuals_.at(i).value().UnwrapExpr())Fortran::common::Deref(actuals_.at(i).value().UnwrapExpr(), "flang/lib/Semantics/expression.cpp"
, 129)
;
130 }
131 Expr<SomeType> &&MoveExpr(std::size_t i) {
132 return std::move(DEREF(actuals_.at(i).value().UnwrapExpr())Fortran::common::Deref(actuals_.at(i).value().UnwrapExpr(), "flang/lib/Semantics/expression.cpp"
, 132)
);
133 }
134 void Analyze(const common::Indirection<parser::Expr> &x) {
135 Analyze(x.value());
136 }
137 void Analyze(const parser::Expr &x) {
138 actuals_.emplace_back(AnalyzeExpr(x));
139 SetArgSourceLocation(actuals_.back(), x.source);
140 fatalErrors_ |= !actuals_.back();
141 }
142 void Analyze(const parser::Variable &);
143 void Analyze(const parser::ActualArgSpec &, bool isSubroutine);
144 void ConvertBOZ(std::optional<DynamicType> &thisType, std::size_t i,
145 std::optional<DynamicType> otherType);
146
147 bool IsIntrinsicRelational(
148 RelationalOperator, const DynamicType &, const DynamicType &) const;
149 bool IsIntrinsicLogical() const;
150 bool IsIntrinsicNumeric(NumericOperator) const;
151 bool IsIntrinsicConcat() const;
152
153 bool CheckConformance();
154 bool CheckAssignmentConformance();
155 bool CheckForNullPointer(const char *where = "as an operand here");
156
157 // Find and return a user-defined operator or report an error.
158 // The provided message is used if there is no such operator.
159 // If a definedOpSymbolPtr is provided, the caller must check
160 // for its accessibility.
161 MaybeExpr TryDefinedOp(
162 const char *, parser::MessageFixedText, bool isUserOp = false);
163 template <typename E>
164 MaybeExpr TryDefinedOp(E opr, parser::MessageFixedText msg) {
165 return TryDefinedOp(
166 context_.context().languageFeatures().GetNames(opr), msg);
167 }
168 // Find and return a user-defined assignment
169 std::optional<ProcedureRef> TryDefinedAssignment();
170 std::optional<ProcedureRef> GetDefinedAssignmentProc();
171 std::optional<DynamicType> GetType(std::size_t) const;
172 void Dump(llvm::raw_ostream &);
173
174private:
175 MaybeExpr TryDefinedOp(std::vector<const char *>, parser::MessageFixedText);
176 MaybeExpr TryBoundOp(const Symbol &, int passIndex);
177 std::optional<ActualArgument> AnalyzeExpr(const parser::Expr &);
178 MaybeExpr AnalyzeExprOrWholeAssumedSizeArray(const parser::Expr &);
179 bool AreConformable() const;
180 const Symbol *FindBoundOp(parser::CharBlock, int passIndex,
181 const Symbol *&generic, bool isSubroutine);
182 void AddAssignmentConversion(
183 const DynamicType &lhsType, const DynamicType &rhsType);
184 bool OkLogicalIntegerAssignment(TypeCategory lhs, TypeCategory rhs);
185 int GetRank(std::size_t) const;
186 bool IsBOZLiteral(std::size_t i) const {
187 return evaluate::IsBOZLiteral(GetExpr(i));
188 }
189 void SayNoMatch(const std::string &, bool isAssignment = false);
190 std::string TypeAsFortran(std::size_t);
191 bool AnyUntypedOrMissingOperand();
192
193 ExpressionAnalyzer &context_;
194 ActualArguments actuals_;
195 parser::CharBlock source_;
196 bool fatalErrors_{false};
197 const bool isProcedureCall_; // false for user-defined op or assignment
198};
199
200// Wraps a data reference in a typed Designator<>, and a procedure
201// or procedure pointer reference in a ProcedureDesignator.
202MaybeExpr ExpressionAnalyzer::Designate(DataRef &&ref) {
203 const Symbol &last{ref.GetLastSymbol()};
204 const Symbol &symbol{BypassGeneric(last).GetUltimate()};
205 if (semantics::IsProcedure(symbol)) {
206 if (symbol.attrs().test(semantics::Attr::ABSTRACT)) {
207 Say("Abstract procedure interface '%s' may not be used as a designator"_err_en_US,
208 last.name());
209 }
210 if (auto *component{std::get_if<Component>(&ref.u)}) {
211 if (!CheckDataRef(ref)) {
212 return std::nullopt;
213 }
214 return Expr<SomeType>{ProcedureDesignator{std::move(*component)}};
215 } else if (!std::holds_alternative<SymbolRef>(ref.u)) {
216 DIE("unexpected alternative in DataRef")Fortran::common::die("unexpected alternative in DataRef" " at "
"flang/lib/Semantics/expression.cpp" "(%d)", 216)
;
217 } else if (!symbol.attrs().test(semantics::Attr::INTRINSIC)) {
218 if (symbol.has<semantics::GenericDetails>()) {
219 Say("'%s' is not a specific procedure"_err_en_US, last.name());
220 } else {
221 return Expr<SomeType>{ProcedureDesignator{symbol}};
222 }
223 } else if (auto interface{context_.intrinsics().IsSpecificIntrinsicFunction(
224 symbol.name().ToString())};
225 interface && !interface->isRestrictedSpecific) {
226 SpecificIntrinsic intrinsic{
227 symbol.name().ToString(), std::move(*interface)};
228 intrinsic.isRestrictedSpecific = interface->isRestrictedSpecific;
229 return Expr<SomeType>{ProcedureDesignator{std::move(intrinsic)}};
230 } else {
231 Say("'%s' is not an unrestricted specific intrinsic procedure"_err_en_US,
232 last.name());
233 }
234 return std::nullopt;
235 } else if (MaybeExpr result{AsGenericExpr(std::move(ref))}) {
236 return result;
237 } else {
238 if (!context_.HasError(last) && !context_.HasError(symbol)) {
239 AttachDeclaration(
240 Say("'%s' is not an object that can appear in an expression"_err_en_US,
241 last.name()),
242 symbol);
243 context_.SetError(last);
244 }
245 return std::nullopt;
246 }
247}
248
249// Some subscript semantic checks must be deferred until all of the
250// subscripts are in hand.
251MaybeExpr ExpressionAnalyzer::CompleteSubscripts(ArrayRef &&ref) {
252 const Symbol &symbol{ref.GetLastSymbol().GetUltimate()};
253 int symbolRank{symbol.Rank()};
254 int subscripts{static_cast<int>(ref.size())};
255 if (subscripts == 0) {
256 return std::nullopt; // error recovery
257 } else if (subscripts != symbolRank) {
258 if (symbolRank != 0) {
259 Say("Reference to rank-%d object '%s' has %d subscripts"_err_en_US,
260 symbolRank, symbol.name(), subscripts);
261 }
262 return std::nullopt;
263 } else if (const auto *object{
264 symbol.detailsIf<semantics::ObjectEntityDetails>()}) {
265 // C928 & C1002
266 if (Triplet *last{std::get_if<Triplet>(&ref.subscript().back().u)}) {
267 if (!last->upper() && object->IsAssumedSize()) {
268 Say("Assumed-size array '%s' must have explicit final "
269 "subscript upper bound value"_err_en_US,
270 symbol.name());
271 return std::nullopt;
272 }
273 }
274 } else {
275 // Shouldn't get here from Analyze(ArrayElement) without a valid base,
276 // which, if not an object, must be a construct entity from
277 // SELECT TYPE/RANK or ASSOCIATE.
278 CHECK(symbol.has<semantics::AssocEntityDetails>())((symbol.has<semantics::AssocEntityDetails>()) || (Fortran
::common::die("CHECK(" "symbol.has<semantics::AssocEntityDetails>()"
") failed" " at " "flang/lib/Semantics/expression.cpp" "(%d)"
, 278), false))
;
279 }
280 if (!semantics::IsNamedConstant(symbol) && !inDataStmtObject_) {
281 // Subscripts of named constants are checked in folding.
282 // Subscripts of DATA statement objects are checked in data statement
283 // conversion to initializers.
284 CheckConstantSubscripts(ref);
285 }
286 return Designate(DataRef{std::move(ref)});
287}
288
289// Applies subscripts to a data reference.
290MaybeExpr ExpressionAnalyzer::ApplySubscripts(
291 DataRef &&dataRef, std::vector<Subscript> &&subscripts) {
292 if (subscripts.empty()) {
293 return std::nullopt; // error recovery
294 }
295 return common::visit(
296 common::visitors{
297 [&](SymbolRef &&symbol) {
298 return CompleteSubscripts(ArrayRef{symbol, std::move(subscripts)});
299 },
300 [&](Component &&c) {
301 return CompleteSubscripts(
302 ArrayRef{std::move(c), std::move(subscripts)});
303 },
304 [&](auto &&) -> MaybeExpr {
305 DIE("bad base for ArrayRef")Fortran::common::die("bad base for ArrayRef" " at " "flang/lib/Semantics/expression.cpp"
"(%d)", 305)
;
306 return std::nullopt;
307 },
308 },
309 std::move(dataRef.u));
310}
311
312void ExpressionAnalyzer::CheckConstantSubscripts(ArrayRef &ref) {
313 // Fold subscript expressions and check for an empty triplet.
314 Shape lb{GetLBOUNDs(foldingContext_, ref.base())};
315 CHECK(lb.size() >= ref.subscript().size())((lb.size() >= ref.subscript().size()) || (Fortran::common
::die("CHECK(" "lb.size() >= ref.subscript().size()" ") failed"
" at " "flang/lib/Semantics/expression.cpp" "(%d)", 315), false
))
;
316 Shape ub{GetUBOUNDs(foldingContext_, ref.base())};
317 CHECK(ub.size() >= ref.subscript().size())((ub.size() >= ref.subscript().size()) || (Fortran::common
::die("CHECK(" "ub.size() >= ref.subscript().size()" ") failed"
" at " "flang/lib/Semantics/expression.cpp" "(%d)", 317), false
))
;
318 bool anyPossiblyEmptyDim{false};
319 int dim{0};
320 for (Subscript &ss : ref.subscript()) {
321 if (Triplet * triplet{std::get_if<Triplet>(&ss.u)}) {
322 auto expr{Fold(triplet->stride())};
323 auto stride{ToInt64(expr)};
324 triplet->set_stride(std::move(expr));
325 std::optional<ConstantSubscript> lower, upper;
326 if (auto expr{triplet->lower()}) {
327 *expr = Fold(std::move(*expr));
328 lower = ToInt64(*expr);
329 triplet->set_lower(std::move(*expr));
330 } else {
331 lower = ToInt64(lb[dim]);
332 }
333 if (auto expr{triplet->upper()}) {
334 *expr = Fold(std::move(*expr));
335 upper = ToInt64(*expr);
336 triplet->set_upper(std::move(*expr));
337 } else {
338 upper = ToInt64(ub[dim]);
339 }
340 if (stride) {
341 if (*stride == 0) {
342 Say("Stride of triplet must not be zero"_err_en_US);
343 return;
344 }
345 if (lower && upper) {
346 if (*stride > 0) {
347 anyPossiblyEmptyDim |= *lower > *upper;
348 } else {
349 anyPossiblyEmptyDim |= *lower < *upper;
350 }
351 } else {
352 anyPossiblyEmptyDim = true;
353 }
354 } else { // non-constant stride
355 if (lower && upper && *lower == *upper) {
356 // stride is not relevant
357 } else {
358 anyPossiblyEmptyDim = true;
359 }
360 }
361 } else { // not triplet
362 auto &expr{std::get<IndirectSubscriptIntegerExpr>(ss.u).value()};
363 expr = Fold(std::move(expr));
364 anyPossiblyEmptyDim |= expr.Rank() > 0; // vector subscript
365 }
366 ++dim;
367 }
368 if (anyPossiblyEmptyDim) {
369 return;
370 }
371 dim = 0;
372 for (Subscript &ss : ref.subscript()) {
373 auto dimLB{ToInt64(lb[dim])};
374 auto dimUB{ToInt64(ub[dim])};
375 std::optional<ConstantSubscript> val[2];
376 int vals{0};
377 if (auto *triplet{std::get_if<Triplet>(&ss.u)}) {
378 auto stride{ToInt64(triplet->stride())};
379 std::optional<ConstantSubscript> lower, upper;
380 if (const auto *lowerExpr{triplet->GetLower()}) {
381 lower = ToInt64(*lowerExpr);
382 } else if (lb[dim]) {
383 lower = ToInt64(*lb[dim]);
384 }
385 if (const auto *upperExpr{triplet->GetUpper()}) {
386 upper = ToInt64(*upperExpr);
387 } else if (ub[dim]) {
388 upper = ToInt64(*ub[dim]);
389 }
390 if (lower) {
391 val[vals++] = *lower;
392 if (upper && *upper != lower && (stride && *stride != 0)) {
393 // Normalize upper bound for non-unit stride
394 // 1:10:2 -> 1:9:2, 10:1:-2 -> 10:2:-2
395 val[vals++] = *lower + *stride * ((*upper - *lower) / *stride);
396 }
397 }
398 } else {
399 val[vals++] =
400 ToInt64(std::get<IndirectSubscriptIntegerExpr>(ss.u).value());
401 }
402 for (int j{0}; j < vals; ++j) {
403 if (val[j]) {
404 if (dimLB && *val[j] < *dimLB) {
405 AttachDeclaration(
406 Say("Subscript %jd is less than lower bound %jd for dimension %d of array"_err_en_US,
407 static_cast<std::intmax_t>(*val[j]),
408 static_cast<std::intmax_t>(*dimLB), dim + 1),
409 ref.base().GetLastSymbol());
410 }
411 if (dimUB && *val[j] > *dimUB) {
412 AttachDeclaration(
413 Say("Subscript %jd is greater than upper bound %jd for dimension %d of array"_err_en_US,
414 static_cast<std::intmax_t>(*val[j]),
415 static_cast<std::intmax_t>(*dimUB), dim + 1),
416 ref.base().GetLastSymbol());
417 }
418 }
419 }
420 ++dim;
421 }
422}
423
424// C919a - only one part-ref of a data-ref may have rank > 0
425bool ExpressionAnalyzer::CheckRanks(const DataRef &dataRef) {
426 return common::visit(
427 common::visitors{
428 [this](const Component &component) {
429 const Symbol &symbol{component.GetLastSymbol()};
430 if (int componentRank{symbol.Rank()}; componentRank > 0) {
431 if (int baseRank{component.base().Rank()}; baseRank > 0) {
432 Say("Reference to whole rank-%d component '%s' of rank-%d array of derived type is not allowed"_err_en_US,
433 componentRank, symbol.name(), baseRank);
434 return false;
435 }
436 } else {
437 return CheckRanks(component.base());
438 }
439 return true;
440 },
441 [this](const ArrayRef &arrayRef) {
442 if (const auto *component{arrayRef.base().UnwrapComponent()}) {
443 int subscriptRank{0};
444 for (const Subscript &subscript : arrayRef.subscript()) {
445 subscriptRank += subscript.Rank();
446 }
447 if (subscriptRank > 0) {
448 if (int componentBaseRank{component->base().Rank()};
449 componentBaseRank > 0) {
450 Say("Subscripts of component '%s' of rank-%d derived type array have rank %d but must all be scalar"_err_en_US,
451 component->GetLastSymbol().name(), componentBaseRank,
452 subscriptRank);
453 return false;
454 }
455 } else {
456 return CheckRanks(component->base());
457 }
458 }
459 return true;
460 },
461 [](const SymbolRef &) { return true; },
462 [](const CoarrayRef &) { return true; },
463 },
464 dataRef.u);
465}
466
467// C911 - if the last name in a data-ref has an abstract derived type,
468// it must also be polymorphic.
469bool ExpressionAnalyzer::CheckPolymorphic(const DataRef &dataRef) {
470 if (auto type{DynamicType::From(dataRef.GetLastSymbol())}) {
471 if (type->category() == TypeCategory::Derived && !type->IsPolymorphic()) {
472 const Symbol &typeSymbol{
473 type->GetDerivedTypeSpec().typeSymbol().GetUltimate()};
474 if (typeSymbol.attrs().test(semantics::Attr::ABSTRACT)) {
475 AttachDeclaration(
476 Say("Reference to object with abstract derived type '%s' must be polymorphic"_err_en_US,
477 typeSymbol.name()),
478 typeSymbol);
479 return false;
480 }
481 }
482 }
483 return true;
484}
485
486bool ExpressionAnalyzer::CheckDataRef(const DataRef &dataRef) {
487 // Always check both, don't short-circuit
488 bool ranksOk{CheckRanks(dataRef)};
489 bool polyOk{CheckPolymorphic(dataRef)};
490 return ranksOk && polyOk;
491}
492
493// Parse tree correction after a substring S(j:k) was misparsed as an
494// array section. Fortran substrings must have a range, not a
495// single index.
496static std::optional<parser::Substring> FixMisparsedSubstringDataRef(
497 parser::DataRef &dataRef) {
498 if (auto *ae{
499 std::get_if<common::Indirection<parser::ArrayElement>>(&dataRef.u)}) {
500 // ...%a(j:k) and "a" is a character scalar
501 parser::ArrayElement &arrElement{ae->value()};
502 if (arrElement.subscripts.size() == 1) {
503 if (auto *triplet{std::get_if<parser::SubscriptTriplet>(
504 &arrElement.subscripts.front().u)}) {
505 if (!std::get<2 /*stride*/>(triplet->t).has_value()) {
506 if (const Symbol *symbol{
507 parser::GetLastName(arrElement.base).symbol}) {
508 const Symbol &ultimate{symbol->GetUltimate()};
509 if (const semantics::DeclTypeSpec *type{ultimate.GetType()}) {
510 if (!ultimate.IsObjectArray() &&
511 type->category() == semantics::DeclTypeSpec::Character) {
512 // The ambiguous S(j:k) was parsed as an array section
513 // reference, but it's now clear that it's a substring.
514 // Fix the parse tree in situ.
515 return arrElement.ConvertToSubstring();
516 }
517 }
518 }
519 }
520 }
521 }
522 }
523 return std::nullopt;
524}
525
526// When a designator is a misparsed type-param-inquiry of a misparsed
527// substring -- it looks like a structure component reference of an array
528// slice -- fix the substring and then convert to an intrinsic function
529// call to KIND() or LEN(). And when the designator is a misparsed
530// substring, convert it into a substring reference in place.
531MaybeExpr ExpressionAnalyzer::FixMisparsedSubstring(
532 const parser::Designator &d) {
533 auto &mutate{const_cast<parser::Designator &>(d)};
534 if (auto *dataRef{std::get_if<parser::DataRef>(&mutate.u)}) {
535 if (auto *sc{std::get_if<common::Indirection<parser::StructureComponent>>(
536 &dataRef->u)}) {
537 parser::StructureComponent &structComponent{sc->value()};
538 parser::CharBlock which{structComponent.component.source};
539 if (which == "kind" || which == "len") {
540 if (auto substring{
541 FixMisparsedSubstringDataRef(structComponent.base)}) {
542 // ...%a(j:k)%kind or %len and "a" is a character scalar
543 mutate.u = std::move(*substring);
544 if (MaybeExpr substringExpr{Analyze(d)}) {
545 return MakeFunctionRef(which,
546 ActualArguments{ActualArgument{std::move(*substringExpr)}});
547 }
548 }
549 }
550 } else if (auto substring{FixMisparsedSubstringDataRef(*dataRef)}) {
551 mutate.u = std::move(*substring);
552 }
553 }
554 return std::nullopt;
555}
556
557MaybeExpr ExpressionAnalyzer::Analyze(const parser::Designator &d) {
558 auto restorer{GetContextualMessages().SetLocation(d.source)};
559 if (auto substringInquiry{FixMisparsedSubstring(d)}) {
560 return substringInquiry;
561 }
562 // These checks have to be deferred to these "top level" data-refs where
563 // we can be sure that there are no following subscripts (yet).
564 MaybeExpr result{Analyze(d.u)};
565 if (result) {
566 std::optional<DataRef> dataRef{ExtractDataRef(std::move(result))};
567 if (!dataRef) {
568 dataRef = ExtractDataRef(std::move(result), /*intoSubstring=*/true);
569 }
570 if (!dataRef) {
571 dataRef = ExtractDataRef(std::move(result),
572 /*intoSubstring=*/false, /*intoComplexPart=*/true);
573 }
574 if (dataRef && !CheckDataRef(*dataRef)) {
575 result.reset();
576 }
577 }
578 return result;
579}
580
581// A utility subroutine to repackage optional expressions of various levels
582// of type specificity as fully general MaybeExpr values.
583template <typename A> common::IfNoLvalue<MaybeExpr, A> AsMaybeExpr(A &&x) {
584 return AsGenericExpr(std::move(x));
585}
586template <typename A> MaybeExpr AsMaybeExpr(std::optional<A> &&x) {
587 if (x) {
588 return AsMaybeExpr(std::move(*x));
589 }
590 return std::nullopt;
591}
592
593// Type kind parameter values for literal constants.
594int ExpressionAnalyzer::AnalyzeKindParam(
595 const std::optional<parser::KindParam> &kindParam, int defaultKind) {
596 if (!kindParam) {
597 return defaultKind;
598 }
599 std::int64_t kind{common::visit(
600 common::visitors{
601 [](std::uint64_t k) { return static_cast<std::int64_t>(k); },
602 [&](const parser::Scalar<
603 parser::Integer<parser::Constant<parser::Name>>> &n) {
604 if (MaybeExpr ie{Analyze(n)}) {
605 return ToInt64(*ie).value_or(defaultKind);
606 }
607 return static_cast<std::int64_t>(defaultKind);
608 },
609 },
610 kindParam->u)};
611 if (kind != static_cast<int>(kind)) {
612 Say("Unsupported type kind value (%jd)"_err_en_US,
613 static_cast<std::intmax_t>(kind));
614 kind = defaultKind;
615 }
616 return static_cast<int>(kind);
617}
618
619// Common handling of parser::IntLiteralConstant and SignedIntLiteralConstant
620struct IntTypeVisitor {
621 using Result = MaybeExpr;
622 using Types = IntegerTypes;
623 template <typename T> Result Test() {
624 if (T::kind >= kind) {
625 const char *p{digits.begin()};
626 using Int = typename T::Scalar;
627 typename Int::ValueWithOverflow num{0, false};
628 if (isNegated) {
629 auto unsignedNum{Int::Read(p, 10, false /*unsigned*/)};
630 num.value = unsignedNum.value.Negate().value;
631 num.overflow = unsignedNum.overflow || num.value > Int{0};
632 if (!num.overflow && num.value.Negate().overflow &&
633 !analyzer.context().IsInModuleFile(digits)) {
634 analyzer.Say(digits,
635 "negated maximum INTEGER(KIND=%d) literal"_port_en_US, T::kind);
636 }
637 } else {
638 num = Int::Read(p, 10, true /*signed*/);
639 }
640 if (!num.overflow) {
641 if (T::kind > kind) {
642 if (!isDefaultKind ||
643 !analyzer.context().IsEnabled(LanguageFeature::BigIntLiterals)) {
644 return std::nullopt;
645 } else if (analyzer.context().ShouldWarn(
646 LanguageFeature::BigIntLiterals)) {
647 analyzer.Say(digits,
648 "Integer literal is too large for default INTEGER(KIND=%d); "
649 "assuming INTEGER(KIND=%d)"_port_en_US,
650 kind, T::kind);
651 }
652 }
653 return Expr<SomeType>{
654 Expr<SomeInteger>{Expr<T>{Constant<T>{std::move(num.value)}}}};
655 }
656 }
657 return std::nullopt;
658 }
659 ExpressionAnalyzer &analyzer;
660 parser::CharBlock digits;
661 std::int64_t kind;
662 bool isDefaultKind;
663 bool isNegated;
664};
665
666template <typename PARSED>
667MaybeExpr ExpressionAnalyzer::IntLiteralConstant(
668 const PARSED &x, bool isNegated) {
669 const auto &kindParam{std::get<std::optional<parser::KindParam>>(x.t)};
670 bool isDefaultKind{!kindParam};
671 int kind{AnalyzeKindParam(kindParam, GetDefaultKind(TypeCategory::Integer))};
672 if (CheckIntrinsicKind(TypeCategory::Integer, kind)) {
673 auto digits{std::get<parser::CharBlock>(x.t)};
674 if (MaybeExpr result{common::SearchTypes(
675 IntTypeVisitor{*this, digits, kind, isDefaultKind, isNegated})}) {
676 return result;
677 } else if (isDefaultKind) {
678 Say(digits,
679 "Integer literal is too large for any allowable "
680 "kind of INTEGER"_err_en_US);
681 } else {
682 Say(digits, "Integer literal is too large for INTEGER(KIND=%d)"_err_en_US,
683 kind);
684 }
685 }
686 return std::nullopt;
687}
688
689MaybeExpr ExpressionAnalyzer::Analyze(
690 const parser::IntLiteralConstant &x, bool isNegated) {
691 auto restorer{
692 GetContextualMessages().SetLocation(std::get<parser::CharBlock>(x.t))};
693 return IntLiteralConstant(x, isNegated);
694}
695
696MaybeExpr ExpressionAnalyzer::Analyze(
697 const parser::SignedIntLiteralConstant &x) {
698 auto restorer{GetContextualMessages().SetLocation(x.source)};
699 return IntLiteralConstant(x);
700}
701
702template <typename TYPE>
703Constant<TYPE> ReadRealLiteral(
704 parser::CharBlock source, FoldingContext &context) {
705 const char *p{source.begin()};
706 auto valWithFlags{
707 Scalar<TYPE>::Read(p, context.targetCharacteristics().roundingMode())};
708 CHECK(p == source.end())((p == source.end()) || (Fortran::common::die("CHECK(" "p == source.end()"
") failed" " at " "flang/lib/Semantics/expression.cpp" "(%d)"
, 708), false))
;
709 RealFlagWarnings(context, valWithFlags.flags, "conversion of REAL literal");
710 auto value{valWithFlags.value};
711 if (context.targetCharacteristics().areSubnormalsFlushedToZero()) {
712 value = value.FlushSubnormalToZero();
713 }
714 return {value};
715}
716
717struct RealTypeVisitor {
718 using Result = std::optional<Expr<SomeReal>>;
719 using Types = RealTypes;
720
721 RealTypeVisitor(int k, parser::CharBlock lit, FoldingContext &ctx)
722 : kind{k}, literal{lit}, context{ctx} {}
723
724 template <typename T> Result Test() {
725 if (kind == T::kind) {
726 return {AsCategoryExpr(ReadRealLiteral<T>(literal, context))};
727 }
728 return std::nullopt;
729 }
730
731 int kind;
732 parser::CharBlock literal;
733 FoldingContext &context;
734};
735
736// Reads a real literal constant and encodes it with the right kind.
737MaybeExpr ExpressionAnalyzer::Analyze(const parser::RealLiteralConstant &x) {
738 // Use a local message context around the real literal for better
739 // provenance on any messages.
740 auto restorer{GetContextualMessages().SetLocation(x.real.source)};
741 // If a kind parameter appears, it defines the kind of the literal and the
742 // letter used in an exponent part must be 'E' (e.g., the 'E' in
743 // "6.02214E+23"). In the absence of an explicit kind parameter, any
744 // exponent letter determines the kind. Otherwise, defaults apply.
745 auto &defaults{context_.defaultKinds()};
746 int defaultKind{defaults.GetDefaultKind(TypeCategory::Real)};
747 const char *end{x.real.source.end()};
748 char expoLetter{' '};
749 std::optional<int> letterKind;
750 for (const char *p{x.real.source.begin()}; p < end; ++p) {
751 if (parser::IsLetter(*p)) {
752 expoLetter = *p;
753 switch (expoLetter) {
754 case 'e':
755 letterKind = defaults.GetDefaultKind(TypeCategory::Real);
756 break;
757 case 'd':
758 letterKind = defaults.doublePrecisionKind();
759 break;
760 case 'q':
761 letterKind = defaults.quadPrecisionKind();
762 break;
763 default:
764 Say("Unknown exponent letter '%c'"_err_en_US, expoLetter);
765 }
766 break;
767 }
768 }
769 if (letterKind) {
770 defaultKind = *letterKind;
771 }
772 // C716 requires 'E' as an exponent.
773 // Extension: allow exponent-letter matching the kind-param.
774 auto kind{AnalyzeKindParam(x.kind, defaultKind)};
775 if (letterKind && expoLetter != 'e') {
776 if (kind != *letterKind) {
777 Say("Explicit kind parameter on real constant disagrees with "
778 "exponent letter '%c'"_warn_en_US,
779 expoLetter);
780 } else if (x.kind &&
781 context_.ShouldWarn(
782 common::LanguageFeature::ExponentMatchingKindParam)) {
783 Say("Explicit kind parameter together with non-'E' exponent letter "
784 "is not standard"_port_en_US);
785 }
786 }
787 auto result{common::SearchTypes(
788 RealTypeVisitor{kind, x.real.source, GetFoldingContext()})};
789 if (!result) { // C717
790 Say("Unsupported REAL(KIND=%d)"_err_en_US, kind);
791 }
792 return AsMaybeExpr(std::move(result));
793}
794
795MaybeExpr ExpressionAnalyzer::Analyze(
796 const parser::SignedRealLiteralConstant &x) {
797 if (auto result{Analyze(std::get<parser::RealLiteralConstant>(x.t))}) {
798 auto &realExpr{std::get<Expr<SomeReal>>(result->u)};
799 if (auto sign{std::get<std::optional<parser::Sign>>(x.t)}) {
800 if (sign == parser::Sign::Negative) {
801 return AsGenericExpr(-std::move(realExpr));
802 }
803 }
804 return result;
805 }
806 return std::nullopt;
807}
808
809MaybeExpr ExpressionAnalyzer::Analyze(
810 const parser::SignedComplexLiteralConstant &x) {
811 auto result{Analyze(std::get<parser::ComplexLiteralConstant>(x.t))};
812 if (!result) {
813 return std::nullopt;
814 } else if (std::get<parser::Sign>(x.t) == parser::Sign::Negative) {
815 return AsGenericExpr(-std::move(std::get<Expr<SomeComplex>>(result->u)));
816 } else {
817 return result;
818 }
819}
820
821MaybeExpr ExpressionAnalyzer::Analyze(const parser::ComplexPart &x) {
822 return Analyze(x.u);
823}
824
825MaybeExpr ExpressionAnalyzer::Analyze(const parser::ComplexLiteralConstant &z) {
826 return AnalyzeComplex(Analyze(std::get<0>(z.t)), Analyze(std::get<1>(z.t)),
827 "complex literal constant");
828}
829
830// CHARACTER literal processing.
831MaybeExpr ExpressionAnalyzer::AnalyzeString(std::string &&string, int kind) {
832 if (!CheckIntrinsicKind(TypeCategory::Character, kind)) {
833 return std::nullopt;
834 }
835 switch (kind) {
836 case 1:
837 return AsGenericExpr(Constant<Type<TypeCategory::Character, 1>>{
838 parser::DecodeString<std::string, parser::Encoding::LATIN_1>(
839 string, true)});
840 case 2:
841 return AsGenericExpr(Constant<Type<TypeCategory::Character, 2>>{
842 parser::DecodeString<std::u16string, parser::Encoding::UTF_8>(
843 string, true)});
844 case 4:
845 return AsGenericExpr(Constant<Type<TypeCategory::Character, 4>>{
846 parser::DecodeString<std::u32string, parser::Encoding::UTF_8>(
847 string, true)});
848 default:
849 CRASH_NO_CASEFortran::common::die("no case" " at " "flang/lib/Semantics/expression.cpp"
"(%d)", 849)
;
850 }
851}
852
853MaybeExpr ExpressionAnalyzer::Analyze(const parser::CharLiteralConstant &x) {
854 int kind{
855 AnalyzeKindParam(std::get<std::optional<parser::KindParam>>(x.t), 1)};
856 auto value{std::get<std::string>(x.t)};
857 return AnalyzeString(std::move(value), kind);
858}
859
860MaybeExpr ExpressionAnalyzer::Analyze(
861 const parser::HollerithLiteralConstant &x) {
862 int kind{GetDefaultKind(TypeCategory::Character)};
863 auto value{x.v};
864 return AnalyzeString(std::move(value), kind);
865}
866
867// .TRUE. and .FALSE. of various kinds
868MaybeExpr ExpressionAnalyzer::Analyze(const parser::LogicalLiteralConstant &x) {
869 auto kind{AnalyzeKindParam(std::get<std::optional<parser::KindParam>>(x.t),
870 GetDefaultKind(TypeCategory::Logical))};
871 bool value{std::get<bool>(x.t)};
872 auto result{common::SearchTypes(
873 TypeKindVisitor<TypeCategory::Logical, Constant, bool>{
874 kind, std::move(value)})};
875 if (!result) {
876 Say("unsupported LOGICAL(KIND=%d)"_err_en_US, kind); // C728
877 }
878 return result;
879}
880
881// BOZ typeless literals
882MaybeExpr ExpressionAnalyzer::Analyze(const parser::BOZLiteralConstant &x) {
883 const char *p{x.v.c_str()};
884 std::uint64_t base{16};
885 switch (*p++) {
886 case 'b':
887 base = 2;
888 break;
889 case 'o':
890 base = 8;
891 break;
892 case 'z':
893 break;
894 case 'x':
895 break;
896 default:
897 CRASH_NO_CASEFortran::common::die("no case" " at " "flang/lib/Semantics/expression.cpp"
"(%d)", 897)
;
898 }
899 CHECK(*p == '"')((*p == '"') || (Fortran::common::die("CHECK(" "*p == '\"'" ") failed"
" at " "flang/lib/Semantics/expression.cpp" "(%d)", 899), false
))
;
900 ++p;
901 auto value{BOZLiteralConstant::Read(p, base, false /*unsigned*/)};
902 if (*p != '"') {
903 Say("Invalid digit ('%c') in BOZ literal '%s'"_err_en_US, *p,
904 x.v); // C7107, C7108
905 return std::nullopt;
906 }
907 if (value.overflow) {
908 Say("BOZ literal '%s' too large"_err_en_US, x.v);
909 return std::nullopt;
910 }
911 return AsGenericExpr(std::move(value.value));
912}
913
914// Names and named constants
915MaybeExpr ExpressionAnalyzer::Analyze(const parser::Name &n) {
916 auto restorer{GetContextualMessages().SetLocation(n.source)};
917 if (std::optional<int> kind{IsImpliedDo(n.source)}) {
918 return AsMaybeExpr(ConvertToKind<TypeCategory::Integer>(
919 *kind, AsExpr(ImpliedDoIndex{n.source})));
920 }
921 if (context_.HasError(n.symbol)) { // includes case of no symbol
922 return std::nullopt;
923 } else {
924 const Symbol &ultimate{n.symbol->GetUltimate()};
925 if (ultimate.has<semantics::TypeParamDetails>()) {
926 // A bare reference to a derived type parameter (within a parameterized
927 // derived type definition)
928 return Fold(ConvertToType(
929 ultimate, AsGenericExpr(TypeParamInquiry{std::nullopt, ultimate})));
930 } else {
931 if (n.symbol->attrs().test(semantics::Attr::VOLATILE)) {
932 if (const semantics::Scope *pure{semantics::FindPureProcedureContaining(
933 context_.FindScope(n.source))}) {
934 SayAt(n,
935 "VOLATILE variable '%s' may not be referenced in pure subprogram '%s'"_err_en_US,
936 n.source, DEREF(pure->symbol())Fortran::common::Deref(pure->symbol(), "flang/lib/Semantics/expression.cpp"
, 936)
.name());
937 n.symbol->attrs().reset(semantics::Attr::VOLATILE);
938 }
939 }
940 if (!isWholeAssumedSizeArrayOk_ &&
941 semantics::IsAssumedSizeArray(*n.symbol)) { // C1002, C1014, C1231
942 AttachDeclaration(
943 SayAt(n,
944 "Whole assumed-size array '%s' may not appear here without subscripts"_err_en_US,
945 n.source),
946 *n.symbol);
947 }
948 return Designate(DataRef{*n.symbol});
949 }
950 }
951}
952
953MaybeExpr ExpressionAnalyzer::Analyze(const parser::NamedConstant &n) {
954 auto restorer{GetContextualMessages().SetLocation(n.v.source)};
955 if (MaybeExpr value{Analyze(n.v)}) {
956 Expr<SomeType> folded{Fold(std::move(*value))};
957 if (IsConstantExpr(folded)) {
958 return folded;
959 }
960 Say(n.v.source, "must be a constant"_err_en_US); // C718
961 }
962 return std::nullopt;
963}
964
965MaybeExpr ExpressionAnalyzer::Analyze(const parser::NullInit &n) {
966 auto restorer{AllowNullPointer()};
967 if (MaybeExpr value{Analyze(n.v.value())}) {
968 // Subtle: when the NullInit is a DataStmtConstant, it might
969 // be a misparse of a structure constructor without parameters
970 // or components (e.g., T()). Checking the result to ensure
971 // that a "=>" data entity initializer actually resolved to
972 // a null pointer has to be done by the caller.
973 return Fold(std::move(*value));
974 }
975 return std::nullopt;
976}
977
978MaybeExpr ExpressionAnalyzer::Analyze(
979 const parser::StmtFunctionStmt &stmtFunc) {
980 inStmtFunctionDefinition_ = true;
981 return Analyze(std::get<parser::Scalar<parser::Expr>>(stmtFunc.t));
982}
983
984MaybeExpr ExpressionAnalyzer::Analyze(const parser::InitialDataTarget &x) {
985 return Analyze(x.value());
986}
987
988MaybeExpr ExpressionAnalyzer::Analyze(const parser::DataStmtValue &x) {
989 if (const auto &repeat{
990 std::get<std::optional<parser::DataStmtRepeat>>(x.t)}) {
991 x.repetitions = -1;
992 if (MaybeExpr expr{Analyze(repeat->u)}) {
993 Expr<SomeType> folded{Fold(std::move(*expr))};
994 if (auto value{ToInt64(folded)}) {
995 if (*value >= 0) { // C882
996 x.repetitions = *value;
997 } else {
998 Say(FindSourceLocation(repeat),
999 "Repeat count (%jd) for data value must not be negative"_err_en_US,
1000 *value);
1001 }
1002 }
1003 }
1004 }
1005 return Analyze(std::get<parser::DataStmtConstant>(x.t));
1006}
1007
1008// Substring references
1009std::optional<Expr<SubscriptInteger>> ExpressionAnalyzer::GetSubstringBound(
1010 const std::optional<parser::ScalarIntExpr> &bound) {
1011 if (bound) {
1012 if (MaybeExpr expr{Analyze(*bound)}) {
1013 if (expr->Rank() > 1) {
1014 Say("substring bound expression has rank %d"_err_en_US, expr->Rank());
1015 }
1016 if (auto *intExpr{std::get_if<Expr<SomeInteger>>(&expr->u)}) {
1017 if (auto *ssIntExpr{std::get_if<Expr<SubscriptInteger>>(&intExpr->u)}) {
1018 return {std::move(*ssIntExpr)};
1019 }
1020 return {Expr<SubscriptInteger>{
1021 Convert<SubscriptInteger, TypeCategory::Integer>{
1022 std::move(*intExpr)}}};
1023 } else {
1024 Say("substring bound expression is not INTEGER"_err_en_US);
1025 }
1026 }
1027 }
1028 return std::nullopt;
1029}
1030
1031MaybeExpr ExpressionAnalyzer::Analyze(const parser::Substring &ss) {
1032 if (MaybeExpr baseExpr{Analyze(std::get<parser::DataRef>(ss.t))}) {
1033 if (std::optional<DataRef> dataRef{ExtractDataRef(std::move(*baseExpr))}) {
1034 if (MaybeExpr newBaseExpr{Designate(std::move(*dataRef))}) {
1035 if (std::optional<DataRef> checked{
1036 ExtractDataRef(std::move(*newBaseExpr))}) {
1037 const parser::SubstringRange &range{
1038 std::get<parser::SubstringRange>(ss.t)};
1039 std::optional<Expr<SubscriptInteger>> first{
1040 GetSubstringBound(std::get<0>(range.t))};
1041 std::optional<Expr<SubscriptInteger>> last{
1042 GetSubstringBound(std::get<1>(range.t))};
1043 const Symbol &symbol{checked->GetLastSymbol()};
1044 if (std::optional<DynamicType> dynamicType{
1045 DynamicType::From(symbol)}) {
1046 if (dynamicType->category() == TypeCategory::Character) {
1047 return WrapperHelper<TypeCategory::Character, Designator,
1048 Substring>(dynamicType->kind(),
1049 Substring{std::move(checked.value()), std::move(first),
1050 std::move(last)});
1051 }
1052 }
1053 Say("substring may apply only to CHARACTER"_err_en_US);
1054 }
1055 }
1056 }
1057 }
1058 return std::nullopt;
1059}
1060
1061// CHARACTER literal substrings
1062MaybeExpr ExpressionAnalyzer::Analyze(
1063 const parser::CharLiteralConstantSubstring &x) {
1064 const parser::SubstringRange &range{std::get<parser::SubstringRange>(x.t)};
1065 std::optional<Expr<SubscriptInteger>> lower{
1066 GetSubstringBound(std::get<0>(range.t))};
1067 std::optional<Expr<SubscriptInteger>> upper{
1068 GetSubstringBound(std::get<1>(range.t))};
1069 if (MaybeExpr string{Analyze(std::get<parser::CharLiteralConstant>(x.t))}) {
1070 if (auto *charExpr{std::get_if<Expr<SomeCharacter>>(&string->u)}) {
1071 Expr<SubscriptInteger> length{
1072 common::visit([](const auto &ckExpr) { return ckExpr.LEN().value(); },
1073 charExpr->u)};
1074 if (!lower) {
1075 lower = Expr<SubscriptInteger>{1};
1076 }
1077 if (!upper) {
1078 upper = Expr<SubscriptInteger>{
1079 static_cast<std::int64_t>(ToInt64(length).value())};
1080 }
1081 return common::visit(
1082 [&](auto &&ckExpr) -> MaybeExpr {
1083 using Result = ResultType<decltype(ckExpr)>;
1084 auto *cp{std::get_if<Constant<Result>>(&ckExpr.u)};
1085 CHECK(DEREF(cp).size() == 1)((Fortran::common::Deref(cp, "flang/lib/Semantics/expression.cpp"
, 1085).size() == 1) || (Fortran::common::die("CHECK(" "DEREF(cp).size() == 1"
") failed" " at " "flang/lib/Semantics/expression.cpp" "(%d)"
, 1085), false))
;
1086 StaticDataObject::Pointer staticData{StaticDataObject::Create()};
1087 staticData->set_alignment(Result::kind)
1088 .set_itemBytes(Result::kind)
1089 .Push(cp->GetScalarValue().value(),
1090 foldingContext_.targetCharacteristics().isBigEndian());
1091 Substring substring{std::move(staticData), std::move(lower.value()),
1092 std::move(upper.value())};
1093 return AsGenericExpr(
1094 Expr<Result>{Designator<Result>{std::move(substring)}});
1095 },
1096 std::move(charExpr->u));
1097 }
1098 }
1099 return std::nullopt;
1100}
1101
1102// substring%KIND/LEN
1103MaybeExpr ExpressionAnalyzer::Analyze(const parser::SubstringInquiry &x) {
1104 if (MaybeExpr substring{Analyze(x.v)}) {
1105 CHECK(x.source.size() >= 8)((x.source.size() >= 8) || (Fortran::common::die("CHECK(" "x.source.size() >= 8"
") failed" " at " "flang/lib/Semantics/expression.cpp" "(%d)"
, 1105), false))
;
1106 int nameLen{x.source.end()[-1] == 'n' ? 3 /*LEN*/ : 4 /*KIND*/};
1107 parser::CharBlock name{
1108 x.source.end() - nameLen, static_cast<std::size_t>(nameLen)};
1109 CHECK(name == "len" || name == "kind")((name == "len" || name == "kind") || (Fortran::common::die("CHECK("
"name == \"len\" || name == \"kind\"" ") failed" " at " "flang/lib/Semantics/expression.cpp"
"(%d)", 1109), false))
;
1110 return MakeFunctionRef(
1111 name, ActualArguments{ActualArgument{std::move(*substring)}});
1112 } else {
1113 return std::nullopt;
1114 }
1115}
1116
1117// Subscripted array references
1118std::optional<Expr<SubscriptInteger>> ExpressionAnalyzer::AsSubscript(
1119 MaybeExpr &&expr) {
1120 if (expr) {
1121 if (expr->Rank() > 1) {
1122 Say("Subscript expression has rank %d greater than 1"_err_en_US,
1123 expr->Rank());
1124 }
1125 if (auto *intExpr{std::get_if<Expr<SomeInteger>>(&expr->u)}) {
1126 if (auto *ssIntExpr{std::get_if<Expr<SubscriptInteger>>(&intExpr->u)}) {
1127 return std::move(*ssIntExpr);
1128 } else {
1129 return Expr<SubscriptInteger>{
1130 Convert<SubscriptInteger, TypeCategory::Integer>{
1131 std::move(*intExpr)}};
1132 }
1133 } else {
1134 Say("Subscript expression is not INTEGER"_err_en_US);
1135 }
1136 }
1137 return std::nullopt;
1138}
1139
1140std::optional<Expr<SubscriptInteger>> ExpressionAnalyzer::TripletPart(
1141 const std::optional<parser::Subscript> &s) {
1142 if (s) {
1143 return AsSubscript(Analyze(*s));
1144 } else {
1145 return std::nullopt;
1146 }
1147}
1148
1149std::optional<Subscript> ExpressionAnalyzer::AnalyzeSectionSubscript(
1150 const parser::SectionSubscript &ss) {
1151 return common::visit(
1152 common::visitors{
1153 [&](const parser::SubscriptTriplet &t) -> std::optional<Subscript> {
1154 const auto &lower{std::get<0>(t.t)};
1155 const auto &upper{std::get<1>(t.t)};
1156 const auto &stride{std::get<2>(t.t)};
1157 auto result{Triplet{
1158 TripletPart(lower), TripletPart(upper), TripletPart(stride)}};
1159 if ((lower && !result.lower()) || (upper && !result.upper())) {
1160 return std::nullopt;
1161 } else {
1162 return std::make_optional<Subscript>(result);
1163 }
1164 },
1165 [&](const auto &s) -> std::optional<Subscript> {
1166 if (auto subscriptExpr{AsSubscript(Analyze(s))}) {
1167 return Subscript{std::move(*subscriptExpr)};
1168 } else {
1169 return std::nullopt;
1170 }
1171 },
1172 },
1173 ss.u);
1174}
1175
1176// Empty result means an error occurred
1177std::vector<Subscript> ExpressionAnalyzer::AnalyzeSectionSubscripts(
1178 const std::list<parser::SectionSubscript> &sss) {
1179 bool error{false};
1180 std::vector<Subscript> subscripts;
1181 for (const auto &s : sss) {
1182 if (auto subscript{AnalyzeSectionSubscript(s)}) {
1183 subscripts.emplace_back(std::move(*subscript));
1184 } else {
1185 error = true;
1186 }
1187 }
1188 return !error ? subscripts : std::vector<Subscript>{};
1189}
1190
1191MaybeExpr ExpressionAnalyzer::Analyze(const parser::ArrayElement &ae) {
1192 MaybeExpr baseExpr;
1193 {
1194 auto restorer{AllowWholeAssumedSizeArray()};
1195 baseExpr = Analyze(ae.base);
1196 }
1197 if (baseExpr) {
1198 if (ae.subscripts.empty()) {
1199 // will be converted to function call later or error reported
1200 } else if (baseExpr->Rank() == 0) {
1201 if (const Symbol *symbol{GetLastSymbol(*baseExpr)}) {
1202 if (!context_.HasError(symbol)) {
1203 if (inDataStmtConstant_) {
1204 // Better error for NULL(X) with a MOLD= argument
1205 Say("'%s' must be an array or structure constructor if used with non-empty parentheses as a DATA statement constant"_err_en_US,
1206 symbol->name());
1207 } else {
1208 Say("'%s' is not an array"_err_en_US, symbol->name());
1209 }
1210 context_.SetError(*symbol);
1211 }
1212 }
1213 } else if (std::optional<DataRef> dataRef{
1214 ExtractDataRef(std::move(*baseExpr))}) {
1215 return ApplySubscripts(
1216 std::move(*dataRef), AnalyzeSectionSubscripts(ae.subscripts));
1217 } else {
1218 Say("Subscripts may be applied only to an object, component, or array constant"_err_en_US);
1219 }
1220 }
1221 // error was reported: analyze subscripts without reporting more errors
1222 auto restorer{GetContextualMessages().DiscardMessages()};
1223 AnalyzeSectionSubscripts(ae.subscripts);
1224 return std::nullopt;
1225}
1226
1227// Type parameter inquiries apply to data references, but don't depend
1228// on any trailing (co)subscripts.
1229static NamedEntity IgnoreAnySubscripts(Designator<SomeDerived> &&designator) {
1230 return common::visit(
1231 common::visitors{
1232 [](SymbolRef &&symbol) { return NamedEntity{symbol}; },
1233 [](Component &&component) {
1234 return NamedEntity{std::move(component)};
1235 },
1236 [](ArrayRef &&arrayRef) { return std::move(arrayRef.base()); },
1237 [](CoarrayRef &&coarrayRef) {
1238 return NamedEntity{coarrayRef.GetLastSymbol()};
1239 },
1240 },
1241 std::move(designator.u));
1242}
1243
1244// Components of parent derived types are explicitly represented as such.
1245std::optional<Component> ExpressionAnalyzer::CreateComponent(
1246 DataRef &&base, const Symbol &component, const semantics::Scope &scope) {
1247 if (IsAllocatableOrPointer(component) && base.Rank() > 0) { // C919b
1248 Say("An allocatable or pointer component reference must be applied to a scalar base"_err_en_US);
1249 }
1250 if (&component.owner() == &scope) {
1251 return Component{std::move(base), component};
1252 }
1253 if (const Symbol *typeSymbol{scope.GetSymbol()}) {
1254 if (const Symbol *parentComponent{typeSymbol->GetParentComponent(&scope)}) {
1255 if (const auto *object{
1256 parentComponent->detailsIf<semantics::ObjectEntityDetails>()}) {
1257 if (const auto *parentType{object->type()}) {
1258 if (const semantics::Scope *parentScope{
1259 parentType->derivedTypeSpec().scope()}) {
1260 return CreateComponent(
1261 DataRef{Component{std::move(base), *parentComponent}},
1262 component, *parentScope);
1263 }
1264 }
1265 }
1266 }
1267 }
1268 return std::nullopt;
1269}
1270
1271// Derived type component references and type parameter inquiries
1272MaybeExpr ExpressionAnalyzer::Analyze(const parser::StructureComponent &sc) {
1273 MaybeExpr base{Analyze(sc.base)};
1274 Symbol *sym{sc.component.symbol};
1275 if (!base || !sym || context_.HasError(sym)) {
1276 return std::nullopt;
1277 }
1278 const auto &name{sc.component.source};
1279 if (auto *dtExpr{UnwrapExpr<Expr<SomeDerived>>(*base)}) {
1280 const auto *dtSpec{GetDerivedTypeSpec(dtExpr->GetType())};
1281 if (sym->detailsIf<semantics::TypeParamDetails>()) {
1282 if (auto *designator{UnwrapExpr<Designator<SomeDerived>>(*dtExpr)}) {
1283 if (std::optional<DynamicType> dyType{DynamicType::From(*sym)}) {
1284 if (dyType->category() == TypeCategory::Integer) {
1285 auto restorer{GetContextualMessages().SetLocation(name)};
1286 return Fold(ConvertToType(*dyType,
1287 AsGenericExpr(TypeParamInquiry{
1288 IgnoreAnySubscripts(std::move(*designator)), *sym})));
1289 }
1290 }
1291 Say(name, "Type parameter is not INTEGER"_err_en_US);
1292 } else {
1293 Say(name,
1294 "A type parameter inquiry must be applied to "
1295 "a designator"_err_en_US);
1296 }
1297 } else if (!dtSpec || !dtSpec->scope()) {
1298 CHECK(context_.AnyFatalError() || !foldingContext_.messages().empty())((context_.AnyFatalError() || !foldingContext_.messages().empty
()) || (Fortran::common::die("CHECK(" "context_.AnyFatalError() || !foldingContext_.messages().empty()"
") failed" " at " "flang/lib/Semantics/expression.cpp" "(%d)"
, 1298), false))
;
1299 return std::nullopt;
1300 } else if (std::optional<DataRef> dataRef{
1301 ExtractDataRef(std::move(*dtExpr))}) {
1302 auto restorer{GetContextualMessages().SetLocation(name)};
1303 if (auto component{
1304 CreateComponent(std::move(*dataRef), *sym, *dtSpec->scope())}) {
1305 return Designate(DataRef{std::move(*component)});
1306 } else {
1307 Say(name, "Component is not in scope of derived TYPE(%s)"_err_en_US,
1308 dtSpec->typeSymbol().name());
1309 }
1310 } else {
1311 Say(name,
1312 "Base of component reference must be a data reference"_err_en_US);
1313 }
1314 } else if (auto *details{sym->detailsIf<semantics::MiscDetails>()}) {
1315 // special part-ref: %re, %im, %kind, %len
1316 // Type errors on the base of %re/%im/%len are detected and
1317 // reported in name resolution.
1318 using MiscKind = semantics::MiscDetails::Kind;
1319 MiscKind kind{details->kind()};
1320 if (kind == MiscKind::ComplexPartRe || kind == MiscKind::ComplexPartIm) {
1321 if (auto *zExpr{std::get_if<Expr<SomeComplex>>(&base->u)}) {
1322 if (std::optional<DataRef> dataRef{ExtractDataRef(*zExpr)}) {
1323 // Represent %RE/%IM as a designator
1324 Expr<SomeReal> realExpr{common::visit(
1325 [&](const auto &z) {
1326 using PartType = typename ResultType<decltype(z)>::Part;
1327 auto part{kind == MiscKind::ComplexPartRe
1328 ? ComplexPart::Part::RE
1329 : ComplexPart::Part::IM};
1330 return AsCategoryExpr(Designator<PartType>{
1331 ComplexPart{std::move(*dataRef), part}});
1332 },
1333 zExpr->u)};
1334 return AsGenericExpr(std::move(realExpr));
1335 }
1336 }
1337 } else if (kind == MiscKind::KindParamInquiry ||
1338 kind == MiscKind::LenParamInquiry) {
1339 ActualArgument arg{std::move(*base)};
1340 SetArgSourceLocation(arg, name);
1341 return MakeFunctionRef(name, ActualArguments{std::move(arg)});
1342 } else {
1343 DIE("unexpected MiscDetails::Kind")Fortran::common::die("unexpected MiscDetails::Kind" " at " "flang/lib/Semantics/expression.cpp"
"(%d)", 1343)
;
1344 }
1345 } else {
1346 Say(name, "derived type required before component reference"_err_en_US);
1347 }
1348 return std::nullopt;
1349}
1350
1351MaybeExpr ExpressionAnalyzer::Analyze(const parser::CoindexedNamedObject &x) {
1352 if (auto maybeDataRef{ExtractDataRef(Analyze(x.base))}) {
1353 DataRef *dataRef{&*maybeDataRef};
1354 std::vector<Subscript> subscripts;
1355 SymbolVector reversed;
1356 if (auto *aRef{std::get_if<ArrayRef>(&dataRef->u)}) {
1357 subscripts = std::move(aRef->subscript());
1358 reversed.push_back(aRef->GetLastSymbol());
1359 if (Component *component{aRef->base().UnwrapComponent()}) {
1360 dataRef = &component->base();
1361 } else {
1362 dataRef = nullptr;
1363 }
1364 }
1365 if (dataRef) {
1366 while (auto *component{std::get_if<Component>(&dataRef->u)}) {
1367 reversed.push_back(component->GetLastSymbol());
1368 dataRef = &component->base();
1369 }
1370 if (auto *baseSym{std::get_if<SymbolRef>(&dataRef->u)}) {
1371 reversed.push_back(*baseSym);
1372 } else {
1373 Say("Base of coindexed named object has subscripts or cosubscripts"_err_en_US);
1374 }
1375 }
1376 std::vector<Expr<SubscriptInteger>> cosubscripts;
1377 bool cosubsOk{true};
1378 for (const auto &cosub :
1379 std::get<std::list<parser::Cosubscript>>(x.imageSelector.t)) {
1380 MaybeExpr coex{Analyze(cosub)};
1381 if (auto *intExpr{UnwrapExpr<Expr<SomeInteger>>(coex)}) {
1382 cosubscripts.push_back(
1383 ConvertToType<SubscriptInteger>(std::move(*intExpr)));
1384 } else {
1385 cosubsOk = false;
1386 }
1387 }
1388 if (cosubsOk && !reversed.empty()) {
1389 int numCosubscripts{static_cast<int>(cosubscripts.size())};
1390 const Symbol &symbol{reversed.front()};
1391 if (numCosubscripts != symbol.Corank()) {
1392 Say("'%s' has corank %d, but coindexed reference has %d cosubscripts"_err_en_US,
1393 symbol.name(), symbol.Corank(), numCosubscripts);
1394 }
1395 }
1396 for (const auto &imageSelSpec :
1397 std::get<std::list<parser::ImageSelectorSpec>>(x.imageSelector.t)) {
1398 common::visit(
1399 common::visitors{
1400 [&](const auto &x) { Analyze(x.v); },
1401 },
1402 imageSelSpec.u);
1403 }
1404 // Reverse the chain of symbols so that the base is first and coarray
1405 // ultimate component is last.
1406 if (cosubsOk) {
1407 return Designate(
1408 DataRef{CoarrayRef{SymbolVector{reversed.crbegin(), reversed.crend()},
1409 std::move(subscripts), std::move(cosubscripts)}});
1410 }
1411 }
1412 return std::nullopt;
1413}
1414
1415int ExpressionAnalyzer::IntegerTypeSpecKind(
1416 const parser::IntegerTypeSpec &spec) {
1417 Expr<SubscriptInteger> value{
1418 AnalyzeKindSelector(TypeCategory::Integer, spec.v)};
1419 if (auto kind{ToInt64(value)}) {
1420 return static_cast<int>(*kind);
1421 }
1422 SayAt(spec, "Constant INTEGER kind value required here"_err_en_US);
1423 return GetDefaultKind(TypeCategory::Integer);
1424}
1425
1426// Array constructors
1427
1428// Inverts a collection of generic ArrayConstructorValues<SomeType> that
1429// all happen to have the same actual type T into one ArrayConstructor<T>.
1430template <typename T>
1431ArrayConstructorValues<T> MakeSpecific(
1432 ArrayConstructorValues<SomeType> &&from) {
1433 ArrayConstructorValues<T> to;
1434 for (ArrayConstructorValue<SomeType> &x : from) {
1435 common::visit(
1436 common::visitors{
1437 [&](common::CopyableIndirection<Expr<SomeType>> &&expr) {
1438 auto *typed{UnwrapExpr<Expr<T>>(expr.value())};
1439 to.Push(std::move(DEREF(typed)Fortran::common::Deref(typed, "flang/lib/Semantics/expression.cpp"
, 1439)
));
1440 },
1441 [&](ImpliedDo<SomeType> &&impliedDo) {
1442 to.Push(ImpliedDo<T>{impliedDo.name(),
1443 std::move(impliedDo.lower()), std::move(impliedDo.upper()),
1444 std::move(impliedDo.stride()),
1445 MakeSpecific<T>(std::move(impliedDo.values()))});
1446 },
1447 },
1448 std::move(x.u));
1449 }
1450 return to;
1451}
1452
1453class ArrayConstructorContext {
1454public:
1455 ArrayConstructorContext(
1456 ExpressionAnalyzer &c, std::optional<DynamicTypeWithLength> &&t)
1457 : exprAnalyzer_{c}, type_{std::move(t)} {}
1458
1459 void Add(const parser::AcValue &);
1460 MaybeExpr ToExpr();
1461
1462 // These interfaces allow *this to be used as a type visitor argument to
1463 // common::SearchTypes() to convert the array constructor to a typed
1464 // expression in ToExpr().
1465 using Result = MaybeExpr;
1466 using Types = AllTypes;
1467 template <typename T> Result Test() {
1468 if (type_ && type_->category() == T::category) {
1469 if constexpr (T::category == TypeCategory::Derived) {
1470 if (!type_->IsUnlimitedPolymorphic()) {
1471 return AsMaybeExpr(ArrayConstructor<T>{type_->GetDerivedTypeSpec(),
1472 MakeSpecific<T>(std::move(values_))});
1473 }
1474 } else if (type_->kind() == T::kind) {
1475 ArrayConstructor<T> result{MakeSpecific<T>(std::move(values_))};
1476 if constexpr (T::category == TypeCategory::Character) {
1477 if (auto len{type_->LEN()}) {
1478 // The ac-do-variables may be treated as constant expressions,
1479 // if some conditions on ac-implied-do-control hold (10.1.12 (12)).
1480 // At the same time, they may be treated as constant expressions
1481 // only in the context of the ac-implied-do, but setting
1482 // the character length here may result in complete elimination
1483 // of the ac-implied-do. For example:
1484 // character(10) :: c
1485 // ... len([(c(i:i), integer(8)::i = 1,4)])
1486 // would be evaulated into:
1487 // ... int(max(0_8,i-i+1_8),kind=4)
1488 // with a dangling reference to the ac-do-variable.
1489 // Prevent this by checking for the ac-do-variable references
1490 // in the 'len' expression.
1491 if (!ContainsAnyImpliedDoIndex(*len) && IsConstantExpr(*len)) {
1492 result.set_LEN(std::move(*len));
1493 }
1494 }
1495 }
1496 return AsMaybeExpr(std::move(result));
1497 }
1498 }
1499 return std::nullopt;
1500 }
1501
1502private:
1503 using ImpliedDoIntType = ResultType<ImpliedDoIndex>;
1504
1505 void Push(MaybeExpr &&);
1506 void Add(const parser::AcValue::Triplet &);
1507 void Add(const parser::Expr &);
1508 void Add(const parser::AcImpliedDo &);
1509 void UnrollConstantImpliedDo(const parser::AcImpliedDo &,
1510 parser::CharBlock name, std::int64_t lower, std::int64_t upper,
1511 std::int64_t stride);
1512
1513 template <int KIND, typename A>
1514 std::optional<Expr<Type<TypeCategory::Integer, KIND>>> GetSpecificIntExpr(
1515 const A &x) {
1516 if (MaybeExpr y{exprAnalyzer_.Analyze(x)}) {
1517 Expr<SomeInteger> *intExpr{UnwrapExpr<Expr<SomeInteger>>(*y)};
1518 return Fold(exprAnalyzer_.GetFoldingContext(),
1519 ConvertToType<Type<TypeCategory::Integer, KIND>>(
1520 std::move(DEREF(intExpr)Fortran::common::Deref(intExpr, "flang/lib/Semantics/expression.cpp"
, 1520)
)));
1521 }
1522 return std::nullopt;
1523 }
1524
1525 // Nested array constructors all reference the same ExpressionAnalyzer,
1526 // which represents the nest of active implied DO loop indices.
1527 ExpressionAnalyzer &exprAnalyzer_;
1528 std::optional<DynamicTypeWithLength> type_;
1529 bool explicitType_{type_.has_value()};
1530 std::optional<std::int64_t> constantLength_;
1531 ArrayConstructorValues<SomeType> values_;
1532 std::uint64_t messageDisplayedSet_{0};
1533};
1534
1535void ArrayConstructorContext::Push(MaybeExpr &&x) {
1536 if (!x) {
1537 return;
1538 }
1539 if (!type_) {
1540 if (auto *boz{std::get_if<BOZLiteralConstant>(&x->u)}) {
1541 // Treat an array constructor of BOZ as if default integer.
1542 if (exprAnalyzer_.context().ShouldWarn(
1543 common::LanguageFeature::BOZAsDefaultInteger)) {
1544 exprAnalyzer_.Say(
1545 "BOZ literal in array constructor without explicit type is assumed to be default INTEGER"_port_en_US);
1546 }
1547 x = AsGenericExpr(ConvertToKind<TypeCategory::Integer>(
1548 exprAnalyzer_.GetDefaultKind(TypeCategory::Integer),
1549 std::move(*boz)));
1550 }
1551 }
1552 std::optional<DynamicType> dyType{x->GetType()};
1553 if (!dyType) {
1554 if (auto *boz{std::get_if<BOZLiteralConstant>(&x->u)}) {
1555 if (!type_) {
1556 // Treat an array constructor of BOZ as if default integer.
1557 if (exprAnalyzer_.context().ShouldWarn(
1558 common::LanguageFeature::BOZAsDefaultInteger)) {
1559 exprAnalyzer_.Say(
1560 "BOZ literal in array constructor without explicit type is assumed to be default INTEGER"_port_en_US);
1561 }
1562 x = AsGenericExpr(ConvertToKind<TypeCategory::Integer>(
1563 exprAnalyzer_.GetDefaultKind(TypeCategory::Integer),
1564 std::move(*boz)));
1565 dyType = x.value().GetType();
1566 } else if (auto cast{ConvertToType(*type_, std::move(*x))}) {
1567 x = std::move(cast);
1568 dyType = *type_;
1569 } else {
1570 if (!(messageDisplayedSet_ & 0x80)) {
1571 exprAnalyzer_.Say(
1572 "BOZ literal is not suitable for use in this array constructor"_err_en_US);
1573 messageDisplayedSet_ |= 0x80;
1574 }
1575 return;
1576 }
1577 } else { // procedure name, &c.
1578 if (!(messageDisplayedSet_ & 0x40)) {
1579 exprAnalyzer_.Say(
1580 "Item is not suitable for use in an array constructor"_err_en_US);
1581 messageDisplayedSet_ |= 0x40;
1582 }
1583 return;
1584 }
1585 } else if (dyType->IsUnlimitedPolymorphic()) {
1586 if (!(messageDisplayedSet_ & 8)) {
1587 exprAnalyzer_.Say("Cannot have an unlimited polymorphic value in an "
1588 "array constructor"_err_en_US); // C7113
1589 messageDisplayedSet_ |= 8;
1590 }
1591 return;
1592 }
1593 DynamicTypeWithLength xType{dyType.value()};
1594 if (Expr<SomeCharacter> * charExpr{UnwrapExpr<Expr<SomeCharacter>>(*x)}) {
1595 CHECK(xType.category() == TypeCategory::Character)((xType.category() == TypeCategory::Character) || (Fortran::common
::die("CHECK(" "xType.category() == TypeCategory::Character" ") failed"
" at " "flang/lib/Semantics/expression.cpp" "(%d)", 1595), false
))
;
1596 xType.length =
1597 common::visit([](const auto &kc) { return kc.LEN(); }, charExpr->u);
1598 }
1599 if (!type_) {
1600 // If there is no explicit type-spec in an array constructor, the type
1601 // of the array is the declared type of all of the elements, which must
1602 // be well-defined and all match.
1603 // TODO: Possible language extension: use the most general type of
1604 // the values as the type of a numeric constructed array, convert all
1605 // of the other values to that type. Alternative: let the first value
1606 // determine the type, and convert the others to that type.
1607 CHECK(!explicitType_)((!explicitType_) || (Fortran::common::die("CHECK(" "!explicitType_"
") failed" " at " "flang/lib/Semantics/expression.cpp" "(%d)"
, 1607), false))
;
1608 type_ = std::move(xType);
1609 constantLength_ = ToInt64(type_->length);
1610 values_.Push(std::move(*x));
1611 } else if (!explicitType_) {
1612 if (type_->IsTkCompatibleWith(xType) && xType.IsTkCompatibleWith(*type_)) {
1613 values_.Push(std::move(*x));
1614 if (auto thisLen{ToInt64(xType.LEN())}) {
1615 if (constantLength_) {
1616 if (exprAnalyzer_.context().warnOnNonstandardUsage() &&
1617 *thisLen != *constantLength_) {
1618 if (!(messageDisplayedSet_ & 1)) {
1619 exprAnalyzer_.Say(
1620 "Character literal in array constructor without explicit "
1621 "type has different length than earlier elements"_port_en_US);
1622 messageDisplayedSet_ |= 1;
1623 }
1624 }
1625 if (*thisLen > *constantLength_) {
1626 // Language extension: use the longest literal to determine the
1627 // length of the array constructor's character elements, not the
1628 // first, when there is no explicit type.
1629 *constantLength_ = *thisLen;
1630 type_->length = xType.LEN();
1631 }
1632 } else {
1633 constantLength_ = *thisLen;
1634 type_->length = xType.LEN();
1635 }
1636 }
1637 } else {
1638 if (!(messageDisplayedSet_ & 2)) {
1639 exprAnalyzer_.Say(
1640 "Values in array constructor must have the same declared type "
1641 "when no explicit type appears"_err_en_US); // C7110
1642 messageDisplayedSet_ |= 2;
1643 }
1644 }
1645 } else {
1646 if (auto cast{ConvertToType(*type_, std::move(*x))}) {
1647 values_.Push(std::move(*cast));
1648 } else if (!(messageDisplayedSet_ & 4)) {
1649 exprAnalyzer_.Say("Value in array constructor of type '%s' could not "
1650 "be converted to the type of the array '%s'"_err_en_US,
1651 x->GetType()->AsFortran(), type_->AsFortran()); // C7111, C7112
1652 messageDisplayedSet_ |= 4;
1653 }
1654 }
1655}
1656
1657void ArrayConstructorContext::Add(const parser::AcValue &x) {
1658 common::visit(
1659 common::visitors{
1660 [&](const parser::AcValue::Triplet &triplet) { Add(triplet); },
1661 [&](const common::Indirection<parser::Expr> &expr) {
1662 Add(expr.value());
1663 },
1664 [&](const common::Indirection<parser::AcImpliedDo> &impliedDo) {
1665 Add(impliedDo.value());
1666 },
1667 },
1668 x.u);
1669}
1670
1671// Transforms l:u(:s) into (_,_=l,u(,s)) with an anonymous index '_'
1672void ArrayConstructorContext::Add(const parser::AcValue::Triplet &triplet) {
1673 std::optional<Expr<ImpliedDoIntType>> lower{
1674 GetSpecificIntExpr<ImpliedDoIntType::kind>(std::get<0>(triplet.t))};
1675 std::optional<Expr<ImpliedDoIntType>> upper{
1676 GetSpecificIntExpr<ImpliedDoIntType::kind>(std::get<1>(triplet.t))};
1677 std::optional<Expr<ImpliedDoIntType>> stride{
1678 GetSpecificIntExpr<ImpliedDoIntType::kind>(std::get<2>(triplet.t))};
1679 if (lower && upper) {
1680 if (!stride) {
1681 stride = Expr<ImpliedDoIntType>{1};
1682 }
1683 if (!type_) {
1684 type_ = DynamicTypeWithLength{ImpliedDoIntType::GetType()};
1685 }
1686 auto v{std::move(values_)};
1687 parser::CharBlock anonymous;
1688 Push(Expr<SomeType>{
1689 Expr<SomeInteger>{Expr<ImpliedDoIntType>{ImpliedDoIndex{anonymous}}}});
1690 std::swap(v, values_);
1691 values_.Push(ImpliedDo<SomeType>{anonymous, std::move(*lower),
1692 std::move(*upper), std::move(*stride), std::move(v)});
1693 }
1694}
1695
1696void ArrayConstructorContext::Add(const parser::Expr &expr) {
1697 auto restorer{exprAnalyzer_.GetContextualMessages().SetLocation(expr.source)};
1698 Push(exprAnalyzer_.Analyze(expr));
1699}
1700
1701void ArrayConstructorContext::Add(const parser::AcImpliedDo &impliedDo) {
1702 const auto &control{std::get<parser::AcImpliedDoControl>(impliedDo.t)};
1703 const auto &bounds{std::get<parser::AcImpliedDoControl::Bounds>(control.t)};
1704 exprAnalyzer_.Analyze(bounds.name);
1705 parser::CharBlock name{bounds.name.thing.thing.source};
1706 const Symbol *symbol{bounds.name.thing.thing.symbol};
1707 int kind{ImpliedDoIntType::kind};
1708 if (const auto dynamicType{DynamicType::From(symbol)}) {
1709 kind = dynamicType->kind();
1710 }
1711 std::optional<Expr<ImpliedDoIntType>> lower{
1712 GetSpecificIntExpr<ImpliedDoIntType::kind>(bounds.lower)};
1713 std::optional<Expr<ImpliedDoIntType>> upper{
1714 GetSpecificIntExpr<ImpliedDoIntType::kind>(bounds.upper)};
1715 if (lower && upper) {
1716 std::optional<Expr<ImpliedDoIntType>> stride{
1717 GetSpecificIntExpr<ImpliedDoIntType::kind>(bounds.step)};
1718 if (!stride) {
1719 stride = Expr<ImpliedDoIntType>{1};
1720 }
1721 if (exprAnalyzer_.AddImpliedDo(name, kind)) {
1722 // Check for constant bounds; the loop may require complete unrolling
1723 // of the parse tree if all bounds are constant in order to allow the
1724 // implied DO loop index to qualify as a constant expression.
1725 auto cLower{ToInt64(lower)};
1726 auto cUpper{ToInt64(upper)};
1727 auto cStride{ToInt64(stride)};
1728 if (!(messageDisplayedSet_ & 0x10) && cStride && *cStride == 0) {
1729 exprAnalyzer_.SayAt(bounds.step.value().thing.thing.value().source,
1730 "The stride of an implied DO loop must not be zero"_err_en_US);
1731 messageDisplayedSet_ |= 0x10;
1732 }
1733 bool isConstant{cLower && cUpper && cStride && *cStride != 0};
1734 bool isNonemptyConstant{isConstant &&
1735 ((*cStride > 0 && *cLower <= *cUpper) ||
1736 (*cStride < 0 && *cLower >= *cUpper))};
1737 bool unrollConstantLoop{false};
1738 parser::Messages buffer;
1739 auto saveMessagesDisplayed{messageDisplayedSet_};
1740 {
1741 auto messageRestorer{
1742 exprAnalyzer_.GetContextualMessages().SetMessages(buffer)};
1743 auto v{std::move(values_)};
1744 for (const auto &value :
1745 std::get<std::list<parser::AcValue>>(impliedDo.t)) {
1746 Add(value);
1747 }
1748 std::swap(v, values_);
1749 if (isNonemptyConstant && buffer.AnyFatalError()) {
1750 unrollConstantLoop = true;
1751 } else {
1752 values_.Push(ImpliedDo<SomeType>{name, std::move(*lower),
1753 std::move(*upper), std::move(*stride), std::move(v)});
1754 }
1755 }
1756 if (unrollConstantLoop) {
1757 messageDisplayedSet_ = saveMessagesDisplayed;
1758 UnrollConstantImpliedDo(impliedDo, name, *cLower, *cUpper, *cStride);
1759 } else if (auto *messages{
1760 exprAnalyzer_.GetContextualMessages().messages()}) {
1761 messages->Annex(std::move(buffer));
1762 }
1763 exprAnalyzer_.RemoveImpliedDo(name);
1764 } else if (!(messageDisplayedSet_ & 0x20)) {
1765 exprAnalyzer_.SayAt(name,
1766 "Implied DO index '%s' is active in a surrounding implied DO loop "
1767 "and may not have the same name"_err_en_US,
1768 name); // C7115
1769 messageDisplayedSet_ |= 0x20;
1770 }
1771 }
1772}
1773
1774// Fortran considers an implied DO index of an array constructor to be
1775// a constant expression if the bounds of the implied DO loop are constant.
1776// Usually this doesn't matter, but if we emitted spurious messages as a
1777// result of not using constant values for the index while analyzing the
1778// items, we need to do it again the "hard" way with multiple iterations over
1779// the parse tree.
1780void ArrayConstructorContext::UnrollConstantImpliedDo(
1781 const parser::AcImpliedDo &impliedDo, parser::CharBlock name,
1782 std::int64_t lower, std::int64_t upper, std::int64_t stride) {
1783 auto &foldingContext{exprAnalyzer_.GetFoldingContext()};
1784 auto restorer{exprAnalyzer_.DoNotUseSavedTypedExprs()};
1785 for (auto &at{foldingContext.StartImpliedDo(name, lower)};
1786 (stride > 0 && at <= upper) || (stride < 0 && at >= upper);
1787 at += stride) {
1788 for (const auto &value :
1789 std::get<std::list<parser::AcValue>>(impliedDo.t)) {
1790 Add(value);
1791 }
1792 }
1793 foldingContext.EndImpliedDo(name);
1794}
1795
1796MaybeExpr ArrayConstructorContext::ToExpr() {
1797 return common::SearchTypes(std::move(*this));
1798}
1799
1800MaybeExpr ExpressionAnalyzer::Analyze(const parser::ArrayConstructor &array) {
1801 const parser::AcSpec &acSpec{array.v};
1802 ArrayConstructorContext acContext{*this, AnalyzeTypeSpec(acSpec.type)};
1803 for (const parser::AcValue &value : acSpec.values) {
1804 acContext.Add(value);
1805 }
1806 return acContext.ToExpr();
1807}
1808
1809MaybeExpr ExpressionAnalyzer::Analyze(
1810 const parser::StructureConstructor &structure) {
1811 auto &parsedType{std::get<parser::DerivedTypeSpec>(structure.t)};
1812 parser::Name structureType{std::get<parser::Name>(parsedType.t)};
1813 parser::CharBlock &typeName{structureType.source};
1814 if (semantics::Symbol *typeSymbol{structureType.symbol}) {
1815 if (typeSymbol->has<semantics::DerivedTypeDetails>()) {
1816 semantics::DerivedTypeSpec dtSpec{typeName, typeSymbol->GetUltimate()};
1817 if (!CheckIsValidForwardReference(dtSpec)) {
1818 return std::nullopt;
1819 }
1820 }
1821 }
1822 if (!parsedType.derivedTypeSpec) {
1823 return std::nullopt;
1824 }
1825 const auto &spec{*parsedType.derivedTypeSpec};
1826 const Symbol &typeSymbol{spec.typeSymbol()};
1827 if (!spec.scope() || !typeSymbol.has<semantics::DerivedTypeDetails>()) {
1828 return std::nullopt; // error recovery
1829 }
1830 const semantics::Scope &scope{context_.FindScope(typeName)};
1831 const semantics::Scope *pureContext{FindPureProcedureContaining(scope)};
1832 const auto &typeDetails{typeSymbol.get<semantics::DerivedTypeDetails>()};
1833 const Symbol *parentComponent{typeDetails.GetParentComponent(*spec.scope())};
1834
1835 if (typeSymbol.attrs().test(semantics::Attr::ABSTRACT)) { // C796
1836 AttachDeclaration(Say(typeName,
1837 "ABSTRACT derived type '%s' may not be used in a "
1838 "structure constructor"_err_en_US,
1839 typeName),
1840 typeSymbol); // C7114
1841 }
1842
1843 // This iterator traverses all of the components in the derived type and its
1844 // parents. The symbols for whole parent components appear after their
1845 // own components and before the components of the types that extend them.
1846 // E.g., TYPE :: A; REAL X; END TYPE
1847 // TYPE, EXTENDS(A) :: B; REAL Y; END TYPE
1848 // produces the component list X, A, Y.
1849 // The order is important below because a structure constructor can
1850 // initialize X or A by name, but not both.
1851 auto components{semantics::OrderedComponentIterator{spec}};
1852 auto nextAnonymous{components.begin()};
1853
1854 std::set<parser::CharBlock> unavailable;
1855 bool anyKeyword{false};
1856 StructureConstructor result{spec};
1857 bool checkConflicts{true}; // until we hit one
1858 auto &messages{GetContextualMessages()};
1859
1860 // NULL() can be a valid component
1861 auto restorer{AllowNullPointer()};
1862
1863 for (const auto &component :
1864 std::get<std::list<parser::ComponentSpec>>(structure.t)) {
1865 const parser::Expr &expr{
1866 std::get<parser::ComponentDataSource>(component.t).v.value()};
1867 parser::CharBlock source{expr.source};
1868 auto restorer{messages.SetLocation(source)};
1869 const Symbol *symbol{nullptr};
1870 MaybeExpr value{Analyze(expr)};
1871 std::optional<DynamicType> valueType{DynamicType::From(value)};
1872 if (const auto &kw{std::get<std::optional<parser::Keyword>>(component.t)}) {
1873 anyKeyword = true;
1874 source = kw->v.source;
1875 symbol = kw->v.symbol;
1876 if (!symbol) {
1877 // Skip overridden inaccessible parent components in favor of
1878 // their later overrides.
1879 for (const Symbol &sym : components) {
1880 if (sym.name() == source) {
1881 symbol = &sym;
1882 }
1883 }
1884 }
1885 if (!symbol) { // C7101
1886 Say(source,
1887 "Keyword '%s=' does not name a component of derived type '%s'"_err_en_US,
1888 source, typeName);
1889 }
1890 } else {
1891 if (anyKeyword) { // C7100
1892 Say(source,
1893 "Value in structure constructor lacks a component name"_err_en_US);
1894 checkConflicts = false; // stem cascade
1895 }
1896 // Here's a regrettably common extension of the standard: anonymous
1897 // initialization of parent components, e.g., T(PT(1)) rather than
1898 // T(1) or T(PT=PT(1)).
1899 if (nextAnonymous == components.begin() && parentComponent &&
1900 valueType == DynamicType::From(*parentComponent) &&
1901 context().IsEnabled(LanguageFeature::AnonymousParents)) {
1902 auto iter{
1903 std::find(components.begin(), components.end(), *parentComponent)};
1904 if (iter != components.end()) {
1905 symbol = parentComponent;
1906 nextAnonymous = ++iter;
1907 if (context().ShouldWarn(LanguageFeature::AnonymousParents)) {
1908 Say(source,
1909 "Whole parent component '%s' in structure "
1910 "constructor should not be anonymous"_port_en_US,
1911 symbol->name());
1912 }
1913 }
1914 }
1915 while (!symbol && nextAnonymous != components.end()) {
1916 const Symbol &next{*nextAnonymous};
1917 ++nextAnonymous;
1918 if (!next.test(Symbol::Flag::ParentComp)) {
1919 symbol = &next;
1920 }
1921 }
1922 if (!symbol) {
1923 Say(source, "Unexpected value in structure constructor"_err_en_US);
1924 }
1925 }
1926 if (symbol) {
1927 const semantics::Scope &innermost{context_.FindScope(expr.source)};
1928 if (auto msg{CheckAccessibleSymbol(innermost, *symbol)}) {
1929 Say(expr.source, std::move(*msg));
1930 }
1931 if (checkConflicts) {
1932 auto componentIter{
1933 std::find(components.begin(), components.end(), *symbol)};
1934 if (unavailable.find(symbol->name()) != unavailable.cend()) {
1935 // C797, C798
1936 Say(source,
1937 "Component '%s' conflicts with another component earlier in "
1938 "this structure constructor"_err_en_US,
1939 symbol->name());
1940 } else if (symbol->test(Symbol::Flag::ParentComp)) {
1941 // Make earlier components unavailable once a whole parent appears.
1942 for (auto it{components.begin()}; it != componentIter; ++it) {
1943 unavailable.insert(it->name());
1944 }
1945 } else {
1946 // Make whole parent components unavailable after any of their
1947 // constituents appear.
1948 for (auto it{componentIter}; it != components.end(); ++it) {
1949 if (it->test(Symbol::Flag::ParentComp)) {
1950 unavailable.insert(it->name());
1951 }
1952 }
1953 }
1954 }
1955 unavailable.insert(symbol->name());
1956 if (value) {
1957 if (symbol->has<semantics::TypeParamDetails>()) {
1958 Say(expr.source,
1959 "Type parameter '%s' may not appear as a component of a structure constructor"_err_en_US,
1960 symbol->name());
1961 }
1962 if (!(symbol->has<semantics::ProcEntityDetails>() ||
1963 symbol->has<semantics::ObjectEntityDetails>())) {
1964 continue; // recovery
1965 }
1966 if (IsPointer(*symbol)) { // C7104, C7105, C1594(4)
1967 semantics::CheckStructConstructorPointerComponent(
1968 GetFoldingContext(), *symbol, *value, innermost);
1969 result.Add(*symbol, Fold(std::move(*value)));
1970 continue;
1971 }
1972 if (IsNullPointer(*value)) {
1973 if (IsAllocatable(*symbol)) {
1974 if (IsBareNullPointer(&*value)) {
1975 // NULL() with no arguments allowed by 7.5.10 para 6 for
1976 // ALLOCATABLE.
1977 result.Add(*symbol, Expr<SomeType>{NullPointer{}});
1978 continue;
1979 }
1980 if (IsNullObjectPointer(*value)) {
1981 AttachDeclaration(
1982 Say(expr.source,
1983 "NULL() with arguments is not standard conforming as the value for allocatable component '%s'"_port_en_US,
1984 symbol->name()),
1985 *symbol);
1986 // proceed to check type & shape
1987 } else {
1988 AttachDeclaration(
1989 Say(expr.source,
1990 "A NULL procedure pointer may not be used as the value for component '%s'"_err_en_US,
1991 symbol->name()),
1992 *symbol);
1993 continue;
1994 }
1995 } else {
1996 AttachDeclaration(
1997 Say(expr.source,
1998 "A NULL pointer may not be used as the value for component '%s'"_err_en_US,
1999 symbol->name()),
2000 *symbol);
2001 continue;
2002 }
2003 } else if (const Symbol * pointer{FindPointerComponent(*symbol)};
2004 pointer && pureContext) { // C1594(4)
2005 if (const Symbol *
2006 visible{semantics::FindExternallyVisibleObject(
2007 *value, *pureContext)}) {
2008 Say(expr.source,
2009 "The externally visible object '%s' may not be used in a pure procedure as the value for component '%s' which has the pointer component '%s'"_err_en_US,
2010 visible->name(), symbol->name(), pointer->name());
2011 }
2012 }
2013 if (MaybeExpr converted{ConvertToType(*symbol, std::move(*value))}) {
2014 if (auto componentShape{GetShape(GetFoldingContext(), *symbol)}) {
2015 if (auto valueShape{GetShape(GetFoldingContext(), *converted)}) {
2016 if (GetRank(*componentShape) == 0 && GetRank(*valueShape) > 0) {
2017 AttachDeclaration(
2018 Say(expr.source,
2019 "Rank-%d array value is not compatible with scalar component '%s'"_err_en_US,
2020 GetRank(*valueShape), symbol->name()),
2021 *symbol);
2022 } else {
2023 auto checked{
2024 CheckConformance(messages, *componentShape, *valueShape,
2025 CheckConformanceFlags::RightIsExpandableDeferred,
2026 "component", "value")};
2027 if (checked && *checked && GetRank(*componentShape) > 0 &&
2028 GetRank(*valueShape) == 0 &&
2029 (IsDeferredShape(*symbol) ||
2030 !IsExpandableScalar(*converted, GetFoldingContext(),
2031 *componentShape, true /*admit PURE call*/))) {
2032 AttachDeclaration(
2033 Say(expr.source,
2034 "Scalar value cannot be expanded to shape of array component '%s'"_err_en_US,
2035 symbol->name()),
2036 *symbol);
2037 }
2038 if (checked.value_or(true)) {
2039 result.Add(*symbol, std::move(*converted));
2040 }
2041 }
2042 } else {
2043 Say(expr.source, "Shape of value cannot be determined"_err_en_US);
2044 }
2045 } else {
2046 AttachDeclaration(
2047 Say(expr.source,
2048 "Shape of component '%s' cannot be determined"_err_en_US,
2049 symbol->name()),
2050 *symbol);
2051 }
2052 } else if (auto symType{DynamicType::From(symbol)}) {
2053 if (IsAllocatable(*symbol) && symType->IsUnlimitedPolymorphic() &&
2054 valueType) {
2055 // ok
2056 } else if (valueType) {
2057 AttachDeclaration(
2058 Say(expr.source,
2059 "Value in structure constructor of type '%s' is "
2060 "incompatible with component '%s' of type '%s'"_err_en_US,
2061 valueType->AsFortran(), symbol->name(),
2062 symType->AsFortran()),
2063 *symbol);
2064 } else {
2065 AttachDeclaration(
2066 Say(expr.source,
2067 "Value in structure constructor is incompatible with "
2068 "component '%s' of type %s"_err_en_US,
2069 symbol->name(), symType->AsFortran()),
2070 *symbol);
2071 }
2072 }
2073 }
2074 }
2075 }
2076
2077 // Ensure that unmentioned component objects have default initializers.
2078 for (const Symbol &symbol : components) {
2079 if (!symbol.test(Symbol::Flag::ParentComp) &&
2080 unavailable.find(symbol.name()) == unavailable.cend()) {
2081 if (IsAllocatable(symbol)) {
2082 // Set all remaining allocatables to explicit NULL().
2083 result.Add(symbol, Expr<SomeType>{NullPointer{}});
2084 } else {
2085 const auto *object{symbol.detailsIf<semantics::ObjectEntityDetails>()};
2086 if (object && object->init()) {
2087 result.Add(symbol, common::Clone(*object->init()));
2088 } else if (IsPointer(symbol)) {
2089 result.Add(symbol, Expr<SomeType>{NullPointer{}});
2090 } else if (object) { // C799
2091 AttachDeclaration(Say(typeName,
2092 "Structure constructor lacks a value for "
2093 "component '%s'"_err_en_US,
2094 symbol.name()),
2095 symbol);
2096 }
2097 }
2098 }
2099 }
2100
2101 return AsMaybeExpr(Expr<SomeDerived>{std::move(result)});
2102}
2103
2104static std::optional<parser::CharBlock> GetPassName(
2105 const semantics::Symbol &proc) {
2106 return common::visit(
2107 [](const auto &details) {
2108 if constexpr (std::is_base_of_v<semantics::WithPassArg,
2109 std::decay_t<decltype(details)>>) {
2110 return details.passName();
2111 } else {
2112 return std::optional<parser::CharBlock>{};
2113 }
2114 },
2115 proc.details());
2116}
2117
2118static int GetPassIndex(const Symbol &proc) {
2119 CHECK(!proc.attrs().test(semantics::Attr::NOPASS))((!proc.attrs().test(semantics::Attr::NOPASS)) || (Fortran::common
::die("CHECK(" "!proc.attrs().test(semantics::Attr::NOPASS)" ") failed"
" at " "flang/lib/Semantics/expression.cpp" "(%d)", 2119), false
))
;
2120 std::optional<parser::CharBlock> passName{GetPassName(proc)};
2121 const auto *interface {
2122 semantics::FindInterface(proc)
2123 };
2124 if (!passName || !interface) {
2125 return 0; // first argument is passed-object
2126 }
2127 const auto &subp{interface->get<semantics::SubprogramDetails>()};
2128 int index{0};
2129 for (const auto *arg : subp.dummyArgs()) {
2130 if (arg && arg->name() == passName) {
2131 return index;
2132 }
2133 ++index;
2134 }
2135 DIE("PASS argument name not in dummy argument list")Fortran::common::die("PASS argument name not in dummy argument list"
" at " "flang/lib/Semantics/expression.cpp" "(%d)", 2135)
;
2136}
2137
2138// Injects an expression into an actual argument list as the "passed object"
2139// for a type-bound procedure reference that is not NOPASS. Adds an
2140// argument keyword if possible, but not when the passed object goes
2141// before a positional argument.
2142// e.g., obj%tbp(x) -> tbp(obj,x).
2143static void AddPassArg(ActualArguments &actuals, const Expr<SomeDerived> &expr,
2144 const Symbol &component, bool isPassedObject = true) {
2145 if (component.attrs().test(semantics::Attr::NOPASS)) {
2146 return;
2147 }
2148 int passIndex{GetPassIndex(component)};
2149 auto iter{actuals.begin()};
2150 int at{0};
2151 while (iter < actuals.end() && at < passIndex) {
2152 if (*iter && (*iter)->keyword()) {
2153 iter = actuals.end();
2154 break;
2155 }
2156 ++iter;
2157 ++at;
2158 }
2159 ActualArgument passed{AsGenericExpr(common::Clone(expr))};
2160 passed.set_isPassedObject(isPassedObject);
2161 if (iter == actuals.end()) {
2162 if (auto passName{GetPassName(component)}) {
2163 passed.set_keyword(*passName);
2164 }
2165 }
2166 actuals.emplace(iter, std::move(passed));
2167}
2168
2169// Return the compile-time resolution of a procedure binding, if possible.
2170static const Symbol *GetBindingResolution(
2171 const std::optional<DynamicType> &baseType, const Symbol &component) {
2172 const auto *binding{component.detailsIf<semantics::ProcBindingDetails>()};
2173 if (!binding) {
2174 return nullptr;
2175 }
2176 if (!component.attrs().test(semantics::Attr::NON_OVERRIDABLE) &&
2177 (!baseType || baseType->IsPolymorphic())) {
2178 return nullptr;
2179 }
2180 return &binding->symbol();
2181}
2182
2183auto ExpressionAnalyzer::AnalyzeProcedureComponentRef(
2184 const parser::ProcComponentRef &pcr, ActualArguments &&arguments,
2185 bool isSubroutine) -> std::optional<CalleeAndArguments> {
2186 const parser::StructureComponent &sc{pcr.v.thing};
2187 if (MaybeExpr base{Analyze(sc.base)}) {
2188 if (const Symbol *sym{sc.component.symbol}) {
2189 if (context_.HasError(sym)) {
2190 return std::nullopt;
2191 }
2192 if (!IsProcedure(*sym)) {
2193 AttachDeclaration(
2194 Say(sc.component.source, "'%s' is not a procedure"_err_en_US,
2195 sc.component.source),
2196 *sym);
2197 return std::nullopt;
2198 }
2199 if (auto *dtExpr{UnwrapExpr<Expr<SomeDerived>>(*base)}) {
2200 if (sym->has<semantics::GenericDetails>()) {
2201 auto dyType{dtExpr->GetType()};
2202 AdjustActuals adjustment{
2203 [&](const Symbol &proc, ActualArguments &actuals) {
2204 if (!proc.attrs().test(semantics::Attr::NOPASS)) {
2205 AddPassArg(actuals, std::move(*dtExpr), proc);
2206 }
2207 return true;
2208 }};
2209 auto pair{ResolveGeneric(*sym, arguments, adjustment, isSubroutine)};
2210 sym = pair.first;
2211 if (sym) {
2212 // re-resolve the name to the specific binding
2213 CHECK(sym->has<semantics::ProcBindingDetails>())((sym->has<semantics::ProcBindingDetails>()) || (Fortran
::common::die("CHECK(" "sym->has<semantics::ProcBindingDetails>()"
") failed" " at " "flang/lib/Semantics/expression.cpp" "(%d)"
, 2213), false))
;
2214 // Use the most recent override of the binding, if any
2215 CHECK(dyType && dyType->category() == TypeCategory::Derived &&((dyType && dyType->category() == TypeCategory::Derived
&& !dyType->IsUnlimitedPolymorphic()) || (Fortran
::common::die("CHECK(" "dyType && dyType->category() == TypeCategory::Derived && !dyType->IsUnlimitedPolymorphic()"
") failed" " at " "flang/lib/Semantics/expression.cpp" "(%d)"
, 2216), false))
2216 !dyType->IsUnlimitedPolymorphic())((dyType && dyType->category() == TypeCategory::Derived
&& !dyType->IsUnlimitedPolymorphic()) || (Fortran
::common::die("CHECK(" "dyType && dyType->category() == TypeCategory::Derived && !dyType->IsUnlimitedPolymorphic()"
") failed" " at " "flang/lib/Semantics/expression.cpp" "(%d)"
, 2216), false))
;
2217 if (const Symbol *latest{
2218 DEREF(dyType->GetDerivedTypeSpec().typeSymbol().scope())Fortran::common::Deref(dyType->GetDerivedTypeSpec().typeSymbol
().scope(), "flang/lib/Semantics/expression.cpp", 2218)
2219 .FindComponent(sym->name())}) {
2220 sym = latest;
2221 }
2222 sc.component.symbol = const_cast<Symbol *>(sym);
2223 } else {
2224 EmitGenericResolutionError(
2225 *sc.component.symbol, pair.second, isSubroutine);
2226 return std::nullopt;
2227 }
2228 }
2229 std::optional<DataRef> dataRef{ExtractDataRef(std::move(*dtExpr))};
2230 if (dataRef && !CheckDataRef(*dataRef)) {
2231 return std::nullopt;
2232 }
2233 if (dataRef && dataRef->Rank() > 0) {
2234 if (sym->has<semantics::ProcBindingDetails>() &&
2235 sym->attrs().test(semantics::Attr::NOPASS)) {
2236 // C1529 seems unnecessary and most compilers don't enforce it.
2237 AttachDeclaration(
2238 Say(sc.component.source,
2239 "Base of NOPASS type-bound procedure reference should be scalar"_port_en_US),
2240 *sym);
2241 } else if (IsProcedurePointer(*sym)) { // C919
2242 Say(sc.component.source,
2243 "Base of procedure component reference must be scalar"_err_en_US);
2244 }
2245 }
2246 if (const Symbol *resolution{
2247 GetBindingResolution(dtExpr->GetType(), *sym)}) {
2248 AddPassArg(arguments, std::move(*dtExpr), *sym, false);
2249 return CalleeAndArguments{
2250 ProcedureDesignator{*resolution}, std::move(arguments)};
2251 } else if (dataRef.has_value()) {
2252 if (sym->attrs().test(semantics::Attr::NOPASS)) {
2253 return CalleeAndArguments{
2254 ProcedureDesignator{Component{std::move(*dataRef), *sym}},
2255 std::move(arguments)};
2256 } else {
2257 AddPassArg(arguments,
2258 Expr<SomeDerived>{Designator<SomeDerived>{std::move(*dataRef)}},
2259 *sym);
2260 return CalleeAndArguments{
2261 ProcedureDesignator{*sym}, std::move(arguments)};
2262 }
2263 }
2264 }
2265 Say(sc.component.source,
2266 "Base of procedure component reference is not a derived-type object"_err_en_US);
2267 }
2268 }
2269 CHECK(context_.AnyFatalError())((context_.AnyFatalError()) || (Fortran::common::die("CHECK("
"context_.AnyFatalError()" ") failed" " at " "flang/lib/Semantics/expression.cpp"
"(%d)", 2269), false))
;
2270 return std::nullopt;
2271}
2272
2273// Can actual be argument associated with dummy?
2274static bool CheckCompatibleArgument(bool isElemental,
2275 const ActualArgument &actual, const characteristics::DummyArgument &dummy) {
2276 const auto *expr{actual.UnwrapExpr()};
2277 return common::visit(
2278 common::visitors{
2279 [&](const characteristics::DummyDataObject &x) {
2280 if (x.attrs.test(characteristics::DummyDataObject::Attr::Pointer) &&
2281 IsBareNullPointer(expr)) {
2282 // NULL() without MOLD= is compatible with any dummy data pointer
2283 // but cannot be allowed to lead to ambiguity.
2284 return true;
2285 } else if (!isElemental && actual.Rank() != x.type.Rank() &&
2286 !x.type.attrs().test(
2287 characteristics::TypeAndShape::Attr::AssumedRank)) {
2288 return false;
2289 } else if (auto actualType{actual.GetType()}) {
2290 return x.type.type().IsTkCompatibleWith(*actualType);
2291 }
2292 return false;
2293 },
2294 [&](const characteristics::DummyProcedure &) {
2295 return expr && IsProcedurePointerTarget(*expr);
2296 },
2297 [&](const characteristics::AlternateReturn &) {
2298 return actual.isAlternateReturn();
2299 },
2300 },
2301 dummy.u);
2302}
2303
2304// Are the actual arguments compatible with the dummy arguments of procedure?
2305static bool CheckCompatibleArguments(
2306 const characteristics::Procedure &procedure,
2307 const ActualArguments &actuals) {
2308 bool isElemental{procedure.IsElemental()};
2309 const auto &dummies{procedure.dummyArguments};
2310 CHECK(dummies.size() == actuals.size())((dummies.size() == actuals.size()) || (Fortran::common::die(
"CHECK(" "dummies.size() == actuals.size()" ") failed" " at "
"flang/lib/Semantics/expression.cpp" "(%d)", 2310), false))
;
2311 for (std::size_t i{0}; i < dummies.size(); ++i) {
2312 const characteristics::DummyArgument &dummy{dummies[i]};
2313 const std::optional<ActualArgument> &actual{actuals[i]};
2314 if (actual && !CheckCompatibleArgument(isElemental, *actual, dummy)) {
2315 return false;
2316 }
2317 }
2318 return true;
2319}
2320
2321// Handles a forward reference to a module function from what must
2322// be a specification expression. Return false if the symbol is
2323// an invalid forward reference.
2324bool ExpressionAnalyzer::ResolveForward(const Symbol &symbol) {
2325 if (context_.HasError(symbol)) {
2326 return false;
2327 }
2328 if (const auto *details{
2329 symbol.detailsIf<semantics::SubprogramNameDetails>()}) {
2330 if (details->kind() == semantics::SubprogramKind::Module) {
2331 // If this symbol is still a SubprogramNameDetails, we must be
2332 // checking a specification expression in a sibling module
2333 // procedure. Resolve its names now so that its interface
2334 // is known.
2335 semantics::ResolveSpecificationParts(context_, symbol);
2336 if (symbol.has<semantics::SubprogramNameDetails>()) {
2337 // When the symbol hasn't had its details updated, we must have
2338 // already been in the process of resolving the function's
2339 // specification part; but recursive function calls are not
2340 // allowed in specification parts (10.1.11 para 5).
2341 Say("The module function '%s' may not be referenced recursively in a specification expression"_err_en_US,
2342 symbol.name());
2343 context_.SetError(symbol);
2344 return false;
2345 }
2346 } else if (inStmtFunctionDefinition_) {
2347 semantics::ResolveSpecificationParts(context_, symbol);
2348 CHECK(symbol.has<semantics::SubprogramDetails>())((symbol.has<semantics::SubprogramDetails>()) || (Fortran
::common::die("CHECK(" "symbol.has<semantics::SubprogramDetails>()"
") failed" " at " "flang/lib/Semantics/expression.cpp" "(%d)"
, 2348), false))
;
2349 } else { // 10.1.11 para 4
2350 Say("The internal function '%s' may not be referenced in a specification expression"_err_en_US,
2351 symbol.name());
2352 context_.SetError(symbol);
2353 return false;
2354 }
2355 }
2356 return true;
2357}
2358
2359// Resolve a call to a generic procedure with given actual arguments.
2360// adjustActuals is called on procedure bindings to handle pass arg.
2361std::pair<const Symbol *, bool> ExpressionAnalyzer::ResolveGeneric(
2362 const Symbol &symbol, const ActualArguments &actuals,
2363 const AdjustActuals &adjustActuals, bool isSubroutine,
2364 bool mightBeStructureConstructor) {
2365 const Symbol *elemental{nullptr}; // matching elemental specific proc
2366 const Symbol *nonElemental{nullptr}; // matching non-elemental specific
2367 const Symbol &ultimate{symbol.GetUltimate()};
2368 // Check for a match with an explicit INTRINSIC
2369 if (ultimate.attrs().test(semantics::Attr::INTRINSIC)) {
2370 parser::Messages buffer;
2371 auto restorer{foldingContext_.messages().SetMessages(buffer)};
2372 ActualArguments localActuals{actuals};
2373 if (context_.intrinsics().Probe(
2374 CallCharacteristics{ultimate.name().ToString(), isSubroutine},
2375 localActuals, foldingContext_) &&
2376 !buffer.AnyFatalError()) {
2377 return {&ultimate, false};
2378 }
2379 }
2380 if (const auto *details{ultimate.detailsIf<semantics::GenericDetails>()}) {
2381 for (const Symbol &specific : details->specificProcs()) {
2382 if (isSubroutine != !IsFunction(specific)) {
2383 continue;
2384 }
2385 if (!ResolveForward(specific)) {
2386 continue;
2387 }
2388 if (std::optional<characteristics::Procedure> procedure{
2389 characteristics::Procedure::Characterize(
2390 ProcedureDesignator{specific}, context_.foldingContext())}) {
2391 ActualArguments localActuals{actuals};
2392 if (specific.has<semantics::ProcBindingDetails>()) {
2393 if (!adjustActuals.value()(specific, localActuals)) {
2394 continue;
2395 }
2396 }
2397 if (semantics::CheckInterfaceForGeneric(*procedure, localActuals,
2398 GetFoldingContext(), false /* no integer conversions */) &&
2399 CheckCompatibleArguments(*procedure, localActuals)) {
2400 if ((procedure->IsElemental() && elemental) ||
2401 (!procedure->IsElemental() && nonElemental)) {
2402 // 16.9.144(6): a bare NULL() is not allowed as an actual
2403 // argument to a generic procedure if the specific procedure
2404 // cannot be unambiguously distinguished
2405 // Underspecified external procedure actual arguments can
2406 // also lead to ambiguity.
2407 return {nullptr, true /* due to ambiguity */};
2408 }
2409 if (!procedure->IsElemental()) {
2410 // takes priority over elemental match
2411 nonElemental = &specific;
2412 } else {
2413 elemental = &specific;
2414 }
2415 }
2416 }
2417 }
2418 if (nonElemental) {
2419 return {&AccessSpecific(symbol, *nonElemental), false};
2420 } else if (elemental) {
2421 return {&AccessSpecific(symbol, *elemental), false};
2422 }
2423 // Check parent derived type
2424 if (const auto *parentScope{symbol.owner().GetDerivedTypeParent()}) {
2425 if (const Symbol *extended{parentScope->FindComponent(symbol.name())}) {
2426 auto pair{ResolveGeneric(
2427 *extended, actuals, adjustActuals, isSubroutine, false)};
2428 if (pair.first) {
2429 return pair;
2430 }
2431 }
2432 }
2433 if (mightBeStructureConstructor && details->derivedType()) {
2434 return {details->derivedType(), false};
2435 }
2436 }
2437 // Check for generic or explicit INTRINSIC of the same name in outer scopes.
2438 // See 15.5.5.2 for details.
2439 if (!symbol.owner().IsGlobal() && !symbol.owner().IsDerivedType()) {
2440 for (const std::string &n : GetAllNames(context_, symbol.name())) {
2441 if (const Symbol *outer{symbol.owner().parent().FindSymbol(n)}) {
2442 auto pair{ResolveGeneric(*outer, actuals, adjustActuals, isSubroutine,
2443 mightBeStructureConstructor)};
2444 if (pair.first) {
2445 return pair;
2446 }
2447 }
2448 }
2449 }
2450 return {nullptr, false};
2451}
2452
2453const Symbol &ExpressionAnalyzer::AccessSpecific(
2454 const Symbol &originalGeneric, const Symbol &specific) {
2455 if (const auto *hosted{
2456 originalGeneric.detailsIf<semantics::HostAssocDetails>()}) {
2457 return AccessSpecific(hosted->symbol(), specific);
2458 } else if (const auto *used{
2459 originalGeneric.detailsIf<semantics::UseDetails>()}) {
2460 const auto &scope{originalGeneric.owner()};
2461 if (auto iter{scope.find(specific.name())}; iter != scope.end()) {
2462 if (const auto *useDetails{
2463 iter->second->detailsIf<semantics::UseDetails>()}) {
2464 const Symbol &usedSymbol{useDetails->symbol()};
2465 const auto *usedGeneric{
2466 usedSymbol.detailsIf<semantics::GenericDetails>()};
2467 if (&usedSymbol == &specific ||
2468 (usedGeneric && usedGeneric->specific() == &specific)) {
2469 return specific;
2470 }
2471 }
2472 }
2473 // Create a renaming USE of the specific procedure.
2474 auto rename{context_.SaveTempName(
2475 used->symbol().owner().GetName().value().ToString() + "$" +
2476 specific.owner().GetName().value().ToString() + "$" +
2477 specific.name().ToString())};
2478 return *const_cast<semantics::Scope &>(scope)
2479 .try_emplace(rename, specific.attrs(),
2480 semantics::UseDetails{rename, specific})
2481 .first->second;
2482 } else {
2483 return specific;
2484 }
2485}
2486
2487void ExpressionAnalyzer::EmitGenericResolutionError(
2488 const Symbol &symbol, bool dueToAmbiguity, bool isSubroutine) {
2489 Say(dueToAmbiguity
2490 ? "One or more actual arguments to the generic procedure '%s' matched multiple specific procedures, perhaps due to use of NULL() without MOLD= or an actual procedure with an implicit interface"_err_en_US
2491 : semantics::IsGenericDefinedOp(symbol)
2492 ? "No specific procedure of generic operator '%s' matches the actual arguments"_err_en_US
2493 : isSubroutine
2494 ? "No specific subroutine of generic '%s' matches the actual arguments"_err_en_US
2495 : "No specific function of generic '%s' matches the actual arguments"_err_en_US,
2496 symbol.name());
2497}
2498
2499auto ExpressionAnalyzer::GetCalleeAndArguments(
2500 const parser::ProcedureDesignator &pd, ActualArguments &&arguments,
2501 bool isSubroutine, bool mightBeStructureConstructor)
2502 -> std::optional<CalleeAndArguments> {
2503 return common::visit(common::visitors{
2504 [&](const parser::Name &name) {
2505 return GetCalleeAndArguments(name,
2506 std::move(arguments), isSubroutine,
2507 mightBeStructureConstructor);
2508 },
2509 [&](const parser::ProcComponentRef &pcr) {
2510 return AnalyzeProcedureComponentRef(
2511 pcr, std::move(arguments), isSubroutine);
2512 },
2513 },
2514 pd.u);
2515}
2516
2517auto ExpressionAnalyzer::GetCalleeAndArguments(const parser::Name &name,
2518 ActualArguments &&arguments, bool isSubroutine,
2519 bool mightBeStructureConstructor) -> std::optional<CalleeAndArguments> {
2520 const Symbol *symbol{name.symbol};
2521 if (context_.HasError(symbol)) {
8
Assuming the condition is false
9
Taking false branch
2522 return std::nullopt; // also handles null symbol
2523 }
2524 const Symbol &ultimate{DEREF(symbol)Fortran::common::Deref(symbol, "flang/lib/Semantics/expression.cpp"
, 2524)
.GetUltimate()};
2525 CheckForBadRecursion(name.source, ultimate);
2526 bool dueToAmbiguity{false};
2527 bool isGenericInterface{ultimate.has<semantics::GenericDetails>()};
2528 bool isExplicitIntrinsic{ultimate.attrs().test(semantics::Attr::INTRINSIC)};
2529 const Symbol *resolution{nullptr};
2530 if (isGenericInterface
9.1
'isGenericInterface' is false
9.1
'isGenericInterface' is false
|| isExplicitIntrinsic
9.2
'isExplicitIntrinsic' is false
9.2
'isExplicitIntrinsic' is false
) {
2531 ExpressionAnalyzer::AdjustActuals noAdjustment;
2532 auto pair{ResolveGeneric(*symbol, arguments, noAdjustment, isSubroutine,
2533 mightBeStructureConstructor)};
2534 resolution = pair.first;
2535 dueToAmbiguity = pair.second;
2536 if (resolution) {
2537 if (context_.GetPPCBuiltinsScope() &&
2538 resolution->name().ToString().rfind("__ppc_", 0) == 0) {
2539 semantics::CheckPPCIntrinsic(
2540 *symbol, *resolution, arguments, GetFoldingContext());
2541 }
2542 // re-resolve name to the specific procedure
2543 name.symbol = const_cast<Symbol *>(resolution);
2544 }
2545 } else if (IsProcedure(ultimate) &&
10
Assuming the condition is false
2546 ultimate.attrs().test(semantics::Attr::ABSTRACT)) {
2547 Say("Abstract procedure interface '%s' may not be referenced"_err_en_US,
2548 name.source);
2549 } else {
2550 resolution = symbol;
2551 }
2552 if (!resolution
10.1
'resolution' is non-null
10.1
'resolution' is non-null
|| resolution->attrs().test(semantics::Attr::INTRINSIC)) {
11
Taking false branch
2553 // Not generic, or no resolution; may be intrinsic
2554 if (std::optional<SpecificCall> specificCall{context_.intrinsics().Probe(
2555 CallCharacteristics{ultimate.name().ToString(), isSubroutine},
2556 arguments, GetFoldingContext())}) {
2557 CheckBadExplicitType(*specificCall, *symbol);
2558 return CalleeAndArguments{
2559 ProcedureDesignator{std::move(specificCall->specificIntrinsic)},
2560 std::move(specificCall->arguments)};
2561 } else {
2562 if (isGenericInterface) {
2563 EmitGenericResolutionError(*symbol, dueToAmbiguity, isSubroutine);
2564 }
2565 return std::nullopt;
2566 }
2567 }
2568 if (resolution->GetUltimate().has<semantics::DerivedTypeDetails>()) {
12
Taking false branch
2569 if (mightBeStructureConstructor) {
2570 return CalleeAndArguments{
2571 semantics::SymbolRef{*resolution}, std::move(arguments)};
2572 }
2573 } else if (IsProcedure(*resolution)) {
13
Assuming the condition is true
14
Taking true branch
2574 return CalleeAndArguments{
2575 ProcedureDesignator{*resolution}, std::move(arguments)};
15
Object 'actuals_' of type 'std::vector' is left in a valid but unspecified state after move
2576 }
2577 if (!context_.HasError(*resolution)) {
2578 AttachDeclaration(
2579 Say(name.source, "'%s' is not a callable procedure"_err_en_US,
2580 name.source),
2581 *resolution);
2582 }
2583 return std::nullopt;
2584}
2585
2586// Fortran 2018 expressly states (8.2 p3) that any declared type for a
2587// generic intrinsic function "has no effect" on the result type of a
2588// call to that intrinsic. So one can declare "character*8 cos" and
2589// still get a real result from "cos(1.)". This is a dangerous feature,
2590// especially since implementations are free to extend their sets of
2591// intrinsics, and in doing so might clash with a name in a program.
2592// So we emit a warning in this situation, and perhaps it should be an
2593// error -- any correctly working program can silence the message by
2594// simply deleting the pointless type declaration.
2595void ExpressionAnalyzer::CheckBadExplicitType(
2596 const SpecificCall &call, const Symbol &intrinsic) {
2597 if (intrinsic.GetUltimate().GetType()) {
2598 const auto &procedure{call.specificIntrinsic.characteristics.value()};
2599 if (const auto &result{procedure.functionResult}) {
2600 if (const auto *typeAndShape{result->GetTypeAndShape()}) {
2601 if (auto declared{
2602 typeAndShape->Characterize(intrinsic, GetFoldingContext())}) {
2603 if (!declared->type().IsTkCompatibleWith(typeAndShape->type())) {
2604 if (auto *msg{Say(
2605 "The result type '%s' of the intrinsic function '%s' is not the explicit declared type '%s'"_warn_en_US,
2606 typeAndShape->AsFortran(), intrinsic.name(),
2607 declared->AsFortran())}) {
2608 msg->Attach(intrinsic.name(),
2609 "Ignored declaration of intrinsic function '%s'"_en_US,
2610 intrinsic.name());
2611 }
2612 }
2613 }
2614 }
2615 }
2616 }
2617}
2618
2619void ExpressionAnalyzer::CheckForBadRecursion(
2620 parser::CharBlock callSite, const semantics::Symbol &proc) {
2621 if (const auto *scope{proc.scope()}) {
2622 if (scope->sourceRange().Contains(callSite)) {
2623 parser::Message *msg{nullptr};
2624 if (proc.attrs().test(semantics::Attr::NON_RECURSIVE)) { // 15.6.2.1(3)
2625 msg = Say("NON_RECURSIVE procedure '%s' cannot call itself"_err_en_US,
2626 callSite);
2627 } else if (IsAssumedLengthCharacter(proc) && IsExternal(proc)) {
2628 // TODO: Also catch assumed PDT type parameters
2629 msg = Say( // 15.6.2.1(3)
2630 "Assumed-length CHARACTER(*) function '%s' cannot call itself"_err_en_US,
2631 callSite);
2632 }
2633 AttachDeclaration(msg, proc);
2634 }
2635 }
2636}
2637
2638template <typename A> static const Symbol *AssumedTypeDummy(const A &x) {
2639 if (const auto *designator{
2640 std::get_if<common::Indirection<parser::Designator>>(&x.u)}) {
2641 if (const auto *dataRef{
2642 std::get_if<parser::DataRef>(&designator->value().u)}) {
2643 if (const auto *name{std::get_if<parser::Name>(&dataRef->u)}) {
2644 return AssumedTypeDummy(*name);
2645 }
2646 }
2647 }
2648 return nullptr;
2649}
2650template <>
2651const Symbol *AssumedTypeDummy<parser::Name>(const parser::Name &name) {
2652 if (const Symbol *symbol{name.symbol}) {
2653 if (const auto *type{symbol->GetType()}) {
2654 if (type->category() == semantics::DeclTypeSpec::TypeStar) {
2655 return symbol;
2656 }
2657 }
2658 }
2659 return nullptr;
2660}
2661template <typename A>
2662static const Symbol *AssumedTypePointerOrAllocatableDummy(const A &object) {
2663 // It is illegal for allocatable of pointer objects to be TYPE(*), but at that
2664 // point it is is not guaranteed that it has been checked the object has
2665 // POINTER or ALLOCATABLE attribute, so do not assume nullptr can be directly
2666 // returned.
2667 return common::visit(
2668 common::visitors{
2669 [&](const parser::StructureComponent &x) {
2670 return AssumedTypeDummy(x.component);
2671 },
2672 [&](const parser::Name &x) { return AssumedTypeDummy(x); },
2673 },
2674 object.u);
2675}
2676template <>
2677const Symbol *AssumedTypeDummy<parser::AllocateObject>(
2678 const parser::AllocateObject &x) {
2679 return AssumedTypePointerOrAllocatableDummy(x);
2680}
2681template <>
2682const Symbol *AssumedTypeDummy<parser::PointerObject>(
2683 const parser::PointerObject &x) {
2684 return AssumedTypePointerOrAllocatableDummy(x);
2685}
2686
2687bool ExpressionAnalyzer::CheckIsValidForwardReference(
2688 const semantics::DerivedTypeSpec &dtSpec) {
2689 if (dtSpec.IsForwardReferenced()) {
2690 Say("Cannot construct value for derived type '%s' "
2691 "before it is defined"_err_en_US,
2692 dtSpec.name());
2693 return false;
2694 }
2695 return true;
2696}
2697
2698MaybeExpr ExpressionAnalyzer::Analyze(const parser::FunctionReference &funcRef,
2699 std::optional<parser::StructureConstructor> *structureConstructor) {
2700 const parser::Call &call{funcRef.v};
2701 auto restorer{GetContextualMessages().SetLocation(call.source)};
2702 ArgumentAnalyzer analyzer{*this, call.source, true /* isProcedureCall */};
2703 for (const auto &arg : std::get<std::list<parser::ActualArgSpec>>(call.t)) {
2704 analyzer.Analyze(arg, false /* not subroutine call */);
2705 }
2706 if (analyzer.fatalErrors()) {
2707 return std::nullopt;
2708 }
2709 if (std::optional<CalleeAndArguments> callee{
2710 GetCalleeAndArguments(std::get<parser::ProcedureDesignator>(call.t),
2711 analyzer.GetActuals(), false /* not subroutine */,
2712 true /* might be structure constructor */)}) {
2713 if (auto *proc{std::get_if<ProcedureDesignator>(&callee->u)}) {
2714 return MakeFunctionRef(
2715 call.source, std::move(*proc), std::move(callee->arguments));
2716 }
2717 CHECK(std::holds_alternative<semantics::SymbolRef>(callee->u))((std::holds_alternative<semantics::SymbolRef>(callee->
u)) || (Fortran::common::die("CHECK(" "std::holds_alternative<semantics::SymbolRef>(callee->u)"
") failed" " at " "flang/lib/Semantics/expression.cpp" "(%d)"
, 2717), false))
;
2718 const Symbol &symbol{*std::get<semantics::SymbolRef>(callee->u)};
2719 if (structureConstructor) {
2720 // Structure constructor misparsed as function reference?
2721 const auto &designator{std::get<parser::ProcedureDesignator>(call.t)};
2722 if (const auto *name{std::get_if<parser::Name>(&designator.u)}) {
2723 semantics::Scope &scope{context_.FindScope(name->source)};
2724 semantics::DerivedTypeSpec dtSpec{name->source, symbol.GetUltimate()};
2725 if (!CheckIsValidForwardReference(dtSpec)) {
2726 return std::nullopt;
2727 }
2728 const semantics::DeclTypeSpec &type{
2729 semantics::FindOrInstantiateDerivedType(scope, std::move(dtSpec))};
2730 auto &mutableRef{const_cast<parser::FunctionReference &>(funcRef)};
2731 *structureConstructor =
2732 mutableRef.ConvertToStructureConstructor(type.derivedTypeSpec());
2733 return Analyze(structureConstructor->value());
2734 }
2735 }
2736 if (!context_.HasError(symbol)) {
2737 AttachDeclaration(
2738 Say("'%s' is called like a function but is not a procedure"_err_en_US,
2739 symbol.name()),
2740 symbol);
2741 context_.SetError(symbol);
2742 }
2743 }
2744 return std::nullopt;
2745}
2746
2747static bool HasAlternateReturns(const evaluate::ActualArguments &args) {
2748 for (const auto &arg : args) {
2749 if (arg && arg->isAlternateReturn()) {
2750 return true;
2751 }
2752 }
2753 return false;
2754}
2755
2756void ExpressionAnalyzer::Analyze(const parser::CallStmt &callStmt) {
2757 const parser::Call &call{callStmt.v};
2758 auto restorer{GetContextualMessages().SetLocation(call.source)};
2759 ArgumentAnalyzer analyzer{*this, call.source, true /* isProcedureCall */};
2760 const auto &actualArgList{std::get<std::list<parser::ActualArgSpec>>(call.t)};
2761 for (const auto &arg : actualArgList) {
2762 analyzer.Analyze(arg, true /* is subroutine call */);
2763 }
2764 if (!analyzer.fatalErrors()) {
2765 if (std::optional<CalleeAndArguments> callee{
2766 GetCalleeAndArguments(std::get<parser::ProcedureDesignator>(call.t),
2767 analyzer.GetActuals(), true /* subroutine */)}) {
2768 ProcedureDesignator *proc{std::get_if<ProcedureDesignator>(&callee->u)};
2769 CHECK(proc)((proc) || (Fortran::common::die("CHECK(" "proc" ") failed" " at "
"flang/lib/Semantics/expression.cpp" "(%d)", 2769), false))
;
2770 if (CheckCall(call.source, *proc, callee->arguments)) {
2771 callStmt.typedCall.Reset(
2772 new ProcedureRef{std::move(*proc), std::move(callee->arguments),
2773 HasAlternateReturns(callee->arguments)},
2774 ProcedureRef::Deleter);
2775 return;
2776 }
2777 }
2778 if (!context_.AnyFatalError()) {
2779 std::string buf;
2780 llvm::raw_string_ostream dump{buf};
2781 parser::DumpTree(dump, callStmt);
2782 Say("Internal error: Expression analysis failed on CALL statement: %s"_err_en_US,
2783 dump.str());
2784 }
2785 }
2786}
2787
2788const Assignment *ExpressionAnalyzer::Analyze(const parser::AssignmentStmt &x) {
2789 if (!x.typedAssignment) {
2790 ArgumentAnalyzer analyzer{*this};
2791 const auto &variable{std::get<parser::Variable>(x.t)};
2792 analyzer.Analyze(variable);
2793 analyzer.Analyze(std::get<parser::Expr>(x.t));
2794 std::optional<Assignment> assignment;
2795 if (!analyzer.fatalErrors()) {
2796 auto restorer{GetContextualMessages().SetLocation(variable.GetSource())};
2797 std::optional<ProcedureRef> procRef{analyzer.TryDefinedAssignment()};
2798 if (!procRef) {
2799 analyzer.CheckForNullPointer(
2800 "in a non-pointer intrinsic assignment statement");
2801 const Expr<SomeType> &lhs{analyzer.GetExpr(0)};
2802 if (auto dyType{lhs.GetType()};
2803 dyType && dyType->IsPolymorphic()) { // 10.2.1.2p1(1)
2804 const Symbol *lastWhole0{UnwrapWholeSymbolOrComponentDataRef(lhs)};
2805 const Symbol *lastWhole{
2806 lastWhole0 ? &lastWhole0->GetUltimate() : nullptr};
2807 if (!lastWhole || !IsAllocatable(*lastWhole)) {
2808 Say("Left-hand side of assignment may not be polymorphic unless assignment is to an entire allocatable"_err_en_US);
2809 } else if (evaluate::IsCoarray(*lastWhole)) {
2810 Say("Left-hand side of assignment may not be polymorphic if it is a coarray"_err_en_US);
2811 }
2812 }
2813 }
2814 assignment.emplace(analyzer.MoveExpr(0), analyzer.MoveExpr(1));
2815 if (procRef) {
2816 assignment->u = std::move(*procRef);
2817 }
2818 }
2819 x.typedAssignment.Reset(new GenericAssignmentWrapper{std::move(assignment)},
2820 GenericAssignmentWrapper::Deleter);
2821 }
2822 return common::GetPtrFromOptional(x.typedAssignment->v);
2823}
2824
2825const Assignment *ExpressionAnalyzer::Analyze(
2826 const parser::PointerAssignmentStmt &x) {
2827 if (!x.typedAssignment) {
2828 MaybeExpr lhs{Analyze(std::get<parser::DataRef>(x.t))};
2829 MaybeExpr rhs;
2830 {
2831 auto restorer{AllowNullPointer()};
2832 rhs = Analyze(std::get<parser::Expr>(x.t));
2833 }
2834 if (!lhs || !rhs) {
2835 x.typedAssignment.Reset(
2836 new GenericAssignmentWrapper{}, GenericAssignmentWrapper::Deleter);
2837 } else {
2838 Assignment assignment{std::move(*lhs), std::move(*rhs)};
2839 common::visit(
2840 common::visitors{
2841 [&](const std::list<parser::BoundsRemapping> &list) {
2842 Assignment::BoundsRemapping bounds;
2843 for (const auto &elem : list) {
2844 auto lower{AsSubscript(Analyze(std::get<0>(elem.t)))};
2845 auto upper{AsSubscript(Analyze(std::get<1>(elem.t)))};
2846 if (lower && upper) {
2847 bounds.emplace_back(
2848 Fold(std::move(*lower)), Fold(std::move(*upper)));
2849 }
2850 }
2851 assignment.u = std::move(bounds);
2852 },
2853 [&](const std::list<parser::BoundsSpec> &list) {
2854 Assignment::BoundsSpec bounds;
2855 for (const auto &bound : list) {
2856 if (auto lower{AsSubscript(Analyze(bound.v))}) {
2857 bounds.emplace_back(Fold(std::move(*lower)));
2858 }
2859 }
2860 assignment.u = std::move(bounds);
2861 },
2862 },
2863 std::get<parser::PointerAssignmentStmt::Bounds>(x.t).u);
2864 x.typedAssignment.Reset(
2865 new GenericAssignmentWrapper{std::move(assignment)},
2866 GenericAssignmentWrapper::Deleter);
2867 }
2868 }
2869 return common::GetPtrFromOptional(x.typedAssignment->v);
2870}
2871
2872static bool IsExternalCalledImplicitly(
2873 parser::CharBlock callSite, const ProcedureDesignator &proc) {
2874 if (const auto *symbol{proc.GetSymbol()}) {
2875 return symbol->has<semantics::SubprogramDetails>() &&
2876 symbol->owner().IsGlobal() &&
2877 (!symbol->scope() /*ENTRY*/ ||
2878 !symbol->scope()->sourceRange().Contains(callSite));
2879 } else {
2880 return false;
2881 }
2882}
2883
2884std::optional<characteristics::Procedure> ExpressionAnalyzer::CheckCall(
2885 parser::CharBlock callSite, const ProcedureDesignator &proc,
2886 ActualArguments &arguments) {
2887 bool treatExternalAsImplicit{IsExternalCalledImplicitly(callSite, proc)};
2888 const Symbol *procSymbol{proc.GetSymbol()};
2889 std::optional<characteristics::Procedure> chars;
2890 if (procSymbol && procSymbol->has<semantics::ProcEntityDetails>() &&
2891 procSymbol->owner().IsGlobal()) {
2892 // Unknown global external, implicit interface; assume
2893 // characteristics from the actual arguments, and check
2894 // for consistency with other references.
2895 chars = characteristics::Procedure::FromActuals(
2896 proc, arguments, context_.foldingContext());
2897 if (chars && procSymbol) {
2898 // Ensure calls over implicit interfaces are consistent
2899 auto name{procSymbol->name()};
2900 if (auto iter{implicitInterfaces_.find(name)};
2901 iter != implicitInterfaces_.end()) {
2902 std::string whyNot;
2903 if (!chars->IsCompatibleWith(iter->second.second, &whyNot)) {
2904 if (auto *msg{Say(callSite,
2905 "Reference to the procedure '%s' has an implicit interface that is distinct from another reference: %s"_warn_en_US,
2906 name, whyNot)}) {
2907 msg->Attach(
2908 iter->second.first, "previous reference to '%s'"_en_US, name);
2909 }
2910 }
2911 } else {
2912 implicitInterfaces_.insert(
2913 std::make_pair(name, std::make_pair(callSite, *chars)));
2914 }
2915 }
2916 }
2917 if (!chars) {
2918 chars = characteristics::Procedure::Characterize(
2919 proc, context_.foldingContext());
2920 }
2921 bool ok{true};
2922 if (chars) {
2923 if (treatExternalAsImplicit && !chars->CanBeCalledViaImplicitInterface()) {
2924 Say(callSite,
2925 "References to the procedure '%s' require an explicit interface"_err_en_US,
2926 DEREF(procSymbol)Fortran::common::Deref(procSymbol, "flang/lib/Semantics/expression.cpp"
, 2926)
.name());
2927 }
2928 const SpecificIntrinsic *specificIntrinsic{proc.GetSpecificIntrinsic()};
2929 bool procIsDummy{procSymbol && IsDummy(*procSymbol)};
2930 if (chars->functionResult &&
2931 chars->functionResult->IsAssumedLengthCharacter() &&
2932 !specificIntrinsic && !procIsDummy) {
2933 Say(callSite,
2934 "Assumed-length character function must be defined with a length to be called"_err_en_US);
2935 }
2936 ok &= semantics::CheckArguments(*chars, arguments, GetFoldingContext(),
2937 context_.FindScope(callSite), treatExternalAsImplicit,
2938 specificIntrinsic);
2939 if (procSymbol && !IsPureProcedure(*procSymbol)) {
2940 if (const semantics::Scope *
2941 pure{semantics::FindPureProcedureContaining(
2942 context_.FindScope(callSite))}) {
2943 Say(callSite,
2944 "Procedure '%s' referenced in pure subprogram '%s' must be pure too"_err_en_US,
2945 procSymbol->name(), DEREF(pure->symbol())Fortran::common::Deref(pure->symbol(), "flang/lib/Semantics/expression.cpp"
, 2945)
.name());
2946 }
2947 }
2948 }
2949 if (ok && !treatExternalAsImplicit && procSymbol &&
2950 !(chars && chars->HasExplicitInterface())) {
2951 if (const Symbol *global{FindGlobal(*procSymbol)};
2952 global && global != procSymbol && IsProcedure(*global)) {
2953 // Check a known global definition behind a local interface
2954 if (auto globalChars{characteristics::Procedure::Characterize(
2955 *global, context_.foldingContext())}) {
2956 semantics::CheckArguments(*globalChars, arguments, GetFoldingContext(),
2957 context_.FindScope(callSite), true,
2958 nullptr /*not specific intrinsic*/);
2959 }
2960 }
2961 }
2962 return chars;
2963}
2964
2965// Unary operations
2966
2967MaybeExpr ExpressionAnalyzer::Analyze(const parser::Expr::Parentheses &x) {
2968 if (MaybeExpr operand{Analyze(x.v.value())}) {
2969 if (const semantics::Symbol *symbol{GetLastSymbol(*operand)}) {
2970 if (const semantics::Symbol *result{FindFunctionResult(*symbol)}) {
2971 if (semantics::IsProcedurePointer(*result)) {
2972 Say("A function reference that returns a procedure "
2973 "pointer may not be parenthesized"_err_en_US); // C1003
2974 }
2975 }
2976 }
2977 return Parenthesize(std::move(*operand));
2978 }
2979 return std::nullopt;
2980}
2981
2982static MaybeExpr NumericUnaryHelper(ExpressionAnalyzer &context,
2983 NumericOperator opr, const parser::Expr::IntrinsicUnary &x) {
2984 ArgumentAnalyzer analyzer{context};
2985 analyzer.Analyze(x.v);
2986 if (!analyzer.fatalErrors()) {
2987 if (analyzer.IsIntrinsicNumeric(opr)) {
2988 analyzer.CheckForNullPointer();
2989 if (opr == NumericOperator::Add) {
2990 return analyzer.MoveExpr(0);
2991 } else {
2992 return Negation(context.GetContextualMessages(), analyzer.MoveExpr(0));
2993 }
2994 } else {
2995 return analyzer.TryDefinedOp(AsFortran(opr),
2996 "Operand of unary %s must be numeric; have %s"_err_en_US);
2997 }
2998 }
2999 return std::nullopt;
3000}
3001
3002MaybeExpr ExpressionAnalyzer::Analyze(const parser::Expr::UnaryPlus &x) {
3003 return NumericUnaryHelper(*this, NumericOperator::Add, x);
3004}
3005
3006MaybeExpr ExpressionAnalyzer::Analyze(const parser::Expr::Negate &x) {
3007 if (const auto *litConst{
3008 std::get_if<parser::LiteralConstant>(&x.v.value().u)}) {
3009 if (const auto *intConst{
3010 std::get_if<parser::IntLiteralConstant>(&litConst->u)}) {
3011 return Analyze(*intConst, true);
3012 }
3013 }
3014 return NumericUnaryHelper(*this, NumericOperator::Subtract, x);
3015}
3016
3017MaybeExpr ExpressionAnalyzer::Analyze(const parser::Expr::NOT &x) {
3018 ArgumentAnalyzer analyzer{*this};
3019 analyzer.Analyze(x.v);
3020 if (!analyzer.fatalErrors()) {
3021 if (analyzer.IsIntrinsicLogical()) {
3022 analyzer.CheckForNullPointer();
3023 return AsGenericExpr(
3024 LogicalNegation(std::get<Expr<SomeLogical>>(analyzer.MoveExpr(0).u)));
3025 } else {
3026 return analyzer.TryDefinedOp(LogicalOperator::Not,
3027 "Operand of %s must be LOGICAL; have %s"_err_en_US);
3028 }
3029 }
3030 return std::nullopt;
3031}
3032
3033MaybeExpr ExpressionAnalyzer::Analyze(const parser::Expr::PercentLoc &x) {
3034 // Represent %LOC() exactly as if it had been a call to the LOC() extension
3035 // intrinsic function.
3036 // Use the actual source for the name of the call for error reporting.
3037 std::optional<ActualArgument> arg;
3038 if (const Symbol *assumedTypeDummy{AssumedTypeDummy(x.v.value())}) {
3039 arg = ActualArgument{ActualArgument::AssumedType{*assumedTypeDummy}};
3040 } else if (MaybeExpr argExpr{Analyze(x.v.value())}) {
3041 arg = ActualArgument{std::move(*argExpr)};
3042 } else {
3043 return std::nullopt;
3044 }
3045 parser::CharBlock at{GetContextualMessages().at()};
3046 CHECK(at.size() >= 4)((at.size() >= 4) || (Fortran::common::die("CHECK(" "at.size() >= 4"
") failed" " at " "flang/lib/Semantics/expression.cpp" "(%d)"
, 3046), false))
;
3047 parser::CharBlock loc{at.begin() + 1, 3};
3048 CHECK(loc == "loc")((loc == "loc") || (Fortran::common::die("CHECK(" "loc == \"loc\""
") failed" " at " "flang/lib/Semantics/expression.cpp" "(%d)"
, 3048), false))
;
3049 return MakeFunctionRef(loc, ActualArguments{std::move(*arg)});
3050}
3051
3052MaybeExpr ExpressionAnalyzer::Analyze(const parser::Expr::DefinedUnary &x) {
3053 const auto &name{std::get<parser::DefinedOpName>(x.t).v};
3054 ArgumentAnalyzer analyzer{*this, name.source};
3055 analyzer.Analyze(std::get<1>(x.t));
3056 return analyzer.TryDefinedOp(name.source.ToString().c_str(),
1
Calling 'ArgumentAnalyzer::TryDefinedOp'
3057 "No operator %s defined for %s"_err_en_US, true);
3058}
3059
3060// Binary (dyadic) operations
3061
3062template <template <typename> class OPR>
3063MaybeExpr NumericBinaryHelper(ExpressionAnalyzer &context, NumericOperator opr,
3064 const parser::Expr::IntrinsicBinary &x) {
3065 ArgumentAnalyzer analyzer{context};
3066 analyzer.Analyze(std::get<0>(x.t));
3067 analyzer.Analyze(std::get<1>(x.t));
3068 if (!analyzer.fatalErrors()) {
3069 if (analyzer.IsIntrinsicNumeric(opr)) {
3070 analyzer.CheckForNullPointer();
3071 analyzer.CheckConformance();
3072 return NumericOperation<OPR>(context.GetContextualMessages(),
3073 analyzer.MoveExpr(0), analyzer.MoveExpr(1),
3074 context.GetDefaultKind(TypeCategory::Real));
3075 } else {
3076 return analyzer.TryDefinedOp(AsFortran(opr),
3077 "Operands of %s must be numeric; have %s and %s"_err_en_US);
3078 }
3079 }
3080 return std::nullopt;
3081}
3082
3083MaybeExpr ExpressionAnalyzer::Analyze(const parser::Expr::Power &x) {
3084 return NumericBinaryHelper<Power>(*this, NumericOperator::Power, x);
3085}
3086
3087MaybeExpr ExpressionAnalyzer::Analyze(const parser::Expr::Multiply &x) {
3088 return NumericBinaryHelper<Multiply>(*this, NumericOperator::Multiply, x);
3089}
3090
3091MaybeExpr ExpressionAnalyzer::Analyze(const parser::Expr::Divide &x) {
3092 return NumericBinaryHelper<Divide>(*this, NumericOperator::Divide, x);
3093}
3094
3095MaybeExpr ExpressionAnalyzer::Analyze(const parser::Expr::Add &x) {
3096 return NumericBinaryHelper<Add>(*this, NumericOperator::Add, x);
3097}
3098
3099MaybeExpr ExpressionAnalyzer::Analyze(const parser::Expr::Subtract &x) {
3100 return NumericBinaryHelper<Subtract>(*this, NumericOperator::Subtract, x);
3101}
3102
3103MaybeExpr ExpressionAnalyzer::Analyze(
3104 const parser::Expr::ComplexConstructor &z) {
3105 return AnalyzeComplex(Analyze(std::get<0>(z.t).value()),
3106 Analyze(std::get<1>(z.t).value()), "complex constructor");
3107}
3108
3109MaybeExpr ExpressionAnalyzer::Analyze(const parser::Expr::Concat &x) {
3110 ArgumentAnalyzer analyzer{*this};
3111 analyzer.Analyze(std::get<0>(x.t));
3112 analyzer.Analyze(std::get<1>(x.t));
3113 if (!analyzer.fatalErrors()) {
3114 if (analyzer.IsIntrinsicConcat()) {
3115 analyzer.CheckForNullPointer();
3116 return common::visit(
3117 [&](auto &&x, auto &&y) -> MaybeExpr {
3118 using T = ResultType<decltype(x)>;
3119 if constexpr (std::is_same_v<T, ResultType<decltype(y)>>) {
3120 return AsGenericExpr(Concat<T::kind>{std::move(x), std::move(y)});
3121 } else {
3122 DIE("different types for intrinsic concat")Fortran::common::die("different types for intrinsic concat" " at "
"flang/lib/Semantics/expression.cpp" "(%d)", 3122)
;
3123 }
3124 },
3125 std::move(std::get<Expr<SomeCharacter>>(analyzer.MoveExpr(0).u).u),
3126 std::move(std::get<Expr<SomeCharacter>>(analyzer.MoveExpr(1).u).u));
3127 } else {
3128 return analyzer.TryDefinedOp("//",
3129 "Operands of %s must be CHARACTER with the same kind; have %s and %s"_err_en_US);
3130 }
3131 }
3132 return std::nullopt;
3133}
3134
3135// The Name represents a user-defined intrinsic operator.
3136// If the actuals match one of the specific procedures, return a function ref.
3137// Otherwise report the error in messages.
3138MaybeExpr ExpressionAnalyzer::AnalyzeDefinedOp(
3139 const parser::Name &name, ActualArguments &&actuals) {
3140 if (auto callee{GetCalleeAndArguments(name, std::move(actuals))}) {
7
Calling 'ExpressionAnalyzer::GetCalleeAndArguments'
16
Returning from 'ExpressionAnalyzer::GetCalleeAndArguments'
3141 CHECK(std::holds_alternative<ProcedureDesignator>(callee->u))((std::holds_alternative<ProcedureDesignator>(callee->
u)) || (Fortran::common::die("CHECK(" "std::holds_alternative<ProcedureDesignator>(callee->u)"
") failed" " at " "flang/lib/Semantics/expression.cpp" "(%d)"
, 3141), false))
;
17
Taking true branch
3142 return MakeFunctionRef(name.source,
3143 std::move(std::get<ProcedureDesignator>(callee->u)),
3144 std::move(callee->arguments));
3145 } else {
3146 return std::nullopt;
3147 }
3148}
3149
3150MaybeExpr RelationHelper(ExpressionAnalyzer &context, RelationalOperator opr,
3151 const parser::Expr::IntrinsicBinary &x) {
3152 ArgumentAnalyzer analyzer{context};
3153 analyzer.Analyze(std::get<0>(x.t));
3154 analyzer.Analyze(std::get<1>(x.t));
3155 if (!analyzer.fatalErrors()) {
3156 std::optional<DynamicType> leftType{analyzer.GetType(0)};
3157 std::optional<DynamicType> rightType{analyzer.GetType(1)};
3158 analyzer.ConvertBOZ(leftType, 0, rightType);
3159 analyzer.ConvertBOZ(rightType, 1, leftType);
3160 if (leftType && rightType &&
3161 analyzer.IsIntrinsicRelational(opr, *leftType, *rightType)) {
3162 analyzer.CheckForNullPointer("as a relational operand");
3163 return AsMaybeExpr(Relate(context.GetContextualMessages(), opr,
3164 analyzer.MoveExpr(0), analyzer.MoveExpr(1)));
3165 } else {
3166 return analyzer.TryDefinedOp(opr,
3167 leftType && leftType->category() == TypeCategory::Logical &&
3168 rightType && rightType->category() == TypeCategory::Logical
3169 ? "LOGICAL operands must be compared using .EQV. or .NEQV."_err_en_US
3170 : "Operands of %s must have comparable types; have %s and %s"_err_en_US);
3171 }
3172 }
3173 return std::nullopt;
3174}
3175
3176MaybeExpr ExpressionAnalyzer::Analyze(const parser::Expr::LT &x) {
3177 return RelationHelper(*this, RelationalOperator::LT, x);
3178}
3179
3180MaybeExpr ExpressionAnalyzer::Analyze(const parser::Expr::LE &x) {
3181 return RelationHelper(*this, RelationalOperator::LE, x);
3182}
3183
3184MaybeExpr ExpressionAnalyzer::Analyze(const parser::Expr::EQ &x) {
3185 return RelationHelper(*this, RelationalOperator::EQ, x);
3186}
3187
3188MaybeExpr ExpressionAnalyzer::Analyze(const parser::Expr::NE &x) {
3189 return RelationHelper(*this, RelationalOperator::NE, x);
3190}
3191
3192MaybeExpr ExpressionAnalyzer::Analyze(const parser::Expr::GE &x) {
3193 return RelationHelper(*this, RelationalOperator::GE, x);
3194}
3195
3196MaybeExpr ExpressionAnalyzer::Analyze(const parser::Expr::GT &x) {
3197 return RelationHelper(*this, RelationalOperator::GT, x);
3198}
3199
3200MaybeExpr LogicalBinaryHelper(ExpressionAnalyzer &context, LogicalOperator opr,
3201 const parser::Expr::IntrinsicBinary &x) {
3202 ArgumentAnalyzer analyzer{context};
3203 analyzer.Analyze(std::get<0>(x.t));
3204 analyzer.Analyze(std::get<1>(x.t));
3205 if (!analyzer.fatalErrors()) {
3206 if (analyzer.IsIntrinsicLogical()) {
3207 analyzer.CheckForNullPointer("as a logical operand");
3208 return AsGenericExpr(BinaryLogicalOperation(opr,
3209 std::get<Expr<SomeLogical>>(analyzer.MoveExpr(0).u),
3210 std::get<Expr<SomeLogical>>(analyzer.MoveExpr(1).u)));
3211 } else {
3212 return analyzer.TryDefinedOp(
3213 opr, "Operands of %s must be LOGICAL; have %s and %s"_err_en_US);
3214 }
3215 }
3216 return std::nullopt;
3217}
3218
3219MaybeExpr ExpressionAnalyzer::Analyze(const parser::Expr::AND &x) {
3220 return LogicalBinaryHelper(*this, LogicalOperator::And, x);
3221}
3222
3223MaybeExpr ExpressionAnalyzer::Analyze(const parser::Expr::OR &x) {
3224 return LogicalBinaryHelper(*this, LogicalOperator::Or, x);
3225}
3226
3227MaybeExpr ExpressionAnalyzer::Analyze(const parser::Expr::EQV &x) {
3228 return LogicalBinaryHelper(*this, LogicalOperator::Eqv, x);
3229}
3230
3231MaybeExpr ExpressionAnalyzer::Analyze(const parser::Expr::NEQV &x) {
3232 return LogicalBinaryHelper(*this, LogicalOperator::Neqv, x);
3233}
3234
3235MaybeExpr ExpressionAnalyzer::Analyze(const parser::Expr::DefinedBinary &x) {
3236 const auto &name{std::get<parser::DefinedOpName>(x.t).v};
3237 ArgumentAnalyzer analyzer{*this, name.source};
3238 analyzer.Analyze(std::get<1>(x.t));
3239 analyzer.Analyze(std::get<2>(x.t));
3240 return analyzer.TryDefinedOp(name.source.ToString().c_str(),
3241 "No operator %s defined for %s and %s"_err_en_US, true);
3242}
3243
3244// Returns true if a parsed function reference should be converted
3245// into an array element reference.
3246static bool CheckFuncRefToArrayElement(semantics::SemanticsContext &context,
3247 const parser::FunctionReference &funcRef) {
3248 // Emit message if the function reference fix will end up an array element
3249 // reference with no subscripts, or subscripts on a scalar, because it will
3250 // not be possible to later distinguish in expressions between an empty
3251 // subscript list due to bad subscripts error recovery or because the
3252 // user did not put any.
3253 auto &proc{std::get<parser::ProcedureDesignator>(funcRef.v.t)};
3254 const auto *name{std::get_if<parser::Name>(&proc.u)};
3255 if (!name) {
3256 name = &std::get<parser::ProcComponentRef>(proc.u).v.thing.component;
3257 }
3258 if (!name->symbol) {
3259 return false;
3260 } else if (name->symbol->Rank() == 0) {
3261 if (const Symbol *function{
3262 semantics::IsFunctionResultWithSameNameAsFunction(*name->symbol)}) {
3263 auto &msg{context.Say(funcRef.v.source,
3264 function->flags().test(Symbol::Flag::StmtFunction)
3265 ? "Recursive call to statement function '%s' is not allowed"_err_en_US
3266 : "Recursive call to '%s' requires a distinct RESULT in its declaration"_err_en_US,
3267 name->source)};
3268 AttachDeclaration(&msg, *function);
3269 name->symbol = const_cast<Symbol *>(function);
3270 }
3271 return false;
3272 } else {
3273 if (std::get<std::list<parser::ActualArgSpec>>(funcRef.v.t).empty()) {
3274 auto &msg{context.Say(funcRef.v.source,
3275 "Reference to array '%s' with empty subscript list"_err_en_US,
3276 name->source)};
3277 if (name->symbol) {
3278 AttachDeclaration(&msg, *name->symbol);
3279 }
3280 }
3281 return true;
3282 }
3283}
3284
3285// Converts, if appropriate, an original misparse of ambiguous syntax like
3286// A(1) as a function reference into an array reference.
3287// Misparsed structure constructors are detected elsewhere after generic
3288// function call resolution fails.
3289template <typename... A>
3290static void FixMisparsedFunctionReference(
3291 semantics::SemanticsContext &context, const std::variant<A...> &constU) {
3292 // The parse tree is updated in situ when resolving an ambiguous parse.
3293 using uType = std::decay_t<decltype(constU)>;
3294 auto &u{const_cast<uType &>(constU)};
3295 if (auto *func{
3296 std::get_if<common::Indirection<parser::FunctionReference>>(&u)}) {
3297 parser::FunctionReference &funcRef{func->value()};
3298 // Ensure that there are no argument keywords
3299 for (const auto &arg :
3300 std::get<std::list<parser::ActualArgSpec>>(funcRef.v.t)) {
3301 if (std::get<std::optional<parser::Keyword>>(arg.t)) {
3302 return;
3303 }
3304 }
3305 auto &proc{std::get<parser::ProcedureDesignator>(funcRef.v.t)};
3306 if (Symbol *origSymbol{
3307 common::visit(common::visitors{
3308 [&](parser::Name &name) { return name.symbol; },
3309 [&](parser::ProcComponentRef &pcr) {
3310 return pcr.v.thing.component.symbol;
3311 },
3312 },
3313 proc.u)}) {
3314 Symbol &symbol{origSymbol->GetUltimate()};
3315 if (symbol.has<semantics::ObjectEntityDetails>() ||
3316 symbol.has<semantics::AssocEntityDetails>()) {
3317 // Note that expression in AssocEntityDetails cannot be a procedure
3318 // pointer as per C1105 so this cannot be a function reference.
3319 if constexpr (common::HasMember<common::Indirection<parser::Designator>,
3320 uType>) {
3321 if (CheckFuncRefToArrayElement(context, funcRef)) {
3322 u = common::Indirection{funcRef.ConvertToArrayElementRef()};
3323 }
3324 } else {
3325 DIE("can't fix misparsed function as array reference")Fortran::common::die("can't fix misparsed function as array reference"
" at " "flang/lib/Semantics/expression.cpp" "(%d)", 3325)
;
3326 }
3327 }
3328 }
3329 }
3330}
3331
3332// Common handling of parse tree node types that retain the
3333// representation of the analyzed expression.
3334template <typename PARSED>
3335MaybeExpr ExpressionAnalyzer::ExprOrVariable(
3336 const PARSED &x, parser::CharBlock source) {
3337 auto restorer{GetContextualMessages().SetLocation(source)};
3338 if constexpr (std::is_same_v<PARSED, parser::Expr> ||
3339 std::is_same_v<PARSED, parser::Variable>) {
3340 FixMisparsedFunctionReference(context_, x.u);
3341 }
3342 if (AssumedTypeDummy(x)) { // C710
3343 Say("TYPE(*) dummy argument may only be used as an actual argument"_err_en_US);
3344 ResetExpr(x);
3345 return std::nullopt;
3346 }
3347 MaybeExpr result;
3348 if constexpr (common::HasMember<parser::StructureConstructor,
3349 std::decay_t<decltype(x.u)>> &&
3350 common::HasMember<common::Indirection<parser::FunctionReference>,
3351 std::decay_t<decltype(x.u)>>) {
3352 if (const auto *funcRef{
3353 std::get_if<common::Indirection<parser::FunctionReference>>(
3354 &x.u)}) {
3355 // Function references in Exprs might turn out to be misparsed structure
3356 // constructors; we have to try generic procedure resolution
3357 // first to be sure.
3358 std::optional<parser::StructureConstructor> ctor;
3359 result = Analyze(funcRef->value(), &ctor);
3360 if (result && ctor) {
3361 // A misparsed function reference is really a structure
3362 // constructor. Repair the parse tree in situ.
3363 const_cast<PARSED &>(x).u = std::move(*ctor);
3364 }
3365 } else {
3366 result = Analyze(x.u);
3367 }
3368 } else {
3369 result = Analyze(x.u);
3370 }
3371 if (result) {
3372 if constexpr (std::is_same_v<PARSED, parser::Expr>) {
3373 if (!isNullPointerOk_ && IsNullPointer(*result)) {
3374 Say(source,
3375 "NULL() may not be used as an expression in this context"_err_en_US);
3376 }
3377 }
3378 SetExpr(x, Fold(std::move(*result)));
3379 return x.typedExpr->v;
3380 } else {
3381 ResetExpr(x);
3382 if (!context_.AnyFatalError()) {
3383 std::string buf;
3384 llvm::raw_string_ostream dump{buf};
3385 parser::DumpTree(dump, x);
3386 Say("Internal error: Expression analysis failed on: %s"_err_en_US,
3387 dump.str());
3388 }
3389 return std::nullopt;
3390 }
3391}
3392
3393// This is an optional preliminary pass over parser::Expr subtrees.
3394// Given an expression tree, iteratively traverse it in a bottom-up order
3395// to analyze all of its subexpressions. A later normal top-down analysis
3396// will then be able to use the results that will have been saved in the
3397// parse tree without having to recurse deeply. This technique keeps
3398// absurdly deep expression parse trees from causing the analyzer to overflow
3399// its stack.
3400MaybeExpr ExpressionAnalyzer::IterativelyAnalyzeSubexpressions(
3401 const parser::Expr &top) {
3402 std::vector<const parser::Expr *> queue, finish;
3403 queue.push_back(&top);
3404 do {
3405 const parser::Expr &expr{*queue.back()};
3406 queue.pop_back();
3407 if (!expr.typedExpr) {
3408 const parser::Expr::IntrinsicUnary *unary{nullptr};
3409 const parser::Expr::IntrinsicBinary *binary{nullptr};
3410 common::visit(
3411 [&unary, &binary](auto &y) {
3412 if constexpr (std::is_convertible_v<decltype(&y),
3413 decltype(unary)>) {
3414 // Don't evaluate a constant operand to Negate
3415 if (!std::holds_alternative<parser::LiteralConstant>(
3416 y.v.value().u)) {
3417 unary = &y;
3418 }
3419 } else if constexpr (std::is_convertible_v<decltype(&y),
3420 decltype(binary)>) {
3421 binary = &y;
3422 }
3423 },
3424 expr.u);
3425 if (unary) {
3426 queue.push_back(&unary->v.value());
3427 } else if (binary) {
3428 queue.push_back(&std::get<0>(binary->t).value());
3429 queue.push_back(&std::get<1>(binary->t).value());
3430 }
3431 finish.push_back(&expr);
3432 }
3433 } while (!queue.empty());
3434 // Analyze the collected subexpressions in bottom-up order.
3435 // On an error, bail out and leave partial results in place.
3436 MaybeExpr result;
3437 for (auto riter{finish.rbegin()}; riter != finish.rend(); ++riter) {
3438 const parser::Expr &expr{**riter};
3439 result = ExprOrVariable(expr, expr.source);
3440 if (!result) {
3441 return result;
3442 }
3443 }
3444 return result; // last value was from analysis of "top"
3445}
3446
3447MaybeExpr ExpressionAnalyzer::Analyze(const parser::Expr &expr) {
3448 bool wasIterativelyAnalyzing{iterativelyAnalyzingSubexpressions_};
3449 MaybeExpr result;
3450 if (useSavedTypedExprs_) {
3451 if (expr.typedExpr) {
3452 return expr.typedExpr->v;
3453 }
3454 if (!wasIterativelyAnalyzing && !context_.anyDefinedIntrinsicOperator()) {
3455 iterativelyAnalyzingSubexpressions_ = true;
3456 result = IterativelyAnalyzeSubexpressions(expr);
3457 }
3458 }
3459 if (!result) {
3460 result = ExprOrVariable(expr, expr.source);
3461 }
3462 iterativelyAnalyzingSubexpressions_ = wasIterativelyAnalyzing;
3463 return result;
3464}
3465
3466MaybeExpr ExpressionAnalyzer::Analyze(const parser::Variable &variable) {
3467 if (useSavedTypedExprs_ && variable.typedExpr) {
3468 return variable.typedExpr->v;
3469 }
3470 return ExprOrVariable(variable, variable.GetSource());
3471}
3472
3473MaybeExpr ExpressionAnalyzer::Analyze(const parser::Selector &selector) {
3474 if (const auto *var{std::get_if<parser::Variable>(&selector.u)}) {
3475 if (!useSavedTypedExprs_ || !var->typedExpr) {
3476 parser::CharBlock source{var->GetSource()};
3477 auto restorer{GetContextualMessages().SetLocation(source)};
3478 FixMisparsedFunctionReference(context_, var->u);
3479 if (const auto *funcRef{
3480 std::get_if<common::Indirection<parser::FunctionReference>>(
3481 &var->u)}) {
3482 // A Selector that parsed as a Variable might turn out during analysis
3483 // to actually be a structure constructor. In that case, repair the
3484 // Variable parse tree node into an Expr
3485 std::optional<parser::StructureConstructor> ctor;
3486 if (MaybeExpr result{Analyze(funcRef->value(), &ctor)}) {
3487 if (ctor) {
3488 auto &writable{const_cast<parser::Selector &>(selector)};
3489 writable.u = parser::Expr{std::move(*ctor)};
3490 auto &expr{std::get<parser::Expr>(writable.u)};
3491 expr.source = source;
3492 SetExpr(expr, Fold(std::move(*result)));
3493 return expr.typedExpr->v;
3494 } else {
3495 SetExpr(*var, Fold(std::move(*result)));
3496 return var->typedExpr->v;
3497 }
3498 } else {
3499 ResetExpr(*var);
3500 if (context_.AnyFatalError()) {
3501 return std::nullopt;
3502 }
3503 }
3504 }
3505 }
3506 }
3507 // Not a Variable -> FunctionReference; handle normally as Variable or Expr
3508 return Analyze(selector.u);
3509}
3510
3511MaybeExpr ExpressionAnalyzer::Analyze(const parser::DataStmtConstant &x) {
3512 auto restorer{common::ScopedSet(inDataStmtConstant_, true)};
3513 return ExprOrVariable(x, x.source);
3514}
3515
3516MaybeExpr ExpressionAnalyzer::Analyze(const parser::AllocateObject &x) {
3517 return ExprOrVariable(x, parser::FindSourceLocation(x));
3518}
3519
3520MaybeExpr ExpressionAnalyzer::Analyze(const parser::PointerObject &x) {
3521 return ExprOrVariable(x, parser::FindSourceLocation(x));
3522}
3523
3524Expr<SubscriptInteger> ExpressionAnalyzer::AnalyzeKindSelector(
3525 TypeCategory category,
3526 const std::optional<parser::KindSelector> &selector) {
3527 int defaultKind{GetDefaultKind(category)};
3528 if (!selector) {
3529 return Expr<SubscriptInteger>{defaultKind};
3530 }
3531 return common::visit(
3532 common::visitors{
3533 [&](const parser::ScalarIntConstantExpr &x) {
3534 if (MaybeExpr kind{Analyze(x)}) {
3535 if (std::optional<std::int64_t> code{ToInt64(*kind)}) {
3536 if (CheckIntrinsicKind(category, *code)) {
3537 return Expr<SubscriptInteger>{*code};
3538 }
3539 } else if (auto *intExpr{UnwrapExpr<Expr<SomeInteger>>(*kind)}) {
3540 return ConvertToType<SubscriptInteger>(std::move(*intExpr));
3541 }
3542 }
3543 return Expr<SubscriptInteger>{defaultKind};
3544 },
3545 [&](const parser::KindSelector::StarSize &x) {
3546 std::intmax_t size = x.v;
3547 if (!CheckIntrinsicSize(category, size)) {
3548 size = defaultKind;
3549 } else if (category == TypeCategory::Complex) {
3550 size /= 2;
3551 }
3552 return Expr<SubscriptInteger>{size};
3553 },
3554 },
3555 selector->u);
3556}
3557
3558int ExpressionAnalyzer::GetDefaultKind(common::TypeCategory category) {
3559 return context_.GetDefaultKind(category);
3560}
3561
3562DynamicType ExpressionAnalyzer::GetDefaultKindOfType(
3563 common::TypeCategory category) {
3564 return {category, GetDefaultKind(category)};
3565}
3566
3567bool ExpressionAnalyzer::CheckIntrinsicKind(
3568 TypeCategory category, std::int64_t kind) {
3569 if (foldingContext_.targetCharacteristics().IsTypeEnabled(
3570 category, kind)) { // C712, C714, C715, C727
3571 return true;
3572 } else if (foldingContext_.targetCharacteristics().CanSupportType(
3573 category, kind)) {
3574 Say("%s(KIND=%jd) is not an enabled type for this targe"_warn_en_US,
3575 ToUpperCase(EnumToString(category)), kind);
3576 return true;
3577 } else {
3578 Say("%s(KIND=%jd) is not a supported type"_err_en_US,
3579 ToUpperCase(EnumToString(category)), kind);
3580 return false;
3581 }
3582}
3583
3584bool ExpressionAnalyzer::CheckIntrinsicSize(
3585 TypeCategory category, std::int64_t size) {
3586 std::int64_t kind{size};
3587 if (category == TypeCategory::Complex) {
3588 // COMPLEX*16 == COMPLEX(KIND=8)
3589 if (size % 2 == 0) {
3590 kind = size / 2;
3591 } else {
3592 Say("COMPLEX*%jd is not a supported type"_err_en_US, size);
3593 return false;
3594 }
3595 }
3596 if (foldingContext_.targetCharacteristics().IsTypeEnabled(
3597 category, kind)) { // C712, C714, C715, C727
3598 return true;
3599 } else if (foldingContext_.targetCharacteristics().CanSupportType(
3600 category, kind)) {
3601 Say("%s*%jd is not an enabled type for this target"_warn_en_US,
3602 ToUpperCase(EnumToString(category)), size);
3603 return true;
3604 } else {
3605 Say("%s*%jd is not a supported type"_err_en_US,
3606 ToUpperCase(EnumToString(category)), size);
3607 return false;
3608 }
3609}
3610
3611bool ExpressionAnalyzer::AddImpliedDo(parser::CharBlock name, int kind) {
3612 return impliedDos_.insert(std::make_pair(name, kind)).second;
3613}
3614
3615void ExpressionAnalyzer::RemoveImpliedDo(parser::CharBlock name) {
3616 auto iter{impliedDos_.find(name)};
3617 if (iter != impliedDos_.end()) {
3618 impliedDos_.erase(iter);
3619 }
3620}
3621
3622std::optional<int> ExpressionAnalyzer::IsImpliedDo(
3623 parser::CharBlock name) const {
3624 auto iter{impliedDos_.find(name)};
3625 if (iter != impliedDos_.cend()) {
3626 return {iter->second};
3627 } else {
3628 return std::nullopt;
3629 }
3630}
3631
3632bool ExpressionAnalyzer::EnforceTypeConstraint(parser::CharBlock at,
3633 const MaybeExpr &result, TypeCategory category, bool defaultKind) {
3634 if (result) {
3635 if (auto type{result->GetType()}) {
3636 if (type->category() != category) { // C885
3637 Say(at, "Must have %s type, but is %s"_err_en_US,
3638 ToUpperCase(EnumToString(category)),
3639 ToUpperCase(type->AsFortran()));
3640 return false;
3641 } else if (defaultKind) {
3642 int kind{context_.GetDefaultKind(category)};
3643 if (type->kind() != kind) {
3644 Say(at, "Must have default kind(%d) of %s type, but is %s"_err_en_US,
3645 kind, ToUpperCase(EnumToString(category)),
3646 ToUpperCase(type->AsFortran()));
3647 return false;
3648 }
3649 }
3650 } else {
3651 Say(at, "Must have %s type, but is typeless"_err_en_US,
3652 ToUpperCase(EnumToString(category)));
3653 return false;
3654 }
3655 }
3656 return true;
3657}
3658
3659MaybeExpr ExpressionAnalyzer::MakeFunctionRef(parser::CharBlock callSite,
3660 ProcedureDesignator &&proc, ActualArguments &&arguments) {
3661 if (const auto *intrinsic{std::get_if<SpecificIntrinsic>(&proc.u)}) {
3662 if (intrinsic->characteristics.value().attrs.test(
3663 characteristics::Procedure::Attr::NullPointer) &&
3664 arguments.empty()) {
3665 return Expr<SomeType>{NullPointer{}};
3666 }
3667 }
3668 if (const Symbol *symbol{proc.GetSymbol()}) {
3669 if (!ResolveForward(*symbol)) {
3670 return std::nullopt;
3671 }
3672 }
3673 if (auto chars{CheckCall(callSite, proc, arguments)}) {
3674 if (chars->functionResult) {
3675 const auto &result{*chars->functionResult};
3676 if (result.IsProcedurePointer()) {
3677 return Expr<SomeType>{
3678 ProcedureRef{std::move(proc), std::move(arguments)}};
3679 } else {
3680 // Not a procedure pointer, so type and shape are known.
3681 return TypedWrapper<FunctionRef, ProcedureRef>(
3682 DEREF(result.GetTypeAndShape())Fortran::common::Deref(result.GetTypeAndShape(), "flang/lib/Semantics/expression.cpp"
, 3682)
.type(),
3683 ProcedureRef{std::move(proc), std::move(arguments)});
3684 }
3685 } else {
3686 Say("Function result characteristics are not known"_err_en_US);
3687 }
3688 }
3689 return std::nullopt;
3690}
3691
3692MaybeExpr ExpressionAnalyzer::MakeFunctionRef(
3693 parser::CharBlock intrinsic, ActualArguments &&arguments) {
3694 if (std::optional<SpecificCall> specificCall{
3695 context_.intrinsics().Probe(CallCharacteristics{intrinsic.ToString()},
3696 arguments, GetFoldingContext())}) {
3697 return MakeFunctionRef(intrinsic,
3698 ProcedureDesignator{std::move(specificCall->specificIntrinsic)},
3699 std::move(specificCall->arguments));
3700 } else {
3701 return std::nullopt;
3702 }
3703}
3704
3705MaybeExpr ExpressionAnalyzer::AnalyzeComplex(
3706 MaybeExpr &&re, MaybeExpr &&im, const char *what) {
3707 if (re && re->Rank() > 0) {
3708 Say("Real part of %s is not scalar"_port_en_US, what);
3709 }
3710 if (im && im->Rank() > 0) {
3711 Say("Imaginary part of %s is not scalar"_port_en_US, what);
3712 }
3713 if (re && im) {
3714 ConformabilityCheck(GetContextualMessages(), *re, *im);
3715 }
3716 return AsMaybeExpr(ConstructComplex(GetContextualMessages(), std::move(re),
3717 std::move(im), GetDefaultKind(TypeCategory::Real)));
3718}
3719
3720void ArgumentAnalyzer::Analyze(const parser::Variable &x) {
3721 source_.ExtendToCover(x.GetSource());
3722 if (MaybeExpr expr{context_.Analyze(x)}) {
3723 if (!IsConstantExpr(*expr)) {
3724 actuals_.emplace_back(std::move(*expr));
3725 SetArgSourceLocation(actuals_.back(), x.GetSource());
3726 return;
3727 }
3728 const Symbol *symbol{GetLastSymbol(*expr)};
3729 if (!symbol) {
3730 context_.SayAt(x, "Assignment to constant '%s' is not allowed"_err_en_US,
3731 x.GetSource());
3732 } else if (IsProcedure(*symbol)) {
3733 if (auto *msg{context_.SayAt(x,
3734 "Assignment to procedure '%s' is not allowed"_err_en_US,
3735 symbol->name())}) {
3736 if (auto *subp{symbol->detailsIf<semantics::SubprogramDetails>()}) {
3737 if (subp->isFunction()) {
3738 const auto &result{subp->result().name()};
3739 msg->Attach(result, "Function result is '%s'"_en_US, result);
3740 }
3741 }
3742 }
3743 } else {
3744 context_.SayAt(
3745 x, "Assignment to '%s' is not allowed"_err_en_US, symbol->name());
3746 }
3747 }
3748 fatalErrors_ = true;
3749}
3750
3751void ArgumentAnalyzer::Analyze(
3752 const parser::ActualArgSpec &arg, bool isSubroutine) {
3753 // TODO: C1534: Don't allow a "restricted" specific intrinsic to be passed.
3754 std::optional<ActualArgument> actual;
3755 common::visit(common::visitors{
3756 [&](const common::Indirection<parser::Expr> &x) {
3757 actual = AnalyzeExpr(x.value());
3758 SetArgSourceLocation(actual, x.value().source);
3759 },
3760 [&](const parser::AltReturnSpec &label) {
3761 if (!isSubroutine) {
3762 context_.Say(
3763 "alternate return specification may not appear on"
3764 " function reference"_err_en_US);
3765 }
3766 actual = ActualArgument(label.v);
3767 },
3768 [&](const parser::ActualArg::PercentRef &) {
3769 context_.Say("%REF() intrinsic for arguments"_todo_en_US);
3770 },
3771 [&](const parser::ActualArg::PercentVal &) {
3772 context_.Say("%VAL() intrinsic for arguments"_todo_en_US);
3773 },
3774 },
3775 std::get<parser::ActualArg>(arg.t).u);
3776 if (actual) {
3777 if (const auto &argKW{std::get<std::optional<parser::Keyword>>(arg.t)}) {
3778 actual->set_keyword(argKW->v.source);
3779 }
3780 actuals_.emplace_back(std::move(*actual));
3781 } else {
3782 fatalErrors_ = true;
3783 }
3784}
3785
3786bool ArgumentAnalyzer::IsIntrinsicRelational(RelationalOperator opr,
3787 const DynamicType &leftType, const DynamicType &rightType) const {
3788 CHECK(actuals_.size() == 2)((actuals_.size() == 2) || (Fortran::common::die("CHECK(" "actuals_.size() == 2"
") failed" " at " "flang/lib/Semantics/expression.cpp" "(%d)"
, 3788), false))
;
3789 return semantics::IsIntrinsicRelational(
3790 opr, leftType, GetRank(0), rightType, GetRank(1));
3791}
3792
3793bool ArgumentAnalyzer::IsIntrinsicNumeric(NumericOperator opr) const {
3794 std::optional<DynamicType> leftType{GetType(0)};
3795 if (actuals_.size() == 1) {
3796 if (IsBOZLiteral(0)) {
3797 return opr == NumericOperator::Add; // unary '+'
3798 } else {
3799 return leftType && semantics::IsIntrinsicNumeric(*leftType);
3800 }
3801 } else {
3802 std::optional<DynamicType> rightType{GetType(1)};
3803 if (IsBOZLiteral(0) && rightType) { // BOZ opr Integer/Real
3804 auto cat1{rightType->category()};
3805 return cat1 == TypeCategory::Integer || cat1 == TypeCategory::Real;
3806 } else if (IsBOZLiteral(1) && leftType) { // Integer/Real opr BOZ
3807 auto cat0{leftType->category()};
3808 return cat0 == TypeCategory::Integer || cat0 == TypeCategory::Real;
3809 } else {
3810 return leftType && rightType &&
3811 semantics::IsIntrinsicNumeric(
3812 *leftType, GetRank(0), *rightType, GetRank(1));
3813 }
3814 }
3815}
3816
3817bool ArgumentAnalyzer::IsIntrinsicLogical() const {
3818 if (std::optional<DynamicType> leftType{GetType(0)}) {
3819 if (actuals_.size() == 1) {
3820 return semantics::IsIntrinsicLogical(*leftType);
3821 } else if (std::optional<DynamicType> rightType{GetType(1)}) {
3822 return semantics::IsIntrinsicLogical(
3823 *leftType, GetRank(0), *rightType, GetRank(1));
3824 }
3825 }
3826 return false;
3827}
3828
3829bool ArgumentAnalyzer::IsIntrinsicConcat() const {
3830 if (std::optional<DynamicType> leftType{GetType(0)}) {
3831 if (std::optional<DynamicType> rightType{GetType(1)}) {
3832 return semantics::IsIntrinsicConcat(
3833 *leftType, GetRank(0), *rightType, GetRank(1));
3834 }
3835 }
3836 return false;
3837}
3838
3839bool ArgumentAnalyzer::CheckConformance() {
3840 if (actuals_.size() == 2) {
3841 const auto *lhs{actuals_.at(0).value().UnwrapExpr()};
3842 const auto *rhs{actuals_.at(1).value().UnwrapExpr()};
3843 if (lhs && rhs) {
3844 auto &foldingContext{context_.GetFoldingContext()};
3845 auto lhShape{GetShape(foldingContext, *lhs)};
3846 auto rhShape{GetShape(foldingContext, *rhs)};
3847 if (lhShape && rhShape) {
3848 if (!evaluate::CheckConformance(foldingContext.messages(), *lhShape,
3849 *rhShape, CheckConformanceFlags::EitherScalarExpandable,
3850 "left operand", "right operand")
3851 .value_or(false /*fail when conformance is not known now*/)) {
3852 fatalErrors_ = true;
3853 return false;
3854 }
3855 }
3856 }
3857 }
3858 return true; // no proven problem
3859}
3860
3861bool ArgumentAnalyzer::CheckAssignmentConformance() {
3862 if (actuals_.size() == 2) {
3863 const auto *lhs{actuals_.at(0).value().UnwrapExpr()};
3864 const auto *rhs{actuals_.at(1).value().UnwrapExpr()};
3865 if (lhs && rhs) {
3866 auto &foldingContext{context_.GetFoldingContext()};
3867 auto lhShape{GetShape(foldingContext, *lhs)};
3868 auto rhShape{GetShape(foldingContext, *rhs)};
3869 if (lhShape && rhShape) {
3870 if (!evaluate::CheckConformance(foldingContext.messages(), *lhShape,
3871 *rhShape, CheckConformanceFlags::RightScalarExpandable,
3872 "left-hand side", "right-hand side")
3873 .value_or(true /*ok when conformance is not known now*/)) {
3874 fatalErrors_ = true;
3875 return false;
3876 }
3877 }
3878 }
3879 }
3880 return true; // no proven problem
3881}
3882
3883bool ArgumentAnalyzer::CheckForNullPointer(const char *where) {
3884 for (const std::optional<ActualArgument> &arg : actuals_) {
3885 if (arg) {
3886 if (const Expr<SomeType> *expr{arg->UnwrapExpr()}) {
3887 if (IsNullPointer(*expr)) {
3888 context_.Say(
3889 source_, "A NULL() pointer is not allowed %s"_err_en_US, where);
3890 fatalErrors_ = true;
3891 return false;
3892 }
3893 }
3894 }
3895 }
3896 return true;
3897}
3898
3899MaybeExpr ArgumentAnalyzer::TryDefinedOp(
3900 const char *opr, parser::MessageFixedText error, bool isUserOp) {
3901 if (AnyUntypedOrMissingOperand()) {
2
Taking false branch
3902 context_.Say(error, ToUpperCase(opr), TypeAsFortran(0), TypeAsFortran(1));
3903 return std::nullopt;
3904 }
3905 MaybeExpr result;
3906 bool anyPossibilities{false};
3907 std::optional<parser::MessageFormattedText> inaccessible;
3908 std::vector<const Symbol *> hit;
3909 std::string oprNameString{
3910 isUserOp
2.1
'isUserOp' is true
2.1
'isUserOp' is true
? std::string{opr} : "operator("s + opr + ')'};
3
'?' condition is true
3911 parser::CharBlock oprName{oprNameString};
3912 {
3913 auto restorer{context_.GetContextualMessages().DiscardMessages()};
3914 const auto &scope{context_.context().FindScope(source_)};
3915 if (Symbol *symbol{scope.FindSymbol(oprName)}) {
4
Assuming 'symbol' is non-null
5
Taking true branch
3916 anyPossibilities = true;
3917 parser::Name name{symbol->name(), symbol};
3918 result = context_.AnalyzeDefinedOp(name, GetActuals());
6
Calling 'ExpressionAnalyzer::AnalyzeDefinedOp'
18
Returning from 'ExpressionAnalyzer::AnalyzeDefinedOp'
3919 if (result) {
19
Taking true branch
3920 inaccessible = CheckAccessibleSymbol(scope, *symbol);
3921 if (inaccessible) {
20
Taking false branch
3922 result.reset();
3923 } else {
3924 hit.push_back(symbol);
3925 }
3926 }
3927 }
3928 for (std::size_t passIndex{0}; passIndex < actuals_.size(); ++passIndex) {
21
Method called on moved-from object 'actuals_' of type 'std::vector'
3929 const Symbol *generic{nullptr};
3930 if (const Symbol *binding{
3931 FindBoundOp(oprName, passIndex, generic, false)}) {
3932 anyPossibilities = true;
3933 if (MaybeExpr thisResult{TryBoundOp(*binding, passIndex)}) {
3934 if (auto thisInaccessible{
3935 CheckAccessibleSymbol(scope, DEREF(generic)Fortran::common::Deref(generic, "flang/lib/Semantics/expression.cpp"
, 3935)
)}) {
3936 inaccessible = thisInaccessible;
3937 } else {
3938 result = std::move(thisResult);
3939 hit.push_back(binding);
3940 }
3941 }
3942 }
3943 }
3944 }
3945 if (result) {
3946 if (hit.size() > 1) {
3947 if (auto *msg{context_.Say(
3948 "%zd matching accessible generic interfaces for %s were found"_err_en_US,
3949 hit.size(), ToUpperCase(opr))}) {
3950 for (const Symbol *symbol : hit) {
3951 AttachDeclaration(*msg, *symbol);
3952 }
3953 }
3954 }
3955 } else if (inaccessible) {
3956 context_.Say(source_, std::move(*inaccessible));
3957 } else if (anyPossibilities) {
3958 SayNoMatch(ToUpperCase(oprNameString), false);
3959 } else if (actuals_.size() == 2 && !AreConformable()) {
3960 context_.Say(
3961 "Operands of %s are not conformable; have rank %d and rank %d"_err_en_US,
3962 ToUpperCase(opr), actuals_[0]->Rank(), actuals_[1]->Rank());
3963 } else if (CheckForNullPointer()) {
3964 context_.Say(error, ToUpperCase(opr), TypeAsFortran(0), TypeAsFortran(1));
3965 }
3966 return result;
3967}
3968
3969MaybeExpr ArgumentAnalyzer::TryDefinedOp(
3970 std::vector<const char *> oprs, parser::MessageFixedText error) {
3971 if (oprs.size() == 1) {
3972 return TryDefinedOp(oprs[0], error);
3973 }
3974 MaybeExpr result;
3975 std::vector<const char *> hit;
3976 {
3977 auto restorer{context_.GetContextualMessages().DiscardMessages()};
3978 for (std::size_t i{0}; i < oprs.size(); ++i) {
3979 if (MaybeExpr thisResult{TryDefinedOp(oprs[i], error)}) {
3980 result = std::move(thisResult);
3981 hit.push_back(oprs[i]);
3982 }
3983 }
3984 }
3985 if (hit.empty()) { // for the error
3986 result = TryDefinedOp(oprs[0], error);
3987 } else if (hit.size() > 1) {
3988 context_.Say(
3989 "Matching accessible definitions were found with %zd variant spellings of the generic operator ('%s', '%s')"_err_en_US,
3990 hit.size(), ToUpperCase(hit[0]), ToUpperCase(hit[1]));
3991 }
3992 return result;
3993}
3994
3995MaybeExpr ArgumentAnalyzer::TryBoundOp(const Symbol &symbol, int passIndex) {
3996 ActualArguments localActuals{actuals_};
3997 const Symbol *proc{GetBindingResolution(GetType(passIndex), symbol)};
3998 if (!proc) {
3999 proc = &symbol;
4000 localActuals.at(passIndex).value().set_isPassedObject();
4001 }
4002 CheckConformance();
4003 return context_.MakeFunctionRef(
4004 source_, ProcedureDesignator{*proc}, std::move(localActuals));
4005}
4006
4007std::optional<ProcedureRef> ArgumentAnalyzer::TryDefinedAssignment() {
4008 using semantics::Tristate;
4009 const Expr<SomeType> &lhs{GetExpr(0)};
4010 const Expr<SomeType> &rhs{GetExpr(1)};
4011 std::optional<DynamicType> lhsType{lhs.GetType()};
4012 std::optional<DynamicType> rhsType{rhs.GetType()};
4013 int lhsRank{lhs.Rank()};
4014 int rhsRank{rhs.Rank()};
4015 Tristate isDefined{
4016 semantics::IsDefinedAssignment(lhsType, lhsRank, rhsType, rhsRank)};
4017 if (isDefined == Tristate::No) {
4018 if (lhsType && rhsType) {
4019 AddAssignmentConversion(*lhsType, *rhsType);
4020 }
4021 if (!fatalErrors_) {
4022 CheckAssignmentConformance();
4023 }
4024 return std::nullopt; // user-defined assignment not allowed for these args
4025 }
4026 auto restorer{context_.GetContextualMessages().SetLocation(source_)};
4027 if (std::optional<ProcedureRef> procRef{GetDefinedAssignmentProc()}) {
4028 if (context_.inWhereBody() && !procRef->proc().IsElemental()) { // C1032
4029 context_.Say(
4030 "Defined assignment in WHERE must be elemental, but '%s' is not"_err_en_US,
4031 DEREF(procRef->proc().GetSymbol())Fortran::common::Deref(procRef->proc().GetSymbol(), "flang/lib/Semantics/expression.cpp"
, 4031)
.name());
4032 }
4033 context_.CheckCall(source_, procRef->proc(), procRef->arguments());
4034 return std::move(*procRef);
4035 }
4036 if (isDefined == Tristate::Yes) {
4037 if (!lhsType || !rhsType || (lhsRank != rhsRank && rhsRank != 0) ||
4038 !OkLogicalIntegerAssignment(lhsType->category(), rhsType->category())) {
4039 SayNoMatch("ASSIGNMENT(=)", true);
4040 }
4041 }
4042 return std::nullopt;
4043}
4044
4045bool ArgumentAnalyzer::OkLogicalIntegerAssignment(
4046 TypeCategory lhs, TypeCategory rhs) {
4047 if (!context_.context().languageFeatures().IsEnabled(
4048 common::LanguageFeature::LogicalIntegerAssignment)) {
4049 return false;
4050 }
4051 std::optional<parser::MessageFixedText> msg;
4052 if (lhs == TypeCategory::Integer && rhs == TypeCategory::Logical) {
4053 // allow assignment to LOGICAL from INTEGER as a legacy extension
4054 msg = "assignment of LOGICAL to INTEGER"_port_en_US;
4055 } else if (lhs == TypeCategory::Logical && rhs == TypeCategory::Integer) {
4056 // ... and assignment to LOGICAL from INTEGER
4057 msg = "assignment of INTEGER to LOGICAL"_port_en_US;
4058 } else {
4059 return false;
4060 }
4061 if (context_.context().languageFeatures().ShouldWarn(
4062 common::LanguageFeature::LogicalIntegerAssignment)) {
4063 context_.Say(std::move(*msg));
4064 }
4065 return true;
4066}
4067
4068std::optional<ProcedureRef> ArgumentAnalyzer::GetDefinedAssignmentProc() {
4069 const Symbol *proc{nullptr};
4070 int passedObjectIndex{-1};
4071 std::string oprNameString{"assignment(=)"};
4072 parser::CharBlock oprName{oprNameString};
4073 const auto &scope{context_.context().FindScope(source_)};
4074 // If multiple resolutions were possible, they will have been already
4075 // diagnosed.
4076 {
4077 auto restorer{context_.GetContextualMessages().DiscardMessages()};
4078 if (const Symbol *symbol{scope.FindSymbol(oprName)}) {
4079 ExpressionAnalyzer::AdjustActuals noAdjustment;
4080 proc =
4081 context_.ResolveGeneric(*symbol, actuals_, noAdjustment, true).first;
4082 }
4083 for (std::size_t i{0}; !proc && i < actuals_.size(); ++i) {
4084 const Symbol *generic{nullptr};
4085 if (const Symbol *binding{FindBoundOp(oprName, i, generic, true)}) {
4086 if (CheckAccessibleSymbol(scope, DEREF(generic)Fortran::common::Deref(generic, "flang/lib/Semantics/expression.cpp"
, 4086)
)) {
4087 // ignore inaccessible type-bound ASSIGNMENT(=) generic
4088 } else if (const Symbol *
4089 resolution{GetBindingResolution(GetType(i), *binding)}) {
4090 proc = resolution;
4091 } else {
4092 proc = binding;
4093 passedObjectIndex = i;
4094 }
4095 }
4096 }
4097 }
4098 if (!proc) {
4099 return std::nullopt;
4100 }
4101 ActualArguments actualsCopy{actuals_};
4102 if (passedObjectIndex >= 0) {
4103 actualsCopy[passedObjectIndex]->set_isPassedObject();
4104 }
4105 return ProcedureRef{ProcedureDesignator{*proc}, std::move(actualsCopy)};
4106}
4107
4108void ArgumentAnalyzer::Dump(llvm::raw_ostream &os) {
4109 os << "source_: " << source_.ToString() << " fatalErrors_ = " << fatalErrors_
4110 << '\n';
4111 for (const auto &actual : actuals_) {
4112 if (!actual.has_value()) {
4113 os << "- error\n";
4114 } else if (const Symbol *symbol{actual->GetAssumedTypeDummy()}) {
4115 os << "- assumed type: " << symbol->name().ToString() << '\n';
4116 } else if (const Expr<SomeType> *expr{actual->UnwrapExpr()}) {
4117 expr->AsFortran(os << "- expr: ") << '\n';
4118 } else {
4119 DIE("bad ActualArgument")Fortran::common::die("bad ActualArgument" " at " "flang/lib/Semantics/expression.cpp"
"(%d)", 4119)
;
4120 }
4121 }
4122}
4123
4124std::optional<ActualArgument> ArgumentAnalyzer::AnalyzeExpr(
4125 const parser::Expr &expr) {
4126 source_.ExtendToCover(expr.source);
4127 if (const Symbol *assumedTypeDummy{AssumedTypeDummy(expr)}) {
4128 ResetExpr(expr);
4129 if (isProcedureCall_) {
4130 ActualArgument arg{ActualArgument::AssumedType{*assumedTypeDummy}};
4131 SetArgSourceLocation(arg, expr.source);
4132 return std::move(arg);
4133 }
4134 context_.SayAt(expr.source,
4135 "TYPE(*) dummy argument may only be used as an actual argument"_err_en_US);
4136 } else if (MaybeExpr argExpr{AnalyzeExprOrWholeAssumedSizeArray(expr)}) {
4137 if (isProcedureCall_ || !IsProcedure(*argExpr)) {
4138 ActualArgument arg{std::move(*argExpr)};
4139 SetArgSourceLocation(arg, expr.source);
4140 return std::move(arg);
4141 }
4142 context_.SayAt(expr.source,
4143 IsFunction(*argExpr) ? "Function call must have argument list"_err_en_US
4144 : "Subroutine name is not allowed here"_err_en_US);
4145 }
4146 return std::nullopt;
4147}
4148
4149MaybeExpr ArgumentAnalyzer::AnalyzeExprOrWholeAssumedSizeArray(
4150 const parser::Expr &expr) {
4151 // If an expression's parse tree is a whole assumed-size array:
4152 // Expr -> Designator -> DataRef -> Name
4153 // treat it as a special case for argument passing and bypass
4154 // the C1002/C1014 constraint checking in expression semantics.
4155 if (const auto *name{parser::Unwrap<parser::Name>(expr)}) {
4156 if (name->symbol && semantics::IsAssumedSizeArray(*name->symbol)) {
4157 auto restorer{context_.AllowWholeAssumedSizeArray()};
4158 return context_.Analyze(expr);
4159 }
4160 }
4161 auto restorer{context_.AllowNullPointer()};
4162 return context_.Analyze(expr);
4163}
4164
4165bool ArgumentAnalyzer::AreConformable() const {
4166 CHECK(actuals_.size() == 2)((actuals_.size() == 2) || (Fortran::common::die("CHECK(" "actuals_.size() == 2"
") failed" " at " "flang/lib/Semantics/expression.cpp" "(%d)"
, 4166), false))
;
4167 return actuals_[0] && actuals_[1] &&
4168 evaluate::AreConformable(*actuals_[0], *actuals_[1]);
4169}
4170
4171// Look for a type-bound operator in the type of arg number passIndex.
4172const Symbol *ArgumentAnalyzer::FindBoundOp(parser::CharBlock oprName,
4173 int passIndex, const Symbol *&generic, bool isSubroutine) {
4174 const auto *type{GetDerivedTypeSpec(GetType(passIndex))};
4175 const semantics::Scope *scope{type ? type->scope() : nullptr};
4176 if (scope) {
4177 // Use the original type definition's scope, since PDT
4178 // instantiations don't have redundant copies of bindings or
4179 // generics.
4180 scope = DEREF(scope->derivedTypeSpec())Fortran::common::Deref(scope->derivedTypeSpec(), "flang/lib/Semantics/expression.cpp"
, 4180)
.typeSymbol().scope();
4181 }
4182 generic = scope ? scope->FindComponent(oprName) : nullptr;
4183 if (generic) {
4184 ExpressionAnalyzer::AdjustActuals adjustment{
4185 [&](const Symbol &proc, ActualArguments &) {
4186 return passIndex == GetPassIndex(proc);
4187 }};
4188 auto pair{
4189 context_.ResolveGeneric(*generic, actuals_, adjustment, isSubroutine)};
4190 if (const Symbol *binding{pair.first}) {
4191 CHECK(binding->has<semantics::ProcBindingDetails>())((binding->has<semantics::ProcBindingDetails>()) || (
Fortran::common::die("CHECK(" "binding->has<semantics::ProcBindingDetails>()"
") failed" " at " "flang/lib/Semantics/expression.cpp" "(%d)"
, 4191), false))
;
4192 // Use the most recent override of the binding, if any
4193 return scope->FindComponent(binding->name());
4194 } else {
4195 context_.EmitGenericResolutionError(*generic, pair.second, isSubroutine);
4196 }
4197 }
4198 return nullptr;
4199}
4200
4201// If there is an implicit conversion between intrinsic types, make it explicit
4202void ArgumentAnalyzer::AddAssignmentConversion(
4203 const DynamicType &lhsType, const DynamicType &rhsType) {
4204 if (lhsType.category() == rhsType.category() &&
4205 (lhsType.category() == TypeCategory::Derived ||
4206 lhsType.kind() == rhsType.kind())) {
4207 // no conversion necessary
4208 } else if (auto rhsExpr{evaluate::Fold(context_.GetFoldingContext(),
4209 evaluate::ConvertToType(lhsType, MoveExpr(1)))}) {
4210 std::optional<parser::CharBlock> source;
4211 if (actuals_[1]) {
4212 source = actuals_[1]->sourceLocation();
4213 }
4214 actuals_[1] = ActualArgument{*rhsExpr};
4215 SetArgSourceLocation(actuals_[1], source);
4216 } else {
4217 actuals_[1] = std::nullopt;
4218 }
4219}
4220
4221std::optional<DynamicType> ArgumentAnalyzer::GetType(std::size_t i) const {
4222 return i < actuals_.size() ? actuals_[i].value().GetType() : std::nullopt;
4223}
4224int ArgumentAnalyzer::GetRank(std::size_t i) const {
4225 return i < actuals_.size() ? actuals_[i].value().Rank() : 0;
4226}
4227
4228// If the argument at index i is a BOZ literal, convert its type to match the
4229// otherType. If it's REAL convert to REAL, otherwise convert to INTEGER.
4230// Note that IBM supports comparing BOZ literals to CHARACTER operands. That
4231// is not currently supported.
4232void ArgumentAnalyzer::ConvertBOZ(std::optional<DynamicType> &thisType,
4233 std::size_t i, std::optional<DynamicType> otherType) {
4234 if (IsBOZLiteral(i)) {
4235 Expr<SomeType> &&argExpr{MoveExpr(i)};
4236 auto *boz{std::get_if<BOZLiteralConstant>(&argExpr.u)};
4237 if (otherType && otherType->category() == TypeCategory::Real) {
4238 int kind{context_.context().GetDefaultKind(TypeCategory::Real)};
4239 MaybeExpr realExpr{
4240 ConvertToKind<TypeCategory::Real>(kind, std::move(*boz))};
4241 actuals_[i] = std::move(*realExpr);
4242 thisType.emplace(TypeCategory::Real, kind);
4243 } else {
4244 int kind{context_.context().GetDefaultKind(TypeCategory::Integer)};
4245 MaybeExpr intExpr{
4246 ConvertToKind<TypeCategory::Integer>(kind, std::move(*boz))};
4247 actuals_[i] = std::move(*intExpr);
4248 thisType.emplace(TypeCategory::Integer, kind);
4249 }
4250 }
4251}
4252
4253// Report error resolving opr when there is a user-defined one available
4254void ArgumentAnalyzer::SayNoMatch(const std::string &opr, bool isAssignment) {
4255 std::string type0{TypeAsFortran(0)};
4256 auto rank0{actuals_[0]->Rank()};
4257 if (actuals_.size() == 1) {
4258 if (rank0 > 0) {
4259 context_.Say("No intrinsic or user-defined %s matches "
4260 "rank %d array of %s"_err_en_US,
4261 opr, rank0, type0);
4262 } else {
4263 context_.Say("No intrinsic or user-defined %s matches "
4264 "operand type %s"_err_en_US,
4265 opr, type0);
4266 }
4267 } else {
4268 std::string type1{TypeAsFortran(1)};
4269 auto rank1{actuals_[1]->Rank()};
4270 if (rank0 > 0 && rank1 > 0 && rank0 != rank1) {
4271 context_.Say("No intrinsic or user-defined %s matches "
4272 "rank %d array of %s and rank %d array of %s"_err_en_US,
4273 opr, rank0, type0, rank1, type1);
4274 } else if (isAssignment && rank0 != rank1) {
4275 if (rank0 == 0) {
4276 context_.Say("No intrinsic or user-defined %s matches "
4277 "scalar %s and rank %d array of %s"_err_en_US,
4278 opr, type0, rank1, type1);
4279 } else {
4280 context_.Say("No intrinsic or user-defined %s matches "
4281 "rank %d array of %s and scalar %s"_err_en_US,
4282 opr, rank0, type0, type1);
4283 }
4284 } else {
4285 context_.Say("No intrinsic or user-defined %s matches "
4286 "operand types %s and %s"_err_en_US,
4287 opr, type0, type1);
4288 }
4289 }
4290}
4291
4292std::string ArgumentAnalyzer::TypeAsFortran(std::size_t i) {
4293 if (i >= actuals_.size() || !actuals_[i]) {
4294 return "missing argument";
4295 } else if (std::optional<DynamicType> type{GetType(i)}) {
4296 return type->IsAssumedType() ? "TYPE(*)"s
4297 : type->IsUnlimitedPolymorphic() ? "CLASS(*)"s
4298 : type->IsPolymorphic() ? type->AsFortran()
4299 : type->category() == TypeCategory::Derived
4300 ? "TYPE("s + type->AsFortran() + ')'
4301 : type->category() == TypeCategory::Character
4302 ? "CHARACTER(KIND="s + std::to_string(type->kind()) + ')'
4303 : ToUpperCase(type->AsFortran());
4304 } else {
4305 return "untyped";
4306 }
4307}
4308
4309bool ArgumentAnalyzer::AnyUntypedOrMissingOperand() {
4310 for (const auto &actual : actuals_) {
4311 if (!actual ||
4312 (!actual->GetType() && !IsBareNullPointer(actual->UnwrapExpr()))) {
4313 return true;
4314 }
4315 }
4316 return false;
4317}
4318} // namespace Fortran::evaluate
4319
4320namespace Fortran::semantics {
4321evaluate::Expr<evaluate::SubscriptInteger> AnalyzeKindSelector(
4322 SemanticsContext &context, common::TypeCategory category,
4323 const std::optional<parser::KindSelector> &selector) {
4324 evaluate::ExpressionAnalyzer analyzer{context};
4325 auto restorer{
4326 analyzer.GetContextualMessages().SetLocation(context.location().value())};
4327 return analyzer.AnalyzeKindSelector(category, selector);
4328}
4329
4330ExprChecker::ExprChecker(SemanticsContext &context) : context_{context} {}
4331
4332bool ExprChecker::Pre(const parser::DataStmtObject &obj) {
4333 exprAnalyzer_.set_inDataStmtObject(true);
4334 return true;
4335}
4336
4337void ExprChecker::Post(const parser::DataStmtObject &obj) {
4338 exprAnalyzer_.set_inDataStmtObject(false);
4339}
4340
4341bool ExprChecker::Pre(const parser::DataImpliedDo &ido) {
4342 parser::Walk(std::get<parser::DataImpliedDo::Bounds>(ido.t), *this);
4343 const auto &bounds{std::get<parser::DataImpliedDo::Bounds>(ido.t)};
4344 auto name{bounds.name.thing.thing};
4345 int kind{evaluate::ResultType<evaluate::ImpliedDoIndex>::kind};
4346 if (const auto dynamicType{evaluate::DynamicType::From(*name.symbol)}) {
4347 if (dynamicType->category() == TypeCategory::Integer) {
4348 kind = dynamicType->kind();
4349 }
4350 }
4351 exprAnalyzer_.AddImpliedDo(name.source, kind);
4352 parser::Walk(std::get<std::list<parser::DataIDoObject>>(ido.t), *this);
4353 exprAnalyzer_.RemoveImpliedDo(name.source);
4354 return false;
4355}
4356
4357bool ExprChecker::Walk(const parser::Program &program) {
4358 parser::Walk(program, *this);
4359 return !context_.AnyFatalError();
4360}
4361} // namespace Fortran::semantics

/usr/lib/gcc/x86_64-linux-gnu/10/../../../../include/c++/10/bits/basic_string.h

1// Components for manipulating sequences of characters -*- C++ -*-
2
3// Copyright (C) 1997-2020 Free Software Foundation, Inc.
4//
5// This file is part of the GNU ISO C++ Library. This library is free
6// software; you can redistribute it and/or modify it under the
7// terms of the GNU General Public License as published by the
8// Free Software Foundation; either version 3, or (at your option)
9// any later version.
10
11// This library is distributed in the hope that it will be useful,
12// but WITHOUT ANY WARRANTY; without even the implied warranty of
13// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14// GNU General Public License for more details.
15
16// Under Section 7 of GPL version 3, you are granted additional
17// permissions described in the GCC Runtime Library Exception, version
18// 3.1, as published by the Free Software Foundation.
19
20// You should have received a copy of the GNU General Public License and
21// a copy of the GCC Runtime Library Exception along with this program;
22// see the files COPYING3 and COPYING.RUNTIME respectively. If not, see
23// <http://www.gnu.org/licenses/>.
24
25/** @file bits/basic_string.h
26 * This is an internal header file, included by other library headers.
27 * Do not attempt to use it directly. @headername{string}
28 */
29
30//
31// ISO C++ 14882: 21 Strings library
32//
33
34#ifndef _BASIC_STRING_H1
35#define _BASIC_STRING_H1 1
36
37#pragma GCC system_header
38
39#include <ext/atomicity.h>
40#include <ext/alloc_traits.h>
41#include <debug/debug.h>
42
43#if __cplusplus201703L >= 201103L
44#include <initializer_list>
45#endif
46
47#if __cplusplus201703L >= 201703L
48# include <string_view>
49#endif
50
51
52namespace std _GLIBCXX_VISIBILITY(default)__attribute__ ((__visibility__ ("default")))
53{
54_GLIBCXX_BEGIN_NAMESPACE_VERSION
55
56#if _GLIBCXX_USE_CXX11_ABI1
57_GLIBCXX_BEGIN_NAMESPACE_CXX11namespace __cxx11 {
58 /**
59 * @class basic_string basic_string.h <string>
60 * @brief Managing sequences of characters and character-like objects.
61 *
62 * @ingroup strings
63 * @ingroup sequences
64 *
65 * @tparam _CharT Type of character
66 * @tparam _Traits Traits for character type, defaults to
67 * char_traits<_CharT>.
68 * @tparam _Alloc Allocator type, defaults to allocator<_CharT>.
69 *
70 * Meets the requirements of a <a href="tables.html#65">container</a>, a
71 * <a href="tables.html#66">reversible container</a>, and a
72 * <a href="tables.html#67">sequence</a>. Of the
73 * <a href="tables.html#68">optional sequence requirements</a>, only
74 * @c push_back, @c at, and @c %array access are supported.
75 */
76 template<typename _CharT, typename _Traits, typename _Alloc>
77 class basic_string
78 {
79 typedef typename __gnu_cxx::__alloc_traits<_Alloc>::template
80 rebind<_CharT>::other _Char_alloc_type;
81 typedef __gnu_cxx::__alloc_traits<_Char_alloc_type> _Alloc_traits;
82
83 // Types:
84 public:
85 typedef _Traits traits_type;
86 typedef typename _Traits::char_type value_type;
87 typedef _Char_alloc_type allocator_type;
88 typedef typename _Alloc_traits::size_type size_type;
89 typedef typename _Alloc_traits::difference_type difference_type;
90 typedef typename _Alloc_traits::reference reference;
91 typedef typename _Alloc_traits::const_reference const_reference;
92 typedef typename _Alloc_traits::pointer pointer;
93 typedef typename _Alloc_traits::const_pointer const_pointer;
94 typedef __gnu_cxx::__normal_iterator<pointer, basic_string> iterator;
95 typedef __gnu_cxx::__normal_iterator<const_pointer, basic_string>
96 const_iterator;
97 typedef std::reverse_iterator<const_iterator> const_reverse_iterator;
98 typedef std::reverse_iterator<iterator> reverse_iterator;
99
100 /// Value returned by various member functions when they fail.
101 static const size_type npos = static_cast<size_type>(-1);
102
103 protected:
104 // type used for positions in insert, erase etc.
105#if __cplusplus201703L < 201103L
106 typedef iterator __const_iterator;
107#else
108 typedef const_iterator __const_iterator;
109#endif
110
111 private:
112#if __cplusplus201703L >= 201703L
113 // A helper type for avoiding boiler-plate.
114 typedef basic_string_view<_CharT, _Traits> __sv_type;
115
116 template<typename _Tp, typename _Res>
117 using _If_sv = enable_if_t<
118 __and_<is_convertible<const _Tp&, __sv_type>,
119 __not_<is_convertible<const _Tp*, const basic_string*>>,
120 __not_<is_convertible<const _Tp&, const _CharT*>>>::value,
121 _Res>;
122
123 // Allows an implicit conversion to __sv_type.
124 static __sv_type
125 _S_to_string_view(__sv_type __svt) noexcept
126 { return __svt; }
127
128 // Wraps a string_view by explicit conversion and thus
129 // allows to add an internal constructor that does not
130 // participate in overload resolution when a string_view
131 // is provided.
132 struct __sv_wrapper
133 {
134 explicit __sv_wrapper(__sv_type __sv) noexcept : _M_sv(__sv) { }
135 __sv_type _M_sv;
136 };
137
138 /**
139 * @brief Only internally used: Construct string from a string view
140 * wrapper.
141 * @param __svw string view wrapper.
142 * @param __a Allocator to use.
143 */
144 explicit
145 basic_string(__sv_wrapper __svw, const _Alloc& __a)
146 : basic_string(__svw._M_sv.data(), __svw._M_sv.size(), __a) { }
147#endif
148
149 // Use empty-base optimization: http://www.cantrip.org/emptyopt.html
150 struct _Alloc_hider : allocator_type // TODO check __is_final
151 {
152#if __cplusplus201703L < 201103L
153 _Alloc_hider(pointer __dat, const _Alloc& __a = _Alloc())
154 : allocator_type(__a), _M_p(__dat) { }
155#else
156 _Alloc_hider(pointer __dat, const _Alloc& __a)
157 : allocator_type(__a), _M_p(__dat) { }
158
159 _Alloc_hider(pointer __dat, _Alloc&& __a = _Alloc())
160 : allocator_type(std::move(__a)), _M_p(__dat) { }
161#endif
162
163 pointer _M_p; // The actual data.
164 };
165
166 _Alloc_hider _M_dataplus;
167 size_type _M_string_length;
168
169 enum { _S_local_capacity = 15 / sizeof(_CharT) };
170
171 union
172 {
173 _CharT _M_local_buf[_S_local_capacity + 1];
174 size_type _M_allocated_capacity;
175 };
176
177 void
178 _M_data(pointer __p)
179 { _M_dataplus._M_p = __p; }
180
181 void
182 _M_length(size_type __length)
183 { _M_string_length = __length; }
184
185 pointer
186 _M_data() const
187 { return _M_dataplus._M_p; }
188
189 pointer
190 _M_local_data()
191 {
192#if __cplusplus201703L >= 201103L
193 return std::pointer_traits<pointer>::pointer_to(*_M_local_buf);
194#else
195 return pointer(_M_local_buf);
196#endif
197 }
198
199 const_pointer
200 _M_local_data() const
201 {
202#if __cplusplus201703L >= 201103L
203 return std::pointer_traits<const_pointer>::pointer_to(*_M_local_buf);
204#else
205 return const_pointer(_M_local_buf);
206#endif
207 }
208
209 void
210 _M_capacity(size_type __capacity)
211 { _M_allocated_capacity = __capacity; }
212
213 void
214 _M_set_length(size_type __n)
215 {
216 _M_length(__n);
217 traits_type::assign(_M_data()[__n], _CharT());
218 }
219
220 bool
221 _M_is_local() const
222 { return _M_data() == _M_local_data(); }
223
224 // Create & Destroy
225 pointer
226 _M_create(size_type&, size_type);
227
228 void
229 _M_dispose()
230 {
231 if (!_M_is_local())
232 _M_destroy(_M_allocated_capacity);
233 }
234
235 void
236 _M_destroy(size_type __size) throw()
237 { _Alloc_traits::deallocate(_M_get_allocator(), _M_data(), __size + 1); }
238
239 // _M_construct_aux is used to implement the 21.3.1 para 15 which
240 // requires special behaviour if _InIterator is an integral type
241 template<typename _InIterator>
242 void
243 _M_construct_aux(_InIterator __beg, _InIterator __end,
244 std::__false_type)
245 {
246 typedef typename iterator_traits<_InIterator>::iterator_category _Tag;
247 _M_construct(__beg, __end, _Tag());
248 }
249
250 // _GLIBCXX_RESOLVE_LIB_DEFECTS
251 // 438. Ambiguity in the "do the right thing" clause
252 template<typename _Integer>
253 void
254 _M_construct_aux(_Integer __beg, _Integer __end, std::__true_type)
255 { _M_construct_aux_2(static_cast<size_type>(__beg), __end); }
256
257 void
258 _M_construct_aux_2(size_type __req, _CharT __c)
259 { _M_construct(__req, __c); }
260
261 template<typename _InIterator>
262 void
263 _M_construct(_InIterator __beg, _InIterator __end)
264 {
265 typedef typename std::__is_integer<_InIterator>::__type _Integral;
266 _M_construct_aux(__beg, __end, _Integral());
267 }
268
269 // For Input Iterators, used in istreambuf_iterators, etc.
270 template<typename _InIterator>
271 void
272 _M_construct(_InIterator __beg, _InIterator __end,
273 std::input_iterator_tag);
274
275 // For forward_iterators up to random_access_iterators, used for
276 // string::iterator, _CharT*, etc.
277 template<typename _FwdIterator>
278 void
279 _M_construct(_FwdIterator __beg, _FwdIterator __end,
280 std::forward_iterator_tag);
281
282 void
283 _M_construct(size_type __req, _CharT __c);
284
285 allocator_type&
286 _M_get_allocator()
287 { return _M_dataplus; }
288
289 const allocator_type&
290 _M_get_allocator() const
291 { return _M_dataplus; }
292
293 private:
294
295#ifdef _GLIBCXX_DISAMBIGUATE_REPLACE_INST
296 // The explicit instantiations in misc-inst.cc require this due to
297 // https://gcc.gnu.org/bugzilla/show_bug.cgi?id=64063
298 template<typename _Tp, bool _Requires =
299 !__are_same<_Tp, _CharT*>::__value
300 && !__are_same<_Tp, const _CharT*>::__value
301 && !__are_same<_Tp, iterator>::__value
302 && !__are_same<_Tp, const_iterator>::__value>
303 struct __enable_if_not_native_iterator
304 { typedef basic_string& __type; };
305 template<typename _Tp>
306 struct __enable_if_not_native_iterator<_Tp, false> { };
307#endif
308
309 size_type
310 _M_check(size_type __pos, const char* __s) const
311 {
312 if (__pos > this->size())
313 __throw_out_of_range_fmt(__N("%s: __pos (which is %zu) > "("%s: __pos (which is %zu) > " "this->size() (which is %zu)"
)
314 "this->size() (which is %zu)")("%s: __pos (which is %zu) > " "this->size() (which is %zu)"
)
,
315 __s, __pos, this->size());
316 return __pos;
317 }
318
319 void
320 _M_check_length(size_type __n1, size_type __n2, const char* __s) const
321 {
322 if (this->max_size() - (this->size() - __n1) < __n2)
323 __throw_length_error(__N(__s)(__s));
324 }
325
326
327 // NB: _M_limit doesn't check for a bad __pos value.
328 size_type
329 _M_limit(size_type __pos, size_type __off) const _GLIBCXX_NOEXCEPTnoexcept
330 {
331 const bool __testoff = __off < this->size() - __pos;
332 return __testoff ? __off : this->size() - __pos;
333 }
334
335 // True if _Rep and source do not overlap.
336 bool
337 _M_disjunct(const _CharT* __s) const _GLIBCXX_NOEXCEPTnoexcept
338 {
339 return (less<const _CharT*>()(__s, _M_data())
340 || less<const _CharT*>()(_M_data() + this->size(), __s));
341 }
342
343 // When __n = 1 way faster than the general multichar
344 // traits_type::copy/move/assign.
345 static void
346 _S_copy(_CharT* __d, const _CharT* __s, size_type __n)
347 {
348 if (__n == 1)
349 traits_type::assign(*__d, *__s);
350 else
351 traits_type::copy(__d, __s, __n);
352 }
353
354 static void
355 _S_move(_CharT* __d, const _CharT* __s, size_type __n)
356 {
357 if (__n == 1)
358 traits_type::assign(*__d, *__s);
359 else
360 traits_type::move(__d, __s, __n);
361 }
362
363 static void
364 _S_assign(_CharT* __d, size_type __n, _CharT __c)
365 {
366 if (__n == 1)
367 traits_type::assign(*__d, __c);
368 else
369 traits_type::assign(__d, __n, __c);
370 }
371
372 // _S_copy_chars is a separate template to permit specialization
373 // to optimize for the common case of pointers as iterators.
374 template<class _Iterator>
375 static void
376 _S_copy_chars(_CharT* __p, _Iterator __k1, _Iterator __k2)
377 {
378 for (; __k1 != __k2; ++__k1, (void)++__p)
379 traits_type::assign(*__p, *__k1); // These types are off.
380 }
381
382 static void
383 _S_copy_chars(_CharT* __p, iterator __k1, iterator __k2) _GLIBCXX_NOEXCEPTnoexcept
384 { _S_copy_chars(__p, __k1.base(), __k2.base()); }
385
386 static void
387 _S_copy_chars(_CharT* __p, const_iterator __k1, const_iterator __k2)
388 _GLIBCXX_NOEXCEPTnoexcept
389 { _S_copy_chars(__p, __k1.base(), __k2.base()); }
390
391 static void
392 _S_copy_chars(_CharT* __p, _CharT* __k1, _CharT* __k2) _GLIBCXX_NOEXCEPTnoexcept
393 { _S_copy(__p, __k1, __k2 - __k1); }
394
395 static void
396 _S_copy_chars(_CharT* __p, const _CharT* __k1, const _CharT* __k2)
397 _GLIBCXX_NOEXCEPTnoexcept
398 { _S_copy(__p, __k1, __k2 - __k1); }
399
400 static int
401 _S_compare(size_type __n1, size_type __n2) _GLIBCXX_NOEXCEPTnoexcept
402 {
403 const difference_type __d = difference_type(__n1 - __n2);
404
405 if (__d > __gnu_cxx::__numeric_traits<int>::__max)
406 return __gnu_cxx::__numeric_traits<int>::__max;
407 else if (__d < __gnu_cxx::__numeric_traits<int>::__min)
408 return __gnu_cxx::__numeric_traits<int>::__min;
409 else
410 return int(__d);
411 }
412
413 void
414 _M_assign(const basic_string&);
415
416 void
417 _M_mutate(size_type __pos, size_type __len1, const _CharT* __s,
418 size_type __len2);
419
420 void
421 _M_erase(size_type __pos, size_type __n);
422
423 public:
424 // Construct/copy/destroy:
425 // NB: We overload ctors in some cases instead of using default
426 // arguments, per 17.4.4.4 para. 2 item 2.
427
428 /**
429 * @brief Default constructor creates an empty string.
430 */
431 basic_string()
432 _GLIBCXX_NOEXCEPT_IF(is_nothrow_default_constructible<_Alloc>::value)noexcept(is_nothrow_default_constructible<_Alloc>::value
)
433 : _M_dataplus(_M_local_data())
434 { _M_set_length(0); }
435
436 /**
437 * @brief Construct an empty string using allocator @a a.
438 */
439 explicit
440 basic_string(const _Alloc& __a) _GLIBCXX_NOEXCEPTnoexcept
441 : _M_dataplus(_M_local_data(), __a)
442 { _M_set_length(0); }
443
444 /**
445 * @brief Construct string with copy of value of @a __str.
446 * @param __str Source string.
447 */
448 basic_string(const basic_string& __str)
449 : _M_dataplus(_M_local_data(),
450 _Alloc_traits::_S_select_on_copy(__str._M_get_allocator()))
451 { _M_construct(__str._M_data(), __str._M_data() + __str.length()); }
452
453 // _GLIBCXX_RESOLVE_LIB_DEFECTS
454 // 2583. no way to supply an allocator for basic_string(str, pos)
455 /**
456 * @brief Construct string as copy of a substring.
457 * @param __str Source string.
458 * @param __pos Index of first character to copy from.
459 * @param __a Allocator to use.
460 */
461 basic_string(const basic_string& __str, size_type __pos,
462 const _Alloc& __a = _Alloc())
463 : _M_dataplus(_M_local_data(), __a)
464 {
465 const _CharT* __start = __str._M_data()
466 + __str._M_check(__pos, "basic_string::basic_string");
467 _M_construct(__start, __start + __str._M_limit(__pos, npos));
468 }
469
470 /**
471 * @brief Construct string as copy of a substring.
472 * @param __str Source string.
473 * @param __pos Index of first character to copy from.
474 * @param __n Number of characters to copy.
475 */
476 basic_string(const basic_string& __str, size_type __pos,
477 size_type __n)
478 : _M_dataplus(_M_local_data())
479 {
480 const _CharT* __start = __str._M_data()
481 + __str._M_check(__pos, "basic_string::basic_string");
482 _M_construct(__start, __start + __str._M_limit(__pos, __n));
483 }
484
485 /**
486 * @brief Construct string as copy of a substring.
487 * @param __str Source string.
488 * @param __pos Index of first character to copy from.
489 * @param __n Number of characters to copy.
490 * @param __a Allocator to use.
491 */
492 basic_string(const basic_string& __str, size_type __pos,
493 size_type __n, const _Alloc& __a)
494 : _M_dataplus(_M_local_data(), __a)
495 {
496 const _CharT* __start
497 = __str._M_data() + __str._M_check(__pos, "string::string");
498 _M_construct(__start, __start + __str._M_limit(__pos, __n));
499 }
500
501 /**
502 * @brief Construct string initialized by a character %array.
503 * @param __s Source character %array.
504 * @param __n Number of characters to copy.
505 * @param __a Allocator to use (default is default allocator).
506 *
507 * NB: @a __s must have at least @a __n characters, &apos;\\0&apos;
508 * has no special meaning.
509 */
510 basic_string(const _CharT* __s, size_type __n,
511 const _Alloc& __a = _Alloc())
512 : _M_dataplus(_M_local_data(), __a)
513 { _M_construct(__s, __s + __n); }
514
515 /**
516 * @brief Construct string as copy of a C string.
517 * @param __s Source C string.
518 * @param __a Allocator to use (default is default allocator).
519 */
520#if __cpp_deduction_guides201703L && ! defined _GLIBCXX_DEFINING_STRING_INSTANTIATIONS
521 // _GLIBCXX_RESOLVE_LIB_DEFECTS
522 // 3076. basic_string CTAD ambiguity
523 template<typename = _RequireAllocator<_Alloc>>
524#endif
525 basic_string(const _CharT* __s, const _Alloc& __a = _Alloc())
526 : _M_dataplus(_M_local_data(), __a)
527 { _M_construct(__s, __s ? __s + traits_type::length(__s) : __s+npos); }
528
529 /**
530 * @brief Construct string as multiple characters.
531 * @param __n Number of characters.
532 * @param __c Character to use.
533 * @param __a Allocator to use (default is default allocator).
534 */
535#if __cpp_deduction_guides201703L && ! defined _GLIBCXX_DEFINING_STRING_INSTANTIATIONS
536 // _GLIBCXX_RESOLVE_LIB_DEFECTS
537 // 3076. basic_string CTAD ambiguity
538 template<typename = _RequireAllocator<_Alloc>>
539#endif
540 basic_string(size_type __n, _CharT __c, const _Alloc& __a = _Alloc())
541 : _M_dataplus(_M_local_data(), __a)
542 { _M_construct(__n, __c); }
543
544#if __cplusplus201703L >= 201103L
545 /**
546 * @brief Move construct string.
547 * @param __str Source string.
548 *
549 * The newly-created string contains the exact contents of @a __str.
550 * @a __str is a valid, but unspecified string.
551 **/
552 basic_string(basic_string&& __str) noexcept
553 : _M_dataplus(_M_local_data(), std::move(__str._M_get_allocator()))
554 {
555 if (__str._M_is_local())
556 {
557 traits_type::copy(_M_local_buf, __str._M_local_buf,
558 _S_local_capacity + 1);
559 }
560 else
561 {
562 _M_data(__str._M_data());
563 _M_capacity(__str._M_allocated_capacity);
564 }
565
566 // Must use _M_length() here not _M_set_length() because
567 // basic_stringbuf relies on writing into unallocated capacity so
568 // we mess up the contents if we put a '\0' in the string.
569 _M_length(__str.length());
570 __str._M_data(__str._M_local_data());
571 __str._M_set_length(0);
572 }
573
574 /**
575 * @brief Construct string from an initializer %list.
576 * @param __l std::initializer_list of characters.
577 * @param __a Allocator to use (default is default allocator).
578 */
579 basic_string(initializer_list<_CharT> __l, const _Alloc& __a = _Alloc())
580 : _M_dataplus(_M_local_data(), __a)
581 { _M_construct(__l.begin(), __l.end()); }
582
583 basic_string(const basic_string& __str, const _Alloc& __a)
584 : _M_dataplus(_M_local_data(), __a)
585 { _M_construct(__str.begin(), __str.end()); }
586
587 basic_string(basic_string&& __str, const _Alloc& __a)
588 noexcept(_Alloc_traits::_S_always_equal())
589 : _M_dataplus(_M_local_data(), __a)
590 {
591 if (__str._M_is_local())
592 {
593 traits_type::copy(_M_local_buf, __str._M_local_buf,
594 _S_local_capacity + 1);
595 _M_length(__str.length());
596 __str._M_set_length(0);
597 }
598 else if (_Alloc_traits::_S_always_equal()
599 || __str.get_allocator() == __a)
600 {
601 _M_data(__str._M_data());
602 _M_length(__str.length());
603 _M_capacity(__str._M_allocated_capacity);
604 __str._M_data(__str._M_local_buf);
605 __str._M_set_length(0);
606 }
607 else
608 _M_construct(__str.begin(), __str.end());
609 }
610
611#endif // C++11
612
613 /**
614 * @brief Construct string as copy of a range.
615 * @param __beg Start of range.
616 * @param __end End of range.
617 * @param __a Allocator to use (default is default allocator).
618 */
619#if __cplusplus201703L >= 201103L
620 template<typename _InputIterator,
621 typename = std::_RequireInputIter<_InputIterator>>
622#else
623 template<typename _InputIterator>
624#endif
625 basic_string(_InputIterator __beg, _InputIterator __end,
626 const _Alloc& __a = _Alloc())
627 : _M_dataplus(_M_local_data(), __a)
628 { _M_construct(__beg, __end); }
629
630#if __cplusplus201703L >= 201703L
631 /**
632 * @brief Construct string from a substring of a string_view.
633 * @param __t Source object convertible to string view.
634 * @param __pos The index of the first character to copy from __t.
635 * @param __n The number of characters to copy from __t.
636 * @param __a Allocator to use.
637 */
638 template<typename _Tp, typename = _If_sv<_Tp, void>>
639 basic_string(const _Tp& __t, size_type __pos, size_type __n,
640 const _Alloc& __a = _Alloc())
641 : basic_string(_S_to_string_view(__t).substr(__pos, __n), __a) { }
642
643 /**
644 * @brief Construct string from a string_view.
645 * @param __t Source object convertible to string view.
646 * @param __a Allocator to use (default is default allocator).
647 */
648 template<typename _Tp, typename = _If_sv<_Tp, void>>
649 explicit
650 basic_string(const _Tp& __t, const _Alloc& __a = _Alloc())
651 : basic_string(__sv_wrapper(_S_to_string_view(__t)), __a) { }
652#endif // C++17
653
654 /**
655 * @brief Destroy the string instance.
656 */
657 ~basic_string()
658 { _M_dispose(); }
659
660 /**
661 * @brief Assign the value of @a str to this string.
662 * @param __str Source string.
663 */
664 basic_string&
665 operator=(const basic_string& __str)
666 {
667 return this->assign(__str);
668 }
669
670 /**
671 * @brief Copy contents of @a s into this string.
672 * @param __s Source null-terminated string.
673 */
674 basic_string&
675 operator=(const _CharT* __s)
676 { return this->assign(__s); }
677
678 /**
679 * @brief Set value to string of length 1.
680 * @param __c Source character.
681 *
682 * Assigning to a character makes this string length 1 and
683 * (*this)[0] == @a c.
684 */
685 basic_string&
686 operator=(_CharT __c)
687 {
688 this->assign(1, __c);
689 return *this;
690 }
691
692#if __cplusplus201703L >= 201103L
693 /**
694 * @brief Move assign the value of @a str to this string.
695 * @param __str Source string.
696 *
697 * The contents of @a str are moved into this string (without copying).
698 * @a str is a valid, but unspecified string.
699 **/
700 // _GLIBCXX_RESOLVE_LIB_DEFECTS
701 // 2063. Contradictory requirements for string move assignment
702 basic_string&
703 operator=(basic_string&& __str)
704 noexcept(_Alloc_traits::_S_nothrow_move())
705 {
706 if (!_M_is_local() && _Alloc_traits::_S_propagate_on_move_assign()
707 && !_Alloc_traits::_S_always_equal()
708 && _M_get_allocator() != __str._M_get_allocator())
709 {
710 // Destroy existing storage before replacing allocator.
711 _M_destroy(_M_allocated_capacity);
712 _M_data(_M_local_data());
713 _M_set_length(0);
714 }
715 // Replace allocator if POCMA is true.
716 std::__alloc_on_move(_M_get_allocator(), __str._M_get_allocator());
717
718 if (__str._M_is_local())
719 {
720 // We've always got room for a short string, just copy it.
721 if (__str.size())
722 this->_S_copy(_M_data(), __str._M_data(), __str.size());
723 _M_set_length(__str.size());
724 }
725 else if (_Alloc_traits::_S_propagate_on_move_assign()
726 || _Alloc_traits::_S_always_equal()
727 || _M_get_allocator() == __str._M_get_allocator())
728 {
729 // Just move the allocated pointer, our allocator can free it.
730 pointer __data = nullptr;
731 size_type __capacity;
732 if (!_M_is_local())
733 {
734 if (_Alloc_traits::_S_always_equal())
735 {
736 // __str can reuse our existing storage.
737 __data = _M_data();
738 __capacity = _M_allocated_capacity;
739 }
740 else // __str can't use it, so free it.
741 _M_destroy(_M_allocated_capacity);
742 }
743
744 _M_data(__str._M_data());
745 _M_length(__str.length());
746 _M_capacity(__str._M_allocated_capacity);
747 if (__data)
748 {
749 __str._M_data(__data);
750 __str._M_capacity(__capacity);
751 }
752 else
753 __str._M_data(__str._M_local_buf);
754 }
755 else // Need to do a deep copy
756 assign(__str);
757 __str.clear();
758 return *this;
759 }
760
761 /**
762 * @brief Set value to string constructed from initializer %list.
763 * @param __l std::initializer_list.
764 */
765 basic_string&
766 operator=(initializer_list<_CharT> __l)
767 {
768 this->assign(__l.begin(), __l.size());
769 return *this;
770 }
771#endif // C++11
772
773#if __cplusplus201703L >= 201703L
774 /**
775 * @brief Set value to string constructed from a string_view.
776 * @param __svt An object convertible to string_view.
777 */
778 template<typename _Tp>
779 _If_sv<_Tp, basic_string&>
780 operator=(const _Tp& __svt)
781 { return this->assign(__svt); }
782
783 /**
784 * @brief Convert to a string_view.
785 * @return A string_view.
786 */
787 operator __sv_type() const noexcept
788 { return __sv_type(data(), size()); }
789#endif // C++17
790
791 // Iterators:
792 /**
793 * Returns a read/write iterator that points to the first character in
794 * the %string.
795 */
796 iterator
797 begin() _GLIBCXX_NOEXCEPTnoexcept
798 { return iterator(_M_data()); }
799
800 /**
801 * Returns a read-only (constant) iterator that points to the first
802 * character in the %string.
803 */
804 const_iterator
805 begin() const _GLIBCXX_NOEXCEPTnoexcept
806 { return const_iterator(_M_data()); }
807
808 /**
809 * Returns a read/write iterator that points one past the last
810 * character in the %string.
811 */
812 iterator
813 end() _GLIBCXX_NOEXCEPTnoexcept
814 { return iterator(_M_data() + this->size()); }
815
816 /**
817 * Returns a read-only (constant) iterator that points one past the
818 * last character in the %string.
819 */
820 const_iterator
821 end() const _GLIBCXX_NOEXCEPTnoexcept
822 { return const_iterator(_M_data() + this->size()); }
823
824 /**
825 * Returns a read/write reverse iterator that points to the last
826 * character in the %string. Iteration is done in reverse element
827 * order.
828 */
829 reverse_iterator
830 rbegin() _GLIBCXX_NOEXCEPTnoexcept
831 { return reverse_iterator(this->end()); }
832
833 /**
834 * Returns a read-only (constant) reverse iterator that points
835 * to the last character in the %string. Iteration is done in
836 * reverse element order.
837 */
838 const_reverse_iterator
839 rbegin() const _GLIBCXX_NOEXCEPTnoexcept
840 { return const_reverse_iterator(this->end()); }
841
842 /**
843 * Returns a read/write reverse iterator that points to one before the
844 * first character in the %string. Iteration is done in reverse
845 * element order.
846 */
847 reverse_iterator
848 rend() _GLIBCXX_NOEXCEPTnoexcept
849 { return reverse_iterator(this->begin()); }
850
851 /**
852 * Returns a read-only (constant) reverse iterator that points
853 * to one before the first character in the %string. Iteration
854 * is done in reverse element order.
855 */
856 const_reverse_iterator
857 rend() const _GLIBCXX_NOEXCEPTnoexcept
858 { return const_reverse_iterator(this->begin()); }
859
860#if __cplusplus201703L >= 201103L
861 /**
862 * Returns a read-only (constant) iterator that points to the first
863 * character in the %string.
864 */
865 const_iterator
866 cbegin() const noexcept
867 { return const_iterator(this->_M_data()); }
868
869 /**
870 * Returns a read-only (constant) iterator that points one past the
871 * last character in the %string.
872 */
873 const_iterator
874 cend() const noexcept
875 { return const_iterator(this->_M_data() + this->size()); }
876
877 /**
878 * Returns a read-only (constant) reverse iterator that points
879 * to the last character in the %string. Iteration is done in
880 * reverse element order.
881 */
882 const_reverse_iterator
883 crbegin() const noexcept
884 { return const_reverse_iterator(this->end()); }
885
886 /**
887 * Returns a read-only (constant) reverse iterator that points
888 * to one before the first character in the %string. Iteration
889 * is done in reverse element order.
890 */
891 const_reverse_iterator
892 crend() const noexcept
893 { return const_reverse_iterator(this->begin()); }
894#endif
895
896 public:
897 // Capacity:
898 /// Returns the number of characters in the string, not including any
899 /// null-termination.
900 size_type
901 size() const _GLIBCXX_NOEXCEPTnoexcept
902 { return _M_string_length; }
903
904 /// Returns the number of characters in the string, not including any
905 /// null-termination.
906 size_type
907 length() const _GLIBCXX_NOEXCEPTnoexcept
908 { return _M_string_length; }
909
910 /// Returns the size() of the largest possible %string.
911 size_type
912 max_size() const _GLIBCXX_NOEXCEPTnoexcept
913 { return (_Alloc_traits::max_size(_M_get_allocator()) - 1) / 2; }
914
915 /**
916 * @brief Resizes the %string to the specified number of characters.
917 * @param __n Number of characters the %string should contain.
918 * @param __c Character to fill any new elements.
919 *
920 * This function will %resize the %string to the specified
921 * number of characters. If the number is smaller than the
922 * %string's current size the %string is truncated, otherwise
923 * the %string is extended and new elements are %set to @a __c.
924 */
925 void
926 resize(size_type __n, _CharT __c);
927
928 /**
929 * @brief Resizes the %string to the specified number of characters.
930 * @param __n Number of characters the %string should contain.
931 *
932 * This function will resize the %string to the specified length. If
933 * the new size is smaller than the %string's current size the %string
934 * is truncated, otherwise the %string is extended and new characters
935 * are default-constructed. For basic types such as char, this means
936 * setting them to 0.
937 */
938 void
939 resize(size_type __n)
940 { this->resize(__n, _CharT()); }
941
942#if __cplusplus201703L >= 201103L
943 /// A non-binding request to reduce capacity() to size().
944 void
945 shrink_to_fit() noexcept
946 {
947#if __cpp_exceptions
948 if (capacity() > size())
949 {
950 try
951 { reserve(0); }
952 catch(...)
953 { }
954 }
955#endif
956 }
957#endif
958
959 /**
960 * Returns the total number of characters that the %string can hold
961 * before needing to allocate more memory.
962 */
963 size_type
964 capacity() const _GLIBCXX_NOEXCEPTnoexcept
965 {
966 return _M_is_local() ? size_type(_S_local_capacity)
967 : _M_allocated_capacity;
968 }
969
970 /**
971 * @brief Attempt to preallocate enough memory for specified number of
972 * characters.
973 * @param __res_arg Number of characters required.
974 * @throw std::length_error If @a __res_arg exceeds @c max_size().
975 *
976 * This function attempts to reserve enough memory for the
977 * %string to hold the specified number of characters. If the
978 * number requested is more than max_size(), length_error is
979 * thrown.
980 *
981 * The advantage of this function is that if optimal code is a
982 * necessity and the user can determine the string length that will be
983 * required, the user can reserve the memory in %advance, and thus
984 * prevent a possible reallocation of memory and copying of %string
985 * data.
986 */
987 void
988 reserve(size_type __res_arg = 0);
989
990 /**
991 * Erases the string, making it empty.
992 */
993 void
994 clear() _GLIBCXX_NOEXCEPTnoexcept
995 { _M_set_length(0); }
996
997 /**
998 * Returns true if the %string is empty. Equivalent to
999 * <code>*this == ""</code>.
1000 */
1001 _GLIBCXX_NODISCARD[[__nodiscard__]] bool
1002 empty() const _GLIBCXX_NOEXCEPTnoexcept
1003 { return this->size() == 0; }
1004
1005 // Element access:
1006 /**
1007 * @brief Subscript access to the data contained in the %string.
1008 * @param __pos The index of the character to access.
1009 * @return Read-only (constant) reference to the character.
1010 *
1011 * This operator allows for easy, array-style, data access.
1012 * Note that data access with this operator is unchecked and
1013 * out_of_range lookups are not defined. (For checked lookups
1014 * see at().)
1015 */
1016 const_reference
1017 operator[] (size_type __pos) const _GLIBCXX_NOEXCEPTnoexcept
1018 {
1019 __glibcxx_assert(__pos <= size())do { if (! (__pos <= size())) std::__replacement_assert("/usr/lib/gcc/x86_64-linux-gnu/10/../../../../include/c++/10/bits/basic_string.h"
, 1019, __PRETTY_FUNCTION__, "__pos <= size()"); } while (
false)
;
1020 return _M_data()[__pos];
1021 }
1022
1023 /**
1024 * @brief Subscript access to the data contained in the %string.
1025 * @param __pos The index of the character to access.
1026 * @return Read/write reference to the character.
1027 *
1028 * This operator allows for easy, array-style, data access.
1029 * Note that data access with this operator is unchecked and
1030 * out_of_range lookups are not defined. (For checked lookups
1031 * see at().)
1032 */
1033 reference
1034 operator[](size_type __pos)
1035 {
1036 // Allow pos == size() both in C++98 mode, as v3 extension,
1037 // and in C++11 mode.
1038 __glibcxx_assert(__pos <= size())do { if (! (__pos <= size())) std::__replacement_assert("/usr/lib/gcc/x86_64-linux-gnu/10/../../../../include/c++/10/bits/basic_string.h"
, 1038, __PRETTY_FUNCTION__, "__pos <= size()"); } while (
false)
;
1039 // In pedantic mode be strict in C++98 mode.
1040 _GLIBCXX_DEBUG_PEDASSERT(__cplusplus >= 201103L || __pos < size());
1041 return _M_data()[__pos];
1042 }
1043
1044 /**
1045 * @brief Provides access to the data contained in the %string.
1046 * @param __n The index of the character to access.
1047 * @return Read-only (const) reference to the character.
1048 * @throw std::out_of_range If @a n is an invalid index.
1049 *
1050 * This function provides for safer data access. The parameter is
1051 * first checked that it is in the range of the string. The function
1052 * throws out_of_range if the check fails.
1053 */
1054 const_reference
1055 at(size_type __n) const
1056 {
1057 if (__n >= this->size())
1058 __throw_out_of_range_fmt(__N("basic_string::at: __n "("basic_string::at: __n " "(which is %zu) >= this->size() "
"(which is %zu)")
1059 "(which is %zu) >= this->size() "("basic_string::at: __n " "(which is %zu) >= this->size() "
"(which is %zu)")
1060 "(which is %zu)")("basic_string::at: __n " "(which is %zu) >= this->size() "
"(which is %zu)")
,
1061 __n, this->size());
1062 return _M_data()[__n];
1063 }
1064
1065 /**
1066 * @brief Provides access to the data contained in the %string.
1067 * @param __n The index of the character to access.
1068 * @return Read/write reference to the character.
1069 * @throw std::out_of_range If @a n is an invalid index.
1070 *
1071 * This function provides for safer data access. The parameter is
1072 * first checked that it is in the range of the string. The function
1073 * throws out_of_range if the check fails.
1074 */
1075 reference
1076 at(size_type __n)
1077 {
1078 if (__n >= size())
1079 __throw_out_of_range_fmt(__N("basic_string::at: __n "("basic_string::at: __n " "(which is %zu) >= this->size() "
"(which is %zu)")
1080 "(which is %zu) >= this->size() "("basic_string::at: __n " "(which is %zu) >= this->size() "
"(which is %zu)")
1081 "(which is %zu)")("basic_string::at: __n " "(which is %zu) >= this->size() "
"(which is %zu)")
,
1082 __n, this->size());
1083 return _M_data()[__n];
1084 }
1085
1086#if __cplusplus201703L >= 201103L
1087 /**
1088 * Returns a read/write reference to the data at the first
1089 * element of the %string.
1090 */
1091 reference
1092 front() noexcept
1093 {
1094 __glibcxx_assert(!empty())do { if (! (!empty())) std::__replacement_assert("/usr/lib/gcc/x86_64-linux-gnu/10/../../../../include/c++/10/bits/basic_string.h"
, 1094, __PRETTY_FUNCTION__, "!empty()"); } while (false)
;
1095 return operator[](0);
1096 }
1097
1098 /**
1099 * Returns a read-only (constant) reference to the data at the first
1100 * element of the %string.
1101 */
1102 const_reference
1103 front() const noexcept
1104 {
1105 __glibcxx_assert(!empty())do { if (! (!empty())) std::__replacement_assert("/usr/lib/gcc/x86_64-linux-gnu/10/../../../../include/c++/10/bits/basic_string.h"
, 1105, __PRETTY_FUNCTION__, "!empty()"); } while (false)
;
1106 return operator[](0);
1107 }
1108
1109 /**
1110 * Returns a read/write reference to the data at the last
1111 * element of the %string.
1112 */
1113 reference
1114 back() noexcept
1115 {
1116 __glibcxx_assert(!empty())do { if (! (!empty())) std::__replacement_assert("/usr/lib/gcc/x86_64-linux-gnu/10/../../../../include/c++/10/bits/basic_string.h"
, 1116, __PRETTY_FUNCTION__, "!empty()"); } while (false)
;
1117 return operator[](this->size() - 1);
1118 }
1119
1120 /**
1121 * Returns a read-only (constant) reference to the data at the
1122 * last element of the %string.
1123 */
1124 const_reference
1125 back() const noexcept
1126 {
1127 __glibcxx_assert(!empty())do { if (! (!empty())) std::__replacement_assert("/usr/lib/gcc/x86_64-linux-gnu/10/../../../../include/c++/10/bits/basic_string.h"
, 1127, __PRETTY_FUNCTION__, "!empty()"); } while (false)
;
1128 return operator[](this->size() - 1);
1129 }
1130#endif
1131
1132 // Modifiers:
1133 /**
1134 * @brief Append a string to this string.
1135 * @param __str The string to append.
1136 * @return Reference to this string.
1137 */
1138 basic_string&
1139 operator+=(const basic_string& __str)
1140 { return this->append(__str); }
1141
1142 /**
1143 * @brief Append a C string.
1144 * @param __s The C string to append.
1145 * @return Reference to this string.
1146 */
1147 basic_string&
1148 operator+=(const _CharT* __s)
1149 { return this->append(__s); }
1150
1151 /**
1152 * @brief Append a character.
1153 * @param __c The character to append.
1154 * @return Reference to this string.
1155 */
1156 basic_string&
1157 operator+=(_CharT __c)
1158 {
1159 this->push_back(__c);
1160 return *this;
1161 }
1162
1163#if __cplusplus201703L >= 201103L
1164 /**
1165 * @brief Append an initializer_list of characters.
1166 * @param __l The initializer_list of characters to be appended.
1167 * @return Reference to this string.
1168 */
1169 basic_string&
1170 operator+=(initializer_list<_CharT> __l)
1171 { return this->append(__l.begin(), __l.size()); }
1172#endif // C++11
1173
1174#if __cplusplus201703L >= 201703L
1175 /**
1176 * @brief Append a string_view.
1177 * @param __svt An object convertible to string_view to be appended.
1178 * @return Reference to this string.
1179 */
1180 template<typename _Tp>
1181 _If_sv<_Tp, basic_string&>
1182 operator+=(const _Tp& __svt)
1183 { return this->append(__svt); }
1184#endif // C++17
1185
1186 /**
1187 * @brief Append a string to this string.
1188 * @param __str The string to append.
1189 * @return Reference to this string.
1190 */
1191 basic_string&
1192 append(const basic_string& __str)
1193 { return _M_append(__str._M_data(), __str.size()); }
1194
1195 /**
1196 * @brief Append a substring.
1197 * @param __str The string to append.
1198 * @param __pos Index of the first character of str to append.
1199 * @param __n The number of characters to append.
1200 * @return Reference to this string.
1201 * @throw std::out_of_range if @a __pos is not a valid index.
1202 *
1203 * This function appends @a __n characters from @a __str
1204 * starting at @a __pos to this string. If @a __n is is larger
1205 * than the number of available characters in @a __str, the
1206 * remainder of @a __str is appended.
1207 */
1208 basic_string&
1209 append(const basic_string& __str, size_type __pos, size_type __n = npos)
1210 { return _M_append(__str._M_data()
1211 + __str._M_check(__pos, "basic_string::append"),
1212 __str._M_limit(__pos, __n)); }
1213
1214 /**
1215 * @brief Append a C substring.
1216 * @param __s The C string to append.
1217 * @param __n The number of characters to append.
1218 * @return Reference to this string.
1219 */
1220 basic_string&
1221 append(const _CharT* __s, size_type __n)
1222 {
1223 __glibcxx_requires_string_len(__s, __n);
1224 _M_check_length(size_type(0), __n, "basic_string::append");
1225 return _M_append(__s, __n);
1226 }
1227
1228 /**
1229 * @brief Append a C string.
1230 * @param __s The C string to append.
1231 * @return Reference to this string.
1232 */
1233 basic_string&
1234 append(const _CharT* __s)
1235 {
1236 __glibcxx_requires_string(__s);
1237 const size_type __n = traits_type::length(__s);
1238 _M_check_length(size_type(0), __n, "basic_string::append");
1239 return _M_append(__s, __n);
1240 }
1241
1242 /**
1243 * @brief Append multiple characters.
1244 * @param __n The number of characters to append.
1245 * @param __c The character to use.
1246 * @return Reference to this string.
1247 *
1248 * Appends __n copies of __c to this string.
1249 */
1250 basic_string&
1251 append(size_type __n, _CharT __c)
1252 { return _M_replace_aux(this->size(), size_type(0), __n, __c); }
1253
1254#if __cplusplus201703L >= 201103L
1255 /**
1256 * @brief Append an initializer_list of characters.
1257 * @param __l The initializer_list of characters to append.
1258 * @return Reference to this string.
1259 */
1260 basic_string&
1261 append(initializer_list<_CharT> __l)
1262 { return this->append(__l.begin(), __l.size()); }
1263#endif // C++11
1264
1265 /**
1266 * @brief Append a range of characters.
1267 * @param __first Iterator referencing the first character to append.
1268 * @param __last Iterator marking the end of the range.
1269 * @return Reference to this string.
1270 *
1271 * Appends characters in the range [__first,__last) to this string.
1272 */
1273#if __cplusplus201703L >= 201103L
1274 template<class _InputIterator,
1275 typename = std::_RequireInputIter<_InputIterator>>
1276#else
1277 template<class _InputIterator>
1278#endif
1279 basic_string&
1280 append(_InputIterator __first, _InputIterator __last)
1281 { return this->replace(end(), end(), __first, __last); }
1282
1283#if __cplusplus201703L >= 201703L
1284 /**
1285 * @brief Append a string_view.
1286 * @param __svt An object convertible to string_view to be appended.
1287 * @return Reference to this string.
1288 */
1289 template<typename _Tp>
1290 _If_sv<_Tp, basic_string&>
1291 append(const _Tp& __svt)
1292 {
1293 __sv_type __sv = __svt;
1294 return this->append(__sv.data(), __sv.size());
1295 }
1296
1297 /**
1298 * @brief Append a range of characters from a string_view.
1299 * @param __svt An object convertible to string_view to be appended from.
1300 * @param __pos The position in the string_view to append from.
1301 * @param __n The number of characters to append from the string_view.
1302 * @return Reference to this string.
1303 */
1304 template<typename _Tp>
1305 _If_sv<_Tp, basic_string&>
1306 append(const _Tp& __svt, size_type __pos, size_type __n = npos)
1307 {
1308 __sv_type __sv = __svt;
1309 return _M_append(__sv.data()
1310 + std::__sv_check(__sv.size(), __pos, "basic_string::append"),
1311 std::__sv_limit(__sv.size(), __pos, __n));
1312 }
1313#endif // C++17
1314
1315 /**
1316 * @brief Append a single character.
1317 * @param __c Character to append.
1318 */
1319 void
1320 push_back(_CharT __c)
1321 {
1322 const size_type __size = this->size();
1323 if (__size + 1 > this->capacity())
1324 this->_M_mutate(__size, size_type(0), 0, size_type(1));
1325 traits_type::assign(this->_M_data()[__size], __c);
1326 this->_M_set_length(__size + 1);
1327 }
1328
1329 /**
1330 * @brief Set value to contents of another string.
1331 * @param __str Source string to use.
1332 * @return Reference to this string.
1333 */
1334 basic_string&
1335 assign(const basic_string& __str)
1336 {
1337#if __cplusplus201703L >= 201103L
1338 if (_Alloc_traits::_S_propagate_on_copy_assign())
1339 {
1340 if (!_Alloc_traits::_S_always_equal() && !_M_is_local()
1341 && _M_get_allocator() != __str._M_get_allocator())
1342 {
1343 // Propagating allocator cannot free existing storage so must
1344 // deallocate it before replacing current allocator.
1345 if (__str.size() <= _S_local_capacity)
1346 {
1347 _M_destroy(_M_allocated_capacity);
1348 _M_data(_M_local_data());
1349 _M_set_length(0);
1350 }
1351 else
1352 {
1353 const auto __len = __str.size();
1354 auto __alloc = __str._M_get_allocator();
1355 // If this allocation throws there are no effects:
1356 auto __ptr = _Alloc_traits::allocate(__alloc, __len + 1);
1357 _M_destroy(_M_allocated_capacity);
1358 _M_data(__ptr);
1359 _M_capacity(__len);
1360 _M_set_length(__len);
1361 }
1362 }
1363 std::__alloc_on_copy(_M_get_allocator(), __str._M_get_allocator());
1364 }
1365#endif
1366 this->_M_assign(__str);
1367 return *this;
1368 }
1369
1370#if __cplusplus201703L >= 201103L
1371 /**
1372 * @brief Set value to contents of another string.
1373 * @param __str Source string to use.
1374 * @return Reference to this string.
1375 *
1376 * This function sets this string to the exact contents of @a __str.
1377 * @a __str is a valid, but unspecified string.
1378 */
1379 basic_string&
1380 assign(basic_string&& __str)
1381 noexcept(_Alloc_traits::_S_nothrow_move())
1382 {
1383 // _GLIBCXX_RESOLVE_LIB_DEFECTS
1384 // 2063. Contradictory requirements for string move assignment
1385 return *this = std::move(__str);
1386 }
1387#endif // C++11
1388
1389 /**
1390 * @brief Set value to a substring of a string.
1391 * @param __str The string to use.
1392 * @param __pos Index of the first character of str.
1393 * @param __n Number of characters to use.
1394 * @return Reference to this string.
1395 * @throw std::out_of_range if @a pos is not a valid index.
1396 *
1397 * This function sets this string to the substring of @a __str
1398 * consisting of @a __n characters at @a __pos. If @a __n is
1399 * is larger than the number of available characters in @a
1400 * __str, the remainder of @a __str is used.
1401 */
1402 basic_string&
1403 assign(const basic_string& __str, size_type __pos, size_type __n = npos)
1404 { return _M_replace(size_type(0), this->size(), __str._M_data()
1405 + __str._M_check(__pos, "basic_string::assign"),
1406 __str._M_limit(__pos, __n)); }
1407
1408 /**
1409 * @brief Set value to a C substring.
1410 * @param __s The C string to use.
1411 * @param __n Number of characters to use.
1412 * @return Reference to this string.
1413 *
1414 * This function sets the value of this string to the first @a __n
1415 * characters of @a __s. If @a __n is is larger than the number of
1416 * available characters in @a __s, the remainder of @a __s is used.
1417 */
1418 basic_string&
1419 assign(const _CharT* __s, size_type __n)
1420 {
1421 __glibcxx_requires_string_len(__s, __n);
1422 return _M_replace(size_type(0), this->size(), __s, __n);
1423 }
1424
1425 /**
1426 * @brief Set value to contents of a C string.
1427 * @param __s The C string to use.
1428 * @return Reference to this string.
1429 *
1430 * This function sets the value of this string to the value of @a __s.
1431 * The data is copied, so there is no dependence on @a __s once the
1432 * function returns.
1433 */
1434 basic_string&
1435 assign(const _CharT* __s)
1436 {
1437 __glibcxx_requires_string(__s);
1438 return _M_replace(size_type(0), this->size(), __s,
1439 traits_type::length(__s));
1440 }
1441
1442 /**
1443 * @brief Set value to multiple characters.
1444 * @param __n Length of the resulting string.
1445 * @param __c The character to use.
1446 * @return Reference to this string.
1447 *
1448 * This function sets the value of this string to @a __n copies of
1449 * character @a __c.
1450 */
1451 basic_string&
1452 assign(size_type __n, _CharT __c)
1453 { return _M_replace_aux(size_type(0), this->size(), __n, __c); }
1454
1455 /**
1456 * @brief Set value to a range of characters.
1457 * @param __first Iterator referencing the first character to append.
1458 * @param __last Iterator marking the end of the range.
1459 * @return Reference to this string.
1460 *
1461 * Sets value of string to characters in the range [__first,__last).
1462 */
1463#if __cplusplus201703L >= 201103L
1464 template<class _InputIterator,
1465 typename = std::_RequireInputIter<_InputIterator>>
1466#else
1467 template<class _InputIterator>
1468#endif
1469 basic_string&
1470 assign(_InputIterator __first, _InputIterator __last)
1471 { return this->replace(begin(), end(), __first, __last); }
1472
1473#if __cplusplus201703L >= 201103L
1474 /**
1475 * @brief Set value to an initializer_list of characters.
1476 * @param __l The initializer_list of characters to assign.
1477 * @return Reference to this string.
1478 */
1479 basic_string&
1480 assign(initializer_list<_CharT> __l)
1481 { return this->assign(__l.begin(), __l.size()); }
1482#endif // C++11
1483
1484#if __cplusplus201703L >= 201703L
1485 /**
1486 * @brief Set value from a string_view.
1487 * @param __svt The source object convertible to string_view.
1488 * @return Reference to this string.
1489 */
1490 template<typename _Tp>
1491 _If_sv<_Tp, basic_string&>
1492 assign(const _Tp& __svt)
1493 {
1494 __sv_type __sv = __svt;
1495 return this->assign(__sv.data(), __sv.size());
1496 }
1497
1498 /**
1499 * @brief Set value from a range of characters in a string_view.
1500 * @param __svt The source object convertible to string_view.
1501 * @param __pos The position in the string_view to assign from.
1502 * @param __n The number of characters to assign.
1503 * @return Reference to this string.
1504 */
1505 template<typename _Tp>
1506 _If_sv<_Tp, basic_string&>
1507 assign(const _Tp& __svt, size_type __pos, size_type __n = npos)
1508 {
1509 __sv_type __sv = __svt;
1510 return _M_replace(size_type(0), this->size(),
1511 __sv.data()
1512 + std::__sv_check(__sv.size(), __pos, "basic_string::assign"),
1513 std::__sv_limit(__sv.size(), __pos, __n));
1514 }
1515#endif // C++17
1516
1517#if __cplusplus201703L >= 201103L
1518 /**
1519 * @brief Insert multiple characters.
1520 * @param __p Const_iterator referencing location in string to
1521 * insert at.
1522 * @param __n Number of characters to insert
1523 * @param __c The character to insert.
1524 * @return Iterator referencing the first inserted char.
1525 * @throw std::length_error If new length exceeds @c max_size().
1526 *
1527 * Inserts @a __n copies of character @a __c starting at the
1528 * position referenced by iterator @a __p. If adding
1529 * characters causes the length to exceed max_size(),
1530 * length_error is thrown. The value of the string doesn't
1531 * change if an error is thrown.
1532 */
1533 iterator
1534 insert(const_iterator __p, size_type __n, _CharT __c)
1535 {
1536 _GLIBCXX_DEBUG_PEDASSERT(__p >= begin() && __p <= end());
1537 const size_type __pos = __p - begin();
1538 this->replace(__p, __p, __n, __c);
1539 return iterator(this->_M_data() + __pos);
1540 }
1541#else
1542 /**
1543 * @brief Insert multiple characters.
1544 * @param __p Iterator referencing location in string to insert at.
1545 * @param __n Number of characters to insert
1546 * @param __c The character to insert.
1547 * @throw std::length_error If new length exceeds @c max_size().
1548 *
1549 * Inserts @a __n copies of character @a __c starting at the
1550 * position referenced by iterator @a __p. If adding
1551 * characters causes the length to exceed max_size(),
1552 * length_error is thrown. The value of the string doesn't
1553 * change if an error is thrown.
1554 */
1555 void
1556 insert(iterator __p, size_type __n, _CharT __c)
1557 { this->replace(__p, __p, __n, __c); }
1558#endif
1559
1560#if __cplusplus201703L >= 201103L
1561 /**
1562 * @brief Insert a range of characters.
1563 * @param __p Const_iterator referencing location in string to
1564 * insert at.
1565 * @param __beg Start of range.
1566 * @param __end End of range.
1567 * @return Iterator referencing the first inserted char.
1568 * @throw std::length_error If new length exceeds @c max_size().
1569 *
1570 * Inserts characters in range [beg,end). If adding characters
1571 * causes the length to exceed max_size(), length_error is
1572 * thrown. The value of the string doesn't change if an error
1573 * is thrown.
1574 */
1575 template<class _InputIterator,
1576 typename = std::_RequireInputIter<_InputIterator>>
1577 iterator
1578 insert(const_iterator __p, _InputIterator __beg, _InputIterator __end)
1579 {
1580 _GLIBCXX_DEBUG_PEDASSERT(__p >= begin() && __p <= end());
1581 const size_type __pos = __p - begin();
1582 this->replace(__p, __p, __beg, __end);
1583 return iterator(this->_M_data() + __pos);
1584 }
1585#else
1586 /**
1587 * @brief Insert a range of characters.
1588 * @param __p Iterator referencing location in string to insert at.
1589 * @param __beg Start of range.
1590 * @param __end End of range.
1591 * @throw std::length_error If new length exceeds @c max_size().
1592 *
1593 * Inserts characters in range [__beg,__end). If adding
1594 * characters causes the length to exceed max_size(),
1595 * length_error is thrown. The value of the string doesn't
1596 * change if an error is thrown.
1597 */
1598 template<class _InputIterator>
1599 void
1600 insert(iterator __p, _InputIterator __beg, _InputIterator __end)
1601 { this->replace(__p, __p, __beg, __end); }
1602#endif
1603
1604#if __cplusplus201703L >= 201103L
1605 /**
1606 * @brief Insert an initializer_list of characters.
1607 * @param __p Iterator referencing location in string to insert at.
1608 * @param __l The initializer_list of characters to insert.
1609 * @throw std::length_error If new length exceeds @c max_size().
1610 */
1611 iterator
1612 insert(const_iterator __p, initializer_list<_CharT> __l)
1613 { return this->insert(__p, __l.begin(), __l.end()); }
1614
1615#ifdef _GLIBCXX_DEFINING_STRING_INSTANTIATIONS
1616 // See PR libstdc++/83328
1617 void
1618 insert(iterator __p, initializer_list<_CharT> __l)
1619 {
1620 _GLIBCXX_DEBUG_PEDASSERT(__p >= begin() && __p <= end());
1621 this->insert(__p - begin(), __l.begin(), __l.size());
1622 }
1623#endif
1624#endif // C++11
1625
1626 /**
1627 * @brief Insert value of a string.
1628 * @param __pos1 Position in string to insert at.
1629 * @param __str The string to insert.
1630 * @return Reference to this string.
1631 * @throw std::length_error If new length exceeds @c max_size().
1632 *
1633 * Inserts value of @a __str starting at @a __pos1. If adding
1634 * characters causes the length to exceed max_size(),
1635 * length_error is thrown. The value of the string doesn't
1636 * change if an error is thrown.
1637 */
1638 basic_string&
1639 insert(size_type __pos1, const basic_string& __str)
1640 { return this->replace(__pos1, size_type(0),
1641 __str._M_data(), __str.size()); }
1642
1643 /**
1644 * @brief Insert a substring.
1645 * @param __pos1 Position in string to insert at.
1646 * @param __str The string to insert.
1647 * @param __pos2 Start of characters in str to insert.
1648 * @param __n Number of characters to insert.
1649 * @return Reference to this string.
1650 * @throw std::length_error If new length exceeds @c max_size().
1651 * @throw std::out_of_range If @a pos1 > size() or
1652 * @a __pos2 > @a str.size().
1653 *
1654 * Starting at @a pos1, insert @a __n character of @a __str
1655 * beginning with @a __pos2. If adding characters causes the
1656 * length to exceed max_size(), length_error is thrown. If @a
1657 * __pos1 is beyond the end of this string or @a __pos2 is
1658 * beyond the end of @a __str, out_of_range is thrown. The
1659 * value of the string doesn't change if an error is thrown.
1660 */
1661 basic_string&
1662 insert(size_type __pos1, const basic_string& __str,
1663 size_type __pos2, size_type __n = npos)
1664 { return this->replace(__pos1, size_type(0), __str._M_data()
1665 + __str._M_check(__pos2, "basic_string::insert"),
1666 __str._M_limit(__pos2, __n)); }
1667
1668 /**
1669 * @brief Insert a C substring.
1670 * @param __pos Position in string to insert at.
1671 * @param __s The C string to insert.
1672 * @param __n The number of characters to insert.
1673 * @return Reference to this string.
1674 * @throw std::length_error If new length exceeds @c max_size().
1675 * @throw std::out_of_range If @a __pos is beyond the end of this
1676 * string.
1677 *
1678 * Inserts the first @a __n characters of @a __s starting at @a
1679 * __pos. If adding characters causes the length to exceed
1680 * max_size(), length_error is thrown. If @a __pos is beyond
1681 * end(), out_of_range is thrown. The value of the string
1682 * doesn't change if an error is thrown.
1683 */
1684 basic_string&
1685 insert(size_type __pos, const _CharT* __s, size_type __n)
1686 { return this->replace(__pos, size_type(0), __s, __n); }
1687
1688 /**
1689 * @brief Insert a C string.
1690 * @param __pos Position in string to insert at.
1691 * @param __s The C string to insert.
1692 * @return Reference to this string.
1693 * @throw std::length_error If new length exceeds @c max_size().
1694 * @throw std::out_of_range If @a pos is beyond the end of this
1695 * string.
1696 *
1697 * Inserts the first @a n characters of @a __s starting at @a __pos. If
1698 * adding characters causes the length to exceed max_size(),
1699 * length_error is thrown. If @a __pos is beyond end(), out_of_range is
1700 * thrown. The value of the string doesn't change if an error is
1701 * thrown.
1702 */
1703 basic_string&
1704 insert(size_type __pos, const _CharT* __s)
1705 {
1706 __glibcxx_requires_string(__s);
1707 return this->replace(__pos, size_type(0), __s,
1708 traits_type::length(__s));
1709 }
1710
1711 /**
1712 * @brief Insert multiple characters.
1713 * @param __pos Index in string to insert at.
1714 * @param __n Number of characters to insert
1715 * @param __c The character to insert.
1716 * @return Reference to this string.
1717 * @throw std::length_error If new length exceeds @c max_size().
1718 * @throw std::out_of_range If @a __pos is beyond the end of this
1719 * string.
1720 *
1721 * Inserts @a __n copies of character @a __c starting at index
1722 * @a __pos. If adding characters causes the length to exceed
1723 * max_size(), length_error is thrown. If @a __pos > length(),
1724 * out_of_range is thrown. The value of the string doesn't
1725 * change if an error is thrown.
1726 */
1727 basic_string&
1728 insert(size_type __pos, size_type __n, _CharT __c)
1729 { return _M_replace_aux(_M_check(__pos, "basic_string::insert"),
1730 size_type(0), __n, __c); }
1731
1732 /**
1733 * @brief Insert one character.
1734 * @param __p Iterator referencing position in string to insert at.
1735 * @param __c The character to insert.
1736 * @return Iterator referencing newly inserted char.
1737 * @throw std::length_error If new length exceeds @c max_size().
1738 *
1739 * Inserts character @a __c at position referenced by @a __p.
1740 * If adding character causes the length to exceed max_size(),
1741 * length_error is thrown. If @a __p is beyond end of string,
1742 * out_of_range is thrown. The value of the string doesn't
1743 * change if an error is thrown.
1744 */
1745 iterator
1746 insert(__const_iterator __p, _CharT __c)
1747 {
1748 _GLIBCXX_DEBUG_PEDASSERT(__p >= begin() && __p <= end());
1749 const size_type __pos = __p - begin();
1750 _M_replace_aux(__pos, size_type(0), size_type(1), __c);
1751 return iterator(_M_data() + __pos);
1752 }
1753
1754#if __cplusplus201703L >= 201703L
1755 /**
1756 * @brief Insert a string_view.
1757 * @param __pos Position in string to insert at.
1758 * @param __svt The object convertible to string_view to insert.
1759 * @return Reference to this string.
1760 */
1761 template<typename _Tp>
1762 _If_sv<_Tp, basic_string&>
1763 insert(size_type __pos, const _Tp& __svt)
1764 {
1765 __sv_type __sv = __svt;
1766 return this->insert(__pos, __sv.data(), __sv.size());
1767 }
1768
1769 /**
1770 * @brief Insert a string_view.
1771 * @param __pos1 Position in string to insert at.
1772 * @param __svt The object convertible to string_view to insert from.
1773 * @param __pos2 Start of characters in str to insert.
1774 * @param __n The number of characters to insert.
1775 * @return Reference to this string.
1776 */
1777 template<typename _Tp>
1778 _If_sv<_Tp, basic_string&>
1779 insert(size_type __pos1, const _Tp& __svt,
1780 size_type __pos2, size_type __n = npos)
1781 {
1782 __sv_type __sv = __svt;
1783 return this->replace(__pos1, size_type(0),
1784 __sv.data()
1785 + std::__sv_check(__sv.size(), __pos2, "basic_string::insert"),
1786 std::__sv_limit(__sv.size(), __pos2, __n));
1787 }
1788#endif // C++17
1789
1790 /**
1791 * @brief Remove characters.
1792 * @param __pos Index of first character to remove (default 0).
1793 * @param __n Number of characters to remove (default remainder).
1794 * @return Reference to this string.
1795 * @throw std::out_of_range If @a pos is beyond the end of this
1796 * string.
1797 *
1798 * Removes @a __n characters from this string starting at @a
1799 * __pos. The length of the string is reduced by @a __n. If
1800 * there are < @a __n characters to remove, the remainder of
1801 * the string is truncated. If @a __p is beyond end of string,
1802 * out_of_range is thrown. The value of the string doesn't
1803 * change if an error is thrown.
1804 */
1805 basic_string&
1806 erase(size_type __pos = 0, size_type __n = npos)
1807 {
1808 _M_check(__pos, "basic_string::erase");
1809 if (__n == npos)
1810 this->_M_set_length(__pos);
1811 else if (__n != 0)
1812 this->_M_erase(__pos, _M_limit(__pos, __n));
1813 return *this;
1814 }
1815
1816 /**
1817 * @brief Remove one character.
1818 * @param __position Iterator referencing the character to remove.
1819 * @return iterator referencing same location after removal.
1820 *
1821 * Removes the character at @a __position from this string. The value
1822 * of the string doesn't change if an error is thrown.
1823 */
1824 iterator
1825 erase(__const_iterator __position)
1826 {
1827 _GLIBCXX_DEBUG_PEDASSERT(__position >= begin()
1828 && __position < end());
1829 const size_type __pos = __position - begin();
1830 this->_M_erase(__pos, size_type(1));
1831 return iterator(_M_data() + __pos);
1832 }
1833
1834 /**
1835 * @brief Remove a range of characters.
1836 * @param __first Iterator referencing the first character to remove.
1837 * @param __last Iterator referencing the end of the range.
1838 * @return Iterator referencing location of first after removal.
1839 *
1840 * Removes the characters in the range [first,last) from this string.
1841 * The value of the string doesn't change if an error is thrown.
1842 */
1843 iterator
1844 erase(__const_iterator __first, __const_iterator __last)
1845 {
1846 _GLIBCXX_DEBUG_PEDASSERT(__first >= begin() && __first <= __last
1847 && __last <= end());
1848 const size_type __pos = __first - begin();
1849 if (__last == end())
1850 this->_M_set_length(__pos);
1851 else
1852 this->_M_erase(__pos, __last - __first);
1853 return iterator(this->_M_data() + __pos);
1854 }
1855
1856#if __cplusplus201703L >= 201103L
1857 /**
1858 * @brief Remove the last character.
1859 *
1860 * The string must be non-empty.
1861 */
1862 void
1863 pop_back() noexcept
1864 {
1865 __glibcxx_assert(!empty())do { if (! (!empty())) std::__replacement_assert("/usr/lib/gcc/x86_64-linux-gnu/10/../../../../include/c++/10/bits/basic_string.h"
, 1865, __PRETTY_FUNCTION__, "!empty()"); } while (false)
;
1866 _M_erase(size() - 1, 1);
1867 }
1868#endif // C++11
1869
1870 /**
1871 * @brief Replace characters with value from another string.
1872 * @param __pos Index of first character to replace.
1873 * @param __n Number of characters to be replaced.
1874 * @param __str String to insert.
1875 * @return Reference to this string.
1876 * @throw std::out_of_range If @a pos is beyond the end of this
1877 * string.
1878 * @throw std::length_error If new length exceeds @c max_size().
1879 *
1880 * Removes the characters in the range [__pos,__pos+__n) from
1881 * this string. In place, the value of @a __str is inserted.
1882 * If @a __pos is beyond end of string, out_of_range is thrown.
1883 * If the length of the result exceeds max_size(), length_error
1884 * is thrown. The value of the string doesn't change if an
1885 * error is thrown.
1886 */
1887 basic_string&
1888 replace(size_type __pos, size_type __n, const basic_string& __str)
1889 { return this->replace(__pos, __n, __str._M_data(), __str.size()); }
1890
1891 /**
1892 * @brief Replace characters with value from another string.
1893 * @param __pos1 Index of first character to replace.
1894 * @param __n1 Number of characters to be replaced.
1895 * @param __str String to insert.
1896 * @param __pos2 Index of first character of str to use.
1897 * @param __n2 Number of characters from str to use.
1898 * @return Reference to this string.
1899 * @throw std::out_of_range If @a __pos1 > size() or @a __pos2 >
1900 * __str.size().
1901 * @throw std::length_error If new length exceeds @c max_size().
1902 *
1903 * Removes the characters in the range [__pos1,__pos1 + n) from this
1904 * string. In place, the value of @a __str is inserted. If @a __pos is
1905 * beyond end of string, out_of_range is thrown. If the length of the
1906 * result exceeds max_size(), length_error is thrown. The value of the
1907 * string doesn't change if an error is thrown.
1908 */
1909 basic_string&
1910 replace(size_type __pos1, size_type __n1, const basic_string& __str,
1911 size_type __pos2, size_type __n2 = npos)
1912 { return this->replace(__pos1, __n1, __str._M_data()
1913 + __str._M_check(__pos2, "basic_string::replace"),
1914 __str._M_limit(__pos2, __n2)); }
1915
1916 /**
1917 * @brief Replace characters with value of a C substring.
1918 * @param __pos Index of first character to replace.
1919 * @param __n1 Number of characters to be replaced.
1920 * @param __s C string to insert.
1921 * @param __n2 Number of characters from @a s to use.
1922 * @return Reference to this string.
1923 * @throw std::out_of_range If @a pos1 > size().
1924 * @throw std::length_error If new length exceeds @c max_size().
1925 *
1926 * Removes the characters in the range [__pos,__pos + __n1)
1927 * from this string. In place, the first @a __n2 characters of
1928 * @a __s are inserted, or all of @a __s if @a __n2 is too large. If
1929 * @a __pos is beyond end of string, out_of_range is thrown. If
1930 * the length of result exceeds max_size(), length_error is
1931 * thrown. The value of the string doesn't change if an error
1932 * is thrown.
1933 */
1934 basic_string&
1935 replace(size_type __pos, size_type __n1, const _CharT* __s,
1936 size_type __n2)
1937 {
1938 __glibcxx_requires_string_len(__s, __n2);
1939 return _M_replace(_M_check(__pos, "basic_string::replace"),
1940 _M_limit(__pos, __n1), __s, __n2);
1941 }
1942
1943 /**
1944 * @brief Replace characters with value of a C string.
1945 * @param __pos Index of first character to replace.
1946 * @param __n1 Number of characters to be replaced.
1947 * @param __s C string to insert.
1948 * @return Reference to this string.
1949 * @throw std::out_of_range If @a pos > size().
1950 * @throw std::length_error If new length exceeds @c max_size().
1951 *
1952 * Removes the characters in the range [__pos,__pos + __n1)
1953 * from this string. In place, the characters of @a __s are
1954 * inserted. If @a __pos is beyond end of string, out_of_range
1955 * is thrown. If the length of result exceeds max_size(),
1956 * length_error is thrown. The value of the string doesn't
1957 * change if an error is thrown.
1958 */
1959 basic_string&
1960 replace(size_type __pos, size_type __n1, const _CharT* __s)
1961 {
1962 __glibcxx_requires_string(__s);
1963 return this->replace(__pos, __n1, __s, traits_type::length(__s));
1964 }
1965
1966 /**
1967 * @brief Replace characters with multiple characters.
1968 * @param __pos Index of first character to replace.
1969 * @param __n1 Number of characters to be replaced.
1970 * @param __n2 Number of characters to insert.
1971 * @param __c Character to insert.
1972 * @return Reference to this string.
1973 * @throw std::out_of_range If @a __pos > size().
1974 * @throw std::length_error If new length exceeds @c max_size().
1975 *
1976 * Removes the characters in the range [pos,pos + n1) from this
1977 * string. In place, @a __n2 copies of @a __c are inserted.
1978 * If @a __pos is beyond end of string, out_of_range is thrown.
1979 * If the length of result exceeds max_size(), length_error is
1980 * thrown. The value of the string doesn't change if an error
1981 * is thrown.
1982 */
1983 basic_string&
1984 replace(size_type __pos, size_type __n1, size_type __n2, _CharT __c)
1985 { return _M_replace_aux(_M_check(__pos, "basic_string::replace"),
1986 _M_limit(__pos, __n1), __n2, __c); }
1987
1988 /**
1989 * @brief Replace range of characters with string.
1990 * @param __i1 Iterator referencing start of range to replace.
1991 * @param __i2 Iterator referencing end of range to replace.
1992 * @param __str String value to insert.
1993 * @return Reference to this string.
1994 * @throw std::length_error If new length exceeds @c max_size().
1995 *
1996 * Removes the characters in the range [__i1,__i2). In place,
1997 * the value of @a __str is inserted. If the length of result
1998 * exceeds max_size(), length_error is thrown. The value of
1999 * the string doesn't change if an error is thrown.
2000 */
2001 basic_string&
2002 replace(__const_iterator __i1, __const_iterator __i2,
2003 const basic_string& __str)
2004 { return this->replace(__i1, __i2, __str._M_data(), __str.size()); }
2005
2006 /**
2007 * @brief Replace range of characters with C substring.
2008 * @param __i1 Iterator referencing start of range to replace.
2009 * @param __i2 Iterator referencing end of range to replace.
2010 * @param __s C string value to insert.
2011 * @param __n Number of characters from s to insert.
2012 * @return Reference to this string.
2013 * @throw std::length_error If new length exceeds @c max_size().
2014 *
2015 * Removes the characters in the range [__i1,__i2). In place,
2016 * the first @a __n characters of @a __s are inserted. If the
2017 * length of result exceeds max_size(), length_error is thrown.
2018 * The value of the string doesn't change if an error is
2019 * thrown.
2020 */
2021 basic_string&
2022 replace(__const_iterator __i1, __const_iterator __i2,
2023 const _CharT* __s, size_type __n)
2024 {
2025 _GLIBCXX_DEBUG_PEDASSERT(begin() <= __i1 && __i1 <= __i2
2026 && __i2 <= end());
2027 return this->replace(__i1 - begin(), __i2 - __i1, __s, __n);
2028 }
2029
2030 /**
2031 * @brief Replace range of characters with C string.
2032 * @param __i1 Iterator referencing start of range to replace.
2033 * @param __i2 Iterator referencing end of range to replace.
2034 * @param __s C string value to insert.
2035 * @return Reference to this string.
2036 * @throw std::length_error If new length exceeds @c max_size().
2037 *
2038 * Removes the characters in the range [__i1,__i2). In place,
2039 * the characters of @a __s are inserted. If the length of
2040 * result exceeds max_size(), length_error is thrown. The
2041 * value of the string doesn't change if an error is thrown.
2042 */
2043 basic_string&
2044 replace(__const_iterator __i1, __const_iterator __i2, const _CharT* __s)
2045 {
2046 __glibcxx_requires_string(__s);
2047 return this->replace(__i1, __i2, __s, traits_type::length(__s));
2048 }
2049
2050 /**
2051 * @brief Replace range of characters with multiple characters
2052 * @param __i1 Iterator referencing start of range to replace.
2053 * @param __i2 Iterator referencing end of range to replace.
2054 * @param __n Number of characters to insert.
2055 * @param __c Character to insert.
2056 * @return Reference to this string.
2057 * @throw std::length_error If new length exceeds @c max_size().
2058 *
2059 * Removes the characters in the range [__i1,__i2). In place,
2060 * @a __n copies of @a __c are inserted. If the length of
2061 * result exceeds max_size(), length_error is thrown. The
2062 * value of the string doesn't change if an error is thrown.
2063 */
2064 basic_string&
2065 replace(__const_iterator __i1, __const_iterator __i2, size_type __n,
2066 _CharT __c)
2067 {
2068 _GLIBCXX_DEBUG_PEDASSERT(begin() <= __i1 && __i1 <= __i2
2069 && __i2 <= end());
2070 return _M_replace_aux(__i1 - begin(), __i2 - __i1, __n, __c);
2071 }
2072
2073 /**
2074 * @brief Replace range of characters with range.
2075 * @param __i1 Iterator referencing start of range to replace.
2076 * @param __i2 Iterator referencing end of range to replace.
2077 * @param __k1 Iterator referencing start of range to insert.
2078 * @param __k2 Iterator referencing end of range to insert.
2079 * @return Reference to this string.
2080 * @throw std::length_error If new length exceeds @c max_size().
2081 *
2082 * Removes the characters in the range [__i1,__i2). In place,
2083 * characters in the range [__k1,__k2) are inserted. If the
2084 * length of result exceeds max_size(), length_error is thrown.
2085 * The value of the string doesn't change if an error is
2086 * thrown.
2087 */
2088#if __cplusplus201703L >= 201103L
2089 template<class _InputIterator,
2090 typename = std::_RequireInputIter<_InputIterator>>
2091 basic_string&
2092 replace(const_iterator __i1, const_iterator __i2,
2093 _InputIterator __k1, _InputIterator __k2)
2094 {
2095 _GLIBCXX_DEBUG_PEDASSERT(begin() <= __i1 && __i1 <= __i2
2096 && __i2 <= end());
2097 __glibcxx_requires_valid_range(__k1, __k2);
2098 return this->_M_replace_dispatch(__i1, __i2, __k1, __k2,
2099 std::__false_type());
2100 }
2101#else
2102 template<class _InputIterator>
2103#ifdef _GLIBCXX_DISAMBIGUATE_REPLACE_INST
2104 typename __enable_if_not_native_iterator<_InputIterator>::__type
2105#else
2106 basic_string&
2107#endif
2108 replace(iterator __i1, iterator __i2,
2109 _InputIterator __k1, _InputIterator __k2)
2110 {
2111 _GLIBCXX_DEBUG_PEDASSERT(begin() <= __i1 && __i1 <= __i2
2112 && __i2 <= end());
2113 __glibcxx_requires_valid_range(__k1, __k2);
2114 typedef typename std::__is_integer<_InputIterator>::__type _Integral;
2115 return _M_replace_dispatch(__i1, __i2, __k1, __k2, _Integral());
2116 }
2117#endif
2118
2119 // Specializations for the common case of pointer and iterator:
2120 // useful to avoid the overhead of temporary buffering in _M_replace.
2121 basic_string&
2122 replace(__const_iterator __i1, __const_iterator __i2,
2123 _CharT* __k1, _CharT* __k2)
2124 {
2125 _GLIBCXX_DEBUG_PEDASSERT(begin() <= __i1 && __i1 <= __i2
2126 && __i2 <= end());
2127 __glibcxx_requires_valid_range(__k1, __k2);
2128 return this->replace(__i1 - begin(), __i2 - __i1,
2129 __k1, __k2 - __k1);
2130 }
2131
2132 basic_string&
2133 replace(__const_iterator __i1, __const_iterator __i2,
2134 const _CharT* __k1, const _CharT* __k2)
2135 {
2136 _GLIBCXX_DEBUG_PEDASSERT(begin() <= __i1 && __i1 <= __i2
2137 && __i2 <= end());
2138 __glibcxx_requires_valid_range(__k1, __k2);
2139 return this->replace(__i1 - begin(), __i2 - __i1,
2140 __k1, __k2 - __k1);
2141 }
2142
2143 basic_string&
2144 replace(__const_iterator __i1, __const_iterator __i2,
2145 iterator __k1, iterator __k2)
2146 {
2147 _GLIBCXX_DEBUG_PEDASSERT(begin() <= __i1 && __i1 <= __i2
2148 && __i2 <= end());
2149 __glibcxx_requires_valid_range(__k1, __k2);
2150 return this->replace(__i1 - begin(), __i2 - __i1,
2151 __k1.base(), __k2 - __k1);
2152 }
2153
2154 basic_string&
2155 replace(__const_iterator __i1, __const_iterator __i2,
2156 const_iterator __k1, const_iterator __k2)
2157 {
2158 _GLIBCXX_DEBUG_PEDASSERT(begin() <= __i1 && __i1 <= __i2
2159 && __i2 <= end());
2160 __glibcxx_requires_valid_range(__k1, __k2);
2161 return this->replace(__i1 - begin(), __i2 - __i1,
2162 __k1.base(), __k2 - __k1);
2163 }
2164
2165#if __cplusplus201703L >= 201103L
2166 /**
2167 * @brief Replace range of characters with initializer_list.
2168 * @param __i1 Iterator referencing start of range to replace.
2169 * @param __i2 Iterator referencing end of range to replace.
2170 * @param __l The initializer_list of characters to insert.
2171 * @return Reference to this string.
2172 * @throw std::length_error If new length exceeds @c max_size().
2173 *
2174 * Removes the characters in the range [__i1,__i2). In place,
2175 * characters in the range [__k1,__k2) are inserted. If the
2176 * length of result exceeds max_size(), length_error is thrown.
2177 * The value of the string doesn't change if an error is
2178 * thrown.
2179 */
2180 basic_string& replace(const_iterator __i1, const_iterator __i2,
2181 initializer_list<_CharT> __l)
2182 { return this->replace(__i1, __i2, __l.begin(), __l.size()); }
2183#endif // C++11
2184
2185#if __cplusplus201703L >= 201703L
2186 /**
2187 * @brief Replace range of characters with string_view.
2188 * @param __pos The position to replace at.
2189 * @param __n The number of characters to replace.
2190 * @param __svt The object convertible to string_view to insert.
2191 * @return Reference to this string.
2192 */
2193 template<typename _Tp>
2194 _If_sv<_Tp, basic_string&>
2195 replace(size_type __pos, size_type __n, const _Tp& __svt)
2196 {
2197 __sv_type __sv = __svt;
2198 return this->replace(__pos, __n, __sv.data(), __sv.size());
2199 }
2200
2201 /**
2202 * @brief Replace range of characters with string_view.
2203 * @param __pos1 The position to replace at.
2204 * @param __n1 The number of characters to replace.
2205 * @param __svt The object convertible to string_view to insert from.
2206 * @param __pos2 The position in the string_view to insert from.
2207 * @param __n2 The number of characters to insert.
2208 * @return Reference to this string.
2209 */
2210 template<typename _Tp>
2211 _If_sv<_Tp, basic_string&>
2212 replace(size_type __pos1, size_type __n1, const _Tp& __svt,
2213 size_type __pos2, size_type __n2 = npos)
2214 {
2215 __sv_type __sv = __svt;
2216 return this->replace(__pos1, __n1,
2217 __sv.data()
2218 + std::__sv_check(__sv.size(), __pos2, "basic_string::replace"),
2219 std::__sv_limit(__sv.size(), __pos2, __n2));
2220 }
2221
2222 /**
2223 * @brief Replace range of characters with string_view.
2224 * @param __i1 An iterator referencing the start position
2225 to replace at.
2226 * @param __i2 An iterator referencing the end position
2227 for the replace.
2228 * @param __svt The object convertible to string_view to insert from.
2229 * @return Reference to this string.
2230 */
2231 template<typename _Tp>
2232 _If_sv<_Tp, basic_string&>
2233 replace(const_iterator __i1, const_iterator __i2, const _Tp& __svt)
2234 {
2235 __sv_type __sv = __svt;
2236 return this->replace(__i1 - begin(), __i2 - __i1, __sv);
2237 }
2238#endif // C++17
2239
2240 private:
2241 template<class _Integer>
2242 basic_string&
2243 _M_replace_dispatch(const_iterator __i1, const_iterator __i2,
2244 _Integer __n, _Integer __val, __true_type)
2245 { return _M_replace_aux(__i1 - begin(), __i2 - __i1, __n, __val); }
2246
2247 template<class _InputIterator>
2248 basic_string&
2249 _M_replace_dispatch(const_iterator __i1, const_iterator __i2,
2250 _InputIterator __k1, _InputIterator __k2,
2251 __false_type);
2252
2253 basic_string&
2254 _M_replace_aux(size_type __pos1, size_type __n1, size_type __n2,
2255 _CharT __c);
2256
2257 basic_string&
2258 _M_replace(size_type __pos, size_type __len1, const _CharT* __s,
2259 const size_type __len2);
2260
2261 basic_string&
2262 _M_append(const _CharT* __s, size_type __n);
2263
2264 public:
2265
2266 /**
2267 * @brief Copy substring into C string.
2268 * @param __s C string to copy value into.
2269 * @param __n Number of characters to copy.
2270 * @param __pos Index of first character to copy.
2271 * @return Number of characters actually copied
2272 * @throw std::out_of_range If __pos > size().
2273 *
2274 * Copies up to @a __n characters starting at @a __pos into the
2275 * C string @a __s. If @a __pos is %greater than size(),
2276 * out_of_range is thrown.
2277 */
2278 size_type
2279 copy(_CharT* __s, size_type __n, size_type __pos = 0) const;
2280
2281 /**
2282 * @brief Swap contents with another string.
2283 * @param __s String to swap with.
2284 *
2285 * Exchanges the contents of this string with that of @a __s in constant
2286 * time.
2287 */
2288 void
2289 swap(basic_string& __s) _GLIBCXX_NOEXCEPTnoexcept;
2290
2291 // String operations:
2292 /**
2293 * @brief Return const pointer to null-terminated contents.
2294 *
2295 * This is a handle to internal data. Do not modify or dire things may
2296 * happen.
2297 */
2298 const _CharT*
2299 c_str() const _GLIBCXX_NOEXCEPTnoexcept
2300 { return _M_data(); }
2301
2302 /**
2303 * @brief Return const pointer to contents.
2304 *
2305 * This is a pointer to internal data. It is undefined to modify
2306 * the contents through the returned pointer. To get a pointer that
2307 * allows modifying the contents use @c &str[0] instead,
2308 * (or in C++17 the non-const @c str.data() overload).
2309 */
2310 const _CharT*
2311 data() const _GLIBCXX_NOEXCEPTnoexcept
2312 { return _M_data(); }
2313
2314#if __cplusplus201703L >= 201703L
2315 /**
2316 * @brief Return non-const pointer to contents.
2317 *
2318 * This is a pointer to the character sequence held by the string.
2319 * Modifying the characters in the sequence is allowed.
2320 */
2321 _CharT*
2322 data() noexcept
2323 { return _M_data(); }
2324#endif
2325
2326 /**
2327 * @brief Return copy of allocator used to construct this string.
2328 */
2329 allocator_type
2330 get_allocator() const _GLIBCXX_NOEXCEPTnoexcept
2331 { return _M_get_allocator(); }
2332
2333 /**
2334 * @brief Find position of a C substring.
2335 * @param __s C string to locate.
2336 * @param __pos Index of character to search from.
2337 * @param __n Number of characters from @a s to search for.
2338 * @return Index of start of first occurrence.
2339 *
2340 * Starting from @a __pos, searches forward for the first @a
2341 * __n characters in @a __s within this string. If found,
2342 * returns the index where it begins. If not found, returns
2343 * npos.
2344 */
2345 size_type
2346 find(const _CharT* __s, size_type __pos, size_type __n) const
2347 _GLIBCXX_NOEXCEPTnoexcept;
2348
2349 /**
2350 * @brief Find position of a string.
2351 * @param __str String to locate.
2352 * @param __pos Index of character to search from (default 0).
2353 * @return Index of start of first occurrence.
2354 *
2355 * Starting from @a __pos, searches forward for value of @a __str within
2356 * this string. If found, returns the index where it begins. If not
2357 * found, returns npos.
2358 */
2359 size_type
2360 find(const basic_string& __str, size_type __pos = 0) const
2361 _GLIBCXX_NOEXCEPTnoexcept
2362 { return this->find(__str.data(), __pos, __str.size()); }
2363
2364#if __cplusplus201703L >= 201703L
2365 /**
2366 * @brief Find position of a string_view.
2367 * @param __svt The object convertible to string_view to locate.
2368 * @param __pos Index of character to search from (default 0).
2369 * @return Index of start of first occurrence.
2370 */
2371 template<typename _Tp>
2372 _If_sv<_Tp, size_type>
2373 find(const _Tp& __svt, size_type __pos = 0) const
2374 noexcept(is_same<_Tp, __sv_type>::value)
2375 {
2376 __sv_type __sv = __svt;
2377 return this->find(__sv.data(), __pos, __sv.size());
2378 }
2379#endif // C++17
2380
2381 /**
2382 * @brief Find position of a C string.
2383 * @param __s C string to locate.
2384 * @param __pos Index of character to search from (default 0).
2385 * @return Index of start of first occurrence.
2386 *
2387 * Starting from @a __pos, searches forward for the value of @a
2388 * __s within this string. If found, returns the index where
2389 * it begins. If not found, returns npos.
2390 */
2391 size_type
2392 find(const _CharT* __s, size_type __pos = 0) const _GLIBCXX_NOEXCEPTnoexcept
2393 {
2394 __glibcxx_requires_string(__s);
2395 return this->find(__s, __pos, traits_type::length(__s));
2396 }
2397
2398 /**
2399 * @brief Find position of a character.
2400 * @param __c Character to locate.
2401 * @param __pos Index of character to search from (default 0).
2402 * @return Index of first occurrence.
2403 *
2404 * Starting from @a __pos, searches forward for @a __c within
2405 * this string. If found, returns the index where it was
2406 * found. If not found, returns npos.
2407 */
2408 size_type
2409 find(_CharT __c, size_type __pos = 0) const _GLIBCXX_NOEXCEPTnoexcept;
2410
2411 /**
2412 * @brief Find last position of a string.
2413 * @param __str String to locate.
2414 * @param __pos Index of character to search back from (default end).
2415 * @return Index of start of last occurrence.
2416 *
2417 * Starting from @a __pos, searches backward for value of @a
2418 * __str within this string. If found, returns the index where
2419 * it begins. If not found, returns npos.
2420 */
2421 size_type
2422 rfind(const basic_string& __str, size_type __pos = npos) const
2423 _GLIBCXX_NOEXCEPTnoexcept
2424 { return this->rfind(__str.data(), __pos, __str.size()); }
2425
2426#if __cplusplus201703L >= 201703L
2427 /**
2428 * @brief Find last position of a string_view.
2429 * @param __svt The object convertible to string_view to locate.
2430 * @param __pos Index of character to search back from (default end).
2431 * @return Index of start of last occurrence.
2432 */
2433 template<typename _Tp>
2434 _If_sv<_Tp, size_type>
2435 rfind(const _Tp& __svt, size_type __pos = npos) const
2436 noexcept(is_same<_Tp, __sv_type>::value)
2437 {
2438 __sv_type __sv = __svt;
2439 return this->rfind(__sv.data(), __pos, __sv.size());
2440 }
2441#endif // C++17
2442
2443 /**
2444 * @brief Find last position of a C substring.
2445 * @param __s C string to locate.
2446 * @param __pos Index of character to search back from.
2447 * @param __n Number of characters from s to search for.
2448 * @return Index of start of last occurrence.
2449 *
2450 * Starting from @a __pos, searches backward for the first @a
2451 * __n characters in @a __s within this string. If found,
2452 * returns the index where it begins. If not found, returns
2453 * npos.
2454 */
2455 size_type
2456 rfind(const _CharT* __s, size_type __pos, size_type __n) const
2457 _GLIBCXX_NOEXCEPTnoexcept;
2458
2459 /**
2460 * @brief Find last position of a C string.
2461 * @param __s C string to locate.
2462 * @param __pos Index of character to start search at (default end).
2463 * @return Index of start of last occurrence.
2464 *
2465 * Starting from @a __pos, searches backward for the value of
2466 * @a __s within this string. If found, returns the index
2467 * where it begins. If not found, returns npos.
2468 */
2469 size_type
2470 rfind(const _CharT* __s, size_type __pos = npos) const
2471 {
2472 __glibcxx_requires_string(__s);
2473 return this->rfind(__s, __pos, traits_type::length(__s));
2474 }
2475
2476 /**
2477 * @brief Find last position of a character.
2478 * @param __c Character to locate.
2479 * @param __pos Index of character to search back from (default end).
2480 * @return Index of last occurrence.
2481 *
2482 * Starting from @a __pos, searches backward for @a __c within
2483 * this string. If found, returns the index where it was
2484 * found. If not found, returns npos.
2485 */
2486 size_type
2487 rfind(_CharT __c, size_type __pos = npos) const _GLIBCXX_NOEXCEPTnoexcept;
2488
2489 /**
2490 * @brief Find position of a character of string.
2491 * @param __str String containing characters to locate.
2492 * @param __pos Index of character to search from (default 0).
2493 * @return Index of first occurrence.
2494 *
2495 * Starting from @a __pos, searches forward for one of the
2496 * characters of @a __str within this string. If found,
2497 * returns the index where it was found. If not found, returns
2498 * npos.
2499 */
2500 size_type
2501 find_first_of(const basic_string& __str, size_type __pos = 0) const
2502 _GLIBCXX_NOEXCEPTnoexcept
2503 { return this->find_first_of(__str.data(), __pos, __str.size()); }
2504
2505#if __cplusplus201703L >= 201703L
2506 /**
2507 * @brief Find position of a character of a string_view.
2508 * @param __svt An object convertible to string_view containing
2509 * characters to locate.
2510 * @param __pos Index of character to search from (default 0).
2511 * @return Index of first occurrence.
2512 */
2513 template<typename _Tp>
2514 _If_sv<_Tp, size_type>
2515 find_first_of(const _Tp& __svt, size_type __pos = 0) const
2516 noexcept(is_same<_Tp, __sv_type>::value)
2517 {
2518 __sv_type __sv = __svt;
2519 return this->find_first_of(__sv.data(), __pos, __sv.size());
2520 }
2521#endif // C++17
2522
2523 /**
2524 * @brief Find position of a character of C substring.
2525 * @param __s String containing characters to locate.
2526 * @param __pos Index of character to search from.
2527 * @param __n Number of characters from s to search for.
2528 * @return Index of first occurrence.
2529 *
2530 * Starting from @a __pos, searches forward for one of the
2531 * first @a __n characters of @a __s within this string. If
2532 * found, returns the index where it was found. If not found,
2533 * returns npos.
2534 */
2535 size_type
2536 find_first_of(const _CharT* __s, size_type __pos, size_type __n) const
2537 _GLIBCXX_NOEXCEPTnoexcept;
2538
2539 /**
2540 * @brief Find position of a character of C string.
2541 * @param __s String containing characters to locate.
2542 * @param __pos Index of character to search from (default 0).
2543 * @return Index of first occurrence.
2544 *
2545 * Starting from @a __pos, searches forward for one of the
2546 * characters of @a __s within this string. If found, returns
2547 * the index where it was found. If not found, returns npos.
2548 */
2549 size_type
2550 find_first_of(const _CharT* __s, size_type __pos = 0) const
2551 _GLIBCXX_NOEXCEPTnoexcept
2552 {
2553 __glibcxx_requires_string(__s);
2554 return this->find_first_of(__s, __pos, traits_type::length(__s));
2555 }
2556
2557 /**
2558 * @brief Find position of a character.
2559 * @param __c Character to locate.
2560 * @param __pos Index of character to search from (default 0).
2561 * @return Index of first occurrence.
2562 *
2563 * Starting from @a __pos, searches forward for the character
2564 * @a __c within this string. If found, returns the index
2565 * where it was found. If not found, returns npos.
2566 *
2567 * Note: equivalent to find(__c, __pos).
2568 */
2569 size_type
2570 find_first_of(_CharT __c, size_type __pos = 0) const _GLIBCXX_NOEXCEPTnoexcept
2571 { return this->find(__c, __pos); }
2572
2573 /**
2574 * @brief Find last position of a character of string.
2575 * @param __str String containing characters to locate.
2576 * @param __pos Index of character to search back from (default end).
2577 * @return Index of last occurrence.
2578 *
2579 * Starting from @a __pos, searches backward for one of the
2580 * characters of @a __str within this string. If found,
2581 * returns the index where it was found. If not found, returns
2582 * npos.
2583 */
2584 size_type
2585 find_last_of(const basic_string& __str, size_type __pos = npos) const
2586 _GLIBCXX_NOEXCEPTnoexcept
2587 { return this->find_last_of(__str.data(), __pos, __str.size()); }
2588
2589#if __cplusplus201703L >= 201703L
2590 /**
2591 * @brief Find last position of a character of string.
2592 * @param __svt An object convertible to string_view containing
2593 * characters to locate.
2594 * @param __pos Index of character to search back from (default end).
2595 * @return Index of last occurrence.
2596 */
2597 template<typename _Tp>
2598 _If_sv<_Tp, size_type>
2599 find_last_of(const _Tp& __svt, size_type __pos = npos) const
2600 noexcept(is_same<_Tp, __sv_type>::value)
2601 {
2602 __sv_type __sv = __svt;
2603 return this->find_last_of(__sv.data(), __pos, __sv.size());
2604 }
2605#endif // C++17
2606
2607 /**
2608 * @brief Find last position of a character of C substring.
2609 * @param __s C string containing characters to locate.
2610 * @param __pos Index of character to search back from.
2611 * @param __n Number of characters from s to search for.
2612 * @return Index of last occurrence.
2613 *
2614 * Starting from @a __pos, searches backward for one of the
2615 * first @a __n characters of @a __s within this string. If
2616 * found, returns the index where it was found. If not found,
2617 * returns npos.
2618 */
2619 size_type
2620 find_last_of(const _CharT* __s, size_type __pos, size_type __n) const
2621 _GLIBCXX_NOEXCEPTnoexcept;
2622
2623 /**
2624 * @brief Find last position of a character of C string.
2625 * @param __s C string containing characters to locate.
2626 * @param __pos Index of character to search back from (default end).
2627 * @return Index of last occurrence.
2628 *
2629 * Starting from @a __pos, searches backward for one of the
2630 * characters of @a __s within this string. If found, returns
2631 * the index where it was found. If not found, returns npos.
2632 */
2633 size_type
2634 find_last_of(const _CharT* __s, size_type __pos = npos) const
2635 _GLIBCXX_NOEXCEPTnoexcept
2636 {
2637 __glibcxx_requires_string(__s);
2638 return this->find_last_of(__s, __pos, traits_type::length(__s));
2639 }
2640
2641 /**
2642 * @brief Find last position of a character.
2643 * @param __c Character to locate.
2644 * @param __pos Index of character to search back from (default end).
2645 * @return Index of last occurrence.
2646 *
2647 * Starting from @a __pos, searches backward for @a __c within
2648 * this string. If found, returns the index where it was
2649 * found. If not found, returns npos.
2650 *
2651 * Note: equivalent to rfind(__c, __pos).
2652 */
2653 size_type
2654 find_last_of(_CharT __c, size_type __pos = npos) const _GLIBCXX_NOEXCEPTnoexcept
2655 { return this->rfind(__c, __pos); }
2656
2657 /**
2658 * @brief Find position of a character not in string.
2659 * @param __str String containing characters to avoid.
2660 * @param __pos Index of character to search from (default 0).
2661 * @return Index of first occurrence.
2662 *
2663 * Starting from @a __pos, searches forward for a character not contained
2664 * in @a __str within this string. If found, returns the index where it
2665 * was found. If not found, returns npos.
2666 */
2667 size_type
2668 find_first_not_of(const basic_string& __str, size_type __pos = 0) const
2669 _GLIBCXX_NOEXCEPTnoexcept
2670 { return this->find_first_not_of(__str.data(), __pos, __str.size()); }
2671
2672#if __cplusplus201703L >= 201703L
2673 /**
2674 * @brief Find position of a character not in a string_view.
2675 * @param __svt A object convertible to string_view containing
2676 * characters to avoid.
2677 * @param __pos Index of character to search from (default 0).
2678 * @return Index of first occurrence.
2679 */
2680 template<typename _Tp>
2681 _If_sv<_Tp, size_type>
2682 find_first_not_of(const _Tp& __svt, size_type __pos = 0) const
2683 noexcept(is_same<_Tp, __sv_type>::value)
2684 {
2685 __sv_type __sv = __svt;
2686 return this->find_first_not_of(__sv.data(), __pos, __sv.size());
2687 }
2688#endif // C++17
2689
2690 /**
2691 * @brief Find position of a character not in C substring.
2692 * @param __s C string containing characters to avoid.
2693 * @param __pos Index of character to search from.
2694 * @param __n Number of characters from __s to consider.
2695 * @return Index of first occurrence.
2696 *
2697 * Starting from @a __pos, searches forward for a character not
2698 * contained in the first @a __n characters of @a __s within
2699 * this string. If found, returns the index where it was
2700 * found. If not found, returns npos.
2701 */
2702 size_type
2703 find_first_not_of(const _CharT* __s, size_type __pos,
2704 size_type __n) const _GLIBCXX_NOEXCEPTnoexcept;
2705
2706 /**
2707 * @brief Find position of a character not in C string.
2708 * @param __s C string containing characters to avoid.
2709 * @param __pos Index of character to search from (default 0).
2710 * @return Index of first occurrence.
2711 *
2712 * Starting from @a __pos, searches forward for a character not
2713 * contained in @a __s within this string. If found, returns
2714 * the index where it was found. If not found, returns npos.
2715 */
2716 size_type
2717 find_first_not_of(const _CharT* __s, size_type __pos = 0) const
2718 _GLIBCXX_NOEXCEPTnoexcept
2719 {
2720 __glibcxx_requires_string(__s);
2721 return this->find_first_not_of(__s, __pos, traits_type::length(__s));
2722 }
2723
2724 /**
2725 * @brief Find position of a different character.
2726 * @param __c Character to avoid.
2727 * @param __pos Index of character to search from (default 0).
2728 * @return Index of first occurrence.
2729 *
2730 * Starting from @a __pos, searches forward for a character
2731 * other than @a __c within this string. If found, returns the
2732 * index where it was found. If not found, returns npos.
2733 */
2734 size_type
2735 find_first_not_of(_CharT __c, size_type __pos = 0) const
2736 _GLIBCXX_NOEXCEPTnoexcept;
2737
2738 /**
2739 * @brief Find last position of a character not in string.
2740 * @param __str String containing characters to avoid.
2741 * @param __pos Index of character to search back from (default end).
2742 * @return Index of last occurrence.
2743 *
2744 * Starting from @a __pos, searches backward for a character
2745 * not contained in @a __str within this string. If found,
2746 * returns the index where it was found. If not found, returns
2747 * npos.
2748 */
2749 size_type
2750 find_last_not_of(const basic_string& __str, size_type __pos = npos) const
2751 _GLIBCXX_NOEXCEPTnoexcept
2752 { return this->find_last_not_of(__str.data(), __pos, __str.size()); }
2753
2754#if __cplusplus201703L >= 201703L
2755 /**
2756 * @brief Find last position of a character not in a string_view.
2757 * @param __svt An object convertible to string_view containing
2758 * characters to avoid.
2759 * @param __pos Index of character to search back from (default end).
2760 * @return Index of last occurrence.
2761 */
2762 template<typename _Tp>
2763 _If_sv<_Tp, size_type>
2764 find_last_not_of(const _Tp& __svt, size_type __pos = npos) const
2765 noexcept(is_same<_Tp, __sv_type>::value)
2766 {
2767 __sv_type __sv = __svt;
2768 return this->find_last_not_of(__sv.data(), __pos, __sv.size());
2769 }
2770#endif // C++17
2771
2772 /**
2773 * @brief Find last position of a character not in C substring.
2774 * @param __s C string containing characters to avoid.
2775 * @param __pos Index of character to search back from.
2776 * @param __n Number of characters from s to consider.
2777 * @return Index of last occurrence.
2778 *
2779 * Starting from @a __pos, searches backward for a character not
2780 * contained in the first @a __n characters of @a __s within this string.
2781 * If found, returns the index where it was found. If not found,
2782 * returns npos.
2783 */
2784 size_type
2785 find_last_not_of(const _CharT* __s, size_type __pos,
2786 size_type __n) const _GLIBCXX_NOEXCEPTnoexcept;
2787 /**
2788 * @brief Find last position of a character not in C string.
2789 * @param __s C string containing characters to avoid.
2790 * @param __pos Index of character to search back from (default end).
2791 * @return Index of last occurrence.
2792 *
2793 * Starting from @a __pos, searches backward for a character
2794 * not contained in @a __s within this string. If found,
2795 * returns the index where it was found. If not found, returns
2796 * npos.
2797 */
2798 size_type
2799 find_last_not_of(const _CharT* __s, size_type __pos = npos) const
2800 _GLIBCXX_NOEXCEPTnoexcept
2801 {
2802 __glibcxx_requires_string(__s);
2803 return this->find_last_not_of(__s, __pos, traits_type::length(__s));
2804 }
2805
2806 /**
2807 * @brief Find last position of a different character.
2808 * @param __c Character to avoid.
2809 * @param __pos Index of character to search back from (default end).
2810 * @return Index of last occurrence.
2811 *
2812 * Starting from @a __pos, searches backward for a character other than
2813 * @a __c within this string. If found, returns the index where it was
2814 * found. If not found, returns npos.
2815 */
2816 size_type
2817 find_last_not_of(_CharT __c, size_type __pos = npos) const
2818 _GLIBCXX_NOEXCEPTnoexcept;
2819
2820 /**
2821 * @brief Get a substring.
2822 * @param __pos Index of first character (default 0).
2823 * @param __n Number of characters in substring (default remainder).
2824 * @return The new string.
2825 * @throw std::out_of_range If __pos > size().
2826 *
2827 * Construct and return a new string using the @a __n
2828 * characters starting at @a __pos. If the string is too
2829 * short, use the remainder of the characters. If @a __pos is
2830 * beyond the end of the string, out_of_range is thrown.
2831 */
2832 basic_string
2833 substr(size_type __pos = 0, size_type __n = npos) const
2834 { return basic_string(*this,
2835 _M_check(__pos, "basic_string::substr"), __n); }
2836
2837 /**
2838 * @brief Compare to a string.
2839 * @param __str String to compare against.
2840 * @return Integer < 0, 0, or > 0.
2841 *
2842 * Returns an integer < 0 if this string is ordered before @a
2843 * __str, 0 if their values are equivalent, or > 0 if this
2844 * string is ordered after @a __str. Determines the effective
2845 * length rlen of the strings to compare as the smallest of
2846 * size() and str.size(). The function then compares the two
2847 * strings by calling traits::compare(data(), str.data(),rlen).
2848 * If the result of the comparison is nonzero returns it,
2849 * otherwise the shorter one is ordered first.
2850 */
2851 int
2852 compare(const basic_string& __str) const
2853 {
2854 const size_type __size = this->size();
2855 const size_type __osize = __str.size();
2856 const size_type __len = std::min(__size, __osize);
2857
2858 int __r = traits_type::compare(_M_data(), __str.data(), __len);
2859 if (!__r)
2860 __r = _S_compare(__size, __osize);
2861 return __r;
2862 }
2863
2864#if __cplusplus201703L >= 201703L
2865 /**
2866 * @brief Compare to a string_view.
2867 * @param __svt An object convertible to string_view to compare against.
2868 * @return Integer < 0, 0, or > 0.
2869 */
2870 template<typename _Tp>
2871 _If_sv<_Tp, int>
2872 compare(const _Tp& __svt) const
2873 noexcept(is_same<_Tp, __sv_type>::value)
2874 {
2875 __sv_type __sv = __svt;
2876 const size_type __size = this->size();
2877 const size_type __osize = __sv.size();
2878 const size_type __len = std::min(__size, __osize);
2879
2880 int __r = traits_type::compare(_M_data(), __sv.data(), __len);
2881 if (!__r)
2882 __r = _S_compare(__size, __osize);
2883 return __r;
2884 }
2885
2886 /**
2887 * @brief Compare to a string_view.
2888 * @param __pos A position in the string to start comparing from.
2889 * @param __n The number of characters to compare.
2890 * @param __svt An object convertible to string_view to compare
2891 * against.
2892 * @return Integer < 0, 0, or > 0.
2893 */
2894 template<typename _Tp>
2895 _If_sv<_Tp, int>
2896 compare(size_type __pos, size_type __n, const _Tp& __svt) const
2897 noexcept(is_same<_Tp, __sv_type>::value)
2898 {
2899 __sv_type __sv = __svt;
2900 return __sv_type(*this).substr(__pos, __n).compare(__sv);
2901 }
2902
2903 /**
2904 * @brief Compare to a string_view.
2905 * @param __pos1 A position in the string to start comparing from.
2906 * @param __n1 The number of characters to compare.
2907 * @param __svt An object convertible to string_view to compare
2908 * against.
2909 * @param __pos2 A position in the string_view to start comparing from.
2910 * @param __n2 The number of characters to compare.
2911 * @return Integer < 0, 0, or > 0.
2912 */
2913 template<typename _Tp>
2914 _If_sv<_Tp, int>
2915 compare(size_type __pos1, size_type __n1, const _Tp& __svt,
2916 size_type __pos2, size_type __n2 = npos) const
2917 noexcept(is_same<_Tp, __sv_type>::value)
2918 {
2919 __sv_type __sv = __svt;
2920 return __sv_type(*this)
2921 .substr(__pos1, __n1).compare(__sv.substr(__pos2, __n2));
2922 }
2923#endif // C++17
2924
2925 /**
2926 * @brief Compare substring to a string.
2927 * @param __pos Index of first character of substring.
2928 * @param __n Number of characters in substring.
2929 * @param __str String to compare against.
2930 * @return Integer < 0, 0, or > 0.
2931 *
2932 * Form the substring of this string from the @a __n characters
2933 * starting at @a __pos. Returns an integer < 0 if the
2934 * substring is ordered before @a __str, 0 if their values are
2935 * equivalent, or > 0 if the substring is ordered after @a
2936 * __str. Determines the effective length rlen of the strings
2937 * to compare as the smallest of the length of the substring
2938 * and @a __str.size(). The function then compares the two
2939 * strings by calling
2940 * traits::compare(substring.data(),str.data(),rlen). If the
2941 * result of the comparison is nonzero returns it, otherwise
2942 * the shorter one is ordered first.
2943 */
2944 int
2945 compare(size_type __pos, size_type __n, const basic_string& __str) const;
2946
2947 /**
2948 * @brief Compare substring to a substring.
2949 * @param __pos1 Index of first character of substring.
2950 * @param __n1 Number of characters in substring.
2951 * @param __str String to compare against.
2952 * @param __pos2 Index of first character of substring of str.
2953 * @param __n2 Number of characters in substring of str.
2954 * @return Integer < 0, 0, or > 0.
2955 *
2956 * Form the substring of this string from the @a __n1
2957 * characters starting at @a __pos1. Form the substring of @a
2958 * __str from the @a __n2 characters starting at @a __pos2.
2959 * Returns an integer < 0 if this substring is ordered before
2960 * the substring of @a __str, 0 if their values are equivalent,
2961 * or > 0 if this substring is ordered after the substring of
2962 * @a __str. Determines the effective length rlen of the
2963 * strings to compare as the smallest of the lengths of the
2964 * substrings. The function then compares the two strings by
2965 * calling
2966 * traits::compare(substring.data(),str.substr(pos2,n2).data(),rlen).
2967 * If the result of the comparison is nonzero returns it,
2968 * otherwise the shorter one is ordered first.
2969 */
2970 int
2971 compare(size_type __pos1, size_type __n1, const basic_string& __str,
2972 size_type __pos2, size_type __n2 = npos) const;
2973
2974 /**
2975 * @brief Compare to a C string.
2976 * @param __s C string to compare against.
2977 * @return Integer < 0, 0, or > 0.
2978 *
2979 * Returns an integer < 0 if this string is ordered before @a __s, 0 if
2980 * their values are equivalent, or > 0 if this string is ordered after
2981 * @a __s. Determines the effective length rlen of the strings to
2982 * compare as the smallest of size() and the length of a string
2983 * constructed from @a __s. The function then compares the two strings
2984 * by calling traits::compare(data(),s,rlen). If the result of the
2985 * comparison is nonzero returns it, otherwise the shorter one is
2986 * ordered first.
2987 */
2988 int
2989 compare(const _CharT* __s) const _GLIBCXX_NOEXCEPTnoexcept;
2990
2991 // _GLIBCXX_RESOLVE_LIB_DEFECTS
2992 // 5 String::compare specification questionable
2993 /**
2994 * @brief Compare substring to a C string.
2995 * @param __pos Index of first character of substring.
2996 * @param __n1 Number of characters in substring.
2997 * @param __s C string to compare against.
2998 * @return Integer < 0, 0, or > 0.
2999 *
3000 * Form the substring of this string from the @a __n1
3001 * characters starting at @a pos. Returns an integer < 0 if
3002 * the substring is ordered before @a __s, 0 if their values
3003 * are equivalent, or > 0 if the substring is ordered after @a
3004 * __s. Determines the effective length rlen of the strings to
3005 * compare as the smallest of the length of the substring and
3006 * the length of a string constructed from @a __s. The
3007 * function then compares the two string by calling
3008 * traits::compare(substring.data(),__s,rlen). If the result of
3009 * the comparison is nonzero returns it, otherwise the shorter
3010 * one is ordered first.
3011 */
3012 int
3013 compare(size_type __pos, size_type __n1, const _CharT* __s) const;
3014
3015 /**
3016 * @brief Compare substring against a character %array.
3017 * @param __pos Index of first character of substring.
3018 * @param __n1 Number of characters in substring.
3019 * @param __s character %array to compare against.
3020 * @param __n2 Number of characters of s.
3021 * @return Integer < 0, 0, or > 0.
3022 *
3023 * Form the substring of this string from the @a __n1
3024 * characters starting at @a __pos. Form a string from the
3025 * first @a __n2 characters of @a __s. Returns an integer < 0
3026 * if this substring is ordered before the string from @a __s,
3027 * 0 if their values are equivalent, or > 0 if this substring
3028 * is ordered after the string from @a __s. Determines the
3029 * effective length rlen of the strings to compare as the
3030 * smallest of the length of the substring and @a __n2. The
3031 * function then compares the two strings by calling
3032 * traits::compare(substring.data(),s,rlen). If the result of
3033 * the comparison is nonzero returns it, otherwise the shorter
3034 * one is ordered first.
3035 *
3036 * NB: s must have at least n2 characters, &apos;\\0&apos; has
3037 * no special meaning.
3038 */
3039 int
3040 compare(size_type __pos, size_type __n1, const _CharT* __s,
3041 size_type __n2) const;
3042
3043#if __cplusplus201703L > 201703L
3044 bool
3045 starts_with(basic_string_view<_CharT, _Traits> __x) const noexcept
3046 { return __sv_type(this->data(), this->size()).starts_with(__x); }
3047
3048 bool
3049 starts_with(_CharT __x) const noexcept
3050 { return __sv_type(this->data(), this->size()).starts_with(__x); }
3051
3052 bool
3053 starts_with(const _CharT* __x) const noexcept
3054 { return __sv_type(this->data(), this->size()).starts_with(__x); }
3055
3056 bool
3057 ends_with(basic_string_view<_CharT, _Traits> __x) const noexcept
3058 { return __sv_type(this->data(), this->size()).ends_with(__x); }
3059
3060 bool
3061 ends_with(_CharT __x) const noexcept
3062 { return __sv_type(this->data(), this->size()).ends_with(__x); }
3063
3064 bool
3065 ends_with(const _CharT* __x) const noexcept
3066 { return __sv_type(this->data(), this->size()).ends_with(__x); }
3067#endif // C++20
3068
3069 // Allow basic_stringbuf::__xfer_bufptrs to call _M_length:
3070 template<typename, typename, typename> friend class basic_stringbuf;
3071 };
3072_GLIBCXX_END_NAMESPACE_CXX11}
3073#else // !_GLIBCXX_USE_CXX11_ABI
3074 // Reference-counted COW string implentation
3075
3076 /**
3077 * @class basic_string basic_string.h <string>
3078 * @brief Managing sequences of characters and character-like objects.
3079 *
3080 * @ingroup strings
3081 * @ingroup sequences
3082 *
3083 * @tparam _CharT Type of character
3084 * @tparam _Traits Traits for character type, defaults to
3085 * char_traits<_CharT>.
3086 * @tparam _Alloc Allocator type, defaults to allocator<_CharT>.
3087 *
3088 * Meets the requirements of a <a href="tables.html#65">container</a>, a
3089 * <a href="tables.html#66">reversible container</a>, and a
3090 * <a href="tables.html#67">sequence</a>. Of the
3091 * <a href="tables.html#68">optional sequence requirements</a>, only
3092 * @c push_back, @c at, and @c %array access are supported.
3093 *
3094 * @doctodo
3095 *
3096 *
3097 * Documentation? What's that?
3098 * Nathan Myers <ncm@cantrip.org>.
3099 *
3100 * A string looks like this:
3101 *
3102 * @code
3103 * [_Rep]
3104 * _M_length
3105 * [basic_string<char_type>] _M_capacity
3106 * _M_dataplus _M_refcount
3107 * _M_p ----------------> unnamed array of char_type
3108 * @endcode
3109 *
3110 * Where the _M_p points to the first character in the string, and
3111 * you cast it to a pointer-to-_Rep and subtract 1 to get a
3112 * pointer to the header.
3113 *
3114 * This approach has the enormous advantage that a string object
3115 * requires only one allocation. All the ugliness is confined
3116 * within a single %pair of inline functions, which each compile to
3117 * a single @a add instruction: _Rep::_M_data(), and
3118 * string::_M_rep(); and the allocation function which gets a
3119 * block of raw bytes and with room enough and constructs a _Rep
3120 * object at the front.
3121 *
3122 * The reason you want _M_data pointing to the character %array and
3123 * not the _Rep is so that the debugger can see the string
3124 * contents. (Probably we should add a non-inline member to get
3125 * the _Rep for the debugger to use, so users can check the actual
3126 * string length.)
3127 *
3128 * Note that the _Rep object is a POD so that you can have a
3129 * static <em>empty string</em> _Rep object already @a constructed before
3130 * static constructors have run. The reference-count encoding is
3131 * chosen so that a 0 indicates one reference, so you never try to
3132 * destroy the empty-string _Rep object.
3133 *
3134 * All but the last paragraph is considered pretty conventional
3135 * for a C++ string implementation.
3136 */
3137 // 21.3 Template class basic_string
3138 template<typename _CharT, typename _Traits, typename _Alloc>
3139 class basic_string
3140 {
3141 typedef typename __gnu_cxx::__alloc_traits<_Alloc>::template
3142 rebind<_CharT>::other _CharT_alloc_type;
3143 typedef __gnu_cxx::__alloc_traits<_CharT_alloc_type> _CharT_alloc_traits;
3144
3145 // Types:
3146 public:
3147 typedef _Traits traits_type;
3148 typedef typename _Traits::char_type value_type;
3149 typedef _Alloc allocator_type;
3150 typedef typename _CharT_alloc_type::size_type size_type;
3151 typedef typename _CharT_alloc_type::difference_type difference_type;
3152#if __cplusplus201703L < 201103L
3153 typedef typename _CharT_alloc_type::reference reference;
3154 typedef typename _CharT_alloc_type::const_reference const_reference;
3155#else
3156 typedef value_type& reference;
3157 typedef const value_type& const_reference;
3158#endif
3159 typedef typename _CharT_alloc_traits::pointer pointer;
3160 typedef typename _CharT_alloc_traits::const_pointer const_pointer;
3161 typedef __gnu_cxx::__normal_iterator<pointer, basic_string> iterator;
3162 typedef __gnu_cxx::__normal_iterator<const_pointer, basic_string>
3163 const_iterator;
3164 typedef std::reverse_iterator<const_iterator> const_reverse_iterator;
3165 typedef std::reverse_iterator<iterator> reverse_iterator;
3166
3167 protected:
3168 // type used for positions in insert, erase etc.
3169 typedef iterator __const_iterator;
3170
3171 private:
3172 // _Rep: string representation
3173 // Invariants:
3174 // 1. String really contains _M_length + 1 characters: due to 21.3.4
3175 // must be kept null-terminated.
3176 // 2. _M_capacity >= _M_length
3177 // Allocated memory is always (_M_capacity + 1) * sizeof(_CharT).
3178 // 3. _M_refcount has three states:
3179 // -1: leaked, one reference, no ref-copies allowed, non-const.
3180 // 0: one reference, non-const.
3181 // n>0: n + 1 references, operations require a lock, const.
3182 // 4. All fields==0 is an empty string, given the extra storage
3183 // beyond-the-end for a null terminator; thus, the shared
3184 // empty string representation needs no constructor.
3185
3186 struct _Rep_base
3187 {
3188 size_type _M_length;
3189 size_type _M_capacity;
3190 _Atomic_word _M_refcount;
3191 };
3192
3193 struct _Rep : _Rep_base
3194 {
3195 // Types:
3196 typedef typename __gnu_cxx::__alloc_traits<_Alloc>::template
3197 rebind<char>::other _Raw_bytes_alloc;
3198
3199 // (Public) Data members:
3200
3201 // The maximum number of individual char_type elements of an
3202 // individual string is determined by _S_max_size. This is the
3203 // value that will be returned by max_size(). (Whereas npos
3204 // is the maximum number of bytes the allocator can allocate.)
3205 // If one was to divvy up the theoretical largest size string,
3206 // with a terminating character and m _CharT elements, it'd
3207 // look like this:
3208 // npos = sizeof(_Rep) + (m * sizeof(_CharT)) + sizeof(_CharT)
3209 // Solving for m:
3210 // m = ((npos - sizeof(_Rep))/sizeof(CharT)) - 1
3211 // In addition, this implementation quarters this amount.
3212 static const size_type _S_max_size;
3213 static const _CharT _S_terminal;
3214
3215 // The following storage is init'd to 0 by the linker, resulting
3216 // (carefully) in an empty string with one reference.
3217 static size_type _S_empty_rep_storage[];
3218
3219 static _Rep&
3220 _S_empty_rep() _GLIBCXX_NOEXCEPTnoexcept
3221 {
3222 // NB: Mild hack to avoid strict-aliasing warnings. Note that
3223 // _S_empty_rep_storage is never modified and the punning should
3224 // be reasonably safe in this case.
3225 void* __p = reinterpret_cast<void*>(&_S_empty_rep_storage);
3226 return *reinterpret_cast<_Rep*>(__p);
3227 }
3228
3229 bool
3230 _M_is_leaked() const _GLIBCXX_NOEXCEPTnoexcept
3231 {
3232#if defined(__GTHREADS1)
3233 // _M_refcount is mutated concurrently by _M_refcopy/_M_dispose,
3234 // so we need to use an atomic load. However, _M_is_leaked
3235 // predicate does not change concurrently (i.e. the string is either
3236 // leaked or not), so a relaxed load is enough.
3237 return __atomic_load_n(&this->_M_refcount, __ATOMIC_RELAXED0) < 0;
3238#else
3239 return this->_M_refcount < 0;
3240#endif
3241 }
3242
3243 bool
3244 _M_is_shared() const _GLIBCXX_NOEXCEPTnoexcept
3245 {
3246#if defined(__GTHREADS1)
3247 // _M_refcount is mutated concurrently by _M_refcopy/_M_dispose,
3248 // so we need to use an atomic load. Another thread can drop last
3249 // but one reference concurrently with this check, so we need this
3250 // load to be acquire to synchronize with release fetch_and_add in
3251 // _M_dispose.
3252 return __atomic_load_n(&this->_M_refcount, __ATOMIC_ACQUIRE2) > 0;
3253#else
3254 return this->_M_refcount > 0;
3255#endif
3256 }
3257
3258 void
3259 _M_set_leaked() _GLIBCXX_NOEXCEPTnoexcept
3260 { this->_M_refcount = -1; }
3261
3262 void
3263 _M_set_sharable() _GLIBCXX_NOEXCEPTnoexcept
3264 { this->_M_refcount = 0; }
3265
3266 void
3267 _M_set_length_and_sharable(size_type __n) _GLIBCXX_NOEXCEPTnoexcept
3268 {
3269#if _GLIBCXX_FULLY_DYNAMIC_STRING0 == 0
3270 if (__builtin_expect(this != &_S_empty_rep(), false))
3271#endif
3272 {
3273 this->_M_set_sharable(); // One reference.
3274 this->_M_length = __n;
3275 traits_type::assign(this->_M_refdata()[__n], _S_terminal);
3276 // grrr. (per 21.3.4)
3277 // You cannot leave those LWG people alone for a second.
3278 }
3279 }
3280
3281 _CharT*
3282 _M_refdata() throw()
3283 { return reinterpret_cast<_CharT*>(this + 1); }
3284
3285 _CharT*
3286 _M_grab(const _Alloc& __alloc1, const _Alloc& __alloc2)
3287 {
3288 return (!_M_is_leaked() && __alloc1 == __alloc2)
3289 ? _M_refcopy() : _M_clone(__alloc1);
3290 }
3291
3292 // Create & Destroy
3293 static _Rep*
3294 _S_create(size_type, size_type, const _Alloc&);
3295
3296 void
3297 _M_dispose(const _Alloc& __a) _GLIBCXX_NOEXCEPTnoexcept
3298 {
3299#if _GLIBCXX_FULLY_DYNAMIC_STRING0 == 0
3300 if (__builtin_expect(this != &_S_empty_rep(), false))
3301#endif
3302 {
3303 // Be race-detector-friendly. For more info see bits/c++config.
3304 _GLIBCXX_SYNCHRONIZATION_HAPPENS_BEFORE(&this->_M_refcount);
3305 // Decrement of _M_refcount is acq_rel, because:
3306 // - all but last decrements need to release to synchronize with
3307 // the last decrement that will delete the object.
3308 // - the last decrement needs to acquire to synchronize with
3309 // all the previous decrements.
3310 // - last but one decrement needs to release to synchronize with
3311 // the acquire load in _M_is_shared that will conclude that
3312 // the object is not shared anymore.
3313 if (__gnu_cxx::__exchange_and_add_dispatch(&this->_M_refcount,
3314 -1) <= 0)
3315 {
3316 _GLIBCXX_SYNCHRONIZATION_HAPPENS_AFTER(&this->_M_refcount);
3317 _M_destroy(__a);
3318 }
3319 }
3320 } // XXX MT
3321
3322 void
3323 _M_destroy(const _Alloc&) throw();
3324
3325 _CharT*
3326 _M_refcopy() throw()
3327 {
3328#if _GLIBCXX_FULLY_DYNAMIC_STRING0 == 0
3329 if (__builtin_expect(this != &_S_empty_rep(), false))
3330#endif
3331 __gnu_cxx::__atomic_add_dispatch(&this->_M_refcount, 1);
3332 return _M_refdata();
3333 } // XXX MT
3334
3335 _CharT*
3336 _M_clone(const _Alloc&, size_type __res = 0);
3337 };
3338
3339 // Use empty-base optimization: http://www.cantrip.org/emptyopt.html
3340 struct _Alloc_hider : _Alloc
3341 {
3342 _Alloc_hider(_CharT* __dat, const _Alloc& __a) _GLIBCXX_NOEXCEPTnoexcept
3343 : _Alloc(__a), _M_p(__dat) { }
3344
3345 _CharT* _M_p; // The actual data.
3346 };
3347
3348 public:
3349 // Data Members (public):
3350 // NB: This is an unsigned type, and thus represents the maximum
3351 // size that the allocator can hold.
3352 /// Value returned by various member functions when they fail.
3353 static const size_type npos = static_cast<size_type>(-1);
3354
3355 private:
3356 // Data Members (private):
3357 mutable _Alloc_hider _M_dataplus;
3358
3359 _CharT*
3360 _M_data() const _GLIBCXX_NOEXCEPTnoexcept
3361 { return _M_dataplus._M_p; }
3362
3363 _CharT*
3364 _M_data(_CharT* __p) _GLIBCXX_NOEXCEPTnoexcept
3365 { return (_M_dataplus._M_p = __p); }
3366
3367 _Rep*
3368 _M_rep() const _GLIBCXX_NOEXCEPTnoexcept
3369 { return &((reinterpret_cast<_Rep*> (_M_data()))[-1]); }
3370
3371 // For the internal use we have functions similar to `begin'/`end'
3372 // but they do not call _M_leak.
3373 iterator
3374 _M_ibegin() const _GLIBCXX_NOEXCEPTnoexcept
3375 { return iterator(_M_data()); }
3376
3377 iterator
3378 _M_iend() const _GLIBCXX_NOEXCEPTnoexcept
3379 { return iterator(_M_data() + this->size()); }
3380
3381 void
3382 _M_leak() // for use in begin() & non-const op[]
3383 {
3384 if (!_M_rep()->_M_is_leaked())
3385 _M_leak_hard();
3386 }
3387
3388 size_type
3389 _M_check(size_type __pos, const char* __s) const
3390 {
3391 if (__pos > this->size())
3392 __throw_out_of_range_fmt(__N("%s: __pos (which is %zu) > "("%s: __pos (which is %zu) > " "this->size() (which is %zu)"
)
3393 "this->size() (which is %zu)")("%s: __pos (which is %zu) > " "this->size() (which is %zu)"
)
,
3394 __s, __pos, this->size());
3395 return __pos;
3396 }
3397
3398 void
3399 _M_check_length(size_type __n1, size_type __n2, const char* __s) const
3400 {
3401 if (this->max_size() - (this->size() - __n1) < __n2)
3402 __throw_length_error(__N(__s)(__s));
3403 }
3404
3405 // NB: _M_limit doesn't check for a bad __pos value.
3406 size_type
3407 _M_limit(size_type __pos, size_type __off) const _GLIBCXX_NOEXCEPTnoexcept
3408 {
3409 const bool __testoff = __off < this->size() - __pos;
3410 return __testoff ? __off : this->size() - __pos;
3411 }
3412
3413 // True if _Rep and source do not overlap.
3414 bool
3415 _M_disjunct(const _CharT* __s) const _GLIBCXX_NOEXCEPTnoexcept
3416 {
3417 return (less<const _CharT*>()(__s, _M_data())
3418 || less<const _CharT*>()(_M_data() + this->size(), __s));
3419 }
3420
3421 // When __n = 1 way faster than the general multichar
3422 // traits_type::copy/move/assign.
3423 static void
3424 _M_copy(_CharT* __d, const _CharT* __s, size_type __n) _GLIBCXX_NOEXCEPTnoexcept
3425 {
3426 if (__n == 1)
3427 traits_type::assign(*__d, *__s);
3428 else
3429 traits_type::copy(__d, __s, __n);
3430 }
3431
3432 static void
3433 _M_move(_CharT* __d, const _CharT* __s, size_type __n) _GLIBCXX_NOEXCEPTnoexcept
3434 {
3435 if (__n == 1)
3436 traits_type::assign(*__d, *__s);
3437 else
3438 traits_type::move(__d, __s, __n);
3439 }
3440
3441 static void
3442 _M_assign(_CharT* __d, size_type __n, _CharT __c) _GLIBCXX_NOEXCEPTnoexcept
3443 {
3444 if (__n == 1)
3445 traits_type::assign(*__d, __c);
3446 else
3447 traits_type::assign(__d, __n, __c);
3448 }
3449
3450 // _S_copy_chars is a separate template to permit specialization
3451 // to optimize for the common case of pointers as iterators.
3452 template<class _Iterator>
3453 static void
3454 _S_copy_chars(_CharT* __p, _Iterator __k1, _Iterator __k2)
3455 {
3456 for (; __k1 != __k2; ++__k1, (void)++__p)
3457 traits_type::assign(*__p, *__k1); // These types are off.
3458 }
3459
3460 static void
3461 _S_copy_chars(_CharT* __p, iterator __k1, iterator __k2) _GLIBCXX_NOEXCEPTnoexcept
3462 { _S_copy_chars(__p, __k1.base(), __k2.base()); }
3463
3464 static void
3465 _S_copy_chars(_CharT* __p, const_iterator __k1, const_iterator __k2)
3466 _GLIBCXX_NOEXCEPTnoexcept
3467 { _S_copy_chars(__p, __k1.base(), __k2.base()); }
3468
3469 static void
3470 _S_copy_chars(_CharT* __p, _CharT* __k1, _CharT* __k2) _GLIBCXX_NOEXCEPTnoexcept
3471 { _M_copy(__p, __k1, __k2 - __k1); }
3472
3473 static void
3474 _S_copy_chars(_CharT* __p, const _CharT* __k1, const _CharT* __k2)
3475 _GLIBCXX_NOEXCEPTnoexcept
3476 { _M_copy(__p, __k1, __k2 - __k1); }
3477
3478 static int
3479 _S_compare(size_type __n1, size_type __n2) _GLIBCXX_NOEXCEPTnoexcept
3480 {
3481 const difference_type __d = difference_type(__n1 - __n2);
3482
3483 if (__d > __gnu_cxx::__numeric_traits<int>::__max)
3484 return __gnu_cxx::__numeric_traits<int>::__max;
3485 else if (__d < __gnu_cxx::__numeric_traits<int>::__min)
3486 return __gnu_cxx::__numeric_traits<int>::__min;
3487 else
3488 return int(__d);
3489 }
3490
3491 void
3492 _M_mutate(size_type __pos, size_type __len1, size_type __len2);
3493
3494 void
3495 _M_leak_hard();
3496
3497 static _Rep&
3498 _S_empty_rep() _GLIBCXX_NOEXCEPTnoexcept
3499 { return _Rep::_S_empty_rep(); }
3500
3501#if __cplusplus201703L >= 201703L
3502 // A helper type for avoiding boiler-plate.
3503 typedef basic_string_view<_CharT, _Traits> __sv_type;
3504
3505 template<typename _Tp, typename _Res>
3506 using _If_sv = enable_if_t<
3507 __and_<is_convertible<const _Tp&, __sv_type>,
3508 __not_<is_convertible<const _Tp*, const basic_string*>>,
3509 __not_<is_convertible<const _Tp&, const _CharT*>>>::value,
3510 _Res>;
3511
3512 // Allows an implicit conversion to __sv_type.
3513 static __sv_type
3514 _S_to_string_view(__sv_type __svt) noexcept
3515 { return __svt; }
3516
3517 // Wraps a string_view by explicit conversion and thus
3518 // allows to add an internal constructor that does not
3519 // participate in overload resolution when a string_view
3520 // is provided.
3521 struct __sv_wrapper
3522 {
3523 explicit __sv_wrapper(__sv_type __sv) noexcept : _M_sv(__sv) { }
3524 __sv_type _M_sv;
3525 };
3526
3527 /**
3528 * @brief Only internally used: Construct string from a string view
3529 * wrapper.
3530 * @param __svw string view wrapper.
3531 * @param __a Allocator to use.
3532 */
3533 explicit
3534 basic_string(__sv_wrapper __svw, const _Alloc& __a)
3535 : basic_string(__svw._M_sv.data(), __svw._M_sv.size(), __a) { }
3536#endif
3537
3538 public:
3539 // Construct/copy/destroy:
3540 // NB: We overload ctors in some cases instead of using default
3541 // arguments, per 17.4.4.4 para. 2 item 2.
3542
3543 /**
3544 * @brief Default constructor creates an empty string.
3545 */
3546 basic_string()
3547#if _GLIBCXX_FULLY_DYNAMIC_STRING0 == 0
3548 _GLIBCXX_NOEXCEPTnoexcept
3549 : _M_dataplus(_S_empty_rep()._M_refdata(), _Alloc())
3550#else
3551 : _M_dataplus(_S_construct(size_type(), _CharT(), _Alloc()), _Alloc())
3552#endif
3553 { }
3554
3555 /**
3556 * @brief Construct an empty string using allocator @a a.
3557 */
3558 explicit
3559 basic_string(const _Alloc& __a);
3560
3561 // NB: per LWG issue 42, semantics different from IS:
3562 /**
3563 * @brief Construct string with copy of value of @a str.
3564 * @param __str Source string.
3565 */
3566 basic_string(const basic_string& __str);
3567
3568 // _GLIBCXX_RESOLVE_LIB_DEFECTS
3569 // 2583. no way to supply an allocator for basic_string(str, pos)
3570 /**
3571 * @brief Construct string as copy of a substring.
3572 * @param __str Source string.
3573 * @param __pos Index of first character to copy from.
3574 * @param __a Allocator to use.
3575 */
3576 basic_string(const basic_string& __str, size_type __pos,
3577 const _Alloc& __a = _Alloc());
3578
3579 /**
3580 * @brief Construct string as copy of a substring.
3581 * @param __str Source string.
3582 * @param __pos Index of first character to copy from.
3583 * @param __n Number of characters to copy.
3584 */
3585 basic_string(const basic_string& __str, size_type __pos,
3586 size_type __n);
3587 /**
3588 * @brief Construct string as copy of a substring.
3589 * @param __str Source string.
3590 * @param __pos Index of first character to copy from.
3591 * @param __n Number of characters to copy.
3592 * @param __a Allocator to use.
3593 */
3594 basic_string(const basic_string& __str, size_type __pos,
3595 size_type __n, const _Alloc& __a);
3596
3597 /**
3598 * @brief Construct string initialized by a character %array.
3599 * @param __s Source character %array.
3600 * @param __n Number of characters to copy.
3601 * @param __a Allocator to use (default is default allocator).
3602 *
3603 * NB: @a __s must have at least @a __n characters, &apos;\\0&apos;
3604 * has no special meaning.
3605 */
3606 basic_string(const _CharT* __s, size_type __n,
3607 const _Alloc& __a = _Alloc());
3608
3609 /**
3610 * @brief Construct string as copy of a C string.
3611 * @param __s Source C string.
3612 * @param __a Allocator to use (default is default allocator).
3613 */
3614#if __cpp_deduction_guides201703L && ! defined _GLIBCXX_DEFINING_STRING_INSTANTIATIONS
3615 // _GLIBCXX_RESOLVE_LIB_DEFECTS
3616 // 3076. basic_string CTAD ambiguity
3617 template<typename = _RequireAllocator<_Alloc>>
3618#endif
3619 basic_string(const _CharT* __s, const _Alloc& __a = _Alloc())
3620 : _M_dataplus(_S_construct(__s, __s ? __s + traits_type::length(__s) :
3621 __s + npos, __a), __a)
3622 { }
3623
3624 /**
3625 * @brief Construct string as multiple characters.
3626 * @param __n Number of characters.
3627 * @param __c Character to use.
3628 * @param __a Allocator to use (default is default allocator).
3629 */
3630 basic_string(size_type __n, _CharT __c, const _Alloc& __a = _Alloc());
3631
3632#if __cplusplus201703L >= 201103L
3633 /**
3634 * @brief Move construct string.
3635 * @param __str Source string.
3636 *
3637 * The newly-created string contains the exact contents of @a __str.
3638 * @a __str is a valid, but unspecified string.
3639 **/
3640 basic_string(basic_string&& __str)
3641#if _GLIBCXX_FULLY_DYNAMIC_STRING0 == 0
3642 noexcept // FIXME C++11: should always be noexcept.
3643#endif
3644 : _M_dataplus(std::move(__str._M_dataplus))
3645 {
3646#if _GLIBCXX_FULLY_DYNAMIC_STRING0 == 0
3647 __str._M_data(_S_empty_rep()._M_refdata());
3648#else
3649 __str._M_data(_S_construct(size_type(), _CharT(), get_allocator()));
3650#endif
3651 }
3652
3653 /**
3654 * @brief Construct string from an initializer %list.
3655 * @param __l std::initializer_list of characters.
3656 * @param __a Allocator to use (default is default allocator).
3657 */
3658 basic_string(initializer_list<_CharT> __l, const _Alloc& __a = _Alloc());
3659
3660 basic_string(const basic_string& __str, const _Alloc& __a)
3661 : _M_dataplus(__str._M_rep()->_M_grab(__a, __str.get_allocator()), __a)
3662 { }
3663
3664 basic_string(basic_string&& __str, const _Alloc& __a)
3665 : _M_dataplus(__str._M_data(), __a)
3666 {
3667 if (__a == __str.get_allocator())
3668 {
3669#if _GLIBCXX_FULLY_DYNAMIC_STRING0 == 0
3670 __str._M_data(_S_empty_rep()._M_refdata());
3671#else
3672 __str._M_data(_S_construct(size_type(), _CharT(), __a));
3673#endif
3674 }
3675 else
3676 _M_dataplus._M_p = _S_construct(__str.begin(), __str.end(), __a);
3677 }
3678#endif // C++11
3679
3680 /**
3681 * @brief Construct string as copy of a range.
3682 * @param __beg Start of range.
3683 * @param __end End of range.
3684 * @param __a Allocator to use (default is default allocator).
3685 */
3686 template<class _InputIterator>
3687 basic_string(_InputIterator __beg, _InputIterator __end,
3688 const _Alloc& __a = _Alloc());
3689
3690#if __cplusplus201703L >= 201703L
3691 /**
3692 * @brief Construct string from a substring of a string_view.
3693 * @param __t Source object convertible to string view.
3694 * @param __pos The index of the first character to copy from __t.
3695 * @param __n The number of characters to copy from __t.
3696 * @param __a Allocator to use.
3697 */
3698 template<typename _Tp, typename = _If_sv<_Tp, void>>
3699 basic_string(const _Tp& __t, size_type __pos, size_type __n,
3700 const _Alloc& __a = _Alloc())
3701 : basic_string(_S_to_string_view(__t).substr(__pos, __n), __a) { }
3702
3703 /**
3704 * @brief Construct string from a string_view.
3705 * @param __t Source object convertible to string view.
3706 * @param __a Allocator to use (default is default allocator).
3707 */
3708 template<typename _Tp, typename = _If_sv<_Tp, void>>
3709 explicit
3710 basic_string(const _Tp& __t, const _Alloc& __a = _Alloc())
3711 : basic_string(__sv_wrapper(_S_to_string_view(__t)), __a) { }
3712#endif // C++17
3713
3714 /**
3715 * @brief Destroy the string instance.
3716 */
3717 ~basic_string() _GLIBCXX_NOEXCEPTnoexcept
3718 { _M_rep()->_M_dispose(this->get_allocator()); }
3719
3720 /**
3721 * @brief Assign the value of @a str to this string.
3722 * @param __str Source string.
3723 */
3724 basic_string&
3725 operator=(const basic_string& __str)
3726 { return this->assign(__str); }
3727
3728 /**
3729 * @brief Copy contents of @a s into this string.
3730 * @param __s Source null-terminated string.
3731 */
3732 basic_string&
3733 operator=(const _CharT* __s)
3734 { return this->assign(__s); }
3735
3736 /**
3737 * @brief Set value to string of length 1.
3738 * @param __c Source character.
3739 *
3740 * Assigning to a character makes this string length 1 and
3741 * (*this)[0] == @a c.
3742 */
3743 basic_string&
3744 operator=(_CharT __c)
3745 {
3746 this->assign(1, __c);
3747 return *this;
3748 }
3749
3750#if __cplusplus201703L >= 201103L
3751 /**
3752 * @brief Move assign the value of @a str to this string.
3753 * @param __str Source string.
3754 *
3755 * The contents of @a str are moved into this string (without copying).
3756 * @a str is a valid, but unspecified string.
3757 **/
3758 basic_string&
3759 operator=(basic_string&& __str)
3760 _GLIBCXX_NOEXCEPT_IF(allocator_traits<_Alloc>::is_always_equal::value)noexcept(allocator_traits<_Alloc>::is_always_equal::value
)
3761 {
3762 // NB: DR 1204.
3763 this->swap(__str);
3764 return *this;
3765 }
3766
3767 /**
3768 * @brief Set value to string constructed from initializer %list.
3769 * @param __l std::initializer_list.
3770 */
3771 basic_string&
3772 operator=(initializer_list<_CharT> __l)
3773 {
3774 this->assign(__l.begin(), __l.size());
3775 return *this;
3776 }
3777#endif // C++11
3778
3779#if __cplusplus201703L >= 201703L
3780 /**
3781 * @brief Set value to string constructed from a string_view.
3782 * @param __svt An object convertible to string_view.
3783 */
3784 template<typename _Tp>
3785 _If_sv<_Tp, basic_string&>
3786 operator=(const _Tp& __svt)
3787 { return this->assign(__svt); }
3788
3789 /**
3790 * @brief Convert to a string_view.
3791 * @return A string_view.
3792 */
3793 operator __sv_type() const noexcept
3794 { return __sv_type(data(), size()); }
3795#endif // C++17
3796
3797 // Iterators:
3798 /**
3799 * Returns a read/write iterator that points to the first character in
3800 * the %string. Unshares the string.
3801 */
3802 iterator
3803 begin() // FIXME C++11: should be noexcept.
3804 {
3805 _M_leak();
3806 return iterator(_M_data());
3807 }
3808
3809 /**
3810 * Returns a read-only (constant) iterator that points to the first
3811 * character in the %string.
3812 */
3813 const_iterator
3814 begin() const _GLIBCXX_NOEXCEPTnoexcept
3815 { return const_iterator(_M_data()); }
3816
3817 /**
3818 * Returns a read/write iterator that points one past the last
3819 * character in the %string. Unshares the string.
3820 */
3821 iterator
3822 end() // FIXME C++11: should be noexcept.
3823 {
3824 _M_leak();
3825 return iterator(_M_data() + this->size());
3826 }
3827
3828 /**
3829 * Returns a read-only (constant) iterator that points one past the
3830 * last character in the %string.
3831 */
3832 const_iterator
3833 end() const _GLIBCXX_NOEXCEPTnoexcept
3834 { return const_iterator(_M_data() + this->size()); }
3835
3836 /**
3837 * Returns a read/write reverse iterator that points to the last
3838 * character in the %string. Iteration is done in reverse element
3839 * order. Unshares the string.
3840 */
3841 reverse_iterator
3842 rbegin() // FIXME C++11: should be noexcept.
3843 { return reverse_iterator(this->end()); }
3844
3845 /**
3846 * Returns a read-only (constant) reverse iterator that points
3847 * to the last character in the %string. Iteration is done in
3848 * reverse element order.
3849 */
3850 const_reverse_iterator
3851 rbegin() const _GLIBCXX_NOEXCEPTnoexcept
3852 { return const_reverse_iterator(this->end()); }
3853
3854 /**
3855 * Returns a read/write reverse iterator that points to one before the
3856 * first character in the %string. Iteration is done in reverse
3857 * element order. Unshares the string.
3858 */
3859 reverse_iterator
3860 rend() // FIXME C++11: should be noexcept.
3861 { return reverse_iterator(this->begin()); }
3862
3863 /**
3864 * Returns a read-only (constant) reverse iterator that points
3865 * to one before the first character in the %string. Iteration
3866 * is done in reverse element order.
3867 */
3868 const_reverse_iterator
3869 rend() const _GLIBCXX_NOEXCEPTnoexcept
3870 { return const_reverse_iterator(this->begin()); }
3871
3872#if __cplusplus201703L >= 201103L
3873 /**
3874 * Returns a read-only (constant) iterator that points to the first
3875 * character in the %string.
3876 */
3877 const_iterator
3878 cbegin() const noexcept
3879 { return const_iterator(this->_M_data()); }
3880
3881 /**
3882 * Returns a read-only (constant) iterator that points one past the
3883 * last character in the %string.
3884 */
3885 const_iterator
3886 cend() const noexcept
3887 { return const_iterator(this->_M_data() + this->size()); }
3888
3889 /**
3890 * Returns a read-only (constant) reverse iterator that points
3891 * to the last character in the %string. Iteration is done in
3892 * reverse element order.
3893 */
3894 const_reverse_iterator
3895 crbegin() const noexcept
3896 { return const_reverse_iterator(this->end()); }
3897
3898 /**
3899 * Returns a read-only (constant) reverse iterator that points
3900 * to one before the first character in the %string. Iteration
3901 * is done in reverse element order.
3902 */
3903 const_reverse_iterator
3904 crend() const noexcept
3905 { return const_reverse_iterator(this->begin()); }
3906#endif
3907
3908 public:
3909 // Capacity:
3910 /// Returns the number of characters in the string, not including any
3911 /// null-termination.
3912 size_type
3913 size() const _GLIBCXX_NOEXCEPTnoexcept
3914 { return _M_rep()->_M_length; }
3915
3916 /// Returns the number of characters in the string, not including any
3917 /// null-termination.
3918 size_type
3919 length() const _GLIBCXX_NOEXCEPTnoexcept
3920 { return _M_rep()->_M_length; }
3921
3922 /// Returns the size() of the largest possible %string.
3923 size_type
3924 max_size() const _GLIBCXX_NOEXCEPTnoexcept
3925 { return _Rep::_S_max_size; }
3926
3927 /**
3928 * @brief Resizes the %string to the specified number of characters.
3929 * @param __n Number of characters the %string should contain.
3930 * @param __c Character to fill any new elements.
3931 *
3932 * This function will %resize the %string to the specified
3933 * number of characters. If the number is smaller than the
3934 * %string's current size the %string is truncated, otherwise
3935 * the %string is extended and new elements are %set to @a __c.
3936 */
3937 void
3938 resize(size_type __n, _CharT __c);
3939
3940 /**
3941 * @brief Resizes the %string to the specified number of characters.
3942 * @param __n Number of characters the %string should contain.
3943 *
3944 * This function will resize the %string to the specified length. If
3945 * the new size is smaller than the %string's current size the %string
3946 * is truncated, otherwise the %string is extended and new characters
3947 * are default-constructed. For basic types such as char, this means
3948 * setting them to 0.
3949 */
3950 void
3951 resize(size_type __n)
3952 { this->resize(__n, _CharT()); }
3953
3954#if __cplusplus201703L >= 201103L
3955 /// A non-binding request to reduce capacity() to size().
3956 void
3957 shrink_to_fit() _GLIBCXX_NOEXCEPTnoexcept
3958 {
3959#if __cpp_exceptions
3960 if (capacity() > size())
3961 {
3962 try
3963 { reserve(0); }
3964 catch(...)
3965 { }
3966 }
3967#endif
3968 }
3969#endif
3970
3971 /**
3972 * Returns the total number of characters that the %string can hold
3973 * before needing to allocate more memory.
3974 */
3975 size_type
3976 capacity() const _GLIBCXX_NOEXCEPTnoexcept
3977 { return _M_rep()->_M_capacity; }
3978
3979 /**
3980 * @brief Attempt to preallocate enough memory for specified number of
3981 * characters.
3982 * @param __res_arg Number of characters required.
3983 * @throw std::length_error If @a __res_arg exceeds @c max_size().
3984 *
3985 * This function attempts to reserve enough memory for the
3986 * %string to hold the specified number of characters. If the
3987 * number requested is more than max_size(), length_error is
3988 * thrown.
3989 *
3990 * The advantage of this function is that if optimal code is a
3991 * necessity and the user can determine the string length that will be
3992 * required, the user can reserve the memory in %advance, and thus
3993 * prevent a possible reallocation of memory and copying of %string
3994 * data.
3995 */
3996 void
3997 reserve(size_type __res_arg = 0);
3998
3999 /**
4000 * Erases the string, making it empty.
4001 */
4002#if _GLIBCXX_FULLY_DYNAMIC_STRING0 == 0
4003 void
4004 clear() _GLIBCXX_NOEXCEPTnoexcept
4005 {
4006 if (_M_rep()->_M_is_shared())
4007 {
4008 _M_rep()->_M_dispose(this->get_allocator());
4009 _M_data(_S_empty_rep()._M_refdata());
4010 }
4011 else
4012 _M_rep()->_M_set_length_and_sharable(0);
4013 }
4014#else
4015 // PR 56166: this should not throw.
4016 void
4017 clear()
4018 { _M_mutate(0, this->size(), 0); }
4019#endif
4020
4021 /**
4022 * Returns true if the %string is empty. Equivalent to
4023 * <code>*this == ""</code>.
4024 */
4025 _GLIBCXX_NODISCARD[[__nodiscard__]] bool
4026 empty() const _GLIBCXX_NOEXCEPTnoexcept
4027 { return this->size() == 0; }
4028
4029 // Element access:
4030 /**
4031 * @brief Subscript access to the data contained in the %string.
4032 * @param __pos The index of the character to access.
4033 * @return Read-only (constant) reference to the character.
4034 *
4035 * This operator allows for easy, array-style, data access.
4036 * Note that data access with this operator is unchecked and
4037 * out_of_range lookups are not defined. (For checked lookups
4038 * see at().)
4039 */
4040 const_reference
4041 operator[] (size_type __pos) const _GLIBCXX_NOEXCEPTnoexcept
4042 {
4043 __glibcxx_assert(__pos <= size())do { if (! (__pos <= size())) std::__replacement_assert("/usr/lib/gcc/x86_64-linux-gnu/10/../../../../include/c++/10/bits/basic_string.h"
, 4043, __PRETTY_FUNCTION__, "__pos <= size()"); } while (
false)
;
4044 return _M_data()[__pos];
4045 }
4046
4047 /**
4048 * @brief Subscript access to the data contained in the %string.
4049 * @param __pos The index of the character to access.
4050 * @return Read/write reference to the character.
4051 *
4052 * This operator allows for easy, array-style, data access.
4053 * Note that data access with this operator is unchecked and
4054 * out_of_range lookups are not defined. (For checked lookups
4055 * see at().) Unshares the string.
4056 */
4057 reference
4058 operator[](size_type __pos)
4059 {
4060 // Allow pos == size() both in C++98 mode, as v3 extension,
4061 // and in C++11 mode.
4062 __glibcxx_assert(__pos <= size())do { if (! (__pos <= size())) std::__replacement_assert("/usr/lib/gcc/x86_64-linux-gnu/10/../../../../include/c++/10/bits/basic_string.h"
, 4062, __PRETTY_FUNCTION__, "__pos <= size()"); } while (
false)
;
4063 // In pedantic mode be strict in C++98 mode.
4064 _GLIBCXX_DEBUG_PEDASSERT(__cplusplus >= 201103L || __pos < size());
4065 _M_leak();
4066 return _M_data()[__pos];
4067 }
4068
4069 /**
4070 * @brief Provides access to the data contained in the %string.
4071 * @param __n The index of the character to access.
4072 * @return Read-only (const) reference to the character.
4073 * @throw std::out_of_range If @a n is an invalid index.
4074 *
4075 * This function provides for safer data access. The parameter is
4076 * first checked that it is in the range of the string. The function
4077 * throws out_of_range if the check fails.
4078 */
4079 const_reference
4080 at(size_type __n) const
4081 {
4082 if (__n >= this->size())
4083 __throw_out_of_range_fmt(__N("basic_string::at: __n "("basic_string::at: __n " "(which is %zu) >= this->size() "
"(which is %zu)")
4084 "(which is %zu) >= this->size() "("basic_string::at: __n " "(which is %zu) >= this->size() "
"(which is %zu)")
4085 "(which is %zu)")("basic_string::at: __n " "(which is %zu) >= this->size() "
"(which is %zu)")
,
4086 __n, this->size());
4087 return _M_data()[__n];
4088 }
4089
4090 /**
4091 * @brief Provides access to the data contained in the %string.
4092 * @param __n The index of the character to access.
4093 * @return Read/write reference to the character.
4094 * @throw std::out_of_range If @a n is an invalid index.
4095 *
4096 * This function provides for safer data access. The parameter is
4097 * first checked that it is in the range of the string. The function
4098 * throws out_of_range if the check fails. Success results in
4099 * unsharing the string.
4100 */
4101 reference
4102 at(size_type __n)
4103 {
4104 if (__n >= size())
4105 __throw_out_of_range_fmt(__N("basic_string::at: __n "("basic_string::at: __n " "(which is %zu) >= this->size() "
"(which is %zu)")
4106 "(which is %zu) >= this->size() "("basic_string::at: __n " "(which is %zu) >= this->size() "
"(which is %zu)")
4107 "(which is %zu)")("basic_string::at: __n " "(which is %zu) >= this->size() "
"(which is %zu)")
,
4108 __n, this->size());
4109 _M_leak();
4110 return _M_data()[__n];
4111 }
4112
4113#if __cplusplus201703L >= 201103L
4114 /**
4115 * Returns a read/write reference to the data at the first
4116 * element of the %string.
4117 */
4118 reference
4119 front()
4120 {
4121 __glibcxx_assert(!empty())do { if (! (!empty())) std::__replacement_assert("/usr/lib/gcc/x86_64-linux-gnu/10/../../../../include/c++/10/bits/basic_string.h"
, 4121, __PRETTY_FUNCTION__, "!empty()"); } while (false)
;
4122 return operator[](0);
4123 }
4124
4125 /**
4126 * Returns a read-only (constant) reference to the data at the first
4127 * element of the %string.
4128 */
4129 const_reference
4130 front() const noexcept
4131 {
4132 __glibcxx_assert(!empty())do { if (! (!empty())) std::__replacement_assert("/usr/lib/gcc/x86_64-linux-gnu/10/../../../../include/c++/10/bits/basic_string.h"
, 4132, __PRETTY_FUNCTION__, "!empty()"); } while (false)
;
4133 return operator[](0);
4134 }
4135
4136 /**
4137 * Returns a read/write reference to the data at the last
4138 * element of the %string.
4139 */
4140 reference
4141 back()
4142 {
4143 __glibcxx_assert(!empty())do { if (! (!empty())) std::__replacement_assert("/usr/lib/gcc/x86_64-linux-gnu/10/../../../../include/c++/10/bits/basic_string.h"
, 4143, __PRETTY_FUNCTION__, "!empty()"); } while (false)
;
4144 return operator[](this->size() - 1);
4145 }
4146
4147 /**
4148 * Returns a read-only (constant) reference to the data at the
4149 * last element of the %string.
4150 */
4151 const_reference
4152 back() const noexcept
4153 {
4154 __glibcxx_assert(!empty())do { if (! (!empty())) std::__replacement_assert("/usr/lib/gcc/x86_64-linux-gnu/10/../../../../include/c++/10/bits/basic_string.h"
, 4154, __PRETTY_FUNCTION__, "!empty()"); } while (false)
;
4155 return operator[](this->size() - 1);
4156 }
4157#endif
4158
4159 // Modifiers:
4160 /**
4161 * @brief Append a string to this string.
4162 * @param __str The string to append.
4163 * @return Reference to this string.
4164 */
4165 basic_string&
4166 operator+=(const basic_string& __str)
4167 { return this->append(__str); }
4168
4169 /**
4170 * @brief Append a C string.
4171 * @param __s The C string to append.
4172 * @return Reference to this string.
4173 */
4174 basic_string&
4175 operator+=(const _CharT* __s)
4176 { return this->append(__s); }
4177
4178 /**
4179 * @brief Append a character.
4180 * @param __c The character to append.
4181 * @return Reference to this string.
4182 */
4183 basic_string&
4184 operator+=(_CharT __c)
4185 {
4186 this->push_back(__c);
4187 return *this;
4188 }
4189
4190#if __cplusplus201703L >= 201103L
4191 /**
4192 * @brief Append an initializer_list of characters.
4193 * @param __l The initializer_list of characters to be appended.
4194 * @return Reference to this string.
4195 */
4196 basic_string&
4197 operator+=(initializer_list<_CharT> __l)
4198 { return this->append(__l.begin(), __l.size()); }
4199#endif // C++11
4200
4201#if __cplusplus201703L >= 201703L
4202 /**
4203 * @brief Append a string_view.
4204 * @param __svt The object convertible to string_view to be appended.
4205 * @return Reference to this string.
4206 */
4207 template<typename _Tp>
4208 _If_sv<_Tp, basic_string&>
4209 operator+=(const _Tp& __svt)
4210 { return this->append(__svt); }
4211#endif // C++17
4212
4213 /**
4214 * @brief Append a string to this string.
4215 * @param __str The string to append.
4216 * @return Reference to this string.
4217 */
4218 basic_string&
4219 append(const basic_string& __str);
4220
4221 /**
4222 * @brief Append a substring.
4223 * @param __str The string to append.
4224 * @param __pos Index of the first character of str to append.
4225 * @param __n The number of characters to append.
4226 * @return Reference to this string.
4227 * @throw std::out_of_range if @a __pos is not a valid index.
4228 *
4229 * This function appends @a __n characters from @a __str
4230 * starting at @a __pos to this string. If @a __n is is larger
4231 * than the number of available characters in @a __str, the
4232 * remainder of @a __str is appended.
4233 */
4234 basic_string&
4235 append(const basic_string& __str, size_type __pos, size_type __n = npos);
4236
4237 /**
4238 * @brief Append a C substring.
4239 * @param __s The C string to append.
4240 * @param __n The number of characters to append.
4241 * @return Reference to this string.
4242 */
4243 basic_string&
4244 append(const _CharT* __s, size_type __n);
4245
4246 /**
4247 * @brief Append a C string.
4248 * @param __s The C string to append.
4249 * @return Reference to this string.
4250 */
4251 basic_string&
4252 append(const _CharT* __s)
4253 {
4254 __glibcxx_requires_string(__s);
4255 return this->append(__s, traits_type::length(__s));
4256 }
4257
4258 /**
4259 * @brief Append multiple characters.
4260 * @param __n The number of characters to append.
4261 * @param __c The character to use.
4262 * @return Reference to this string.
4263 *
4264 * Appends __n copies of __c to this string.
4265 */
4266 basic_string&
4267 append(size_type __n, _CharT __c);
4268
4269#if __cplusplus201703L >= 201103L
4270 /**
4271 * @brief Append an initializer_list of characters.
4272 * @param __l The initializer_list of characters to append.
4273 * @return Reference to this string.
4274 */
4275 basic_string&
4276 append(initializer_list<_CharT> __l)
4277 { return this->append(__l.begin(), __l.size()); }
4278#endif // C++11
4279
4280 /**
4281 * @brief Append a range of characters.
4282 * @param __first Iterator referencing the first character to append.
4283 * @param __last Iterator marking the end of the range.
4284 * @return Reference to this string.
4285 *
4286 * Appends characters in the range [__first,__last) to this string.
4287 */
4288 template<class _InputIterator>
4289 basic_string&
4290 append(_InputIterator __first, _InputIterator __last)
4291 { return this->replace(_M_iend(), _M_iend(), __first, __last); }
4292
4293#if __cplusplus201703L >= 201703L
4294 /**
4295 * @brief Append a string_view.
4296 * @param __svt The object convertible to string_view to be appended.
4297 * @return Reference to this string.
4298 */
4299 template<typename _Tp>
4300 _If_sv<_Tp, basic_string&>
4301 append(const _Tp& __svt)
4302 {
4303 __sv_type __sv = __svt;
4304 return this->append(__sv.data(), __sv.size());
4305 }
4306
4307 /**
4308 * @brief Append a range of characters from a string_view.
4309 * @param __svt The object convertible to string_view to be appended
4310 * from.
4311 * @param __pos The position in the string_view to append from.
4312 * @param __n The number of characters to append from the string_view.
4313 * @return Reference to this string.
4314 */
4315 template<typename _Tp>
4316 _If_sv<_Tp, basic_string&>
4317 append(const _Tp& __svt, size_type __pos, size_type __n = npos)
4318 {
4319 __sv_type __sv = __svt;
4320 return append(__sv.data()
4321 + std::__sv_check(__sv.size(), __pos, "basic_string::append"),
4322 std::__sv_limit(__sv.size(), __pos, __n));
4323 }
4324#endif // C++17
4325
4326 /**
4327 * @brief Append a single character.
4328 * @param __c Character to append.
4329 */
4330 void
4331 push_back(_CharT __c)
4332 {
4333 const size_type __len = 1 + this->size();
4334 if (__len > this->capacity() || _M_rep()->_M_is_shared())
4335 this->reserve(__len);
4336 traits_type::assign(_M_data()[this->size()], __c);
4337 _M_rep()->_M_set_length_and_sharable(__len);
4338 }
4339
4340 /**
4341 * @brief Set value to contents of another string.
4342 * @param __str Source string to use.
4343 * @return Reference to this string.
4344 */
4345 basic_string&
4346 assign(const basic_string& __str);
4347
4348#if __cplusplus201703L >= 201103L
4349 /**
4350 * @brief Set value to contents of another string.
4351 * @param __str Source string to use.
4352 * @return Reference to this string.
4353 *
4354 * This function sets this string to the exact contents of @a __str.
4355 * @a __str is a valid, but unspecified string.
4356 */
4357 basic_string&
4358 assign(basic_string&& __str)
4359 noexcept(allocator_traits<_Alloc>::is_always_equal::value)
4360 {
4361 this->swap(__str);
4362 return *this;
4363 }
4364#endif // C++11
4365
4366 /**
4367 * @brief Set value to a substring of a string.
4368 * @param __str The string to use.
4369 * @param __pos Index of the first character of str.
4370 * @param __n Number of characters to use.
4371 * @return Reference to this string.
4372 * @throw std::out_of_range if @a pos is not a valid index.
4373 *
4374 * This function sets this string to the substring of @a __str
4375 * consisting of @a __n characters at @a __pos. If @a __n is
4376 * is larger than the number of available characters in @a
4377 * __str, the remainder of @a __str is used.
4378 */
4379 basic_string&
4380 assign(const basic_string& __str, size_type __pos, size_type __n = npos)
4381 { return this->assign(__str._M_data()
4382 + __str._M_check(__pos, "basic_string::assign"),
4383 __str._M_limit(__pos, __n)); }
4384
4385 /**
4386 * @brief Set value to a C substring.
4387 * @param __s The C string to use.
4388 * @param __n Number of characters to use.
4389 * @return Reference to this string.
4390 *
4391 * This function sets the value of this string to the first @a __n
4392 * characters of @a __s. If @a __n is is larger than the number of
4393 * available characters in @a __s, the remainder of @a __s is used.
4394 */
4395 basic_string&
4396 assign(const _CharT* __s, size_type __n);
4397
4398 /**
4399 * @brief Set value to contents of a C string.
4400 * @param __s The C string to use.
4401 * @return Reference to this string.
4402 *
4403 * This function sets the value of this string to the value of @a __s.
4404 * The data is copied, so there is no dependence on @a __s once the
4405 * function returns.
4406 */
4407 basic_string&
4408 assign(const _CharT* __s)
4409 {
4410 __glibcxx_requires_string(__s);
4411 return this->assign(__s, traits_type::length(__s));
4412 }
4413
4414 /**
4415 * @brief Set value to multiple characters.
4416 * @param __n Length of the resulting string.
4417 * @param __c The character to use.
4418 * @return Reference to this string.
4419 *
4420 * This function sets the value of this string to @a __n copies of
4421 * character @a __c.
4422 */
4423 basic_string&
4424 assign(size_type __n, _CharT __c)
4425 { return _M_replace_aux(size_type(0), this->size(), __n, __c); }
4426
4427 /**
4428 * @brief Set value to a range of characters.
4429 * @param __first Iterator referencing the first character to append.
4430 * @param __last Iterator marking the end of the range.
4431 * @return Reference to this string.
4432 *
4433 * Sets value of string to characters in the range [__first,__last).
4434 */
4435 template<class _InputIterator>
4436 basic_string&
4437 assign(_InputIterator __first, _InputIterator __last)
4438 { return this->replace(_M_ibegin(), _M_iend(), __first, __last); }
4439
4440#if __cplusplus201703L >= 201103L
4441 /**
4442 * @brief Set value to an initializer_list of characters.
4443 * @param __l The initializer_list of characters to assign.
4444 * @return Reference to this string.
4445 */
4446 basic_string&
4447 assign(initializer_list<_CharT> __l)
4448 { return this->assign(__l.begin(), __l.size()); }
4449#endif // C++11
4450
4451#if __cplusplus201703L >= 201703L
4452 /**
4453 * @brief Set value from a string_view.
4454 * @param __svt The source object convertible to string_view.
4455 * @return Reference to this string.
4456 */
4457 template<typename _Tp>
4458 _If_sv<_Tp, basic_string&>
4459 assign(const _Tp& __svt)
4460 {
4461 __sv_type __sv = __svt;
4462 return this->assign(__sv.data(), __sv.size());
4463 }
4464
4465 /**
4466 * @brief Set value from a range of characters in a string_view.
4467 * @param __svt The source object convertible to string_view.
4468 * @param __pos The position in the string_view to assign from.
4469 * @param __n The number of characters to assign.
4470 * @return Reference to this string.
4471 */
4472 template<typename _Tp>
4473 _If_sv<_Tp, basic_string&>
4474 assign(const _Tp& __svt, size_type __pos, size_type __n = npos)
4475 {
4476 __sv_type __sv = __svt;
4477 return assign(__sv.data()
4478 + std::__sv_check(__sv.size(), __pos, "basic_string::assign"),
4479 std::__sv_limit(__sv.size(), __pos, __n));
4480 }
4481#endif // C++17
4482
4483 /**
4484 * @brief Insert multiple characters.
4485 * @param __p Iterator referencing location in string to insert at.
4486 * @param __n Number of characters to insert
4487 * @param __c The character to insert.
4488 * @throw std::length_error If new length exceeds @c max_size().
4489 *
4490 * Inserts @a __n copies of character @a __c starting at the
4491 * position referenced by iterator @a __p. If adding
4492 * characters causes the length to exceed max_size(),
4493 * length_error is thrown. The value of the string doesn't
4494 * change if an error is thrown.
4495 */
4496 void
4497 insert(iterator __p, size_type __n, _CharT __c)
4498 { this->replace(__p, __p, __n, __c); }
4499
4500 /**
4501 * @brief Insert a range of characters.
4502 * @param __p Iterator referencing location in string to insert at.
4503 * @param __beg Start of range.
4504 * @param __end End of range.
4505 * @throw std::length_error If new length exceeds @c max_size().
4506 *
4507 * Inserts characters in range [__beg,__end). If adding
4508 * characters causes the length to exceed max_size(),
4509 * length_error is thrown. The value of the string doesn't
4510 * change if an error is thrown.
4511 */
4512 template<class _InputIterator>
4513 void
4514 insert(iterator __p, _InputIterator __beg, _InputIterator __end)
4515 { this->replace(__p, __p, __beg, __end); }
4516
4517#if __cplusplus201703L >= 201103L
4518 /**
4519 * @brief Insert an initializer_list of characters.
4520 * @param __p Iterator referencing location in string to insert at.
4521 * @param __l The initializer_list of characters to insert.
4522 * @throw std::length_error If new length exceeds @c max_size().
4523 */
4524 void
4525 insert(iterator __p, initializer_list<_CharT> __l)
4526 {
4527 _GLIBCXX_DEBUG_PEDASSERT(__p >= _M_ibegin() && __p <= _M_iend());
4528 this->insert(__p - _M_ibegin(), __l.begin(), __l.size());
4529 }
4530#endif // C++11
4531
4532 /**
4533 * @brief Insert value of a string.
4534 * @param __pos1 Position in string to insert at.
4535 * @param __str The string to insert.
4536 * @return Reference to this string.
4537 * @throw std::length_error If new length exceeds @c max_size().
4538 *
4539 * Inserts value of @a __str starting at @a __pos1. If adding
4540 * characters causes the length to exceed max_size(),
4541 * length_error is thrown. The value of the string doesn't
4542 * change if an error is thrown.
4543 */
4544 basic_string&
4545 insert(size_type __pos1, const basic_string& __str)
4546 { return this->insert(__pos1, __str, size_type(0), __str.size()); }
4547
4548 /**
4549 * @brief Insert a substring.
4550 * @param __pos1 Position in string to insert at.
4551 * @param __str The string to insert.
4552 * @param __pos2 Start of characters in str to insert.
4553 * @param __n Number of characters to insert.
4554 * @return Reference to this string.
4555 * @throw std::length_error If new length exceeds @c max_size().
4556 * @throw std::out_of_range If @a pos1 > size() or
4557 * @a __pos2 > @a str.size().
4558 *
4559 * Starting at @a pos1, insert @a __n character of @a __str
4560 * beginning with @a __pos2. If adding characters causes the
4561 * length to exceed max_size(), length_error is thrown. If @a
4562 * __pos1 is beyond the end of this string or @a __pos2 is
4563 * beyond the end of @a __str, out_of_range is thrown. The
4564 * value of the string doesn't change if an error is thrown.
4565 */
4566 basic_string&
4567 insert(size_type __pos1, const basic_string& __str,
4568 size_type __pos2, size_type __n = npos)
4569 { return this->insert(__pos1, __str._M_data()
4570 + __str._M_check(__pos2, "basic_string::insert"),
4571 __str._M_limit(__pos2, __n)); }
4572
4573 /**
4574 * @brief Insert a C substring.
4575 * @param __pos Position in string to insert at.
4576 * @param __s The C string to insert.
4577 * @param __n The number of characters to insert.
4578 * @return Reference to this string.
4579 * @throw std::length_error If new length exceeds @c max_size().
4580 * @throw std::out_of_range If @a __pos is beyond the end of this
4581 * string.
4582 *
4583 * Inserts the first @a __n characters of @a __s starting at @a
4584 * __pos. If adding characters causes the length to exceed
4585 * max_size(), length_error is thrown. If @a __pos is beyond
4586 * end(), out_of_range is thrown. The value of the string
4587 * doesn't change if an error is thrown.
4588 */
4589 basic_string&
4590 insert(size_type __pos, const _CharT* __s, size_type __n);
4591
4592 /**
4593 * @brief Insert a C string.
4594 * @param __pos Position in string to insert at.
4595 * @param __s The C string to insert.
4596 * @return Reference to this string.
4597 * @throw std::length_error If new length exceeds @c max_size().
4598 * @throw std::out_of_range If @a pos is beyond the end of this
4599 * string.
4600 *
4601 * Inserts the first @a n characters of @a __s starting at @a __pos. If
4602 * adding characters causes the length to exceed max_size(),
4603 * length_error is thrown. If @a __pos is beyond end(), out_of_range is
4604 * thrown. The value of the string doesn't change if an error is
4605 * thrown.
4606 */
4607 basic_string&
4608 insert(size_type __pos, const _CharT* __s)
4609 {
4610 __glibcxx_requires_string(__s);
4611 return this->insert(__pos, __s, traits_type::length(__s));
4612 }
4613
4614 /**
4615 * @brief Insert multiple characters.
4616 * @param __pos Index in string to insert at.
4617 * @param __n Number of characters to insert
4618 * @param __c The character to insert.
4619 * @return Reference to this string.
4620 * @throw std::length_error If new length exceeds @c max_size().
4621 * @throw std::out_of_range If @a __pos is beyond the end of this
4622 * string.
4623 *
4624 * Inserts @a __n copies of character @a __c starting at index
4625 * @a __pos. If adding characters causes the length to exceed
4626 * max_size(), length_error is thrown. If @a __pos > length(),
4627 * out_of_range is thrown. The value of the string doesn't
4628 * change if an error is thrown.
4629 */
4630 basic_string&
4631 insert(size_type __pos, size_type __n, _CharT __c)
4632 { return _M_replace_aux(_M_check(__pos, "basic_string::insert"),
4633 size_type(0), __n, __c); }
4634
4635 /**
4636 * @brief Insert one character.
4637 * @param __p Iterator referencing position in string to insert at.
4638 * @param __c The character to insert.
4639 * @return Iterator referencing newly inserted char.
4640 * @throw std::length_error If new length exceeds @c max_size().
4641 *
4642 * Inserts character @a __c at position referenced by @a __p.
4643 * If adding character causes the length to exceed max_size(),
4644 * length_error is thrown. If @a __p is beyond end of string,
4645 * out_of_range is thrown. The value of the string doesn't
4646 * change if an error is thrown.
4647 */
4648 iterator
4649 insert(iterator __p, _CharT __c)
4650 {
4651 _GLIBCXX_DEBUG_PEDASSERT(__p >= _M_ibegin() && __p <= _M_iend());
4652 const size_type __pos = __p - _M_ibegin();
4653 _M_replace_aux(__pos, size_type(0), size_type(1), __c);
4654 _M_rep()->_M_set_leaked();
4655 return iterator(_M_data() + __pos);
4656 }
4657
4658#if __cplusplus201703L >= 201703L
4659 /**
4660 * @brief Insert a string_view.
4661 * @param __pos Position in string to insert at.
4662 * @param __svt The object convertible to string_view to insert.
4663 * @return Reference to this string.
4664 */
4665 template<typename _Tp>
4666 _If_sv<_Tp, basic_string&>
4667 insert(size_type __pos, const _Tp& __svt)
4668 {
4669 __sv_type __sv = __svt;
4670 return this->insert(__pos, __sv.data(), __sv.size());
4671 }
4672
4673 /**
4674 * @brief Insert a string_view.
4675 * @param __pos Position in string to insert at.
4676 * @param __svt The object convertible to string_view to insert from.
4677 * @param __pos Position in string_view to insert
4678 * from.
4679 * @param __n The number of characters to insert.
4680 * @return Reference to this string.
4681 */
4682 template<typename _Tp>
4683 _If_sv<_Tp, basic_string&>
4684 insert(size_type __pos1, const _Tp& __svt,
4685 size_type __pos2, size_type __n = npos)
4686 {
4687 __sv_type __sv = __svt;
4688 return this->replace(__pos1, size_type(0), __sv.data()
4689 + std::__sv_check(__sv.size(), __pos2, "basic_string::insert"),
4690 std::__sv_limit(__sv.size(), __pos2, __n));
4691 }
4692#endif // C++17
4693
4694 /**
4695 * @brief Remove characters.
4696 * @param __pos Index of first character to remove (default 0).
4697 * @param __n Number of characters to remove (default remainder).
4698 * @return Reference to this string.
4699 * @throw std::out_of_range If @a pos is beyond the end of this
4700 * string.
4701 *
4702 * Removes @a __n characters from this string starting at @a
4703 * __pos. The length of the string is reduced by @a __n. If
4704 * there are < @a __n characters to remove, the remainder of
4705 * the string is truncated. If @a __p is beyond end of string,
4706 * out_of_range is thrown. The value of the string doesn't
4707 * change if an error is thrown.
4708 */
4709 basic_string&
4710 erase(size_type __pos = 0, size_type __n = npos)
4711 {
4712 _M_mutate(_M_check(__pos, "basic_string::erase"),
4713 _M_limit(__pos, __n), size_type(0));
4714 return *this;
4715 }
4716
4717 /**
4718 * @brief Remove one character.
4719 * @param __position Iterator referencing the character to remove.
4720 * @return iterator referencing same location after removal.
4721 *
4722 * Removes the character at @a __position from this string. The value
4723 * of the string doesn't change if an error is thrown.
4724 */
4725 iterator
4726 erase(iterator __position)
4727 {
4728 _GLIBCXX_DEBUG_PEDASSERT(__position >= _M_ibegin()
4729 && __position < _M_iend());
4730 const size_type __pos = __position - _M_ibegin();
4731 _M_mutate(__pos, size_type(1), size_type(0));
4732 _M_rep()->_M_set_leaked();
4733 return iterator(_M_data() + __pos);
4734 }
4735
4736 /**
4737 * @brief Remove a range of characters.
4738 * @param __first Iterator referencing the first character to remove.
4739 * @param __last Iterator referencing the end of the range.
4740 * @return Iterator referencing location of first after removal.
4741 *
4742 * Removes the characters in the range [first,last) from this string.
4743 * The value of the string doesn't change if an error is thrown.
4744 */
4745 iterator
4746 erase(iterator __first, iterator __last);
4747
4748#if __cplusplus201703L >= 201103L
4749 /**
4750 * @brief Remove the last character.
4751 *
4752 * The string must be non-empty.
4753 */
4754 void
4755 pop_back() // FIXME C++11: should be noexcept.
4756 {
4757 __glibcxx_assert(!empty())do { if (! (!empty())) std::__replacement_assert("/usr/lib/gcc/x86_64-linux-gnu/10/../../../../include/c++/10/bits/basic_string.h"
, 4757, __PRETTY_FUNCTION__, "!empty()"); } while (false)
;
4758 erase(size() - 1, 1);
4759 }
4760#endif // C++11
4761
4762 /**
4763 * @brief Replace characters with value from another string.
4764 * @param __pos Index of first character to replace.
4765 * @param __n Number of characters to be replaced.
4766 * @param __str String to insert.
4767 * @return Reference to this string.
4768 * @throw std::out_of_range If @a pos is beyond the end of this
4769 * string.
4770 * @throw std::length_error If new length exceeds @c max_size().
4771 *
4772 * Removes the characters in the range [__pos,__pos+__n) from
4773 * this string. In place, the value of @a __str is inserted.
4774 * If @a __pos is beyond end of string, out_of_range is thrown.
4775 * If the length of the result exceeds max_size(), length_error
4776 * is thrown. The value of the string doesn't change if an
4777 * error is thrown.
4778 */
4779 basic_string&
4780 replace(size_type __pos, size_type __n, const basic_string& __str)
4781 { return this->replace(__pos, __n, __str._M_data(), __str.size()); }
4782
4783 /**
4784 * @brief Replace characters with value from another string.
4785 * @param __pos1 Index of first character to replace.
4786 * @param __n1 Number of characters to be replaced.
4787 * @param __str String to insert.
4788 * @param __pos2 Index of first character of str to use.
4789 * @param __n2 Number of characters from str to use.
4790 * @return Reference to this string.
4791 * @throw std::out_of_range If @a __pos1 > size() or @a __pos2 >
4792 * __str.size().
4793 * @throw std::length_error If new length exceeds @c max_size().
4794 *
4795 * Removes the characters in the range [__pos1,__pos1 + n) from this
4796 * string. In place, the value of @a __str is inserted. If @a __pos is
4797 * beyond end of string, out_of_range is thrown. If the length of the
4798 * result exceeds max_size(), length_error is thrown. The value of the
4799 * string doesn't change if an error is thrown.
4800 */
4801 basic_string&
4802 replace(size_type __pos1, size_type __n1, const basic_string& __str,
4803 size_type __pos2, size_type __n2 = npos)
4804 { return this->replace(__pos1, __n1, __str._M_data()
4805 + __str._M_check(__pos2, "basic_string::replace"),
4806 __str._M_limit(__pos2, __n2)); }
4807
4808 /**
4809 * @brief Replace characters with value of a C substring.
4810 * @param __pos Index of first character to replace.
4811 * @param __n1 Number of characters to be replaced.
4812 * @param __s C string to insert.
4813 * @param __n2 Number of characters from @a s to use.
4814 * @return Reference to this string.
4815 * @throw std::out_of_range If @a pos1 > size().
4816 * @throw std::length_error If new length exceeds @c max_size().
4817 *
4818 * Removes the characters in the range [__pos,__pos + __n1)
4819 * from this string. In place, the first @a __n2 characters of
4820 * @a __s are inserted, or all of @a __s if @a __n2 is too large. If
4821 * @a __pos is beyond end of string, out_of_range is thrown. If
4822 * the length of result exceeds max_size(), length_error is
4823 * thrown. The value of the string doesn't change if an error
4824 * is thrown.
4825 */
4826 basic_string&
4827 replace(size_type __pos, size_type __n1, const _CharT* __s,
4828 size_type __n2);
4829
4830 /**
4831 * @brief Replace characters with value of a C string.
4832 * @param __pos Index of first character to replace.
4833 * @param __n1 Number of characters to be replaced.
4834 * @param __s C string to insert.
4835 * @return Reference to this string.
4836 * @throw std::out_of_range If @a pos > size().
4837 * @throw std::length_error If new length exceeds @c max_size().
4838 *
4839 * Removes the characters in the range [__pos,__pos + __n1)
4840 * from this string. In place, the characters of @a __s are
4841 * inserted. If @a __pos is beyond end of string, out_of_range
4842 * is thrown. If the length of result exceeds max_size(),
4843 * length_error is thrown. The value of the string doesn't
4844 * change if an error is thrown.
4845 */
4846 basic_string&
4847 replace(size_type __pos, size_type __n1, const _CharT* __s)
4848 {
4849 __glibcxx_requires_string(__s);
4850 return this->replace(__pos, __n1, __s, traits_type::length(__s));
4851 }
4852
4853 /**
4854 * @brief Replace characters with multiple characters.
4855 * @param __pos Index of first character to replace.
4856 * @param __n1 Number of characters to be replaced.
4857 * @param __n2 Number of characters to insert.
4858 * @param __c Character to insert.
4859 * @return Reference to this string.
4860 * @throw std::out_of_range If @a __pos > size().
4861 * @throw std::length_error If new length exceeds @c max_size().
4862 *
4863 * Removes the characters in the range [pos,pos + n1) from this
4864 * string. In place, @a __n2 copies of @a __c are inserted.
4865 * If @a __pos is beyond end of string, out_of_range is thrown.
4866 * If the length of result exceeds max_size(), length_error is
4867 * thrown. The value of the string doesn't change if an error
4868 * is thrown.
4869 */
4870 basic_string&
4871 replace(size_type __pos, size_type __n1, size_type __n2, _CharT __c)
4872 { return _M_replace_aux(_M_check(__pos, "basic_string::replace"),
4873 _M_limit(__pos, __n1), __n2, __c); }
4874
4875 /**
4876 * @brief Replace range of characters with string.
4877 * @param __i1 Iterator referencing start of range to replace.
4878 * @param __i2 Iterator referencing end of range to replace.
4879 * @param __str String value to insert.
4880 * @return Reference to this string.
4881 * @throw std::length_error If new length exceeds @c max_size().
4882 *
4883 * Removes the characters in the range [__i1,__i2). In place,
4884 * the value of @a __str is inserted. If the length of result
4885 * exceeds max_size(), length_error is thrown. The value of
4886 * the string doesn't change if an error is thrown.
4887 */
4888 basic_string&
4889 replace(iterator __i1, iterator __i2, const basic_string& __str)
4890 { return this->replace(__i1, __i2, __str._M_data(), __str.size()); }
4891
4892 /**
4893 * @brief Replace range of characters with C substring.
4894 * @param __i1 Iterator referencing start of range to replace.
4895 * @param __i2 Iterator referencing end of range to replace.
4896 * @param __s C string value to insert.
4897 * @param __n Number of characters from s to insert.
4898 * @return Reference to this string.
4899 * @throw std::length_error If new length exceeds @c max_size().
4900 *
4901 * Removes the characters in the range [__i1,__i2). In place,
4902 * the first @a __n characters of @a __s are inserted. If the
4903 * length of result exceeds max_size(), length_error is thrown.
4904 * The value of the string doesn't change if an error is
4905 * thrown.
4906 */
4907 basic_string&
4908 replace(iterator __i1, iterator __i2, const _CharT* __s, size_type __n)
4909 {
4910 _GLIBCXX_DEBUG_PEDASSERT(_M_ibegin() <= __i1 && __i1 <= __i2
4911 && __i2 <= _M_iend());
4912 return this->replace(__i1 - _M_ibegin(), __i2 - __i1, __s, __n);
4913 }
4914
4915 /**
4916 * @brief Replace range of characters with C string.
4917 * @param __i1 Iterator referencing start of range to replace.
4918 * @param __i2 Iterator referencing end of range to replace.
4919 * @param __s C string value to insert.
4920 * @return Reference to this string.
4921 * @throw std::length_error If new length exceeds @c max_size().
4922 *
4923 * Removes the characters in the range [__i1,__i2). In place,
4924 * the characters of @a __s are inserted. If the length of
4925 * result exceeds max_size(), length_error is thrown. The
4926 * value of the string doesn't change if an error is thrown.
4927 */
4928 basic_string&
4929 replace(iterator __i1, iterator __i2, const _CharT* __s)
4930 {
4931 __glibcxx_requires_string(__s);
4932 return this->replace(__i1, __i2, __s, traits_type::length(__s));
4933 }
4934
4935 /**
4936 * @brief Replace range of characters with multiple characters
4937 * @param __i1 Iterator referencing start of range to replace.
4938 * @param __i2 Iterator referencing end of range to replace.
4939 * @param __n Number of characters to insert.
4940 * @param __c Character to insert.
4941 * @return Reference to this string.
4942 * @throw std::length_error If new length exceeds @c max_size().
4943 *
4944 * Removes the characters in the range [__i1,__i2). In place,
4945 * @a __n copies of @a __c are inserted. If the length of
4946 * result exceeds max_size(), length_error is thrown. The
4947 * value of the string doesn't change if an error is thrown.
4948 */
4949 basic_string&
4950 replace(iterator __i1, iterator __i2, size_type __n, _CharT __c)
4951 {
4952 _GLIBCXX_DEBUG_PEDASSERT(_M_ibegin() <= __i1 && __i1 <= __i2
4953 && __i2 <= _M_iend());
4954 return _M_replace_aux(__i1 - _M_ibegin(), __i2 - __i1, __n, __c);
4955 }
4956
4957 /**
4958 * @brief Replace range of characters with range.
4959 * @param __i1 Iterator referencing start of range to replace.
4960 * @param __i2 Iterator referencing end of range to replace.
4961 * @param __k1 Iterator referencing start of range to insert.
4962 * @param __k2 Iterator referencing end of range to insert.
4963 * @return Reference to this string.
4964 * @throw std::length_error If new length exceeds @c max_size().
4965 *
4966 * Removes the characters in the range [__i1,__i2). In place,
4967 * characters in the range [__k1,__k2) are inserted. If the
4968 * length of result exceeds max_size(), length_error is thrown.
4969 * The value of the string doesn't change if an error is
4970 * thrown.
4971 */
4972 template<class _InputIterator>
4973 basic_string&
4974 replace(iterator __i1, iterator __i2,
4975 _InputIterator __k1, _InputIterator __k2)
4976 {
4977 _GLIBCXX_DEBUG_PEDASSERT(_M_ibegin() <= __i1 && __i1 <= __i2
4978 && __i2 <= _M_iend());
4979 __glibcxx_requires_valid_range(__k1, __k2);
4980 typedef typename std::__is_integer<_InputIterator>::__type _Integral;
4981 return _M_replace_dispatch(__i1, __i2, __k1, __k2, _Integral());
4982 }
4983
4984 // Specializations for the common case of pointer and iterator:
4985 // useful to avoid the overhead of temporary buffering in _M_replace.
4986 basic_string&
4987 replace(iterator __i1, iterator __i2, _CharT* __k1, _CharT* __k2)
4988 {
4989 _GLIBCXX_DEBUG_PEDASSERT(_M_ibegin() <= __i1 && __i1 <= __i2
4990 && __i2 <= _M_iend());
4991 __glibcxx_requires_valid_range(__k1, __k2);
4992 return this->replace(__i1 - _M_ibegin(), __i2 - __i1,
4993 __k1, __k2 - __k1);
4994 }
4995
4996 basic_string&
4997 replace(iterator __i1, iterator __i2,
4998 const _CharT* __k1, const _CharT* __k2)
4999 {
5000 _GLIBCXX_DEBUG_PEDASSERT(_M_ibegin() <= __i1 && __i1 <= __i2
5001 && __i2 <= _M_iend());
5002 __glibcxx_requires_valid_range(__k1, __k2);
5003 return this->replace(__i1 - _M_ibegin(), __i2 - __i1,
5004 __k1, __k2 - __k1);
5005 }
5006
5007 basic_string&
5008 replace(iterator __i1, iterator __i2, iterator __k1, iterator __k2)
5009 {
5010 _GLIBCXX_DEBUG_PEDASSERT(_M_ibegin() <= __i1 && __i1 <= __i2
5011 && __i2 <= _M_iend());
5012 __glibcxx_requires_valid_range(__k1, __k2);
5013 return this->replace(__i1 - _M_ibegin(), __i2 - __i1,
5014 __k1.base(), __k2 - __k1);
5015 }
5016
5017 basic_string&
5018 replace(iterator __i1, iterator __i2,
5019 const_iterator __k1, const_iterator __k2)
5020 {
5021 _GLIBCXX_DEBUG_PEDASSERT(_M_ibegin() <= __i1 && __i1 <= __i2
5022 && __i2 <= _M_iend());
5023 __glibcxx_requires_valid_range(__k1, __k2);
5024 return this->replace(__i1 - _M_ibegin(), __i2 - __i1,
5025 __k1.base(), __k2 - __k1);
5026 }
5027
5028#if __cplusplus201703L >= 201103L
5029 /**
5030 * @brief Replace range of characters with initializer_list.
5031 * @param __i1 Iterator referencing start of range to replace.
5032 * @param __i2 Iterator referencing end of range to replace.
5033 * @param __l The initializer_list of characters to insert.
5034 * @return Reference to this string.
5035 * @throw std::length_error If new length exceeds @c max_size().
5036 *
5037 * Removes the characters in the range [__i1,__i2). In place,
5038 * characters in the range [__k1,__k2) are inserted. If the
5039 * length of result exceeds max_size(), length_error is thrown.
5040 * The value of the string doesn't change if an error is
5041 * thrown.
5042 */
5043 basic_string& replace(iterator __i1, iterator __i2,
5044 initializer_list<_CharT> __l)
5045 { return this->replace(__i1, __i2, __l.begin(), __l.end()); }
5046#endif // C++11
5047
5048#if __cplusplus201703L >= 201703L
5049 /**
5050 * @brief Replace range of characters with string_view.
5051 * @param __pos The position to replace at.
5052 * @param __n The number of characters to replace.
5053 * @param __svt The object convertible to string_view to insert.
5054 * @return Reference to this string.
5055 */
5056 template<typename _Tp>
5057 _If_sv<_Tp, basic_string&>
5058 replace(size_type __pos, size_type __n, const _Tp& __svt)
5059 {
5060 __sv_type __sv = __svt;
5061 return this->replace(__pos, __n, __sv.data(), __sv.size());
5062 }
5063
5064 /**
5065 * @brief Replace range of characters with string_view.
5066 * @param __pos1 The position to replace at.
5067 * @param __n1 The number of characters to replace.
5068 * @param __svt The object convertible to string_view to insert from.
5069 * @param __pos2 The position in the string_view to insert from.
5070 * @param __n2 The number of characters to insert.
5071 * @return Reference to this string.
5072 */
5073 template<typename _Tp>
5074 _If_sv<_Tp, basic_string&>
5075 replace(size_type __pos1, size_type __n1, const _Tp& __svt,
5076 size_type __pos2, size_type __n2 = npos)
5077 {
5078 __sv_type __sv = __svt;
5079 return this->replace(__pos1, __n1,
5080 __sv.data()
5081 + std::__sv_check(__sv.size(), __pos2, "basic_string::replace"),
5082 std::__sv_limit(__sv.size(), __pos2, __n2));
5083 }
5084
5085 /**
5086 * @brief Replace range of characters with string_view.
5087 * @param __i1 An iterator referencing the start position
5088 to replace at.
5089 * @param __i2 An iterator referencing the end position
5090 for the replace.
5091 * @param __svt The object convertible to string_view to insert from.
5092 * @return Reference to this string.
5093 */
5094 template<typename _Tp>
5095 _If_sv<_Tp, basic_string&>
5096 replace(const_iterator __i1, const_iterator __i2, const _Tp& __svt)
5097 {
5098 __sv_type __sv = __svt;
5099 return this->replace(__i1 - begin(), __i2 - __i1, __sv);
5100 }
5101#endif // C++17
5102
5103 private:
5104 template<class _Integer>
5105 basic_string&
5106 _M_replace_dispatch(iterator __i1, iterator __i2, _Integer __n,
5107 _Integer __val, __true_type)
5108 { return _M_replace_aux(__i1 - _M_ibegin(), __i2 - __i1, __n, __val); }
5109
5110 template<class _InputIterator>
5111 basic_string&
5112 _M_replace_dispatch(iterator __i1, iterator __i2, _InputIterator __k1,
5113 _InputIterator __k2, __false_type);
5114
5115 basic_string&
5116 _M_replace_aux(size_type __pos1, size_type __n1, size_type __n2,
5117 _CharT __c);
5118
5119 basic_string&
5120 _M_replace_safe(size_type __pos1, size_type __n1, const _CharT* __s,
5121 size_type __n2);
5122
5123 // _S_construct_aux is used to implement the 21.3.1 para 15 which
5124 // requires special behaviour if _InIter is an integral type
5125 template<class _InIterator>
5126 static _CharT*
5127 _S_construct_aux(_InIterator __beg, _InIterator __end,
5128 const _Alloc& __a, __false_type)
5129 {
5130 typedef typename iterator_traits<_InIterator>::iterator_category _Tag;
5131 return _S_construct(__beg, __end, __a, _Tag());
5132 }
5133
5134 // _GLIBCXX_RESOLVE_LIB_DEFECTS
5135 // 438. Ambiguity in the "do the right thing" clause
5136 template<class _Integer>
5137 static _CharT*
5138 _S_construct_aux(_Integer __beg, _Integer __end,
5139 const _Alloc& __a, __true_type)
5140 { return _S_construct_aux_2(static_cast<size_type>(__beg),
5141 __end, __a); }
5142
5143 static _CharT*
5144 _S_construct_aux_2(size_type __req, _CharT __c, const _Alloc& __a)
5145 { return _S_construct(__req, __c, __a); }
5146
5147 template<class _InIterator>
5148 static _CharT*
5149 _S_construct(_InIterator __beg, _InIterator __end, const _Alloc& __a)
5150 {
5151 typedef typename std::__is_integer<_InIterator>::__type _Integral;
5152 return _S_construct_aux(__beg, __end, __a, _Integral());
5153 }
5154
5155 // For Input Iterators, used in istreambuf_iterators, etc.
5156 template<class _InIterator>
5157 static _CharT*
5158 _S_construct(_InIterator __beg, _InIterator __end, const _Alloc& __a,
5159 input_iterator_tag);
5160
5161 // For forward_iterators up to random_access_iterators, used for
5162 // string::iterator, _CharT*, etc.
5163 template<class _FwdIterator>
5164 static _CharT*
5165 _S_construct(_FwdIterator __beg, _FwdIterator __end, const _Alloc& __a,
5166 forward_iterator_tag);
5167
5168 static _CharT*
5169 _S_construct(size_type __req, _CharT __c, const _Alloc& __a);
5170
5171 public:
5172
5173 /**
5174 * @brief Copy substring into C string.
5175 * @param __s C string to copy value into.
5176 * @param __n Number of characters to copy.
5177 * @param __pos Index of first character to copy.
5178 * @return Number of characters actually copied
5179 * @throw std::out_of_range If __pos > size().
5180 *
5181 * Copies up to @a __n characters starting at @a __pos into the
5182 * C string @a __s. If @a __pos is %greater than size(),
5183 * out_of_range is thrown.
5184 */
5185 size_type
5186 copy(_CharT* __s, size_type __n, size_type __pos = 0) const;
5187
5188 /**
5189 * @brief Swap contents with another string.
5190 * @param __s String to swap with.
5191 *
5192 * Exchanges the contents of this string with that of @a __s in constant
5193 * time.
5194 */
5195 void
5196 swap(basic_string& __s)
5197 _GLIBCXX_NOEXCEPT_IF(allocator_traits<_Alloc>::is_always_equal::value)noexcept(allocator_traits<_Alloc>::is_always_equal::value
)
;
5198
5199 // String operations:
5200 /**
5201 * @brief Return const pointer to null-terminated contents.
5202 *
5203 * This is a handle to internal data. Do not modify or dire things may
5204 * happen.
5205 */
5206 const _CharT*
5207 c_str() const _GLIBCXX_NOEXCEPTnoexcept
5208 { return _M_data(); }
5209
5210 /**
5211 * @brief Return const pointer to contents.
5212 *
5213 * This is a pointer to internal data. It is undefined to modify
5214 * the contents through the returned pointer. To get a pointer that
5215 * allows modifying the contents use @c &str[0] instead,
5216 * (or in C++17 the non-const @c str.data() overload).
5217 */
5218 const _CharT*
5219 data() const _GLIBCXX_NOEXCEPTnoexcept
5220 { return _M_data(); }
5221
5222#if __cplusplus201703L >= 201703L
5223 /**
5224 * @brief Return non-const pointer to contents.
5225 *
5226 * This is a pointer to the character sequence held by the string.
5227 * Modifying the characters in the sequence is allowed.
5228 */
5229 _CharT*
5230 data() noexcept
5231 {
5232 _M_leak();
5233 return _M_data();
5234 }
5235#endif
5236
5237 /**
5238 * @brief Return copy of allocator used to construct this string.
5239 */
5240 allocator_type
5241 get_allocator() const _GLIBCXX_NOEXCEPTnoexcept
5242 { return _M_dataplus; }
5243
5244 /**
5245 * @brief Find position of a C substring.
5246 * @param __s C string to locate.
5247 * @param __pos Index of character to search from.
5248 * @param __n Number of characters from @a s to search for.
5249 * @return Index of start of first occurrence.
5250 *
5251 * Starting from @a __pos, searches forward for the first @a
5252 * __n characters in @a __s within this string. If found,
5253 * returns the index where it begins. If not found, returns
5254 * npos.
5255 */
5256 size_type
5257 find(const _CharT* __s, size_type __pos, size_type __n) const
5258 _GLIBCXX_NOEXCEPTnoexcept;
5259
5260 /**
5261 * @brief Find position of a string.
5262 * @param __str String to locate.
5263 * @param __pos Index of character to search from (default 0).
5264 * @return Index of start of first occurrence.
5265 *
5266 * Starting from @a __pos, searches forward for value of @a __str within
5267 * this string. If found, returns the index where it begins. If not
5268 * found, returns npos.
5269 */
5270 size_type
5271 find(const basic_string& __str, size_type __pos = 0) const
5272 _GLIBCXX_NOEXCEPTnoexcept
5273 { return this->find(__str.data(), __pos, __str.size()); }
5274
5275 /**
5276 * @brief Find position of a C string.
5277 * @param __s C string to locate.
5278 * @param __pos Index of character to search from (default 0).
5279 * @return Index of start of first occurrence.
5280 *
5281 * Starting from @a __pos, searches forward for the value of @a
5282 * __s within this string. If found, returns the index where
5283 * it begins. If not found, returns npos.
5284 */
5285 size_type
5286 find(const _CharT* __s, size_type __pos = 0) const _GLIBCXX_NOEXCEPTnoexcept
5287 {
5288 __glibcxx_requires_string(__s);
5289 return this->find(__s, __pos, traits_type::length(__s));
5290 }
5291
5292 /**
5293 * @brief Find position of a character.
5294 * @param __c Character to locate.
5295 * @param __pos Index of character to search from (default 0).
5296 * @return Index of first occurrence.
5297 *
5298 * Starting from @a __pos, searches forward for @a __c within
5299 * this string. If found, returns the index where it was
5300 * found. If not found, returns npos.
5301 */
5302 size_type
5303 find(_CharT __c, size_type __pos = 0) const _GLIBCXX_NOEXCEPTnoexcept;
5304
5305#if __cplusplus201703L >= 201703L
5306 /**
5307 * @brief Find position of a string_view.
5308 * @param __svt The object convertible to string_view to locate.
5309 * @param __pos Index of character to search from (default 0).
5310 * @return Index of start of first occurrence.
5311 */
5312 template<typename _Tp>
5313 _If_sv<_Tp, size_type>
5314 find(const _Tp& __svt, size_type __pos = 0) const
5315 noexcept(is_same<_Tp, __sv_type>::value)
5316 {
5317 __sv_type __sv = __svt;
5318 return this->find(__sv.data(), __pos, __sv.size());
5319 }
5320#endif // C++17
5321
5322 /**
5323 * @brief Find last position of a string.
5324 * @param __str String to locate.
5325 * @param __pos Index of character to search back from (default end).
5326 * @return Index of start of last occurrence.
5327 *
5328 * Starting from @a __pos, searches backward for value of @a
5329 * __str within this string. If found, returns the index where
5330 * it begins. If not found, returns npos.
5331 */
5332 size_type
5333 rfind(const basic_string& __str, size_type __pos = npos) const
5334 _GLIBCXX_NOEXCEPTnoexcept
5335 { return this->rfind(__str.data(), __pos, __str.size()); }
5336
5337 /**
5338 * @brief Find last position of a C substring.
5339 * @param __s C string to locate.
5340 * @param __pos Index of character to search back from.
5341 * @param __n Number of characters from s to search for.
5342 * @return Index of start of last occurrence.
5343 *
5344 * Starting from @a __pos, searches backward for the first @a
5345 * __n characters in @a __s within this string. If found,
5346 * returns the index where it begins. If not found, returns
5347 * npos.
5348 */
5349 size_type
5350 rfind(const _CharT* __s, size_type __pos, size_type __n) const
5351 _GLIBCXX_NOEXCEPTnoexcept;
5352
5353 /**
5354 * @brief Find last position of a C string.
5355 * @param __s C string to locate.
5356 * @param __pos Index of character to start search at (default end).
5357 * @return Index of start of last occurrence.
5358 *
5359 * Starting from @a __pos, searches backward for the value of
5360 * @a __s within this string. If found, returns the index
5361 * where it begins. If not found, returns npos.
5362 */
5363 size_type
5364 rfind(const _CharT* __s, size_type __pos = npos) const _GLIBCXX_NOEXCEPTnoexcept
5365 {
5366 __glibcxx_requires_string(__s);
5367 return this->rfind(__s, __pos, traits_type::length(__s));
5368 }
5369
5370 /**
5371 * @brief Find last position of a character.
5372 * @param __c Character to locate.
5373 * @param __pos Index of character to search back from (default end).
5374 * @return Index of last occurrence.
5375 *
5376 * Starting from @a __pos, searches backward for @a __c within
5377 * this string. If found, returns the index where it was
5378 * found. If not found, returns npos.
5379 */
5380 size_type
5381 rfind(_CharT __c, size_type __pos = npos) const _GLIBCXX_NOEXCEPTnoexcept;
5382
5383#if __cplusplus201703L >= 201703L
5384 /**
5385 * @brief Find last position of a string_view.
5386 * @param __svt The object convertible to string_view to locate.
5387 * @param __pos Index of character to search back from (default end).
5388 * @return Index of start of last occurrence.
5389 */
5390 template<typename _Tp>
5391 _If_sv<_Tp, size_type>
5392 rfind(const _Tp& __svt, size_type __pos = npos) const
5393 noexcept(is_same<_Tp, __sv_type>::value)
5394 {
5395 __sv_type __sv = __svt;
5396 return this->rfind(__sv.data(), __pos, __sv.size());
5397 }
5398#endif // C++17
5399
5400 /**
5401 * @brief Find position of a character of string.
5402 * @param __str String containing characters to locate.
5403 * @param __pos Index of character to search from (default 0).
5404 * @return Index of first occurrence.
5405 *
5406 * Starting from @a __pos, searches forward for one of the
5407 * characters of @a __str within this string. If found,
5408 * returns the index where it was found. If not found, returns
5409 * npos.
5410 */
5411 size_type
5412 find_first_of(const basic_string& __str, size_type __pos = 0) const
5413 _GLIBCXX_NOEXCEPTnoexcept
5414 { return this->find_first_of(__str.data(), __pos, __str.size()); }
5415
5416 /**
5417 * @brief Find position of a character of C substring.
5418 * @param __s String containing characters to locate.
5419 * @param __pos Index of character to search from.
5420 * @param __n Number of characters from s to search for.
5421 * @return Index of first occurrence.
5422 *
5423 * Starting from @a __pos, searches forward for one of the
5424 * first @a __n characters of @a __s within this string. If
5425 * found, returns the index where it was found. If not found,
5426 * returns npos.
5427 */
5428 size_type
5429 find_first_of(const _CharT* __s, size_type __pos, size_type __n) const
5430 _GLIBCXX_NOEXCEPTnoexcept;
5431
5432 /**
5433 * @brief Find position of a character of C string.
5434 * @param __s String containing characters to locate.
5435 * @param __pos Index of character to search from (default 0).
5436 * @return Index of first occurrence.
5437 *
5438 * Starting from @a __pos, searches forward for one of the
5439 * characters of @a __s within this string. If found, returns
5440 * the index where it was found. If not found, returns npos.
5441 */
5442 size_type
5443 find_first_of(const _CharT* __s, size_type __pos = 0) const
5444 _GLIBCXX_NOEXCEPTnoexcept
5445 {
5446 __glibcxx_requires_string(__s);
5447 return this->find_first_of(__s, __pos, traits_type::length(__s));
5448 }
5449
5450 /**
5451 * @brief Find position of a character.
5452 * @param __c Character to locate.
5453 * @param __pos Index of character to search from (default 0).
5454 * @return Index of first occurrence.
5455 *
5456 * Starting from @a __pos, searches forward for the character
5457 * @a __c within this string. If found, returns the index
5458 * where it was found. If not found, returns npos.
5459 *
5460 * Note: equivalent to find(__c, __pos).
5461 */
5462 size_type
5463 find_first_of(_CharT __c, size_type __pos = 0) const _GLIBCXX_NOEXCEPTnoexcept
5464 { return this->find(__c, __pos); }
5465
5466#if __cplusplus201703L >= 201703L
5467 /**
5468 * @brief Find position of a character of a string_view.
5469 * @param __svt An object convertible to string_view containing
5470 * characters to locate.
5471 * @param __pos Index of character to search from (default 0).
5472 * @return Index of first occurrence.
5473 */
5474 template<typename _Tp>
5475 _If_sv<_Tp, size_type>
5476 find_first_of(const _Tp& __svt, size_type __pos = 0) const
5477 noexcept(is_same<_Tp, __sv_type>::value)
5478 {
5479 __sv_type __sv = __svt;
5480 return this->find_first_of(__sv.data(), __pos, __sv.size());
5481 }
5482#endif // C++17
5483
5484 /**
5485 * @brief Find last position of a character of string.
5486 * @param __str String containing characters to locate.
5487 * @param __pos Index of character to search back from (default end).
5488 * @return Index of last occurrence.
5489 *
5490 * Starting from @a __pos, searches backward for one of the
5491 * characters of @a __str within this string. If found,
5492 * returns the index where it was found. If not found, returns
5493 * npos.
5494 */
5495 size_type
5496 find_last_of(const basic_string& __str, size_type __pos = npos) const
5497 _GLIBCXX_NOEXCEPTnoexcept
5498 { return this->find_last_of(__str.data(), __pos, __str.size()); }
5499
5500 /**
5501 * @brief Find last position of a character of C substring.
5502 * @param __s C string containing characters to locate.
5503 * @param __pos Index of character to search back from.
5504 * @param __n Number of characters from s to search for.
5505 * @return Index of last occurrence.
5506 *
5507 * Starting from @a __pos, searches backward for one of the
5508 * first @a __n characters of @a __s within this string. If
5509 * found, returns the index where it was found. If not found,
5510 * returns npos.
5511 */
5512 size_type
5513 find_last_of(const _CharT* __s, size_type __pos, size_type __n) const
5514 _GLIBCXX_NOEXCEPTnoexcept;
5515
5516 /**
5517 * @brief Find last position of a character of C string.
5518 * @param __s C string containing characters to locate.
5519 * @param __pos Index of character to search back from (default end).
5520 * @return Index of last occurrence.
5521 *
5522 * Starting from @a __pos, searches backward for one of the
5523 * characters of @a __s within this string. If found, returns
5524 * the index where it was found. If not found, returns npos.
5525 */
5526 size_type
5527 find_last_of(const _CharT* __s, size_type __pos = npos) const
5528 _GLIBCXX_NOEXCEPTnoexcept
5529 {
5530 __glibcxx_requires_string(__s);
5531 return this->find_last_of(__s, __pos, traits_type::length(__s));
5532 }
5533
5534 /**
5535 * @brief Find last position of a character.
5536 * @param __c Character to locate.
5537 * @param __pos Index of character to search back from (default end).
5538 * @return Index of last occurrence.
5539 *
5540 * Starting from @a __pos, searches backward for @a __c within
5541 * this string. If found, returns the index where it was
5542 * found. If not found, returns npos.
5543 *
5544 * Note: equivalent to rfind(__c, __pos).
5545 */
5546 size_type
5547 find_last_of(_CharT __c, size_type __pos = npos) const _GLIBCXX_NOEXCEPTnoexcept
5548 { return this->rfind(__c, __pos); }
5549
5550#if __cplusplus201703L >= 201703L
5551 /**
5552 * @brief Find last position of a character of string.
5553 * @param __svt An object convertible to string_view containing
5554 * characters to locate.
5555 * @param __pos Index of character to search back from (default end).
5556 * @return Index of last occurrence.
5557 */
5558 template<typename _Tp>
5559 _If_sv<_Tp, size_type>
5560 find_last_of(const _Tp& __svt, size_type __pos = npos) const
5561 noexcept(is_same<_Tp, __sv_type>::value)
5562 {
5563 __sv_type __sv = __svt;
5564 return this->find_last_of(__sv.data(), __pos, __sv.size());
5565 }
5566#endif // C++17
5567
5568 /**
5569 * @brief Find position of a character not in string.
5570 * @param __str String containing characters to avoid.
5571 * @param __pos Index of character to search from (default 0).
5572 * @return Index of first occurrence.
5573 *
5574 * Starting from @a __pos, searches forward for a character not contained
5575 * in @a __str within this string. If found, returns the index where it
5576 * was found. If not found, returns npos.
5577 */
5578 size_type
5579 find_first_not_of(const basic_string& __str, size_type __pos = 0) const
5580 _GLIBCXX_NOEXCEPTnoexcept
5581 { return this->find_first_not_of(__str.data(), __pos, __str.size()); }
5582
5583 /**
5584 * @brief Find position of a character not in C substring.
5585 * @param __s C string containing characters to avoid.
5586 * @param __pos Index of character to search from.
5587 * @param __n Number of characters from __s to consider.
5588 * @return Index of first occurrence.
5589 *
5590 * Starting from @a __pos, searches forward for a character not
5591 * contained in the first @a __n characters of @a __s within
5592 * this string. If found, returns the index where it was
5593 * found. If not found, returns npos.
5594 */
5595 size_type
5596 find_first_not_of(const _CharT* __s, size_type __pos,
5597 size_type __n) const _GLIBCXX_NOEXCEPTnoexcept;
5598
5599 /**
5600 * @brief Find position of a character not in C string.
5601 * @param __s C string containing characters to avoid.
5602 * @param __pos Index of character to search from (default 0).
5603 * @return Index of first occurrence.
5604 *
5605 * Starting from @a __pos, searches forward for a character not
5606 * contained in @a __s within this string. If found, returns
5607 * the index where it was found. If not found, returns npos.
5608 */
5609 size_type
5610 find_first_not_of(const _CharT* __s, size_type __pos = 0) const
5611 _GLIBCXX_NOEXCEPTnoexcept
5612 {
5613 __glibcxx_requires_string(__s);
5614 return this->find_first_not_of(__s, __pos, traits_type::length(__s));
5615 }
5616
5617 /**
5618 * @brief Find position of a different character.
5619 * @param __c Character to avoid.
5620 * @param __pos Index of character to search from (default 0).
5621 * @return Index of first occurrence.
5622 *
5623 * Starting from @a __pos, searches forward for a character
5624 * other than @a __c within this string. If found, returns the
5625 * index where it was found. If not found, returns npos.
5626 */
5627 size_type
5628 find_first_not_of(_CharT __c, size_type __pos = 0) const
5629 _GLIBCXX_NOEXCEPTnoexcept;
5630
5631#if __cplusplus201703L >= 201703L
5632 /**
5633 * @brief Find position of a character not in a string_view.
5634 * @param __svt An object convertible to string_view containing
5635 * characters to avoid.
5636 * @param __pos Index of character to search from (default 0).
5637 * @return Index of first occurrence.
5638 */
5639 template<typename _Tp>
5640 _If_sv<_Tp, size_type>
5641 find_first_not_of(const _Tp& __svt, size_type __pos = 0) const
5642 noexcept(is_same<_Tp, __sv_type>::value)
5643 {
5644 __sv_type __sv = __svt;
5645 return this->find_first_not_of(__sv.data(), __pos, __sv.size());
5646 }
5647#endif // C++17
5648
5649 /**
5650 * @brief Find last position of a character not in string.
5651 * @param __str String containing characters to avoid.
5652 * @param __pos Index of character to search back from (default end).
5653 * @return Index of last occurrence.
5654 *
5655 * Starting from @a __pos, searches backward for a character
5656 * not contained in @a __str within this string. If found,
5657 * returns the index where it was found. If not found, returns
5658 * npos.
5659 */
5660 size_type
5661 find_last_not_of(const basic_string& __str, size_type __pos = npos) const
5662 _GLIBCXX_NOEXCEPTnoexcept
5663 { return this->find_last_not_of(__str.data(), __pos, __str.size()); }
5664
5665 /**
5666 * @brief Find last position of a character not in C substring.
5667 * @param __s C string containing characters to avoid.
5668 * @param __pos Index of character to search back from.
5669 * @param __n Number of characters from s to consider.
5670 * @return Index of last occurrence.
5671 *
5672 * Starting from @a __pos, searches backward for a character not
5673 * contained in the first @a __n characters of @a __s within this string.
5674 * If found, returns the index where it was found. If not found,
5675 * returns npos.
5676 */
5677 size_type
5678 find_last_not_of(const _CharT* __s, size_type __pos,
5679 size_type __n) const _GLIBCXX_NOEXCEPTnoexcept;
5680 /**
5681 * @brief Find last position of a character not in C string.
5682 * @param __s C string containing characters to avoid.
5683 * @param __pos Index of character to search back from (default end).
5684 * @return Index of last occurrence.
5685 *
5686 * Starting from @a __pos, searches backward for a character
5687 * not contained in @a __s within this string. If found,
5688 * returns the index where it was found. If not found, returns
5689 * npos.
5690 */
5691 size_type
5692 find_last_not_of(const _CharT* __s, size_type __pos = npos) const
5693 _GLIBCXX_NOEXCEPTnoexcept
5694 {
5695 __glibcxx_requires_string(__s);
5696 return this->find_last_not_of(__s, __pos, traits_type::length(__s));
5697 }
5698
5699 /**
5700 * @brief Find last position of a different character.
5701 * @param __c Character to avoid.
5702 * @param __pos Index of character to search back from (default end).
5703 * @return Index of last occurrence.
5704 *
5705 * Starting from @a __pos, searches backward for a character other than
5706 * @a __c within this string. If found, returns the index where it was
5707 * found. If not found, returns npos.
5708 */
5709 size_type
5710 find_last_not_of(_CharT __c, size_type __pos = npos) const
5711 _GLIBCXX_NOEXCEPTnoexcept;
5712
5713#if __cplusplus201703L >= 201703L
5714 /**
5715 * @brief Find last position of a character not in a string_view.
5716 * @param __svt An object convertible to string_view containing
5717 * characters to avoid.
5718 * @param __pos Index of character to search back from (default end).
5719 * @return Index of last occurrence.
5720 */
5721 template<typename _Tp>
5722 _If_sv<_Tp, size_type>
5723 find_last_not_of(const _Tp& __svt, size_type __pos = npos) const
5724 noexcept(is_same<_Tp, __sv_type>::value)
5725 {
5726 __sv_type __sv = __svt;
5727 return this->find_last_not_of(__sv.data(), __pos, __sv.size());
5728 }
5729#endif // C++17
5730
5731 /**
5732 * @brief Get a substring.
5733 * @param __pos Index of first character (default 0).
5734 * @param __n Number of characters in substring (default remainder).
5735 * @return The new string.
5736 * @throw std::out_of_range If __pos > size().
5737 *
5738 * Construct and return a new string using the @a __n
5739 * characters starting at @a __pos. If the string is too
5740 * short, use the remainder of the characters. If @a __pos is
5741 * beyond the end of the string, out_of_range is thrown.
5742 */
5743 basic_string
5744 substr(size_type __pos = 0, size_type __n = npos) const
5745 { return basic_string(*this,
5746 _M_check(__pos, "basic_string::substr"), __n); }
5747
5748 /**
5749 * @brief Compare to a string.
5750 * @param __str String to compare against.
5751 * @return Integer < 0, 0, or > 0.
5752 *
5753 * Returns an integer < 0 if this string is ordered before @a
5754 * __str, 0 if their values are equivalent, or > 0 if this
5755 * string is ordered after @a __str. Determines the effective
5756 * length rlen of the strings to compare as the smallest of
5757 * size() and str.size(). The function then compares the two
5758 * strings by calling traits::compare(data(), str.data(),rlen).
5759 * If the result of the comparison is nonzero returns it,
5760 * otherwise the shorter one is ordered first.
5761 */
5762 int
5763 compare(const basic_string& __str) const
5764 {
5765 const size_type __size = this->size();
5766 const size_type __osize = __str.size();
5767 const size_type __len = std::min(__size, __osize);
5768
5769 int __r = traits_type::compare(_M_data(), __str.data(), __len);
5770 if (!__r)
5771 __r = _S_compare(__size, __osize);
5772 return __r;
5773 }
5774
5775#if __cplusplus201703L >= 201703L
5776 /**
5777 * @brief Compare to a string_view.
5778 * @param __svt An object convertible to string_view to compare against.
5779 * @return Integer < 0, 0, or > 0.
5780 */
5781 template<typename _Tp>
5782 _If_sv<_Tp, int>
5783 compare(const _Tp& __svt) const
5784 noexcept(is_same<_Tp, __sv_type>::value)
5785 {
5786 __sv_type __sv = __svt;
5787 const size_type __size = this->size();
5788 const size_type __osize = __sv.size();
5789 const size_type __len = std::min(__size, __osize);
5790
5791 int __r = traits_type::compare(_M_data(), __sv.data(), __len);
5792 if (!__r)
5793 __r = _S_compare(__size, __osize);
5794 return __r;
5795 }
5796
5797 /**
5798 * @brief Compare to a string_view.
5799 * @param __pos A position in the string to start comparing from.
5800 * @param __n The number of characters to compare.
5801 * @param __svt An object convertible to string_view to compare
5802 * against.
5803 * @return Integer < 0, 0, or > 0.
5804 */
5805 template<typename _Tp>
5806 _If_sv<_Tp, int>
5807 compare(size_type __pos, size_type __n, const _Tp& __svt) const
5808 noexcept(is_same<_Tp, __sv_type>::value)
5809 {
5810 __sv_type __sv = __svt;
5811 return __sv_type(*this).substr(__pos, __n).compare(__sv);
5812 }
5813
5814 /**
5815 * @brief Compare to a string_view.
5816 * @param __pos1 A position in the string to start comparing from.
5817 * @param __n1 The number of characters to compare.
5818 * @param __svt An object convertible to string_view to compare
5819 * against.
5820 * @param __pos2 A position in the string_view to start comparing from.
5821 * @param __n2 The number of characters to compare.
5822 * @return Integer < 0, 0, or > 0.
5823 */
5824 template<typename _Tp>
5825 _If_sv<_Tp, int>
5826 compare(size_type __pos1, size_type __n1, const _Tp& __svt,
5827 size_type __pos2, size_type __n2 = npos) const
5828 noexcept(is_same<_Tp, __sv_type>::value)
5829 {
5830 __sv_type __sv = __svt;
5831 return __sv_type(*this)
5832 .substr(__pos1, __n1).compare(__sv.substr(__pos2, __n2));
5833 }
5834#endif // C++17
5835
5836 /**
5837 * @brief Compare substring to a string.
5838 * @param __pos Index of first character of substring.
5839 * @param __n Number of characters in substring.
5840 * @param __str String to compare against.
5841 * @return Integer < 0, 0, or > 0.
5842 *
5843 * Form the substring of this string from the @a __n characters
5844 * starting at @a __pos. Returns an integer < 0 if the
5845 * substring is ordered before @a __str, 0 if their values are
5846 * equivalent, or > 0 if the substring is ordered after @a
5847 * __str. Determines the effective length rlen of the strings
5848 * to compare as the smallest of the length of the substring
5849 * and @a __str.size(). The function then compares the two
5850 * strings by calling
5851 * traits::compare(substring.data(),str.data(),rlen). If the
5852 * result of the comparison is nonzero returns it, otherwise
5853 * the shorter one is ordered first.
5854 */
5855 int
5856 compare(size_type __pos, size_type __n, const basic_string& __str) const;
5857
5858 /**
5859 * @brief Compare substring to a substring.
5860 * @param __pos1 Index of first character of substring.
5861 * @param __n1 Number of characters in substring.
5862 * @param __str String to compare against.
5863 * @param __pos2 Index of first character of substring of str.
5864 * @param __n2 Number of characters in substring of str.
5865 * @return Integer < 0, 0, or > 0.
5866 *
5867 * Form the substring of this string from the @a __n1
5868 * characters starting at @a __pos1. Form the substring of @a
5869 * __str from the @a __n2 characters starting at @a __pos2.
5870 * Returns an integer < 0 if this substring is ordered before
5871 * the substring of @a __str, 0 if their values are equivalent,
5872 * or > 0 if this substring is ordered after the substring of
5873 * @a __str. Determines the effective length rlen of the
5874 * strings to compare as the smallest of the lengths of the
5875 * substrings. The function then compares the two strings by
5876 * calling
5877 * traits::compare(substring.data(),str.substr(pos2,n2).data(),rlen).
5878 * If the result of the comparison is nonzero returns it,
5879 * otherwise the shorter one is ordered first.
5880 */
5881 int
5882 compare(size_type __pos1, size_type __n1, const basic_string& __str,
5883 size_type __pos2, size_type __n2 = npos) const;
5884
5885 /**
5886 * @brief Compare to a C string.
5887 * @param __s C string to compare against.
5888 * @return Integer < 0, 0, or > 0.
5889 *
5890 * Returns an integer < 0 if this string is ordered before @a __s, 0 if
5891 * their values are equivalent, or > 0 if this string is ordered after
5892 * @a __s. Determines the effective length rlen of the strings to
5893 * compare as the smallest of size() and the length of a string
5894 * constructed from @a __s. The function then compares the two strings
5895 * by calling traits::compare(data(),s,rlen). If the result of the
5896 * comparison is nonzero returns it, otherwise the shorter one is
5897 * ordered first.
5898 */
5899 int
5900 compare(const _CharT* __s) const _GLIBCXX_NOEXCEPTnoexcept;
5901
5902 // _GLIBCXX_RESOLVE_LIB_DEFECTS
5903 // 5 String::compare specification questionable
5904 /**
5905 * @brief Compare substring to a C string.
5906 * @param __pos Index of first character of substring.
5907 * @param __n1 Number of characters in substring.
5908 * @param __s C string to compare against.
5909 * @return Integer < 0, 0, or > 0.
5910 *
5911 * Form the substring of this string from the @a __n1
5912 * characters starting at @a pos. Returns an integer < 0 if
5913 * the substring is ordered before @a __s, 0 if their values
5914 * are equivalent, or > 0 if the substring is ordered after @a
5915 * __s. Determines the effective length rlen of the strings to
5916 * compare as the smallest of the length of the substring and
5917 * the length of a string constructed from @a __s. The
5918 * function then compares the two string by calling
5919 * traits::compare(substring.data(),__s,rlen). If the result of
5920 * the comparison is nonzero returns it, otherwise the shorter
5921 * one is ordered first.
5922 */
5923 int
5924 compare(size_type __pos, size_type __n1, const _CharT* __s) const;
5925
5926 /**
5927 * @brief Compare substring against a character %array.
5928 * @param __pos Index of first character of substring.
5929 * @param __n1 Number of characters in substring.
5930 * @param __s character %array to compare against.
5931 * @param __n2 Number of characters of s.
5932 * @return Integer < 0, 0, or > 0.
5933 *
5934 * Form the substring of this string from the @a __n1
5935 * characters starting at @a __pos. Form a string from the
5936 * first @a __n2 characters of @a __s. Returns an integer < 0
5937 * if this substring is ordered before the string from @a __s,
5938 * 0 if their values are equivalent, or > 0 if this substring
5939 * is ordered after the string from @a __s. Determines the
5940 * effective length rlen of the strings to compare as the
5941 * smallest of the length of the substring and @a __n2. The
5942 * function then compares the two strings by calling
5943 * traits::compare(substring.data(),s,rlen). If the result of
5944 * the comparison is nonzero returns it, otherwise the shorter
5945 * one is ordered first.
5946 *
5947 * NB: s must have at least n2 characters, &apos;\\0&apos; has
5948 * no special meaning.
5949 */
5950 int
5951 compare(size_type __pos, size_type __n1, const _CharT* __s,
5952 size_type __n2) const;
5953
5954#if __cplusplus201703L > 201703L
5955 bool
5956 starts_with(basic_string_view<_CharT, _Traits> __x) const noexcept
5957 { return __sv_type(this->data(), this->size()).starts_with(__x); }
5958
5959 bool
5960 starts_with(_CharT __x) const noexcept
5961 { return __sv_type(this->data(), this->size()).starts_with(__x); }
5962
5963 bool
5964 starts_with(const _CharT* __x) const noexcept
5965 { return __sv_type(this->data(), this->size()).starts_with(__x); }
5966
5967 bool
5968 ends_with(basic_string_view<_CharT, _Traits> __x) const noexcept
5969 { return __sv_type(this->data(), this->size()).ends_with(__x); }
5970
5971 bool
5972 ends_with(_CharT __x) const noexcept
5973 { return __sv_type(this->data(), this->size()).ends_with(__x); }
5974
5975 bool
5976 ends_with(const _CharT* __x) const noexcept
5977 { return __sv_type(this->data(), this->size()).ends_with(__x); }
5978#endif // C++20
5979
5980# ifdef _GLIBCXX_TM_TS_INTERNAL
5981 friend void
5982 ::_txnal_cow_string_C1_for_exceptions(void* that, const char* s,
5983 void* exc);
5984 friend const char*
5985 ::_txnal_cow_string_c_str(const void *that);
5986 friend void
5987 ::_txnal_cow_string_D1(void *that);
5988 friend void
5989 ::_txnal_cow_string_D1_commit(void *that);
5990# endif
5991 };
5992#endif // !_GLIBCXX_USE_CXX11_ABI
5993
5994#if __cpp_deduction_guides201703L >= 201606
5995_GLIBCXX_BEGIN_NAMESPACE_CXX11namespace __cxx11 {
5996 template<typename _InputIterator, typename _CharT
5997 = typename iterator_traits<_InputIterator>::value_type,
5998 typename _Allocator = allocator<_CharT>,
5999 typename = _RequireInputIter<_InputIterator>,
6000 typename = _RequireAllocator<_Allocator>>
6001 basic_string(_InputIterator, _InputIterator, _Allocator = _Allocator())
6002 -> basic_string<_CharT, char_traits<_CharT>, _Allocator>;
6003
6004 // _GLIBCXX_RESOLVE_LIB_DEFECTS
6005 // 3075. basic_string needs deduction guides from basic_string_view
6006 template<typename _CharT, typename _Traits,
6007 typename _Allocator = allocator<_CharT>,
6008 typename = _RequireAllocator<_Allocator>>
6009 basic_string(basic_string_view<_CharT, _Traits>, const _Allocator& = _Allocator())
6010 -> basic_string<_CharT, _Traits, _Allocator>;
6011
6012 template<typename _CharT, typename _Traits,
6013 typename _Allocator = allocator<_CharT>,
6014 typename = _RequireAllocator<_Allocator>>
6015 basic_string(basic_string_view<_CharT, _Traits>,
6016 typename basic_string<_CharT, _Traits, _Allocator>::size_type,
6017 typename basic_string<_CharT, _Traits, _Allocator>::size_type,
6018 const _Allocator& = _Allocator())
6019 -> basic_string<_CharT, _Traits, _Allocator>;
6020_GLIBCXX_END_NAMESPACE_CXX11}
6021#endif
6022
6023 // operator+
6024 /**
6025 * @brief Concatenate two strings.
6026 * @param __lhs First string.
6027 * @param __rhs Last string.
6028 * @return New string with value of @a __lhs followed by @a __rhs.
6029 */
6030 template<typename _CharT, typename _Traits, typename _Alloc>
6031 basic_string<_CharT, _Traits, _Alloc>
6032 operator+(const basic_string<_CharT, _Traits, _Alloc>& __lhs,
6033 const basic_string<_CharT, _Traits, _Alloc>& __rhs)
6034 {
6035 basic_string<_CharT, _Traits, _Alloc> __str(__lhs);
6036 __str.append(__rhs);
6037 return __str;
6038 }
6039
6040 /**
6041 * @brief Concatenate C string and string.
6042 * @param __lhs First string.
6043 * @param __rhs Last string.
6044 * @return New string with value of @a __lhs followed by @a __rhs.
6045 */
6046 template<typename _CharT, typename _Traits, typename _Alloc>
6047 basic_string<_CharT,_Traits,_Alloc>
6048 operator+(const _CharT* __lhs,
6049 const basic_string<_CharT,_Traits,_Alloc>& __rhs);
6050
6051 /**
6052 * @brief Concatenate character and string.
6053 * @param __lhs First string.
6054 * @param __rhs Last string.
6055 * @return New string with @a __lhs followed by @a __rhs.
6056 */
6057 template<typename _CharT, typename _Traits, typename _Alloc>
6058 basic_string<_CharT,_Traits,_Alloc>
6059 operator+(_CharT __lhs, const basic_string<_CharT,_Traits,_Alloc>& __rhs);
6060
6061 /**
6062 * @brief Concatenate string and C string.
6063 * @param __lhs First string.
6064 * @param __rhs Last string.
6065 * @return New string with @a __lhs followed by @a __rhs.
6066 */
6067 template<typename _CharT, typename _Traits, typename _Alloc>
6068 inline basic_string<_CharT, _Traits, _Alloc>
6069 operator+(const basic_string<_CharT, _Traits, _Alloc>& __lhs,
6070 const _CharT* __rhs)
6071 {
6072 basic_string<_CharT, _Traits, _Alloc> __str(__lhs);
6073 __str.append(__rhs);
6074 return __str;
6075 }
6076
6077 /**
6078 * @brief Concatenate string and character.
6079 * @param __lhs First string.
6080 * @param __rhs Last string.
6081 * @return New string with @a __lhs followed by @a __rhs.
6082 */
6083 template<typename _CharT, typename _Traits, typename _Alloc>
6084 inline basic_string<_CharT, _Traits, _Alloc>
6085 operator+(const basic_string<_CharT, _Traits, _Alloc>& __lhs, _CharT __rhs)
6086 {
6087 typedef basic_string<_CharT, _Traits, _Alloc> __string_type;
6088 typedef typename __string_type::size_type __size_type;
6089 __string_type __str(__lhs);
6090 __str.append(__size_type(1), __rhs);
6091 return __str;
6092 }
6093
6094#if __cplusplus201703L >= 201103L
6095 template<typename _CharT, typename _Traits, typename _Alloc>
6096 inline basic_string<_CharT, _Traits, _Alloc>
6097 operator+(basic_string<_CharT, _Traits, _Alloc>&& __lhs,
6098 const basic_string<_CharT, _Traits, _Alloc>& __rhs)
6099 { return std::move(__lhs.append(__rhs)); }
6100
6101 template<typename _CharT, typename _Traits, typename _Alloc>
6102 inline basic_string<_CharT, _Traits, _Alloc>
6103 operator+(const basic_string<_CharT, _Traits, _Alloc>& __lhs,
6104 basic_string<_CharT, _Traits, _Alloc>&& __rhs)
6105 { return std::move(__rhs.insert(0, __lhs)); }
6106
6107 template<typename _CharT, typename _Traits, typename _Alloc>
6108 inline basic_string<_CharT, _Traits, _Alloc>
6109 operator+(basic_string<_CharT, _Traits, _Alloc>&& __lhs,
6110 basic_string<_CharT, _Traits, _Alloc>&& __rhs)
6111 {
6112#if _GLIBCXX_USE_CXX11_ABI1
6113 using _Alloc_traits = allocator_traits<_Alloc>;
6114 bool __use_rhs = false;
6115 if _GLIBCXX17_CONSTEXPRconstexpr (typename _Alloc_traits::is_always_equal{})
6116 __use_rhs = true;
6117 else if (__lhs.get_allocator() == __rhs.get_allocator())
6118 __use_rhs = true;
6119 if (__use_rhs)
6120#endif
6121 {
6122 const auto __size = __lhs.size() + __rhs.size();
6123 if (__size > __lhs.capacity() && __size <= __rhs.capacity())
6124 return std::move(__rhs.insert(0, __lhs));
6125 }
6126 return std::move(__lhs.append(__rhs));
6127 }
6128
6129 template<typename _CharT, typename _Traits, typename _Alloc>
6130 inline basic_string<_CharT, _Traits, _Alloc>
6131 operator+(const _CharT* __lhs,
6132 basic_string<_CharT, _Traits, _Alloc>&& __rhs)
6133 { return std::move(__rhs.insert(0, __lhs)); }
6134
6135 template<typename _CharT, typename _Traits, typename _Alloc>
6136 inline basic_string<_CharT, _Traits, _Alloc>
6137 operator+(_CharT __lhs,
6138 basic_string<_CharT, _Traits, _Alloc>&& __rhs)
6139 { return std::move(__rhs.insert(0, 1, __lhs)); }
6140
6141 template<typename _CharT, typename _Traits, typename _Alloc>
6142 inline basic_string<_CharT, _Traits, _Alloc>
6143 operator+(basic_string<_CharT, _Traits, _Alloc>&& __lhs,
6144 const _CharT* __rhs)
6145 { return std::move(__lhs.append(__rhs)); }
6146
6147 template<typename _CharT, typename _Traits, typename _Alloc>
6148 inline basic_string<_CharT, _Traits, _Alloc>
6149 operator+(basic_string<_CharT, _Traits, _Alloc>&& __lhs,
6150 _CharT __rhs)
6151 { return std::move(__lhs.append(1, __rhs)); }
6152#endif
6153
6154 // operator ==
6155 /**
6156 * @brief Test equivalence of two strings.
6157 * @param __lhs First string.
6158 * @param __rhs Second string.
6159 * @return True if @a __lhs.compare(@a __rhs) == 0. False otherwise.
6160 */
6161 template<typename _CharT, typename _Traits, typename _Alloc>
6162 inline bool
6163 operator==(const basic_string<_CharT, _Traits, _Alloc>& __lhs,
6164 const basic_string<_CharT, _Traits, _Alloc>& __rhs)
6165 _GLIBCXX_NOEXCEPTnoexcept
6166 { return __lhs.compare(__rhs) == 0; }
6167
6168 template<typename _CharT>
6169 inline
6170 typename __gnu_cxx::__enable_if<__is_char<_CharT>::__value, bool>::__type
6171 operator==(const basic_string<_CharT>& __lhs,
6172 const basic_string<_CharT>& __rhs) _GLIBCXX_NOEXCEPTnoexcept
6173 { return (__lhs.size() == __rhs.size()
6174 && !std::char_traits<_CharT>::compare(__lhs.data(), __rhs.data(),
6175 __lhs.size())); }
6176
6177 /**
6178 * @brief Test equivalence of string and C string.
6179 * @param __lhs String.
6180 * @param __rhs C string.
6181 * @return True if @a __lhs.compare(@a __rhs) == 0. False otherwise.
6182 */
6183 template<typename _CharT, typename _Traits, typename _Alloc>
6184 inline bool
6185 operator==(const basic_string<_CharT, _Traits, _Alloc>& __lhs,
6186 const _CharT* __rhs)
6187 { return __lhs.compare(__rhs) == 0; }
6188
6189#if __cpp_lib_three_way_comparison
6190 /**
6191 * @brief Three-way comparison of a string and a C string.
6192 * @param __lhs A string.
6193 * @param __rhs A null-terminated string.
6194 * @return A value indicating whether `__lhs` is less than, equal to,
6195 * greater than, or incomparable with `__rhs`.
6196 */
6197 template<typename _CharT, typename _Traits, typename _Alloc>
6198 inline auto
6199 operator<=>(const basic_string<_CharT, _Traits, _Alloc>& __lhs,
6200 const basic_string<_CharT, _Traits, _Alloc>& __rhs) noexcept
6201 -> decltype(__detail::__char_traits_cmp_cat<_Traits>(0))
6202 { return __detail::__char_traits_cmp_cat<_Traits>(__lhs.compare(__rhs)); }
6203
6204 /**
6205 * @brief Three-way comparison of a string and a C string.
6206 * @param __lhs A string.
6207 * @param __rhs A null-terminated string.
6208 * @return A value indicating whether `__lhs` is less than, equal to,
6209 * greater than, or incomparable with `__rhs`.
6210 */
6211 template<typename _CharT, typename _Traits, typename _Alloc>
6212 inline auto
6213 operator<=>(const basic_string<_CharT, _Traits, _Alloc>& __lhs,
6214 const _CharT* __rhs) noexcept
6215 -> decltype(__detail::__char_traits_cmp_cat<_Traits>(0))
6216 { return __detail::__char_traits_cmp_cat<_Traits>(__lhs.compare(__rhs)); }
6217#else
6218 /**
6219 * @brief Test equivalence of C string and string.
6220 * @param __lhs C string.
6221 * @param __rhs String.
6222 * @return True if @a __rhs.compare(@a __lhs) == 0. False otherwise.
6223 */
6224 template<typename _CharT, typename _Traits, typename _Alloc>
6225 inline bool
6226 operator==(const _CharT* __lhs,
6227 const basic_string<_CharT, _Traits, _Alloc>& __rhs)
6228 { return __rhs.compare(__lhs) == 0; }
6229
6230 // operator !=
6231 /**
6232 * @brief Test difference of two strings.
6233 * @param __lhs First string.
6234 * @param __rhs Second string.
6235 * @return True if @a __lhs.compare(@a __rhs) != 0. False otherwise.
6236 */
6237 template<typename _CharT, typename _Traits, typename _Alloc>
6238 inline bool
6239 operator!=(const basic_string<_CharT, _Traits, _Alloc>& __lhs,
6240 const basic_string<_CharT, _Traits, _Alloc>& __rhs)
6241 _GLIBCXX_NOEXCEPTnoexcept
6242 { return !(__lhs == __rhs); }
6243
6244 /**
6245 * @brief Test difference of C string and string.
6246 * @param __lhs C string.
6247 * @param __rhs String.
6248 * @return True if @a __rhs.compare(@a __lhs) != 0. False otherwise.
6249 */
6250 template<typename _CharT, typename _Traits, typename _Alloc>
6251 inline bool
6252 operator!=(const _CharT* __lhs,
6253 const basic_string<_CharT, _Traits, _Alloc>& __rhs)
6254 { return !(__lhs == __rhs); }
6255
6256 /**
6257 * @brief Test difference of string and C string.
6258 * @param __lhs String.
6259 * @param __rhs C string.
6260 * @return True if @a __lhs.compare(@a __rhs) != 0. False otherwise.
6261 */
6262 template<typename _CharT, typename _Traits, typename _Alloc>
6263 inline bool
6264 operator!=(const basic_string<_CharT, _Traits, _Alloc>& __lhs,
6265 const _CharT* __rhs)
6266 { return !(__lhs == __rhs); }
6267
6268 // operator <
6269 /**
6270 * @brief Test if string precedes string.
6271 * @param __lhs First string.
6272 * @param __rhs Second string.
6273 * @return True if @a __lhs precedes @a __rhs. False otherwise.
6274 */
6275 template<typename _CharT, typename _Traits, typename _Alloc>
6276 inline bool
6277 operator<(const basic_string<_CharT, _Traits, _Alloc>& __lhs,
6278 const basic_string<_CharT, _Traits, _Alloc>& __rhs)
6279 _GLIBCXX_NOEXCEPTnoexcept
6280 { return __lhs.compare(__rhs) < 0; }
6281
6282 /**
6283 * @brief Test if string precedes C string.
6284 * @param __lhs String.
6285 * @param __rhs C string.
6286 * @return True if @a __lhs precedes @a __rhs. False otherwise.
6287 */
6288 template<typename _CharT, typename _Traits, typename _Alloc>
6289 inline bool
6290 operator<(const basic_string<_CharT, _Traits, _Alloc>& __lhs,
6291 const _CharT* __rhs)
6292 { return __lhs.compare(__rhs) < 0; }
6293
6294 /**
6295 * @brief Test if C string precedes string.
6296 * @param __lhs C string.
6297 * @param __rhs String.
6298 * @return True if @a __lhs precedes @a __rhs. False otherwise.
6299 */
6300 template<typename _CharT, typename _Traits, typename _Alloc>
6301 inline bool
6302 operator<(const _CharT* __lhs,
6303 const basic_string<_CharT, _Traits, _Alloc>& __rhs)
6304 { return __rhs.compare(__lhs) > 0; }
6305
6306 // operator >
6307 /**
6308 * @brief Test if string follows string.
6309 * @param __lhs First string.
6310 * @param __rhs Second string.
6311 * @return True if @a __lhs follows @a __rhs. False otherwise.
6312 */
6313 template<typename _CharT, typename _Traits, typename _Alloc>
6314 inline bool
6315 operator>(const basic_string<_CharT, _Traits, _Alloc>& __lhs,
6316 const basic_string<_CharT, _Traits, _Alloc>& __rhs)
6317 _GLIBCXX_NOEXCEPTnoexcept
6318 { return __lhs.compare(__rhs) > 0; }
6319
6320 /**
6321 * @brief Test if string follows C string.
6322 * @param __lhs String.
6323 * @param __rhs C string.
6324 * @return True if @a __lhs follows @a __rhs. False otherwise.
6325 */
6326 template<typename _CharT, typename _Traits, typename _Alloc>
6327 inline bool
6328 operator>(const basic_string<_CharT, _Traits, _Alloc>& __lhs,
6329 const _CharT* __rhs)
6330 { return __lhs.compare(__rhs) > 0; }
6331
6332 /**
6333 * @brief Test if C string follows string.
6334 * @param __lhs C string.
6335 * @param __rhs String.
6336 * @return True if @a __lhs follows @a __rhs. False otherwise.
6337 */
6338 template<typename _CharT, typename _Traits, typename _Alloc>
6339 inline bool
6340 operator>(const _CharT* __lhs,
6341 const basic_string<_CharT, _Traits, _Alloc>& __rhs)
6342 { return __rhs.compare(__lhs) < 0; }
6343
6344 // operator <=
6345 /**
6346 * @brief Test if string doesn't follow string.
6347 * @param __lhs First string.
6348 * @param __rhs Second string.
6349 * @return True if @a __lhs doesn't follow @a __rhs. False otherwise.
6350 */
6351 template<typename _CharT, typename _Traits, typename _Alloc>
6352 inline bool
6353 operator<=(const basic_string<_CharT, _Traits, _Alloc>& __lhs,
6354 const basic_string<_CharT, _Traits, _Alloc>& __rhs)
6355 _GLIBCXX_NOEXCEPTnoexcept
6356 { return __lhs.compare(__rhs) <= 0; }
6357
6358 /**
6359 * @brief Test if string doesn't follow C string.
6360 * @param __lhs String.
6361 * @param __rhs C string.
6362 * @return True if @a __lhs doesn't follow @a __rhs. False otherwise.
6363 */
6364 template<typename _CharT, typename _Traits, typename _Alloc>
6365 inline bool
6366 operator<=(const basic_string<_CharT, _Traits, _Alloc>& __lhs,
6367 const _CharT* __rhs)
6368 { return __lhs.compare(__rhs) <= 0; }
6369
6370 /**
6371 * @brief Test if C string doesn't follow string.
6372 * @param __lhs C string.
6373 * @param __rhs String.
6374 * @return True if @a __lhs doesn't follow @a __rhs. False otherwise.
6375 */
6376 template<typename _CharT, typename _Traits, typename _Alloc>
6377 inline bool
6378 operator<=(const _CharT* __lhs,
6379 const basic_string<_CharT, _Traits, _Alloc>& __rhs)
6380 { return __rhs.compare(__lhs) >= 0; }
6381
6382 // operator >=
6383 /**
6384 * @brief Test if string doesn't precede string.
6385 * @param __lhs First string.
6386 * @param __rhs Second string.
6387 * @return True if @a __lhs doesn't precede @a __rhs. False otherwise.
6388 */
6389 template<typename _CharT, typename _Traits, typename _Alloc>
6390 inline bool
6391 operator>=(const basic_string<_CharT, _Traits, _Alloc>& __lhs,
6392 const basic_string<_CharT, _Traits, _Alloc>& __rhs)
6393 _GLIBCXX_NOEXCEPTnoexcept
6394 { return __lhs.compare(__rhs) >= 0; }
6395
6396 /**
6397 * @brief Test if string doesn't precede C string.
6398 * @param __lhs String.
6399 * @param __rhs C string.
6400 * @return True if @a __lhs doesn't precede @a __rhs. False otherwise.
6401 */
6402 template<typename _CharT, typename _Traits, typename _Alloc>
6403 inline bool
6404 operator>=(const basic_string<_CharT, _Traits, _Alloc>& __lhs,
6405 const _CharT* __rhs)
6406 { return __lhs.compare(__rhs) >= 0; }
6407
6408 /**
6409 * @brief Test if C string doesn't precede string.
6410 * @param __lhs C string.
6411 * @param __rhs String.
6412 * @return True if @a __lhs doesn't precede @a __rhs. False otherwise.
6413 */
6414 template<typename _CharT, typename _Traits, typename _Alloc>
6415 inline bool
6416 operator>=(const _CharT* __lhs,
6417 const basic_string<_CharT, _Traits, _Alloc>& __rhs)
6418 { return __rhs.compare(__lhs) <= 0; }
6419#endif // three-way comparison
6420
6421 /**
6422 * @brief Swap contents of two strings.
6423 * @param __lhs First string.
6424 * @param __rhs Second string.
6425 *
6426 * Exchanges the contents of @a __lhs and @a __rhs in constant time.
6427 */
6428 template<typename _CharT, typename _Traits, typename _Alloc>
6429 inline void
6430 swap(basic_string<_CharT, _Traits, _Alloc>& __lhs,
6431 basic_string<_CharT, _Traits, _Alloc>& __rhs)
6432 _GLIBCXX_NOEXCEPT_IF(noexcept(__lhs.swap(__rhs)))noexcept(noexcept(__lhs.swap(__rhs)))
6433 { __lhs.swap(__rhs); }
6434
6435
6436 /**
6437 * @brief Read stream into a string.
6438 * @param __is Input stream.
6439 * @param __str Buffer to store into.
6440 * @return Reference to the input stream.
6441 *
6442 * Stores characters from @a __is into @a __str until whitespace is
6443 * found, the end of the stream is encountered, or str.max_size()
6444 * is reached. If is.width() is non-zero, that is the limit on the
6445 * number of characters stored into @a __str. Any previous
6446 * contents of @a __str are erased.
6447 */
6448 template<typename _CharT, typename _Traits, typename _Alloc>
6449 basic_istream<_CharT, _Traits>&
6450 operator>>(basic_istream<_CharT, _Traits>& __is,
6451 basic_string<_CharT, _Traits, _Alloc>& __str);
6452
6453 template<>
6454 basic_istream<char>&
6455 operator>>(basic_istream<char>& __is, basic_string<char>& __str);
6456
6457 /**
6458 * @brief Write string to a stream.
6459 * @param __os Output stream.
6460 * @param __str String to write out.
6461 * @return Reference to the output stream.
6462 *
6463 * Output characters of @a __str into os following the same rules as for
6464 * writing a C string.
6465 */
6466 template<typename _CharT, typename _Traits, typename _Alloc>
6467 inline basic_ostream<_CharT, _Traits>&
6468 operator<<(basic_ostream<_CharT, _Traits>& __os,
6469 const basic_string<_CharT, _Traits, _Alloc>& __str)
6470 {
6471 // _GLIBCXX_RESOLVE_LIB_DEFECTS
6472 // 586. string inserter not a formatted function
6473 return __ostream_insert(__os, __str.data(), __str.size());
6474 }
6475
6476 /**
6477 * @brief Read a line from stream into a string.
6478 * @param __is Input stream.
6479 * @param __str Buffer to store into.
6480 * @param __delim Character marking end of line.
6481 * @return Reference to the input stream.
6482 *
6483 * Stores characters from @a __is into @a __str until @a __delim is
6484 * found, the end of the stream is encountered, or str.max_size()
6485 * is reached. Any previous contents of @a __str are erased. If
6486 * @a __delim is encountered, it is extracted but not stored into
6487 * @a __str.
6488 */
6489 template<typename _CharT, typename _Traits, typename _Alloc>
6490 basic_istream<_CharT, _Traits>&
6491 getline(basic_istream<_CharT, _Traits>& __is,
6492 basic_string<_CharT, _Traits, _Alloc>& __str, _CharT __delim);
6493
6494 /**
6495 * @brief Read a line from stream into a string.
6496 * @param __is Input stream.
6497 * @param __str Buffer to store into.
6498 * @return Reference to the input stream.
6499 *
6500 * Stores characters from is into @a __str until &apos;\n&apos; is
6501 * found, the end of the stream is encountered, or str.max_size()
6502 * is reached. Any previous contents of @a __str are erased. If
6503 * end of line is encountered, it is extracted but not stored into
6504 * @a __str.
6505 */
6506 template<typename _CharT, typename _Traits, typename _Alloc>
6507 inline basic_istream<_CharT, _Traits>&
6508 getline(basic_istream<_CharT, _Traits>& __is,
6509 basic_string<_CharT, _Traits, _Alloc>& __str)
6510 { return std::getline(__is, __str, __is.widen('\n')); }
6511
6512#if __cplusplus201703L >= 201103L
6513 /// Read a line from an rvalue stream into a string.
6514 template<typename _CharT, typename _Traits, typename _Alloc>
6515 inline basic_istream<_CharT, _Traits>&
6516 getline(basic_istream<_CharT, _Traits>&& __is,
6517 basic_string<_CharT, _Traits, _Alloc>& __str, _CharT __delim)
6518 { return std::getline(__is, __str, __delim); }
6519
6520 /// Read a line from an rvalue stream into a string.
6521 template<typename _CharT, typename _Traits, typename _Alloc>
6522 inline basic_istream<_CharT, _Traits>&
6523 getline(basic_istream<_CharT, _Traits>&& __is,
6524 basic_string<_CharT, _Traits, _Alloc>& __str)
6525 { return std::getline(__is, __str); }
6526#endif
6527
6528 template<>
6529 basic_istream<char>&
6530 getline(basic_istream<char>& __in, basic_string<char>& __str,
6531 char __delim);
6532
6533#ifdef _GLIBCXX_USE_WCHAR_T1
6534 template<>
6535 basic_istream<wchar_t>&
6536 getline(basic_istream<wchar_t>& __in, basic_string<wchar_t>& __str,
6537 wchar_t __delim);
6538#endif
6539
6540_GLIBCXX_END_NAMESPACE_VERSION
6541} // namespace
6542
6543#if __cplusplus201703L >= 201103L
6544
6545#include <ext/string_conversions.h>
6546#include <bits/charconv.h>
6547
6548namespace std _GLIBCXX_VISIBILITY(default)__attribute__ ((__visibility__ ("default")))
6549{
6550_GLIBCXX_BEGIN_NAMESPACE_VERSION
6551_GLIBCXX_BEGIN_NAMESPACE_CXX11namespace __cxx11 {
6552
6553#if _GLIBCXX_USE_C99_STDLIB1
6554 // 21.4 Numeric Conversions [string.conversions].
6555 inline int
6556 stoi(const string& __str, size_t* __idx = 0, int __base = 10)
6557 { return __gnu_cxx::__stoa<long, int>(&std::strtol, "stoi", __str.c_str(),
6558 __idx, __base); }
6559
6560 inline long
6561 stol(const string& __str, size_t* __idx = 0, int __base = 10)
6562 { return __gnu_cxx::__stoa(&std::strtol, "stol", __str.c_str(),
6563 __idx, __base); }
6564
6565 inline unsigned long
6566 stoul(const string& __str, size_t* __idx = 0, int __base = 10)
6567 { return __gnu_cxx::__stoa(&std::strtoul, "stoul", __str.c_str(),
6568 __idx, __base); }
6569
6570 inline long long
6571 stoll(const string& __str, size_t* __idx = 0, int __base = 10)
6572 { return __gnu_cxx::__stoa(&std::strtoll, "stoll", __str.c_str(),
6573 __idx, __base); }
6574
6575 inline unsigned long long
6576 stoull(const string& __str, size_t* __idx = 0, int __base = 10)
6577 { return __gnu_cxx::__stoa(&std::strtoull, "stoull", __str.c_str(),
6578 __idx, __base); }
6579
6580 // NB: strtof vs strtod.
6581 inline float
6582 stof(const string& __str, size_t* __idx = 0)
6583 { return __gnu_cxx::__stoa(&std::strtof, "stof", __str.c_str(), __idx); }
6584
6585 inline double
6586 stod(const string& __str, size_t* __idx = 0)
6587 { return __gnu_cxx::__stoa(&std::strtod, "stod", __str.c_str(), __idx); }
6588
6589 inline long double
6590 stold(const string& __str, size_t* __idx = 0)
6591 { return __gnu_cxx::__stoa(&std::strtold, "stold", __str.c_str(), __idx); }
6592#endif // _GLIBCXX_USE_C99_STDLIB
6593
6594 // DR 1261. Insufficent overloads for to_string / to_wstring
6595
6596 inline string
6597 to_string(int __val)
6598 {
6599 const bool __neg = __val < 0;
6600 const unsigned __uval = __neg ? (unsigned)~__val + 1u : __val;
6601 const auto __len = __detail::__to_chars_len(__uval);
6602 string __str(__neg + __len, '-');
6603 __detail::__to_chars_10_impl(&__str[__neg], __len, __uval);
6604 return __str;
6605 }
6606
6607 inline string
6608 to_string(unsigned __val)
6609 {
6610 string __str(__detail::__to_chars_len(__val), '\0');
6611 __detail::__to_chars_10_impl(&__str[0], __str.size(), __val);
6612 return __str;
6613 }
6614
6615 inline string
6616 to_string(long __val)
6617 {
6618 const bool __neg = __val < 0;
6619 const unsigned long __uval = __neg ? (unsigned long)~__val + 1ul : __val;
6620 const auto __len = __detail::__to_chars_len(__uval);
6621 string __str(__neg + __len, '-');
6622 __detail::__to_chars_10_impl(&__str[__neg], __len, __uval);
6623 return __str;
6624 }
6625
6626 inline string
6627 to_string(unsigned long __val)
6628 {
6629 string __str(__detail::__to_chars_len(__val), '\0');
6630 __detail::__to_chars_10_impl(&__str[0], __str.size(), __val);
6631 return __str;
6632 }
6633
6634 inline string
6635 to_string(long long __val)
6636 {
6637 const bool __neg = __val < 0;
6638 const unsigned long long __uval
6639 = __neg ? (unsigned long long)~__val + 1ull : __val;
6640 const auto __len = __detail::__to_chars_len(__uval);
6641 string __str(__neg + __len, '-');
6642 __detail::__to_chars_10_impl(&__str[__neg], __len, __uval);
6643 return __str;
6644 }
6645
6646 inline string
6647 to_string(unsigned long long __val)
6648 {
6649 string __str(__detail::__to_chars_len(__val), '\0');
6650 __detail::__to_chars_10_impl(&__str[0], __str.size(), __val);
6651 return __str;
6652 }
6653
6654#if _GLIBCXX_USE_C99_STDIO1
6655 // NB: (v)snprintf vs sprintf.
6656
6657 inline string
6658 to_string(float __val)
6659 {
6660 const int __n =
6661 __gnu_cxx::__numeric_traits<float>::__max_exponent10 + 20;
6662 return __gnu_cxx::__to_xstring<string>(&std::vsnprintf, __n,
6663 "%f", __val);
6664 }
6665
6666 inline string
6667 to_string(double __val)
6668 {
6669 const int __n =
6670 __gnu_cxx::__numeric_traits<double>::__max_exponent10 + 20;
6671 return __gnu_cxx::__to_xstring<string>(&std::vsnprintf, __n,
6672 "%f", __val);
6673 }
6674
6675 inline string
6676 to_string(long double __val)
6677 {
6678 const int __n =
6679 __gnu_cxx::__numeric_traits<long double>::__max_exponent10 + 20;
6680 return __gnu_cxx::__to_xstring<string>(&std::vsnprintf, __n,
6681 "%Lf", __val);
6682 }
6683#endif // _GLIBCXX_USE_C99_STDIO
6684
6685#if defined(_GLIBCXX_USE_WCHAR_T1) && _GLIBCXX_USE_C99_WCHAR1
6686 inline int
6687 stoi(const wstring& __str, size_t* __idx = 0, int __base = 10)
6688 { return __gnu_cxx::__stoa<long, int>(&std::wcstol, "stoi", __str.c_str(),
6689 __idx, __base); }
6690
6691 inline long
6692 stol(const wstring& __str, size_t* __idx = 0, int __base = 10)
6693 { return __gnu_cxx::__stoa(&std::wcstol, "stol", __str.c_str(),
6694 __idx, __base); }
6695
6696 inline unsigned long
6697 stoul(const wstring& __str, size_t* __idx = 0, int __base = 10)
6698 { return __gnu_cxx::__stoa(&std::wcstoul, "stoul", __str.c_str(),
6699 __idx, __base); }
6700
6701 inline long long
6702 stoll(const wstring& __str, size_t* __idx = 0, int __base = 10)
6703 { return __gnu_cxx::__stoa(&std::wcstoll, "stoll", __str.c_str(),
6704 __idx, __base); }
6705
6706 inline unsigned long long
6707 stoull(const wstring& __str, size_t* __idx = 0, int __base = 10)
6708 { return __gnu_cxx::__stoa(&std::wcstoull, "stoull", __str.c_str(),
6709 __idx, __base); }
6710
6711 // NB: wcstof vs wcstod.
6712 inline float
6713 stof(const wstring& __str, size_t* __idx = 0)
6714 { return __gnu_cxx::__stoa(&std::wcstof, "stof", __str.c_str(), __idx); }
6715
6716 inline double
6717 stod(const wstring& __str, size_t* __idx = 0)
6718 { return __gnu_cxx::__stoa(&std::wcstod, "stod", __str.c_str(), __idx); }
6719
6720 inline long double
6721 stold(const wstring& __str, size_t* __idx = 0)
6722 { return __gnu_cxx::__stoa(&std::wcstold, "stold", __str.c_str(), __idx); }
6723
6724#ifndef _GLIBCXX_HAVE_BROKEN_VSWPRINTF
6725 // DR 1261.
6726 inline wstring
6727 to_wstring(int __val)
6728 { return __gnu_cxx::__to_xstring<wstring>(&std::vswprintf, 4 * sizeof(int),
6729 L"%d", __val); }
6730
6731 inline wstring
6732 to_wstring(unsigned __val)
6733 { return __gnu_cxx::__to_xstring<wstring>(&std::vswprintf,
6734 4 * sizeof(unsigned),
6735 L"%u", __val); }
6736
6737 inline wstring
6738 to_wstring(long __val)
6739 { return __gnu_cxx::__to_xstring<wstring>(&std::vswprintf, 4 * sizeof(long),
6740 L"%ld", __val); }
6741
6742 inline wstring
6743 to_wstring(unsigned long __val)
6744 { return __gnu_cxx::__to_xstring<wstring>(&std::vswprintf,
6745 4 * sizeof(unsigned long),
6746 L"%lu", __val); }
6747
6748 inline wstring
6749 to_wstring(long long __val)
6750 { return __gnu_cxx::__to_xstring<wstring>(&std::vswprintf,
6751 4 * sizeof(long long),
6752 L"%lld", __val); }
6753
6754 inline wstring
6755 to_wstring(unsigned long long __val)
6756 { return __gnu_cxx::__to_xstring<wstring>(&std::vswprintf,
6757 4 * sizeof(unsigned long long),
6758 L"%llu", __val); }
6759
6760 inline wstring
6761 to_wstring(float __val)
6762 {
6763 const int __n =
6764 __gnu_cxx::__numeric_traits<float>::__max_exponent10 + 20;
6765 return __gnu_cxx::__to_xstring<wstring>(&std::vswprintf, __n,
6766 L"%f", __val);
6767 }
6768
6769 inline wstring
6770 to_wstring(double __val)
6771 {
6772 const int __n =
6773 __gnu_cxx::__numeric_traits<double>::__max_exponent10 + 20;
6774 return __gnu_cxx::__to_xstring<wstring>(&std::vswprintf, __n,
6775 L"%f", __val);
6776 }
6777
6778 inline wstring
6779 to_wstring(long double __val)
6780 {
6781 const int __n =
6782 __gnu_cxx::__numeric_traits<long double>::__max_exponent10 + 20;
6783 return __gnu_cxx::__to_xstring<wstring>(&std::vswprintf, __n,
6784 L"%Lf", __val);
6785 }
6786#endif // _GLIBCXX_HAVE_BROKEN_VSWPRINTF
6787#endif // _GLIBCXX_USE_WCHAR_T && _GLIBCXX_USE_C99_WCHAR
6788
6789_GLIBCXX_END_NAMESPACE_CXX11}
6790_GLIBCXX_END_NAMESPACE_VERSION
6791} // namespace
6792
6793#endif /* C++11 */
6794
6795#if __cplusplus201703L >= 201103L
6796
6797#include <bits/functional_hash.h>
6798
6799namespace std _GLIBCXX_VISIBILITY(default)__attribute__ ((__visibility__ ("default")))
6800{
6801_GLIBCXX_BEGIN_NAMESPACE_VERSION
6802
6803 // DR 1182.
6804
6805#ifndef _GLIBCXX_COMPATIBILITY_CXX0X
6806 /// std::hash specialization for string.
6807 template<>
6808 struct hash<string>
6809 : public __hash_base<size_t, string>
6810 {
6811 size_t
6812 operator()(const string& __s) const noexcept
6813 { return std::_Hash_impl::hash(__s.data(), __s.length()); }
6814 };
6815
6816 template<>
6817 struct __is_fast_hash<hash<string>> : std::false_type
6818 { };
6819
6820#ifdef _GLIBCXX_USE_WCHAR_T1
6821 /// std::hash specialization for wstring.
6822 template<>
6823 struct hash<wstring>
6824 : public __hash_base<size_t, wstring>
6825 {
6826 size_t
6827 operator()(const wstring& __s) const noexcept
6828 { return std::_Hash_impl::hash(__s.data(),
6829 __s.length() * sizeof(wchar_t)); }
6830 };
6831
6832 template<>
6833 struct __is_fast_hash<hash<wstring>> : std::false_type
6834 { };
6835#endif
6836#endif /* _GLIBCXX_COMPATIBILITY_CXX0X */
6837
6838#ifdef _GLIBCXX_USE_CHAR8_T
6839 /// std::hash specialization for u8string.
6840 template<>
6841 struct hash<u8string>
6842 : public __hash_base<size_t, u8string>
6843 {
6844 size_t
6845 operator()(const u8string& __s) const noexcept
6846 { return std::_Hash_impl::hash(__s.data(),
6847 __s.length() * sizeof(char8_t)); }
6848 };
6849
6850 template<>
6851 struct __is_fast_hash<hash<u8string>> : std::false_type
6852 { };
6853#endif
6854
6855 /// std::hash specialization for u16string.
6856 template<>
6857 struct hash<u16string>
6858 : public __hash_base<size_t, u16string>
6859 {
6860 size_t
6861 operator()(const u16string& __s) const noexcept
6862 { return std::_Hash_impl::hash(__s.data(),
6863 __s.length() * sizeof(char16_t)); }
6864 };
6865
6866 template<>
6867 struct __is_fast_hash<hash<u16string>> : std::false_type
6868 { };
6869
6870 /// std::hash specialization for u32string.
6871 template<>
6872 struct hash<u32string>
6873 : public __hash_base<size_t, u32string>
6874 {
6875 size_t
6876 operator()(const u32string& __s) const noexcept
6877 { return std::_Hash_impl::hash(__s.data(),
6878 __s.length() * sizeof(char32_t)); }
6879 };
6880
6881 template<>
6882 struct __is_fast_hash<hash<u32string>> : std::false_type
6883 { };
6884
6885#if __cplusplus201703L >= 201402L
6886
6887#define __cpp_lib_string_udls201304 201304
6888
6889 inline namespace literals
6890 {
6891 inline namespace string_literals
6892 {
6893#pragma GCC diagnostic push
6894#pragma GCC diagnostic ignored "-Wliteral-suffix"
6895 _GLIBCXX_DEFAULT_ABI_TAG__attribute ((__abi_tag__ ("cxx11")))
6896 inline basic_string<char>
6897 operator""s(const char* __str, size_t __len)
6898 { return basic_string<char>{__str, __len}; }
6899
6900#ifdef _GLIBCXX_USE_WCHAR_T1
6901 _GLIBCXX_DEFAULT_ABI_TAG__attribute ((__abi_tag__ ("cxx11")))
6902 inline basic_string<wchar_t>
6903 operator""s(const wchar_t* __str, size_t __len)
6904 { return basic_string<wchar_t>{__str, __len}; }
6905#endif
6906
6907#ifdef _GLIBCXX_USE_CHAR8_T
6908 _GLIBCXX_DEFAULT_ABI_TAG__attribute ((__abi_tag__ ("cxx11")))
6909 inline basic_string<char8_t>
6910 operator""s(const char8_t* __str, size_t __len)
6911 { return basic_string<char8_t>{__str, __len}; }
6912#endif
6913
6914 _GLIBCXX_DEFAULT_ABI_TAG__attribute ((__abi_tag__ ("cxx11")))
6915 inline basic_string<char16_t>
6916 operator""s(const char16_t* __str, size_t __len)
6917 { return basic_string<char16_t>{__str, __len}; }
6918
6919 _GLIBCXX_DEFAULT_ABI_TAG__attribute ((__abi_tag__ ("cxx11")))
6920 inline basic_string<char32_t>
6921 operator""s(const char32_t* __str, size_t __len)
6922 { return basic_string<char32_t>{__str, __len}; }
6923
6924#pragma GCC diagnostic pop
6925 } // inline namespace string_literals
6926 } // inline namespace literals
6927
6928#if __cplusplus201703L >= 201703L
6929 namespace __detail::__variant
6930 {
6931 template<typename> struct _Never_valueless_alt; // see <variant>
6932
6933 // Provide the strong exception-safety guarantee when emplacing a
6934 // basic_string into a variant, but only if moving the string cannot throw.
6935 template<typename _Tp, typename _Traits, typename _Alloc>
6936 struct _Never_valueless_alt<std::basic_string<_Tp, _Traits, _Alloc>>
6937 : __and_<
6938 is_nothrow_move_constructible<std::basic_string<_Tp, _Traits, _Alloc>>,
6939 is_nothrow_move_assignable<std::basic_string<_Tp, _Traits, _Alloc>>
6940 >::type
6941 { };
6942 } // namespace __detail::__variant
6943#endif // C++17
6944#endif // C++14
6945
6946_GLIBCXX_END_NAMESPACE_VERSION
6947} // namespace std
6948
6949#endif // C++11
6950
6951#endif /* _BASIC_STRING_H */