1//===--- SemaAttr.cpp - Semantic Analysis for Attributes ------------------===//
2//
3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4// See https://llvm.org/LICENSE.txt for license information.
5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6//
7//===----------------------------------------------------------------------===//
8//
9// This file implements semantic analysis for non-trivial attributes and
10// pragmas.
11//
12//===----------------------------------------------------------------------===//
13
14#include "clang/AST/ASTConsumer.h"
15#include "clang/AST/Attr.h"
16#include "clang/AST/DeclCXX.h"
17#include "clang/AST/Expr.h"
18#include "clang/Analysis/Analyses/LifetimeSafety/LifetimeAnnotations.h"
19#include "clang/Basic/TargetInfo.h"
20#include "clang/Lex/Preprocessor.h"
21#include "clang/Sema/Lookup.h"
22#include <optional>
23using namespace clang;
24
25//===----------------------------------------------------------------------===//
26// Pragma 'pack' and 'options align'
27//===----------------------------------------------------------------------===//
28
29Sema::PragmaStackSentinelRAII::PragmaStackSentinelRAII(Sema &S,
30 StringRef SlotLabel,
31 bool ShouldAct)
32 : S(S), SlotLabel(SlotLabel), ShouldAct(ShouldAct) {
33 if (ShouldAct) {
34 S.VtorDispStack.SentinelAction(Action: PSK_Push, Label: SlotLabel);
35 S.DataSegStack.SentinelAction(Action: PSK_Push, Label: SlotLabel);
36 S.BSSSegStack.SentinelAction(Action: PSK_Push, Label: SlotLabel);
37 S.ConstSegStack.SentinelAction(Action: PSK_Push, Label: SlotLabel);
38 S.CodeSegStack.SentinelAction(Action: PSK_Push, Label: SlotLabel);
39 S.StrictGuardStackCheckStack.SentinelAction(Action: PSK_Push, Label: SlotLabel);
40 }
41}
42
43Sema::PragmaStackSentinelRAII::~PragmaStackSentinelRAII() {
44 if (ShouldAct) {
45 S.VtorDispStack.SentinelAction(Action: PSK_Pop, Label: SlotLabel);
46 S.DataSegStack.SentinelAction(Action: PSK_Pop, Label: SlotLabel);
47 S.BSSSegStack.SentinelAction(Action: PSK_Pop, Label: SlotLabel);
48 S.ConstSegStack.SentinelAction(Action: PSK_Pop, Label: SlotLabel);
49 S.CodeSegStack.SentinelAction(Action: PSK_Pop, Label: SlotLabel);
50 S.StrictGuardStackCheckStack.SentinelAction(Action: PSK_Pop, Label: SlotLabel);
51 }
52}
53
54void Sema::AddAlignmentAttributesForRecord(RecordDecl *RD) {
55 AlignPackInfo InfoVal = AlignPackStack.CurrentValue;
56 AlignPackInfo::Mode M = InfoVal.getAlignMode();
57 bool IsPackSet = InfoVal.IsPackSet();
58 bool IsXLPragma = getLangOpts().XLPragmaPack;
59
60 // If we are not under mac68k/natural alignment mode and also there is no pack
61 // value, we don't need any attributes.
62 if (!IsPackSet && M != AlignPackInfo::Mac68k && M != AlignPackInfo::Natural)
63 return;
64
65 if (M == AlignPackInfo::Mac68k && (IsXLPragma || InfoVal.IsAlignAttr())) {
66 RD->addAttr(A: AlignMac68kAttr::CreateImplicit(Ctx&: Context));
67 } else if (IsPackSet) {
68 // Check to see if we need a max field alignment attribute.
69 RD->addAttr(A: MaxFieldAlignmentAttr::CreateImplicit(
70 Ctx&: Context, Alignment: InfoVal.getPackNumber() * 8));
71 }
72
73 if (IsXLPragma && M == AlignPackInfo::Natural)
74 RD->addAttr(A: AlignNaturalAttr::CreateImplicit(Ctx&: Context));
75
76 if (AlignPackIncludeStack.empty())
77 return;
78 // The #pragma align/pack affected a record in an included file, so Clang
79 // should warn when that pragma was written in a file that included the
80 // included file.
81 for (auto &AlignPackedInclude : llvm::reverse(C&: AlignPackIncludeStack)) {
82 if (AlignPackedInclude.CurrentPragmaLocation !=
83 AlignPackStack.CurrentPragmaLocation)
84 break;
85 if (AlignPackedInclude.HasNonDefaultValue)
86 AlignPackedInclude.ShouldWarnOnInclude = true;
87 }
88}
89
90void Sema::AddMsStructLayoutForRecord(RecordDecl *RD) {
91 if (MSStructPragmaOn)
92 RD->addAttr(A: MSStructAttr::CreateImplicit(Ctx&: Context));
93
94 // FIXME: We should merge AddAlignmentAttributesForRecord with
95 // AddMsStructLayoutForRecord into AddPragmaAttributesForRecord, which takes
96 // all active pragmas and applies them as attributes to class definitions.
97 if (VtorDispStack.CurrentValue != getLangOpts().getVtorDispMode())
98 RD->addAttr(A: MSVtorDispAttr::CreateImplicit(
99 Ctx&: Context, Vdm: unsigned(VtorDispStack.CurrentValue)));
100}
101
102template <typename Attribute>
103static void addGslOwnerPointerAttributeIfNotExisting(ASTContext &Context,
104 CXXRecordDecl *Record) {
105 if (Record->hasAttr<OwnerAttr>() || Record->hasAttr<PointerAttr>())
106 return;
107
108 for (Decl *Redecl : Record->redecls())
109 Redecl->addAttr(A: Attribute::CreateImplicit(Context, /*DerefType=*/nullptr));
110}
111
112void Sema::inferGslPointerAttribute(NamedDecl *ND,
113 CXXRecordDecl *UnderlyingRecord) {
114 if (!UnderlyingRecord)
115 return;
116
117 const auto *Parent = dyn_cast<CXXRecordDecl>(Val: ND->getDeclContext());
118 if (!Parent)
119 return;
120
121 static const llvm::StringSet<> Containers{
122 "array",
123 "basic_string",
124 "deque",
125 "forward_list",
126 "vector",
127 "list",
128 "map",
129 "multiset",
130 "multimap",
131 "priority_queue",
132 "queue",
133 "set",
134 "stack",
135 "unordered_set",
136 "unordered_map",
137 "unordered_multiset",
138 "unordered_multimap",
139 "flat_map",
140 "flat_set",
141 };
142
143 static const llvm::StringSet<> Iterators{"iterator", "const_iterator",
144 "reverse_iterator",
145 "const_reverse_iterator"};
146
147 if (Parent->isInStdNamespace() && Iterators.count(Key: ND->getName()) &&
148 Containers.count(Key: Parent->getName()))
149 addGslOwnerPointerAttributeIfNotExisting<PointerAttr>(Context,
150 Record: UnderlyingRecord);
151}
152
153void Sema::inferGslPointerAttribute(TypedefNameDecl *TD) {
154
155 QualType Canonical = TD->getUnderlyingType().getCanonicalType();
156
157 CXXRecordDecl *RD = Canonical->getAsCXXRecordDecl();
158 if (!RD) {
159 if (auto *TST =
160 dyn_cast<TemplateSpecializationType>(Val: Canonical.getTypePtr())) {
161
162 if (const auto *TD = TST->getTemplateName().getAsTemplateDecl())
163 RD = dyn_cast_or_null<CXXRecordDecl>(Val: TD->getTemplatedDecl());
164 }
165 }
166
167 inferGslPointerAttribute(ND: TD, UnderlyingRecord: RD);
168}
169
170void Sema::inferGslOwnerPointerAttribute(CXXRecordDecl *Record) {
171 static const llvm::StringSet<> StdOwners{
172 "any",
173 "array",
174 "basic_regex",
175 "basic_string",
176 "deque",
177 "forward_list",
178 "vector",
179 "list",
180 "map",
181 "multiset",
182 "multimap",
183 "optional",
184 "priority_queue",
185 "queue",
186 "set",
187 "stack",
188 "unique_ptr",
189 "unordered_set",
190 "unordered_map",
191 "unordered_multiset",
192 "unordered_multimap",
193 "variant",
194 "flat_map",
195 "flat_set",
196 };
197 static const llvm::StringSet<> StdPointers{
198 "basic_string_view",
199 "reference_wrapper",
200 "regex_iterator",
201 "span",
202 };
203
204 if (!Record->getIdentifier())
205 return;
206
207 // Handle classes that directly appear in std namespace.
208 if (Record->isInStdNamespace()) {
209 if (Record->hasAttr<OwnerAttr>() || Record->hasAttr<PointerAttr>())
210 return;
211
212 if (StdOwners.count(Key: Record->getName()))
213 addGslOwnerPointerAttributeIfNotExisting<OwnerAttr>(Context, Record);
214 else if (StdPointers.count(Key: Record->getName()))
215 addGslOwnerPointerAttributeIfNotExisting<PointerAttr>(Context, Record);
216
217 return;
218 }
219
220 // Handle nested classes that could be a gsl::Pointer.
221 inferGslPointerAttribute(ND: Record, UnderlyingRecord: Record);
222}
223
224// This uses recursion and is only safe for small Stmt (e.g., the body of
225// std::make_unique). Do not use this for other Stmt without addressing the
226// potential for stack exhaustion.
227static const CXXNewExpr *findCXXNewExpr(const Stmt *S) {
228 if (!S)
229 return nullptr;
230 if (const auto *E = dyn_cast<CXXNewExpr>(Val: S))
231 return E;
232 for (const Stmt *Child : S->children())
233 if (const CXXNewExpr *E = findCXXNewExpr(S: Child))
234 return E;
235 return nullptr;
236}
237
238void Sema::inferLifetimeBoundAttribute(FunctionDecl *FD) {
239 if (FD->getNumParams() == 0)
240 return;
241 // Skip void returning functions (except constructors). This can occur in
242 // cases like 'as_const'.
243 if (!isa<CXXConstructorDecl>(Val: FD) && FD->getReturnType()->isVoidType())
244 return;
245
246 if (unsigned BuiltinID = FD->getBuiltinID()) {
247 // Add lifetime attribute to std::move, std::fowrard et al.
248 switch (BuiltinID) {
249 case Builtin::BIaddressof:
250 case Builtin::BI__addressof:
251 case Builtin::BI__builtin_addressof:
252 case Builtin::BIas_const:
253 case Builtin::BIforward:
254 case Builtin::BIforward_like:
255 case Builtin::BImove:
256 case Builtin::BImove_if_noexcept:
257 if (ParmVarDecl *P = FD->getParamDecl(i: 0u);
258 !P->hasAttr<LifetimeBoundAttr>())
259 P->addAttr(
260 A: LifetimeBoundAttr::CreateImplicit(Ctx&: Context, Range: FD->getLocation()));
261 break;
262 default:
263 break;
264 }
265 return;
266 }
267
268 // Handle std::make_unique to propagate lifetimebound attributes from the
269 // constructed type's constructor to make_unique's parameters by looking
270 // into its body.
271 if (FD->getDeclName().isIdentifier() && FD->getName() == "make_unique") {
272 const FunctionDecl *BodyDecl = nullptr;
273 if (FD->getBody(Definition&: BodyDecl))
274 if (const CXXNewExpr *NewExpr = findCXXNewExpr(S: BodyDecl->getBody()))
275 if (const CXXConstructExpr *ConstructExpr = NewExpr->getConstructExpr())
276 if (const CXXConstructorDecl *Ctor = ConstructExpr->getConstructor())
277 for (unsigned I = 0; I < Ctor->getNumParams(); ++I)
278 // Only infer lifetimebound for references. For pointers and
279 // views, the forwarding reference in make_unique would
280 // incorrectly track the lifetime of the local pointer variable
281 // itself, rather than the data it points to.
282 if (I < FD->getNumParams() &&
283 Ctor->getParamDecl(i: I)->hasAttr<LifetimeBoundAttr>() &&
284 Ctor->getParamDecl(i: I)->getType()->isReferenceType())
285 FD->getParamDecl(i: I)->addAttr(A: LifetimeBoundAttr::CreateImplicit(
286 Ctx&: Context, Range: FD->getLocation()));
287 return;
288 }
289
290 if (auto *CMD = dyn_cast<CXXMethodDecl>(Val: FD)) {
291 const auto *CRD = CMD->getParent();
292 if (!CRD->isInStdNamespace() || !CRD->getIdentifier())
293 return;
294
295 if (isa<CXXConstructorDecl>(Val: CMD)) {
296 auto *Param = CMD->getParamDecl(i: 0);
297 if (Param->hasAttr<LifetimeBoundAttr>())
298 return;
299 if (CRD->getName() == "basic_string_view" &&
300 Param->getType()->isPointerType()) {
301 // construct from a char array pointed by a pointer.
302 // basic_string_view(const CharT* s);
303 // basic_string_view(const CharT* s, size_type count);
304 Param->addAttr(
305 A: LifetimeBoundAttr::CreateImplicit(Ctx&: Context, Range: FD->getLocation()));
306 } else if (CRD->getName() == "span") {
307 // construct from a reference of array.
308 // span(std::type_identity_t<element_type> (&arr)[N]);
309 const auto *LRT = Param->getType()->getAs<LValueReferenceType>();
310 if (LRT && LRT->getPointeeType().IgnoreParens()->isArrayType())
311 Param->addAttr(
312 A: LifetimeBoundAttr::CreateImplicit(Ctx&: Context, Range: FD->getLocation()));
313 }
314 }
315 }
316}
317
318void Sema::inferLifetimeCaptureByAttribute(FunctionDecl *FD) {
319 auto *MD = dyn_cast_if_present<CXXMethodDecl>(Val: FD);
320 if (!MD || !MD->getParent()->isInStdNamespace())
321 return;
322 auto Annotate = [this](const FunctionDecl *MD) {
323 // Do not infer if any parameter is explicitly annotated.
324 for (ParmVarDecl *PVD : MD->parameters())
325 if (PVD->hasAttr<LifetimeCaptureByAttr>())
326 return;
327 for (ParmVarDecl *PVD : MD->parameters()) {
328 // Methods in standard containers that capture values typically accept
329 // reference-type parameters, e.g., `void push_back(const T& value)`.
330 // We only apply the lifetime_capture_by attribute to parameters of
331 // pointer-like reference types (`const T&`, `T&&`).
332 if (PVD->getType()->isReferenceType() &&
333 lifetimes::isGslPointerType(QT: PVD->getType().getNonReferenceType())) {
334 int CaptureByThis[] = {LifetimeCaptureByAttr::This};
335 PVD->addAttr(
336 A: LifetimeCaptureByAttr::CreateImplicit(Ctx&: Context, Params: CaptureByThis, ParamsSize: 1));
337 }
338 }
339 };
340
341 if (!MD->getIdentifier()) {
342 static const llvm::StringSet<> MapLikeContainer{
343 "map",
344 "multimap",
345 "unordered_map",
346 "unordered_multimap",
347 };
348 // Infer for the map's operator []:
349 // std::map<string_view, ...> m;
350 // m[ReturnString(..)] = ...; // !dangling references in m.
351 if (MD->getOverloadedOperator() == OO_Subscript &&
352 MapLikeContainer.contains(key: MD->getParent()->getName()))
353 Annotate(MD);
354 return;
355 }
356 static const llvm::StringSet<> CapturingMethods{
357 "insert", "insert_or_assign", "push", "push_front", "push_back"};
358 if (!CapturingMethods.contains(key: MD->getName()))
359 return;
360 if (MD->getName() == "insert" && MD->getParent()->getName() == "basic_string")
361 return;
362 Annotate(MD);
363}
364
365void Sema::inferNullableClassAttribute(CXXRecordDecl *CRD) {
366 static const llvm::StringSet<> Nullable{
367 "auto_ptr", "shared_ptr", "unique_ptr", "exception_ptr",
368 "coroutine_handle", "function", "move_only_function",
369 };
370
371 if (CRD->isInStdNamespace() && Nullable.count(Key: CRD->getName()) &&
372 !CRD->hasAttr<TypeNullableAttr>())
373 for (Decl *Redecl : CRD->redecls())
374 Redecl->addAttr(A: TypeNullableAttr::CreateImplicit(Ctx&: Context));
375}
376
377void Sema::ActOnPragmaOptionsAlign(PragmaOptionsAlignKind Kind,
378 SourceLocation PragmaLoc) {
379 PragmaMsStackAction Action = Sema::PSK_Reset;
380 AlignPackInfo::Mode ModeVal = AlignPackInfo::Native;
381
382 switch (Kind) {
383 // For most of the platforms we support, native and natural are the same.
384 // With XL, native is the same as power, natural means something else.
385 case PragmaOptionsAlignKind::Native:
386 case PragmaOptionsAlignKind::Power:
387 Action = Sema::PSK_Push_Set;
388 break;
389 case PragmaOptionsAlignKind::Natural:
390 Action = Sema::PSK_Push_Set;
391 ModeVal = AlignPackInfo::Natural;
392 break;
393
394 // Note that '#pragma options align=packed' is not equivalent to attribute
395 // packed, it has a different precedence relative to attribute aligned.
396 case PragmaOptionsAlignKind::Packed:
397 Action = Sema::PSK_Push_Set;
398 ModeVal = AlignPackInfo::Packed;
399 break;
400
401 case PragmaOptionsAlignKind::Mac68k:
402 // Check if the target supports this.
403 if (!this->Context.getTargetInfo().hasAlignMac68kSupport()) {
404 Diag(Loc: PragmaLoc, DiagID: diag::err_pragma_options_align_mac68k_target_unsupported);
405 return;
406 }
407 Action = Sema::PSK_Push_Set;
408 ModeVal = AlignPackInfo::Mac68k;
409 break;
410 case PragmaOptionsAlignKind::Reset:
411 // Reset just pops the top of the stack, or resets the current alignment to
412 // default.
413 Action = Sema::PSK_Pop;
414 if (AlignPackStack.Stack.empty()) {
415 if (AlignPackStack.CurrentValue.getAlignMode() != AlignPackInfo::Native ||
416 AlignPackStack.CurrentValue.IsPackAttr()) {
417 Action = Sema::PSK_Reset;
418 } else {
419 Diag(Loc: PragmaLoc, DiagID: diag::warn_pragma_options_align_reset_failed)
420 << "stack empty";
421 return;
422 }
423 }
424 break;
425 }
426
427 AlignPackInfo Info(ModeVal, getLangOpts().XLPragmaPack);
428
429 AlignPackStack.Act(PragmaLocation: PragmaLoc, Action, StackSlotLabel: StringRef(), Value: Info);
430}
431
432void Sema::ActOnPragmaClangSection(SourceLocation PragmaLoc,
433 PragmaClangSectionAction Action,
434 PragmaClangSectionKind SecKind,
435 StringRef SecName) {
436 PragmaClangSection *CSec;
437 int SectionFlags = ASTContext::PSF_Read;
438 switch (SecKind) {
439 case PragmaClangSectionKind::BSS:
440 CSec = &PragmaClangBSSSection;
441 SectionFlags |= ASTContext::PSF_Write | ASTContext::PSF_ZeroInit;
442 break;
443 case PragmaClangSectionKind::Data:
444 CSec = &PragmaClangDataSection;
445 SectionFlags |= ASTContext::PSF_Write;
446 break;
447 case PragmaClangSectionKind::Rodata:
448 CSec = &PragmaClangRodataSection;
449 break;
450 case PragmaClangSectionKind::Relro:
451 CSec = &PragmaClangRelroSection;
452 break;
453 case PragmaClangSectionKind::Text:
454 CSec = &PragmaClangTextSection;
455 SectionFlags |= ASTContext::PSF_Execute;
456 break;
457 default:
458 llvm_unreachable("invalid clang section kind");
459 }
460
461 if (Action == PragmaClangSectionAction::Clear) {
462 CSec->Valid = false;
463 return;
464 }
465
466 if (llvm::Error E = isValidSectionSpecifier(Str: SecName)) {
467 Diag(Loc: PragmaLoc, DiagID: diag::err_pragma_section_invalid_for_target)
468 << toString(E: std::move(E));
469 CSec->Valid = false;
470 return;
471 }
472
473 if (UnifySection(SectionName: SecName, SectionFlags, PragmaSectionLocation: PragmaLoc))
474 return;
475
476 CSec->Valid = true;
477 CSec->SectionName = std::string(SecName);
478 CSec->PragmaLocation = PragmaLoc;
479}
480
481void Sema::ActOnPragmaPack(SourceLocation PragmaLoc, PragmaMsStackAction Action,
482 StringRef SlotLabel, Expr *Alignment) {
483 bool IsXLPragma = getLangOpts().XLPragmaPack;
484 // XL pragma pack does not support identifier syntax.
485 if (IsXLPragma && !SlotLabel.empty()) {
486 Diag(Loc: PragmaLoc, DiagID: diag::err_pragma_pack_identifer_not_supported);
487 return;
488 }
489
490 const AlignPackInfo CurVal = AlignPackStack.CurrentValue;
491
492 // If specified then alignment must be a "small" power of two.
493 unsigned AlignmentVal = 0;
494 AlignPackInfo::Mode ModeVal = CurVal.getAlignMode();
495
496 if (Alignment) {
497 std::optional<llvm::APSInt> Val;
498 Val = Alignment->getIntegerConstantExpr(Ctx: Context);
499
500 // pack(0) is like pack(), which just works out since that is what
501 // we use 0 for in PackAttr.
502 if (Alignment->isTypeDependent() || !Val ||
503 !(*Val == 0 || Val->isPowerOf2()) || Val->getZExtValue() > 16) {
504 Diag(Loc: PragmaLoc, DiagID: diag::warn_pragma_pack_invalid_alignment);
505 return; // Ignore
506 }
507
508 if (IsXLPragma && *Val == 0) {
509 // pack(0) does not work out with XL.
510 Diag(Loc: PragmaLoc, DiagID: diag::err_pragma_pack_invalid_alignment);
511 return; // Ignore
512 }
513
514 AlignmentVal = (unsigned)Val->getZExtValue();
515 }
516
517 if (Action == Sema::PSK_Show) {
518 // Show the current alignment, making sure to show the right value
519 // for the default.
520 // FIXME: This should come from the target.
521 AlignmentVal = CurVal.IsPackSet() ? CurVal.getPackNumber() : 8;
522 if (ModeVal == AlignPackInfo::Mac68k &&
523 (IsXLPragma || CurVal.IsAlignAttr()))
524 Diag(Loc: PragmaLoc, DiagID: diag::warn_pragma_pack_show) << "mac68k";
525 else
526 Diag(Loc: PragmaLoc, DiagID: diag::warn_pragma_pack_show) << AlignmentVal;
527 }
528
529 // MSDN, C/C++ Preprocessor Reference > Pragma Directives > pack:
530 // "#pragma pack(pop, identifier, n) is undefined"
531 if (Action & Sema::PSK_Pop) {
532 if (Alignment && !SlotLabel.empty())
533 Diag(Loc: PragmaLoc, DiagID: diag::warn_pragma_pack_pop_identifier_and_alignment);
534 if (AlignPackStack.Stack.empty()) {
535 assert(CurVal.getAlignMode() == AlignPackInfo::Native &&
536 "Empty pack stack can only be at Native alignment mode.");
537 Diag(Loc: PragmaLoc, DiagID: diag::warn_pragma_pop_failed) << "pack" << "stack empty";
538 }
539 }
540
541 AlignPackInfo Info(ModeVal, AlignmentVal, IsXLPragma);
542
543 AlignPackStack.Act(PragmaLocation: PragmaLoc, Action, StackSlotLabel: SlotLabel, Value: Info);
544}
545
546bool Sema::ConstantFoldAttrArgs(const AttributeCommonInfo &CI,
547 MutableArrayRef<Expr *> Args) {
548 llvm::SmallVector<PartialDiagnosticAt, 8> Notes;
549 for (unsigned Idx = 0; Idx < Args.size(); Idx++) {
550 Expr *&E = Args.begin()[Idx];
551 assert(E && "error are handled before");
552 if (E->isValueDependent() || E->isTypeDependent())
553 continue;
554
555 // FIXME: Use DefaultFunctionArrayLValueConversion() in place of the logic
556 // that adds implicit casts here.
557 if (E->getType()->isArrayType())
558 E = ImpCastExprToType(E, Type: Context.getPointerType(T: E->getType()),
559 CK: clang::CK_ArrayToPointerDecay)
560 .get();
561 if (E->getType()->isFunctionType())
562 E = ImplicitCastExpr::Create(Context,
563 T: Context.getPointerType(T: E->getType()),
564 Kind: clang::CK_FunctionToPointerDecay, Operand: E, BasePath: nullptr,
565 Cat: VK_PRValue, FPO: FPOptionsOverride());
566 if (E->isLValue())
567 E = ImplicitCastExpr::Create(Context, T: E->getType().getNonReferenceType(),
568 Kind: clang::CK_LValueToRValue, Operand: E, BasePath: nullptr,
569 Cat: VK_PRValue, FPO: FPOptionsOverride());
570
571 Expr::EvalResult Eval;
572 Notes.clear();
573 Eval.Diag = &Notes;
574
575 bool Result = E->EvaluateAsConstantExpr(Result&: Eval, Ctx: Context);
576
577 /// Result means the expression can be folded to a constant.
578 /// Note.empty() means the expression is a valid constant expression in the
579 /// current language mode.
580 if (!Result || !Notes.empty()) {
581 Diag(Loc: E->getBeginLoc(), DiagID: diag::err_attribute_argument_n_type)
582 << CI << (Idx + 1) << AANT_ArgumentConstantExpr;
583 for (auto &Note : Notes)
584 Diag(Loc: Note.first, PD: Note.second);
585 return false;
586 }
587 E = ConstantExpr::Create(Context, E, Result: Eval.Val);
588 }
589
590 return true;
591}
592
593void Sema::DiagnoseNonDefaultPragmaAlignPack(PragmaAlignPackDiagnoseKind Kind,
594 SourceLocation IncludeLoc) {
595 if (Kind == PragmaAlignPackDiagnoseKind::NonDefaultStateAtInclude) {
596 SourceLocation PrevLocation = AlignPackStack.CurrentPragmaLocation;
597 // Warn about non-default alignment at #includes (without redundant
598 // warnings for the same directive in nested includes).
599 // The warning is delayed until the end of the file to avoid warnings
600 // for files that don't have any records that are affected by the modified
601 // alignment.
602 bool HasNonDefaultValue =
603 AlignPackStack.hasValue() &&
604 (AlignPackIncludeStack.empty() ||
605 AlignPackIncludeStack.back().CurrentPragmaLocation != PrevLocation);
606 AlignPackIncludeStack.push_back(
607 Elt: {.CurrentValue: AlignPackStack.CurrentValue,
608 .CurrentPragmaLocation: AlignPackStack.hasValue() ? PrevLocation : SourceLocation(),
609 .HasNonDefaultValue: HasNonDefaultValue, /*ShouldWarnOnInclude*/ false});
610 return;
611 }
612
613 assert(Kind == PragmaAlignPackDiagnoseKind::ChangedStateAtExit &&
614 "invalid kind");
615 AlignPackIncludeState PrevAlignPackState =
616 AlignPackIncludeStack.pop_back_val();
617 // FIXME: AlignPackStack may contain both #pragma align and #pragma pack
618 // information, diagnostics below might not be accurate if we have mixed
619 // pragmas.
620 if (PrevAlignPackState.ShouldWarnOnInclude) {
621 // Emit the delayed non-default alignment at #include warning.
622 Diag(Loc: IncludeLoc, DiagID: diag::warn_pragma_pack_non_default_at_include);
623 Diag(Loc: PrevAlignPackState.CurrentPragmaLocation, DiagID: diag::note_pragma_pack_here);
624 }
625 // Warn about modified alignment after #includes.
626 if (PrevAlignPackState.CurrentValue != AlignPackStack.CurrentValue) {
627 Diag(Loc: IncludeLoc, DiagID: diag::warn_pragma_pack_modified_after_include);
628 Diag(Loc: AlignPackStack.CurrentPragmaLocation, DiagID: diag::note_pragma_pack_here);
629 }
630}
631
632void Sema::DiagnoseUnterminatedPragmaAlignPack() {
633 if (AlignPackStack.Stack.empty())
634 return;
635 bool IsInnermost = true;
636
637 // FIXME: AlignPackStack may contain both #pragma align and #pragma pack
638 // information, diagnostics below might not be accurate if we have mixed
639 // pragmas.
640 for (const auto &StackSlot : llvm::reverse(C&: AlignPackStack.Stack)) {
641 Diag(Loc: StackSlot.PragmaPushLocation, DiagID: diag::warn_pragma_pack_no_pop_eof);
642 // The user might have already reset the alignment, so suggest replacing
643 // the reset with a pop.
644 if (IsInnermost &&
645 AlignPackStack.CurrentValue == AlignPackStack.DefaultValue) {
646 auto DB = Diag(Loc: AlignPackStack.CurrentPragmaLocation,
647 DiagID: diag::note_pragma_pack_pop_instead_reset);
648 SourceLocation FixItLoc =
649 Lexer::findLocationAfterToken(loc: AlignPackStack.CurrentPragmaLocation,
650 TKind: tok::l_paren, SM: SourceMgr, LangOpts,
651 /*SkipTrailing=*/SkipTrailingWhitespaceAndNewLine: false);
652 if (FixItLoc.isValid())
653 DB << FixItHint::CreateInsertion(InsertionLoc: FixItLoc, Code: "pop");
654 }
655 IsInnermost = false;
656 }
657}
658
659void Sema::ActOnPragmaMSStruct(PragmaMSStructKind Kind) {
660 MSStructPragmaOn = (Kind == PMSST_ON);
661}
662
663void Sema::ActOnPragmaMSComment(SourceLocation CommentLoc,
664 PragmaMSCommentKind Kind, StringRef Arg) {
665 auto *PCD = PragmaCommentDecl::Create(
666 C: Context, DC: Context.getTranslationUnitDecl(), CommentLoc, CommentKind: Kind, Arg);
667 Context.getTranslationUnitDecl()->addDecl(D: PCD);
668 Consumer.HandleTopLevelDecl(D: DeclGroupRef(PCD));
669}
670
671void Sema::ActOnPragmaDetectMismatch(SourceLocation Loc, StringRef Name,
672 StringRef Value) {
673 auto *PDMD = PragmaDetectMismatchDecl::Create(
674 C: Context, DC: Context.getTranslationUnitDecl(), Loc, Name, Value);
675 Context.getTranslationUnitDecl()->addDecl(D: PDMD);
676 Consumer.HandleTopLevelDecl(D: DeclGroupRef(PDMD));
677}
678
679void Sema::ActOnPragmaFPEvalMethod(SourceLocation Loc,
680 LangOptions::FPEvalMethodKind Value) {
681 FPOptionsOverride NewFPFeatures = CurFPFeatureOverrides();
682 switch (Value) {
683 default:
684 llvm_unreachable("invalid pragma eval_method kind");
685 case LangOptions::FEM_Source:
686 NewFPFeatures.setFPEvalMethodOverride(LangOptions::FEM_Source);
687 break;
688 case LangOptions::FEM_Double:
689 NewFPFeatures.setFPEvalMethodOverride(LangOptions::FEM_Double);
690 break;
691 case LangOptions::FEM_Extended:
692 NewFPFeatures.setFPEvalMethodOverride(LangOptions::FEM_Extended);
693 break;
694 }
695 if (getLangOpts().ApproxFunc)
696 Diag(Loc, DiagID: diag::err_setting_eval_method_used_in_unsafe_context) << 0 << 0;
697 if (getLangOpts().AllowFPReassoc)
698 Diag(Loc, DiagID: diag::err_setting_eval_method_used_in_unsafe_context) << 0 << 1;
699 if (getLangOpts().AllowRecip)
700 Diag(Loc, DiagID: diag::err_setting_eval_method_used_in_unsafe_context) << 0 << 2;
701 FpPragmaStack.Act(PragmaLocation: Loc, Action: PSK_Set, StackSlotLabel: StringRef(), Value: NewFPFeatures);
702 CurFPFeatures = NewFPFeatures.applyOverrides(LO: getLangOpts());
703 PP.setCurrentFPEvalMethod(PragmaLoc: Loc, Val: Value);
704}
705
706void Sema::ActOnPragmaFloatControl(SourceLocation Loc,
707 PragmaMsStackAction Action,
708 PragmaFloatControlKind Value) {
709 FPOptionsOverride NewFPFeatures = CurFPFeatureOverrides();
710 if ((Action == PSK_Push_Set || Action == PSK_Push || Action == PSK_Pop) &&
711 !CurContext->getRedeclContext()->isFileContext()) {
712 // Push and pop can only occur at file or namespace scope, or within a
713 // language linkage declaration.
714 Diag(Loc, DiagID: diag::err_pragma_fc_pp_scope);
715 return;
716 }
717 switch (Value) {
718 default:
719 llvm_unreachable("invalid pragma float_control kind");
720 case PFC_Precise:
721 NewFPFeatures.setFPPreciseEnabled(true);
722 FpPragmaStack.Act(PragmaLocation: Loc, Action, StackSlotLabel: StringRef(), Value: NewFPFeatures);
723 break;
724 case PFC_NoPrecise:
725 if (CurFPFeatures.getExceptionMode() == LangOptions::FPE_Strict)
726 Diag(Loc, DiagID: diag::err_pragma_fc_noprecise_requires_noexcept);
727 else if (CurFPFeatures.getAllowFEnvAccess())
728 Diag(Loc, DiagID: diag::err_pragma_fc_noprecise_requires_nofenv);
729 else
730 NewFPFeatures.setFPPreciseEnabled(false);
731 FpPragmaStack.Act(PragmaLocation: Loc, Action, StackSlotLabel: StringRef(), Value: NewFPFeatures);
732 break;
733 case PFC_Except:
734 if (!isPreciseFPEnabled())
735 Diag(Loc, DiagID: diag::err_pragma_fc_except_requires_precise);
736 else
737 NewFPFeatures.setSpecifiedExceptionModeOverride(LangOptions::FPE_Strict);
738 FpPragmaStack.Act(PragmaLocation: Loc, Action, StackSlotLabel: StringRef(), Value: NewFPFeatures);
739 break;
740 case PFC_NoExcept:
741 NewFPFeatures.setSpecifiedExceptionModeOverride(LangOptions::FPE_Ignore);
742 FpPragmaStack.Act(PragmaLocation: Loc, Action, StackSlotLabel: StringRef(), Value: NewFPFeatures);
743 break;
744 case PFC_Push:
745 FpPragmaStack.Act(PragmaLocation: Loc, Action: Sema::PSK_Push_Set, StackSlotLabel: StringRef(), Value: NewFPFeatures);
746 break;
747 case PFC_Pop:
748 if (FpPragmaStack.Stack.empty()) {
749 Diag(Loc, DiagID: diag::warn_pragma_pop_failed) << "float_control"
750 << "stack empty";
751 return;
752 }
753 FpPragmaStack.Act(PragmaLocation: Loc, Action, StackSlotLabel: StringRef(), Value: NewFPFeatures);
754 NewFPFeatures = FpPragmaStack.CurrentValue;
755 break;
756 }
757 CurFPFeatures = NewFPFeatures.applyOverrides(LO: getLangOpts());
758}
759
760void Sema::ActOnPragmaMSPointersToMembers(
761 LangOptions::PragmaMSPointersToMembersKind RepresentationMethod,
762 SourceLocation PragmaLoc) {
763 MSPointerToMemberRepresentationMethod = RepresentationMethod;
764 ImplicitMSInheritanceAttrLoc = PragmaLoc;
765}
766
767void Sema::ActOnPragmaMSVtorDisp(PragmaMsStackAction Action,
768 SourceLocation PragmaLoc,
769 MSVtorDispMode Mode) {
770 if (Action & PSK_Pop && VtorDispStack.Stack.empty())
771 Diag(Loc: PragmaLoc, DiagID: diag::warn_pragma_pop_failed) << "vtordisp"
772 << "stack empty";
773 VtorDispStack.Act(PragmaLocation: PragmaLoc, Action, StackSlotLabel: StringRef(), Value: Mode);
774}
775
776template <>
777void Sema::PragmaStack<Sema::AlignPackInfo>::Act(SourceLocation PragmaLocation,
778 PragmaMsStackAction Action,
779 llvm::StringRef StackSlotLabel,
780 AlignPackInfo Value) {
781 if (Action == PSK_Reset) {
782 CurrentValue = DefaultValue;
783 CurrentPragmaLocation = PragmaLocation;
784 return;
785 }
786 if (Action & PSK_Push)
787 Stack.emplace_back(Args: Slot(StackSlotLabel, CurrentValue, CurrentPragmaLocation,
788 PragmaLocation));
789 else if (Action & PSK_Pop) {
790 if (!StackSlotLabel.empty()) {
791 // If we've got a label, try to find it and jump there.
792 auto I = llvm::find_if(Range: llvm::reverse(C&: Stack), P: [&](const Slot &x) {
793 return x.StackSlotLabel == StackSlotLabel;
794 });
795 // We found the label, so pop from there.
796 if (I != Stack.rend()) {
797 CurrentValue = I->Value;
798 CurrentPragmaLocation = I->PragmaLocation;
799 Stack.erase(CS: std::prev(x: I.base()), CE: Stack.end());
800 }
801 } else if (Value.IsXLStack() && Value.IsAlignAttr() &&
802 CurrentValue.IsPackAttr()) {
803 // XL '#pragma align(reset)' would pop the stack until
804 // a current in effect pragma align is popped.
805 auto I = llvm::find_if(Range: llvm::reverse(C&: Stack), P: [&](const Slot &x) {
806 return x.Value.IsAlignAttr();
807 });
808 // If we found pragma align so pop from there.
809 if (I != Stack.rend()) {
810 Stack.erase(CS: std::prev(x: I.base()), CE: Stack.end());
811 if (Stack.empty()) {
812 CurrentValue = DefaultValue;
813 CurrentPragmaLocation = PragmaLocation;
814 } else {
815 CurrentValue = Stack.back().Value;
816 CurrentPragmaLocation = Stack.back().PragmaLocation;
817 Stack.pop_back();
818 }
819 }
820 } else if (!Stack.empty()) {
821 // xl '#pragma align' sets the baseline, and `#pragma pack` cannot pop
822 // over the baseline.
823 if (Value.IsXLStack() && Value.IsPackAttr() && CurrentValue.IsAlignAttr())
824 return;
825
826 // We don't have a label, just pop the last entry.
827 CurrentValue = Stack.back().Value;
828 CurrentPragmaLocation = Stack.back().PragmaLocation;
829 Stack.pop_back();
830 }
831 }
832 if (Action & PSK_Set) {
833 CurrentValue = Value;
834 CurrentPragmaLocation = PragmaLocation;
835 }
836}
837
838bool Sema::UnifySection(StringRef SectionName, int SectionFlags,
839 NamedDecl *Decl) {
840 SourceLocation PragmaLocation;
841 if (auto A = Decl->getAttr<SectionAttr>())
842 if (A->isImplicit())
843 PragmaLocation = A->getLocation();
844 auto [SectionIt, Inserted] = Context.SectionInfos.try_emplace(
845 Key: SectionName, Args&: Decl, Args&: PragmaLocation, Args&: SectionFlags);
846 if (Inserted)
847 return false;
848 // A pre-declared section takes precedence w/o diagnostic.
849 const auto &Section = SectionIt->second;
850 if (Section.SectionFlags == SectionFlags ||
851 ((SectionFlags & ASTContext::PSF_Implicit) &&
852 !(Section.SectionFlags & ASTContext::PSF_Implicit)))
853 return false;
854 Diag(Loc: Decl->getLocation(), DiagID: diag::err_section_conflict) << Decl << Section;
855 if (Section.Decl)
856 Diag(Loc: Section.Decl->getLocation(), DiagID: diag::note_declared_at);
857 if (PragmaLocation.isValid())
858 Diag(Loc: PragmaLocation, DiagID: diag::note_pragma_entered_here);
859 if (Section.PragmaSectionLocation.isValid())
860 Diag(Loc: Section.PragmaSectionLocation, DiagID: diag::note_pragma_entered_here);
861 return true;
862}
863
864bool Sema::UnifySection(StringRef SectionName,
865 int SectionFlags,
866 SourceLocation PragmaSectionLocation) {
867 auto SectionIt = Context.SectionInfos.find(Key: SectionName);
868 if (SectionIt != Context.SectionInfos.end()) {
869 const auto &Section = SectionIt->second;
870 if (Section.SectionFlags == SectionFlags)
871 return false;
872 if (!(Section.SectionFlags & ASTContext::PSF_Implicit)) {
873 Diag(Loc: PragmaSectionLocation, DiagID: diag::err_section_conflict)
874 << "this" << Section;
875 if (Section.Decl)
876 Diag(Loc: Section.Decl->getLocation(), DiagID: diag::note_declared_at);
877 if (Section.PragmaSectionLocation.isValid())
878 Diag(Loc: Section.PragmaSectionLocation, DiagID: diag::note_pragma_entered_here);
879 return true;
880 }
881 }
882 Context.SectionInfos[SectionName] =
883 ASTContext::SectionInfo(nullptr, PragmaSectionLocation, SectionFlags);
884 return false;
885}
886
887/// Called on well formed \#pragma bss_seg().
888void Sema::ActOnPragmaMSSeg(SourceLocation PragmaLocation,
889 PragmaMsStackAction Action,
890 llvm::StringRef StackSlotLabel,
891 StringLiteral *SegmentName,
892 llvm::StringRef PragmaName) {
893 PragmaStack<StringLiteral *> *Stack =
894 llvm::StringSwitch<PragmaStack<StringLiteral *> *>(PragmaName)
895 .Case(S: "data_seg", Value: &DataSegStack)
896 .Case(S: "bss_seg", Value: &BSSSegStack)
897 .Case(S: "const_seg", Value: &ConstSegStack)
898 .Case(S: "code_seg", Value: &CodeSegStack);
899 if (Action & PSK_Pop && Stack->Stack.empty())
900 Diag(Loc: PragmaLocation, DiagID: diag::warn_pragma_pop_failed) << PragmaName
901 << "stack empty";
902 if (SegmentName) {
903 if (!checkSectionName(LiteralLoc: SegmentName->getBeginLoc(), Str: SegmentName->getString()))
904 return;
905
906 if (SegmentName->getString() == ".drectve" &&
907 Context.getTargetInfo().getCXXABI().isMicrosoft())
908 Diag(Loc: PragmaLocation, DiagID: diag::warn_attribute_section_drectve) << PragmaName;
909 }
910
911 Stack->Act(PragmaLocation, Action, StackSlotLabel, Value: SegmentName);
912}
913
914/// Called on well formed \#pragma strict_gs_check().
915void Sema::ActOnPragmaMSStrictGuardStackCheck(SourceLocation PragmaLocation,
916 PragmaMsStackAction Action,
917 bool Value) {
918 if (Action & PSK_Pop && StrictGuardStackCheckStack.Stack.empty())
919 Diag(Loc: PragmaLocation, DiagID: diag::warn_pragma_pop_failed) << "strict_gs_check"
920 << "stack empty";
921
922 StrictGuardStackCheckStack.Act(PragmaLocation, Action, StackSlotLabel: StringRef(), Value);
923}
924
925/// Called on well formed \#pragma bss_seg().
926void Sema::ActOnPragmaMSSection(SourceLocation PragmaLocation,
927 int SectionFlags, StringLiteral *SegmentName) {
928 UnifySection(SectionName: SegmentName->getString(), SectionFlags, PragmaSectionLocation: PragmaLocation);
929}
930
931void Sema::ActOnPragmaMSInitSeg(SourceLocation PragmaLocation,
932 StringLiteral *SegmentName) {
933 // There's no stack to maintain, so we just have a current section. When we
934 // see the default section, reset our current section back to null so we stop
935 // tacking on unnecessary attributes.
936 CurInitSeg = SegmentName->getString() == ".CRT$XCU" ? nullptr : SegmentName;
937 CurInitSegLoc = PragmaLocation;
938}
939
940void Sema::ActOnPragmaMSAllocText(
941 SourceLocation PragmaLocation, StringRef Section,
942 const SmallVector<std::tuple<IdentifierInfo *, SourceLocation>>
943 &Functions) {
944 if (!CurContext->getRedeclContext()->isFileContext()) {
945 Diag(Loc: PragmaLocation, DiagID: diag::err_pragma_expected_file_scope) << "alloc_text";
946 return;
947 }
948
949 for (auto &Function : Functions) {
950 IdentifierInfo *II;
951 SourceLocation Loc;
952 std::tie(args&: II, args&: Loc) = Function;
953
954 DeclarationName DN(II);
955 NamedDecl *ND = LookupSingleName(S: TUScope, Name: DN, Loc, NameKind: LookupOrdinaryName);
956 if (!ND) {
957 Diag(Loc, DiagID: diag::err_undeclared_use) << II->getName();
958 return;
959 }
960
961 auto *FD = dyn_cast<FunctionDecl>(Val: ND->getCanonicalDecl());
962 if (!FD) {
963 Diag(Loc, DiagID: diag::err_pragma_alloc_text_not_function);
964 return;
965 }
966
967 if (getLangOpts().CPlusPlus && !FD->isInExternCContext()) {
968 Diag(Loc, DiagID: diag::err_pragma_alloc_text_c_linkage);
969 return;
970 }
971
972 FunctionToSectionMap[II->getName()] = std::make_tuple(args&: Section, args&: Loc);
973 }
974}
975
976void Sema::ActOnPragmaUnused(const Token &IdTok, Scope *curScope,
977 SourceLocation PragmaLoc) {
978
979 IdentifierInfo *Name = IdTok.getIdentifierInfo();
980 LookupResult Lookup(*this, Name, IdTok.getLocation(), LookupOrdinaryName);
981 LookupName(R&: Lookup, S: curScope, /*AllowBuiltinCreation=*/true);
982
983 if (Lookup.empty()) {
984 Diag(Loc: PragmaLoc, DiagID: diag::warn_pragma_unused_undeclared_var)
985 << Name << SourceRange(IdTok.getLocation());
986 return;
987 }
988
989 VarDecl *VD = Lookup.getAsSingle<VarDecl>();
990 if (!VD) {
991 Diag(Loc: PragmaLoc, DiagID: diag::warn_pragma_unused_expected_var_arg)
992 << Name << SourceRange(IdTok.getLocation());
993 return;
994 }
995
996 // Warn if this was used before being marked unused.
997 if (VD->isUsed())
998 Diag(Loc: PragmaLoc, DiagID: diag::warn_used_but_marked_unused) << Name;
999
1000 VD->addAttr(A: UnusedAttr::CreateImplicit(Ctx&: Context, Range: IdTok.getLocation(),
1001 S: UnusedAttr::GNU_unused));
1002}
1003
1004namespace {
1005
1006std::optional<attr::SubjectMatchRule>
1007getParentAttrMatcherRule(attr::SubjectMatchRule Rule) {
1008 using namespace attr;
1009 switch (Rule) {
1010 default:
1011 return std::nullopt;
1012#define ATTR_MATCH_RULE(Value, Spelling, IsAbstract)
1013#define ATTR_MATCH_SUB_RULE(Value, Spelling, IsAbstract, Parent, IsNegated) \
1014 case Value: \
1015 return Parent;
1016#include "clang/Basic/AttrSubMatchRulesList.inc"
1017 }
1018}
1019
1020bool isNegatedAttrMatcherSubRule(attr::SubjectMatchRule Rule) {
1021 using namespace attr;
1022 switch (Rule) {
1023 default:
1024 return false;
1025#define ATTR_MATCH_RULE(Value, Spelling, IsAbstract)
1026#define ATTR_MATCH_SUB_RULE(Value, Spelling, IsAbstract, Parent, IsNegated) \
1027 case Value: \
1028 return IsNegated;
1029#include "clang/Basic/AttrSubMatchRulesList.inc"
1030 }
1031}
1032
1033CharSourceRange replacementRangeForListElement(const Sema &S,
1034 SourceRange Range) {
1035 // Make sure that the ',' is removed as well.
1036 SourceLocation AfterCommaLoc = Lexer::findLocationAfterToken(
1037 loc: Range.getEnd(), TKind: tok::comma, SM: S.getSourceManager(), LangOpts: S.getLangOpts(),
1038 /*SkipTrailingWhitespaceAndNewLine=*/false);
1039 if (AfterCommaLoc.isValid())
1040 return CharSourceRange::getCharRange(B: Range.getBegin(), E: AfterCommaLoc);
1041 else
1042 return CharSourceRange::getTokenRange(R: Range);
1043}
1044
1045std::string
1046attrMatcherRuleListToString(ArrayRef<attr::SubjectMatchRule> Rules) {
1047 std::string Result;
1048 llvm::raw_string_ostream OS(Result);
1049 for (const auto &I : llvm::enumerate(First&: Rules)) {
1050 if (I.index())
1051 OS << (I.index() == Rules.size() - 1 ? ", and " : ", ");
1052 OS << "'" << attr::getSubjectMatchRuleSpelling(Rule: I.value()) << "'";
1053 }
1054 return Result;
1055}
1056
1057} // end anonymous namespace
1058
1059void Sema::ActOnPragmaAttributeAttribute(
1060 ParsedAttr &Attribute, SourceLocation PragmaLoc,
1061 attr::ParsedSubjectMatchRuleSet Rules) {
1062 Attribute.setIsPragmaClangAttribute();
1063 SmallVector<attr::SubjectMatchRule, 4> SubjectMatchRules;
1064 // Gather the subject match rules that are supported by the attribute.
1065 SmallVector<std::pair<attr::SubjectMatchRule, bool>, 4>
1066 StrictSubjectMatchRuleSet;
1067 Attribute.getMatchRules(LangOpts, MatchRules&: StrictSubjectMatchRuleSet);
1068
1069 // Figure out which subject matching rules are valid.
1070 if (StrictSubjectMatchRuleSet.empty()) {
1071 // Check for contradicting match rules. Contradicting match rules are
1072 // either:
1073 // - a top-level rule and one of its sub-rules. E.g. variable and
1074 // variable(is_parameter).
1075 // - a sub-rule and a sibling that's negated. E.g.
1076 // variable(is_thread_local) and variable(unless(is_parameter))
1077 llvm::SmallDenseMap<int, std::pair<int, SourceRange>, 2>
1078 RulesToFirstSpecifiedNegatedSubRule;
1079 for (const auto &Rule : Rules) {
1080 attr::SubjectMatchRule MatchRule = attr::SubjectMatchRule(Rule.first);
1081 std::optional<attr::SubjectMatchRule> ParentRule =
1082 getParentAttrMatcherRule(Rule: MatchRule);
1083 if (!ParentRule)
1084 continue;
1085 auto It = Rules.find(Val: *ParentRule);
1086 if (It != Rules.end()) {
1087 // A sub-rule contradicts a parent rule.
1088 Diag(Loc: Rule.second.getBegin(),
1089 DiagID: diag::err_pragma_attribute_matcher_subrule_contradicts_rule)
1090 << attr::getSubjectMatchRuleSpelling(Rule: MatchRule)
1091 << attr::getSubjectMatchRuleSpelling(Rule: *ParentRule) << It->second
1092 << FixItHint::CreateRemoval(
1093 RemoveRange: replacementRangeForListElement(S: *this, Range: Rule.second));
1094 // Keep going without removing this rule as it won't change the set of
1095 // declarations that receive the attribute.
1096 continue;
1097 }
1098 if (isNegatedAttrMatcherSubRule(Rule: MatchRule))
1099 RulesToFirstSpecifiedNegatedSubRule.insert(
1100 KV: std::make_pair(x&: *ParentRule, y: Rule));
1101 }
1102 bool IgnoreNegatedSubRules = false;
1103 for (const auto &Rule : Rules) {
1104 attr::SubjectMatchRule MatchRule = attr::SubjectMatchRule(Rule.first);
1105 std::optional<attr::SubjectMatchRule> ParentRule =
1106 getParentAttrMatcherRule(Rule: MatchRule);
1107 if (!ParentRule)
1108 continue;
1109 auto It = RulesToFirstSpecifiedNegatedSubRule.find(Val: *ParentRule);
1110 if (It != RulesToFirstSpecifiedNegatedSubRule.end() &&
1111 It->second != Rule) {
1112 // Negated sub-rule contradicts another sub-rule.
1113 Diag(
1114 Loc: It->second.second.getBegin(),
1115 DiagID: diag::
1116 err_pragma_attribute_matcher_negated_subrule_contradicts_subrule)
1117 << attr::getSubjectMatchRuleSpelling(
1118 Rule: attr::SubjectMatchRule(It->second.first))
1119 << attr::getSubjectMatchRuleSpelling(Rule: MatchRule) << Rule.second
1120 << FixItHint::CreateRemoval(
1121 RemoveRange: replacementRangeForListElement(S: *this, Range: It->second.second));
1122 // Keep going but ignore all of the negated sub-rules.
1123 IgnoreNegatedSubRules = true;
1124 RulesToFirstSpecifiedNegatedSubRule.erase(I: It);
1125 }
1126 }
1127
1128 if (!IgnoreNegatedSubRules) {
1129 for (const auto &Rule : Rules)
1130 SubjectMatchRules.push_back(Elt: attr::SubjectMatchRule(Rule.first));
1131 } else {
1132 for (const auto &Rule : Rules) {
1133 if (!isNegatedAttrMatcherSubRule(Rule: attr::SubjectMatchRule(Rule.first)))
1134 SubjectMatchRules.push_back(Elt: attr::SubjectMatchRule(Rule.first));
1135 }
1136 }
1137 Rules.clear();
1138 } else {
1139 // Each rule in Rules must be a strict subset of the attribute's
1140 // SubjectMatch rules. I.e. we're allowed to use
1141 // `apply_to=variables(is_global)` on an attrubute with SubjectList<[Var]>,
1142 // but should not allow `apply_to=variables` on an attribute which has
1143 // `SubjectList<[GlobalVar]>`.
1144 for (const auto &StrictRule : StrictSubjectMatchRuleSet) {
1145 // First, check for exact match.
1146 if (Rules.erase(Val: StrictRule.first)) {
1147 // Add the rule to the set of attribute receivers only if it's supported
1148 // in the current language mode.
1149 if (StrictRule.second)
1150 SubjectMatchRules.push_back(Elt: StrictRule.first);
1151 }
1152 }
1153 // Check remaining rules for subset matches.
1154 auto RulesToCheck = Rules;
1155 for (const auto &Rule : RulesToCheck) {
1156 attr::SubjectMatchRule MatchRule = attr::SubjectMatchRule(Rule.first);
1157 if (auto ParentRule = getParentAttrMatcherRule(Rule: MatchRule)) {
1158 if (llvm::any_of(Range&: StrictSubjectMatchRuleSet,
1159 P: [ParentRule](const auto &StrictRule) {
1160 return StrictRule.first == *ParentRule &&
1161 StrictRule.second; // IsEnabled
1162 })) {
1163 SubjectMatchRules.push_back(Elt: MatchRule);
1164 Rules.erase(Val: MatchRule);
1165 }
1166 }
1167 }
1168 }
1169
1170 if (!Rules.empty()) {
1171 auto Diagnostic =
1172 Diag(Loc: PragmaLoc, DiagID: diag::err_pragma_attribute_invalid_matchers)
1173 << Attribute;
1174 SmallVector<attr::SubjectMatchRule, 2> ExtraRules;
1175 for (const auto &Rule : Rules) {
1176 ExtraRules.push_back(Elt: attr::SubjectMatchRule(Rule.first));
1177 Diagnostic << FixItHint::CreateRemoval(
1178 RemoveRange: replacementRangeForListElement(S: *this, Range: Rule.second));
1179 }
1180 Diagnostic << attrMatcherRuleListToString(Rules: ExtraRules);
1181 }
1182
1183 if (PragmaAttributeStack.empty()) {
1184 Diag(Loc: PragmaLoc, DiagID: diag::err_pragma_attr_attr_no_push);
1185 return;
1186 }
1187
1188 PragmaAttributeStack.back().Entries.push_back(
1189 Elt: {.Loc: PragmaLoc, .Attribute: &Attribute, .MatchRules: std::move(SubjectMatchRules), /*IsUsed=*/false});
1190}
1191
1192void Sema::ActOnPragmaAttributeEmptyPush(SourceLocation PragmaLoc,
1193 const IdentifierInfo *Namespace) {
1194 PragmaAttributeStack.emplace_back();
1195 PragmaAttributeStack.back().Loc = PragmaLoc;
1196 PragmaAttributeStack.back().Namespace = Namespace;
1197}
1198
1199void Sema::ActOnPragmaAttributePop(SourceLocation PragmaLoc,
1200 const IdentifierInfo *Namespace) {
1201 if (PragmaAttributeStack.empty()) {
1202 Diag(Loc: PragmaLoc, DiagID: diag::err_pragma_attribute_stack_mismatch) << 1;
1203 return;
1204 }
1205
1206 // Dig back through the stack trying to find the most recently pushed group
1207 // that in Namespace. Note that this works fine if no namespace is present,
1208 // think of push/pops without namespaces as having an implicit "nullptr"
1209 // namespace.
1210 for (size_t Index = PragmaAttributeStack.size(); Index;) {
1211 --Index;
1212 if (PragmaAttributeStack[Index].Namespace == Namespace) {
1213 for (const PragmaAttributeEntry &Entry :
1214 PragmaAttributeStack[Index].Entries) {
1215 if (!Entry.IsUsed) {
1216 assert(Entry.Attribute && "Expected an attribute");
1217 Diag(Loc: Entry.Attribute->getLoc(), DiagID: diag::warn_pragma_attribute_unused)
1218 << *Entry.Attribute;
1219 Diag(Loc: PragmaLoc, DiagID: diag::note_pragma_attribute_region_ends_here);
1220 }
1221 }
1222 PragmaAttributeStack.erase(CI: PragmaAttributeStack.begin() + Index);
1223 return;
1224 }
1225 }
1226
1227 if (Namespace)
1228 Diag(Loc: PragmaLoc, DiagID: diag::err_pragma_attribute_stack_mismatch)
1229 << 0 << Namespace->getName();
1230 else
1231 Diag(Loc: PragmaLoc, DiagID: diag::err_pragma_attribute_stack_mismatch) << 1;
1232}
1233
1234void Sema::AddPragmaAttributes(Scope *S, Decl *D) {
1235 if (PragmaAttributeStack.empty())
1236 return;
1237
1238 if (const auto *P = dyn_cast<ParmVarDecl>(Val: D))
1239 if (P->getType()->isVoidType())
1240 return;
1241
1242 for (auto &Group : PragmaAttributeStack) {
1243 for (auto &Entry : Group.Entries) {
1244 ParsedAttr *Attribute = Entry.Attribute;
1245 assert(Attribute && "Expected an attribute");
1246 assert(Attribute->isPragmaClangAttribute() &&
1247 "expected #pragma clang attribute");
1248
1249 // Ensure that the attribute can be applied to the given declaration.
1250 bool Applies = false;
1251 for (const auto &Rule : Entry.MatchRules) {
1252 if (Attribute->appliesToDecl(D, MatchRule: Rule)) {
1253 Applies = true;
1254 break;
1255 }
1256 }
1257 if (!Applies)
1258 continue;
1259 Entry.IsUsed = true;
1260 PragmaAttributeCurrentTargetDecl = D;
1261 ParsedAttributesView Attrs;
1262 Attrs.addAtEnd(newAttr: Attribute);
1263 ProcessDeclAttributeList(S, D, AttrList: Attrs);
1264 PragmaAttributeCurrentTargetDecl = nullptr;
1265 }
1266 }
1267}
1268
1269void Sema::PrintPragmaAttributeInstantiationPoint(
1270 InstantiationContextDiagFuncRef DiagFunc) {
1271 assert(PragmaAttributeCurrentTargetDecl && "Expected an active declaration");
1272 DiagFunc(PragmaAttributeCurrentTargetDecl->getBeginLoc(),
1273 PDiag(DiagID: diag::note_pragma_attribute_applied_decl_here));
1274}
1275
1276void Sema::DiagnosePrecisionLossInComplexDivision() {
1277 for (auto &[Type, Num] : ExcessPrecisionNotSatisfied) {
1278 assert(LocationOfExcessPrecisionNotSatisfied.isValid() &&
1279 "expected a valid source location");
1280 Diag(Loc: LocationOfExcessPrecisionNotSatisfied,
1281 DiagID: diag::warn_excess_precision_not_supported)
1282 << static_cast<bool>(Num);
1283 }
1284}
1285
1286void Sema::DiagnoseUnterminatedPragmaAttribute() {
1287 if (PragmaAttributeStack.empty())
1288 return;
1289 Diag(Loc: PragmaAttributeStack.back().Loc, DiagID: diag::err_pragma_attribute_no_pop_eof);
1290}
1291
1292void Sema::ActOnPragmaOptimize(bool On, SourceLocation PragmaLoc) {
1293 if(On)
1294 OptimizeOffPragmaLocation = SourceLocation();
1295 else
1296 OptimizeOffPragmaLocation = PragmaLoc;
1297}
1298
1299void Sema::ActOnPragmaMSOptimize(SourceLocation Loc, bool IsOn) {
1300 if (!CurContext->getRedeclContext()->isFileContext()) {
1301 Diag(Loc, DiagID: diag::err_pragma_expected_file_scope) << "optimize";
1302 return;
1303 }
1304
1305 MSPragmaOptimizeIsOn = IsOn;
1306}
1307
1308void Sema::ActOnPragmaMSFunction(
1309 SourceLocation Loc, const llvm::SmallVectorImpl<StringRef> &NoBuiltins) {
1310 if (!CurContext->getRedeclContext()->isFileContext()) {
1311 Diag(Loc, DiagID: diag::err_pragma_expected_file_scope) << "function";
1312 return;
1313 }
1314
1315 MSFunctionNoBuiltins.insert_range(R: NoBuiltins);
1316}
1317
1318void Sema::AddRangeBasedOptnone(FunctionDecl *FD) {
1319 // In the future, check other pragmas if they're implemented (e.g. pragma
1320 // optimize 0 will probably map to this functionality too).
1321 if(OptimizeOffPragmaLocation.isValid())
1322 AddOptnoneAttributeIfNoConflicts(FD, Loc: OptimizeOffPragmaLocation);
1323}
1324
1325void Sema::AddSectionMSAllocText(FunctionDecl *FD) {
1326 if (!FD->getIdentifier())
1327 return;
1328
1329 StringRef Name = FD->getName();
1330 auto It = FunctionToSectionMap.find(Key: Name);
1331 if (It != FunctionToSectionMap.end()) {
1332 StringRef Section;
1333 SourceLocation Loc;
1334 std::tie(args&: Section, args&: Loc) = It->second;
1335
1336 if (!FD->hasAttr<SectionAttr>())
1337 FD->addAttr(A: SectionAttr::CreateImplicit(Ctx&: Context, Name: Section));
1338 }
1339}
1340
1341void Sema::ModifyFnAttributesMSPragmaOptimize(FunctionDecl *FD) {
1342 // Don't modify the function attributes if it's "on". "on" resets the
1343 // optimizations to the ones listed on the command line
1344 if (!MSPragmaOptimizeIsOn)
1345 AddOptnoneAttributeIfNoConflicts(FD, Loc: FD->getBeginLoc());
1346}
1347
1348void Sema::AddOptnoneAttributeIfNoConflicts(FunctionDecl *FD,
1349 SourceLocation Loc) {
1350 // Don't add a conflicting attribute. No diagnostic is needed.
1351 if (FD->hasAttr<MinSizeAttr>() || FD->hasAttr<AlwaysInlineAttr>())
1352 return;
1353
1354 // Add attributes only if required. Optnone requires noinline as well, but if
1355 // either is already present then don't bother adding them.
1356 if (!FD->hasAttr<OptimizeNoneAttr>())
1357 FD->addAttr(A: OptimizeNoneAttr::CreateImplicit(Ctx&: Context, Range: Loc));
1358 if (!FD->hasAttr<NoInlineAttr>())
1359 FD->addAttr(A: NoInlineAttr::CreateImplicit(Ctx&: Context, Range: Loc));
1360}
1361
1362void Sema::AddImplicitMSFunctionNoBuiltinAttr(FunctionDecl *FD) {
1363 if (FD->isDeleted() || FD->isDefaulted())
1364 return;
1365 SmallVector<StringRef> V(MSFunctionNoBuiltins.begin(),
1366 MSFunctionNoBuiltins.end());
1367 if (!MSFunctionNoBuiltins.empty())
1368 FD->addAttr(A: NoBuiltinAttr::CreateImplicit(Ctx&: Context, BuiltinNames: V.data(), BuiltinNamesSize: V.size()));
1369}
1370
1371NamedDecl *Sema::lookupExternCFunctionOrVariable(IdentifierInfo *IdentId,
1372 SourceLocation NameLoc,
1373 Scope *curScope) {
1374 LookupResult Result(*this, IdentId, NameLoc, LookupOrdinaryName);
1375 LookupName(R&: Result, S: curScope);
1376 if (!getLangOpts().CPlusPlus)
1377 return Result.getAsSingle<NamedDecl>();
1378 for (NamedDecl *D : Result) {
1379 if (auto *FD = dyn_cast<FunctionDecl>(Val: D))
1380 if (FD->isExternC())
1381 return D;
1382 if (isa<VarDecl>(Val: D))
1383 return D;
1384 }
1385 return nullptr;
1386}
1387
1388void Sema::ActOnPragmaExport(IdentifierInfo *IdentId, SourceLocation NameLoc,
1389 Scope *curScope) {
1390 if (!CurContext->getRedeclContext()->isFileContext()) {
1391 Diag(Loc: NameLoc, DiagID: diag::err_pragma_expected_file_scope) << "export";
1392 return;
1393 }
1394
1395 PendingPragmaInfo Info;
1396 Info.NameLoc = NameLoc;
1397 Info.Used = false;
1398
1399 NamedDecl *PrevDecl =
1400 lookupExternCFunctionOrVariable(IdentId, NameLoc, curScope);
1401 if (!PrevDecl) {
1402 PendingExportedNames[IdentId] = Info;
1403 return;
1404 }
1405
1406 if (auto *FD = dyn_cast<FunctionDecl>(Val: PrevDecl->getCanonicalDecl())) {
1407 if (!FD->hasExternalFormalLinkage()) {
1408 Diag(Loc: NameLoc, DiagID: diag::warn_pragma_not_applied) << "export" << PrevDecl;
1409 return;
1410 }
1411 if (FD->hasBody()) {
1412 Diag(Loc: NameLoc, DiagID: diag::warn_pragma_not_applied_to_defined_symbol)
1413 << "export";
1414 return;
1415 }
1416 } else if (auto *VD = dyn_cast<VarDecl>(Val: PrevDecl->getCanonicalDecl())) {
1417 if (!VD->hasExternalFormalLinkage()) {
1418 Diag(Loc: NameLoc, DiagID: diag::warn_pragma_not_applied) << "export" << PrevDecl;
1419 return;
1420 }
1421 if (VD->hasDefinition() == VarDecl::Definition) {
1422 Diag(Loc: NameLoc, DiagID: diag::warn_pragma_not_applied_to_defined_symbol)
1423 << "export";
1424 return;
1425 }
1426 }
1427 mergeVisibilityType(D: PrevDecl->getCanonicalDecl(), Loc: NameLoc,
1428 Type: VisibilityAttr::Default);
1429}
1430
1431typedef std::vector<std::pair<unsigned, SourceLocation> > VisStack;
1432enum : unsigned { NoVisibility = ~0U };
1433
1434void Sema::AddPushedVisibilityAttribute(Decl *D) {
1435 if (!VisContext)
1436 return;
1437
1438 NamedDecl *ND = dyn_cast<NamedDecl>(Val: D);
1439 if (ND && ND->getExplicitVisibility(kind: NamedDecl::VisibilityForValue))
1440 return;
1441
1442 VisStack *Stack = static_cast<VisStack*>(VisContext);
1443 unsigned rawType = Stack->back().first;
1444 if (rawType == NoVisibility) return;
1445
1446 VisibilityAttr::VisibilityType type
1447 = (VisibilityAttr::VisibilityType) rawType;
1448 SourceLocation loc = Stack->back().second;
1449
1450 D->addAttr(A: VisibilityAttr::CreateImplicit(Ctx&: Context, Visibility: type, Range: loc));
1451}
1452
1453void Sema::FreeVisContext() {
1454 delete static_cast<VisStack*>(VisContext);
1455 VisContext = nullptr;
1456}
1457
1458static void PushPragmaVisibility(Sema &S, unsigned type, SourceLocation loc) {
1459 // Put visibility on stack.
1460 if (!S.VisContext)
1461 S.VisContext = new VisStack;
1462
1463 VisStack *Stack = static_cast<VisStack*>(S.VisContext);
1464 Stack->push_back(x: std::make_pair(x&: type, y&: loc));
1465}
1466
1467void Sema::ActOnPragmaVisibility(const IdentifierInfo* VisType,
1468 SourceLocation PragmaLoc) {
1469 if (VisType) {
1470 // Compute visibility to use.
1471 VisibilityAttr::VisibilityType T;
1472 if (!VisibilityAttr::ConvertStrToVisibilityType(Val: VisType->getName(), Out&: T)) {
1473 Diag(Loc: PragmaLoc, DiagID: diag::warn_attribute_unknown_visibility) << VisType;
1474 return;
1475 }
1476 PushPragmaVisibility(S&: *this, type: T, loc: PragmaLoc);
1477 } else {
1478 PopPragmaVisibility(IsNamespaceEnd: false, EndLoc: PragmaLoc);
1479 }
1480}
1481
1482void Sema::ActOnPragmaFPContract(SourceLocation Loc,
1483 LangOptions::FPModeKind FPC) {
1484 FPOptionsOverride NewFPFeatures = CurFPFeatureOverrides();
1485 switch (FPC) {
1486 case LangOptions::FPM_On:
1487 NewFPFeatures.setAllowFPContractWithinStatement();
1488 break;
1489 case LangOptions::FPM_Fast:
1490 case LangOptions::FPM_FastHonorPragmas:
1491 NewFPFeatures.setAllowFPContractAcrossStatement();
1492 break;
1493 case LangOptions::FPM_Off:
1494 NewFPFeatures.setDisallowFPContract();
1495 break;
1496 }
1497 FpPragmaStack.Act(PragmaLocation: Loc, Action: Sema::PSK_Set, StackSlotLabel: StringRef(), Value: NewFPFeatures);
1498 CurFPFeatures = NewFPFeatures.applyOverrides(LO: getLangOpts());
1499}
1500
1501void Sema::ActOnPragmaFPValueChangingOption(SourceLocation Loc,
1502 PragmaFPKind Kind, bool IsEnabled) {
1503 if (IsEnabled) {
1504 // For value unsafe context, combining this pragma with eval method
1505 // setting is not recommended. See comment in function FixupInvocation#506.
1506 int Reason = -1;
1507 if (getLangOpts().getFPEvalMethod() != LangOptions::FEM_UnsetOnCommandLine)
1508 // Eval method set using the option 'ffp-eval-method'.
1509 Reason = 1;
1510 if (PP.getLastFPEvalPragmaLocation().isValid())
1511 // Eval method set using the '#pragma clang fp eval_method'.
1512 // We could have both an option and a pragma used to the set the eval
1513 // method. The pragma overrides the option in the command line. The Reason
1514 // of the diagnostic is overriden too.
1515 Reason = 0;
1516 if (Reason != -1)
1517 Diag(Loc, DiagID: diag::err_setting_eval_method_used_in_unsafe_context)
1518 << Reason << (Kind == PFK_Reassociate ? 4 : 5);
1519 }
1520
1521 FPOptionsOverride NewFPFeatures = CurFPFeatureOverrides();
1522 switch (Kind) {
1523 case PFK_Reassociate:
1524 NewFPFeatures.setAllowFPReassociateOverride(IsEnabled);
1525 break;
1526 case PFK_Reciprocal:
1527 NewFPFeatures.setAllowReciprocalOverride(IsEnabled);
1528 break;
1529 default:
1530 llvm_unreachable("unhandled value changing pragma fp");
1531 }
1532
1533 FpPragmaStack.Act(PragmaLocation: Loc, Action: PSK_Set, StackSlotLabel: StringRef(), Value: NewFPFeatures);
1534 CurFPFeatures = NewFPFeatures.applyOverrides(LO: getLangOpts());
1535}
1536
1537void Sema::ActOnPragmaFEnvRound(SourceLocation Loc, llvm::RoundingMode FPR) {
1538 FPOptionsOverride NewFPFeatures = CurFPFeatureOverrides();
1539 NewFPFeatures.setConstRoundingModeOverride(FPR);
1540 FpPragmaStack.Act(PragmaLocation: Loc, Action: PSK_Set, StackSlotLabel: StringRef(), Value: NewFPFeatures);
1541 CurFPFeatures = NewFPFeatures.applyOverrides(LO: getLangOpts());
1542}
1543
1544void Sema::setExceptionMode(SourceLocation Loc,
1545 LangOptions::FPExceptionModeKind FPE) {
1546 FPOptionsOverride NewFPFeatures = CurFPFeatureOverrides();
1547 NewFPFeatures.setSpecifiedExceptionModeOverride(FPE);
1548 FpPragmaStack.Act(PragmaLocation: Loc, Action: PSK_Set, StackSlotLabel: StringRef(), Value: NewFPFeatures);
1549 CurFPFeatures = NewFPFeatures.applyOverrides(LO: getLangOpts());
1550}
1551
1552void Sema::ActOnPragmaFEnvAccess(SourceLocation Loc, bool IsEnabled) {
1553 FPOptionsOverride NewFPFeatures = CurFPFeatureOverrides();
1554 if (IsEnabled) {
1555 // Verify Microsoft restriction:
1556 // You can't enable fenv_access unless precise semantics are enabled.
1557 // Precise semantics can be enabled either by the float_control
1558 // pragma, or by using the /fp:precise or /fp:strict compiler options
1559 if (!isPreciseFPEnabled())
1560 Diag(Loc, DiagID: diag::err_pragma_fenv_requires_precise);
1561 }
1562 NewFPFeatures.setAllowFEnvAccessOverride(IsEnabled);
1563 NewFPFeatures.setRoundingMathOverride(IsEnabled);
1564 FpPragmaStack.Act(PragmaLocation: Loc, Action: PSK_Set, StackSlotLabel: StringRef(), Value: NewFPFeatures);
1565 CurFPFeatures = NewFPFeatures.applyOverrides(LO: getLangOpts());
1566}
1567
1568void Sema::ActOnPragmaCXLimitedRange(SourceLocation Loc,
1569 LangOptions::ComplexRangeKind Range) {
1570 FPOptionsOverride NewFPFeatures = CurFPFeatureOverrides();
1571 NewFPFeatures.setComplexRangeOverride(Range);
1572 FpPragmaStack.Act(PragmaLocation: Loc, Action: PSK_Set, StackSlotLabel: StringRef(), Value: NewFPFeatures);
1573 CurFPFeatures = NewFPFeatures.applyOverrides(LO: getLangOpts());
1574}
1575
1576void Sema::ActOnPragmaFPExceptions(SourceLocation Loc,
1577 LangOptions::FPExceptionModeKind FPE) {
1578 setExceptionMode(Loc, FPE);
1579}
1580
1581void Sema::PushNamespaceVisibilityAttr(const VisibilityAttr *Attr,
1582 SourceLocation Loc) {
1583 // Visibility calculations will consider the namespace's visibility.
1584 // Here we just want to note that we're in a visibility context
1585 // which overrides any enclosing #pragma context, but doesn't itself
1586 // contribute visibility.
1587 PushPragmaVisibility(S&: *this, type: NoVisibility, loc: Loc);
1588}
1589
1590void Sema::PopPragmaVisibility(bool IsNamespaceEnd, SourceLocation EndLoc) {
1591 if (!VisContext) {
1592 Diag(Loc: EndLoc, DiagID: diag::err_pragma_pop_visibility_mismatch);
1593 return;
1594 }
1595
1596 // Pop visibility from stack
1597 VisStack *Stack = static_cast<VisStack*>(VisContext);
1598
1599 const std::pair<unsigned, SourceLocation> *Back = &Stack->back();
1600 bool StartsWithPragma = Back->first != NoVisibility;
1601 if (StartsWithPragma && IsNamespaceEnd) {
1602 Diag(Loc: Back->second, DiagID: diag::err_pragma_push_visibility_mismatch);
1603 Diag(Loc: EndLoc, DiagID: diag::note_surrounding_namespace_ends_here);
1604
1605 // For better error recovery, eat all pushes inside the namespace.
1606 do {
1607 Stack->pop_back();
1608 Back = &Stack->back();
1609 StartsWithPragma = Back->first != NoVisibility;
1610 } while (StartsWithPragma);
1611 } else if (!StartsWithPragma && !IsNamespaceEnd) {
1612 Diag(Loc: EndLoc, DiagID: diag::err_pragma_pop_visibility_mismatch);
1613 Diag(Loc: Back->second, DiagID: diag::note_surrounding_namespace_starts_here);
1614 return;
1615 }
1616
1617 Stack->pop_back();
1618 // To simplify the implementation, never keep around an empty stack.
1619 if (Stack->empty())
1620 FreeVisContext();
1621}
1622
1623template <typename Ty>
1624static bool checkCommonAttributeFeatures(Sema &S, const Ty *Node,
1625 const ParsedAttr &A,
1626 bool SkipArgCountCheck) {
1627 // Several attributes carry different semantics than the parsing requires, so
1628 // those are opted out of the common argument checks.
1629 //
1630 // We also bail on unknown and ignored attributes because those are handled
1631 // as part of the target-specific handling logic.
1632 if (A.getKind() == ParsedAttr::UnknownAttribute)
1633 return false;
1634 // Check whether the attribute requires specific language extensions to be
1635 // enabled.
1636 if (!A.diagnoseLangOpts(S))
1637 return true;
1638 // Check whether the attribute appertains to the given subject.
1639 if (!A.diagnoseAppertainsTo(S, Node))
1640 return true;
1641 // Check whether the attribute is mutually exclusive with other attributes
1642 // that have already been applied to the declaration.
1643 if (!A.diagnoseMutualExclusion(S, Node))
1644 return true;
1645 // Check whether the attribute exists in the target architecture.
1646 if (S.CheckAttrTarget(CurrAttr: A))
1647 return true;
1648
1649 if (A.hasCustomParsing())
1650 return false;
1651
1652 if (!SkipArgCountCheck) {
1653 if (A.getMinArgs() == A.getMaxArgs()) {
1654 // If there are no optional arguments, then checking for the argument
1655 // count is trivial.
1656 if (!A.checkExactlyNumArgs(S, Num: A.getMinArgs()))
1657 return true;
1658 } else {
1659 // There are optional arguments, so checking is slightly more involved.
1660 if (A.getMinArgs() && !A.checkAtLeastNumArgs(S, Num: A.getMinArgs()))
1661 return true;
1662 else if (!A.hasVariadicArg() && A.getMaxArgs() &&
1663 !A.checkAtMostNumArgs(S, Num: A.getMaxArgs()))
1664 return true;
1665 }
1666 }
1667
1668 return false;
1669}
1670
1671bool Sema::checkCommonAttributeFeatures(const Decl *D, const ParsedAttr &A,
1672 bool SkipArgCountCheck) {
1673 return ::checkCommonAttributeFeatures(S&: *this, Node: D, A, SkipArgCountCheck);
1674}
1675bool Sema::checkCommonAttributeFeatures(const Stmt *S, const ParsedAttr &A,
1676 bool SkipArgCountCheck) {
1677 return ::checkCommonAttributeFeatures(S&: *this, Node: S, A, SkipArgCountCheck);
1678}
1679