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

Provided by KDAB

Privacy Policy
Update your C++ knowledge – Modern C++11/14/17 Training
Find out more

source code of clang/lib/Sema/SemaAttr.cpp