1 //===--- SemaAttr.cpp - Semantic Analysis for Attributes ------------------===//
3 // The LLVM Compiler Infrastructure
5 // This file is distributed under the University of Illinois Open Source
6 // License. See LICENSE.TXT for details.
8 //===----------------------------------------------------------------------===//
10 // This file implements semantic analysis for non-trivial attributes and
13 //===----------------------------------------------------------------------===//
15 #include "clang/AST/ASTConsumer.h"
16 #include "clang/AST/Attr.h"
17 #include "clang/AST/Expr.h"
18 #include "clang/Basic/TargetInfo.h"
19 #include "clang/Lex/Preprocessor.h"
20 #include "clang/Sema/Lookup.h"
21 #include "clang/Sema/SemaInternal.h"
22 using namespace clang;
24 //===----------------------------------------------------------------------===//
25 // Pragma 'pack' and 'options align'
26 //===----------------------------------------------------------------------===//
28 Sema::PragmaStackSentinelRAII::PragmaStackSentinelRAII(Sema &S,
31 : S(S), SlotLabel(SlotLabel), ShouldAct(ShouldAct) {
33 S.VtorDispStack.SentinelAction(PSK_Push, SlotLabel);
34 S.DataSegStack.SentinelAction(PSK_Push, SlotLabel);
35 S.BSSSegStack.SentinelAction(PSK_Push, SlotLabel);
36 S.ConstSegStack.SentinelAction(PSK_Push, SlotLabel);
37 S.CodeSegStack.SentinelAction(PSK_Push, SlotLabel);
41 Sema::PragmaStackSentinelRAII::~PragmaStackSentinelRAII() {
43 S.VtorDispStack.SentinelAction(PSK_Pop, SlotLabel);
44 S.DataSegStack.SentinelAction(PSK_Pop, SlotLabel);
45 S.BSSSegStack.SentinelAction(PSK_Pop, SlotLabel);
46 S.ConstSegStack.SentinelAction(PSK_Pop, SlotLabel);
47 S.CodeSegStack.SentinelAction(PSK_Pop, SlotLabel);
51 void Sema::AddAlignmentAttributesForRecord(RecordDecl *RD) {
52 // If there is no pack value, we don't need any attributes.
53 if (!PackStack.CurrentValue)
56 // Otherwise, check to see if we need a max field alignment attribute.
57 if (unsigned Alignment = PackStack.CurrentValue) {
58 if (Alignment == Sema::kMac68kAlignmentSentinel)
59 RD->addAttr(AlignMac68kAttr::CreateImplicit(Context));
61 RD->addAttr(MaxFieldAlignmentAttr::CreateImplicit(Context,
66 void Sema::AddMsStructLayoutForRecord(RecordDecl *RD) {
68 RD->addAttr(MSStructAttr::CreateImplicit(Context));
70 // FIXME: We should merge AddAlignmentAttributesForRecord with
71 // AddMsStructLayoutForRecord into AddPragmaAttributesForRecord, which takes
72 // all active pragmas and applies them as attributes to class definitions.
73 if (VtorDispStack.CurrentValue != getLangOpts().VtorDispMode)
75 MSVtorDispAttr::CreateImplicit(Context, VtorDispStack.CurrentValue));
78 void Sema::ActOnPragmaOptionsAlign(PragmaOptionsAlignKind Kind,
79 SourceLocation PragmaLoc) {
80 PragmaMsStackAction Action = Sema::PSK_Reset;
81 unsigned Alignment = 0;
83 // For all targets we support native and natural are the same.
85 // FIXME: This is not true on Darwin/PPC.
89 Action = Sema::PSK_Push_Set;
93 // Note that '#pragma options align=packed' is not equivalent to attribute
94 // packed, it has a different precedence relative to attribute aligned.
96 Action = Sema::PSK_Push_Set;
101 // Check if the target supports this.
102 if (!this->Context.getTargetInfo().hasAlignMac68kSupport()) {
103 Diag(PragmaLoc, diag::err_pragma_options_align_mac68k_target_unsupported);
106 Action = Sema::PSK_Push_Set;
107 Alignment = Sema::kMac68kAlignmentSentinel;
111 // Reset just pops the top of the stack, or resets the current alignment to
113 Action = Sema::PSK_Pop;
114 if (PackStack.Stack.empty()) {
115 if (PackStack.CurrentValue) {
116 Action = Sema::PSK_Reset;
118 Diag(PragmaLoc, diag::warn_pragma_options_align_reset_failed)
126 PackStack.Act(PragmaLoc, Action, StringRef(), Alignment);
129 void Sema::ActOnPragmaPack(SourceLocation PragmaLoc, PragmaMsStackAction Action,
130 StringRef SlotLabel, Expr *alignment) {
131 Expr *Alignment = static_cast<Expr *>(alignment);
133 // If specified then alignment must be a "small" power of two.
134 unsigned AlignmentVal = 0;
138 // pack(0) is like pack(), which just works out since that is what
139 // we use 0 for in PackAttr.
140 if (Alignment->isTypeDependent() ||
141 Alignment->isValueDependent() ||
142 !Alignment->isIntegerConstantExpr(Val, Context) ||
143 !(Val == 0 || Val.isPowerOf2()) ||
144 Val.getZExtValue() > 16) {
145 Diag(PragmaLoc, diag::warn_pragma_pack_invalid_alignment);
149 AlignmentVal = (unsigned) Val.getZExtValue();
151 if (Action == Sema::PSK_Show) {
152 // Show the current alignment, making sure to show the right value
154 // FIXME: This should come from the target.
155 AlignmentVal = PackStack.CurrentValue;
156 if (AlignmentVal == 0)
158 if (AlignmentVal == Sema::kMac68kAlignmentSentinel)
159 Diag(PragmaLoc, diag::warn_pragma_pack_show) << "mac68k";
161 Diag(PragmaLoc, diag::warn_pragma_pack_show) << AlignmentVal;
163 // MSDN, C/C++ Preprocessor Reference > Pragma Directives > pack:
164 // "#pragma pack(pop, identifier, n) is undefined"
165 if (Action & Sema::PSK_Pop) {
166 if (Alignment && !SlotLabel.empty())
167 Diag(PragmaLoc, diag::warn_pragma_pack_pop_identifer_and_alignment);
168 if (PackStack.Stack.empty())
169 Diag(PragmaLoc, diag::warn_pragma_pop_failed) << "pack" << "stack empty";
172 PackStack.Act(PragmaLoc, Action, SlotLabel, AlignmentVal);
175 void Sema::ActOnPragmaMSStruct(PragmaMSStructKind Kind) {
176 MSStructPragmaOn = (Kind == PMSST_ON);
179 void Sema::ActOnPragmaMSComment(SourceLocation CommentLoc,
180 PragmaMSCommentKind Kind, StringRef Arg) {
181 auto *PCD = PragmaCommentDecl::Create(
182 Context, Context.getTranslationUnitDecl(), CommentLoc, Kind, Arg);
183 Context.getTranslationUnitDecl()->addDecl(PCD);
184 Consumer.HandleTopLevelDecl(DeclGroupRef(PCD));
187 void Sema::ActOnPragmaDetectMismatch(SourceLocation Loc, StringRef Name,
189 auto *PDMD = PragmaDetectMismatchDecl::Create(
190 Context, Context.getTranslationUnitDecl(), Loc, Name, Value);
191 Context.getTranslationUnitDecl()->addDecl(PDMD);
192 Consumer.HandleTopLevelDecl(DeclGroupRef(PDMD));
195 void Sema::ActOnPragmaMSPointersToMembers(
196 LangOptions::PragmaMSPointersToMembersKind RepresentationMethod,
197 SourceLocation PragmaLoc) {
198 MSPointerToMemberRepresentationMethod = RepresentationMethod;
199 ImplicitMSInheritanceAttrLoc = PragmaLoc;
202 void Sema::ActOnPragmaMSVtorDisp(PragmaMsStackAction Action,
203 SourceLocation PragmaLoc,
204 MSVtorDispAttr::Mode Mode) {
205 if (Action & PSK_Pop && VtorDispStack.Stack.empty())
206 Diag(PragmaLoc, diag::warn_pragma_pop_failed) << "vtordisp"
208 VtorDispStack.Act(PragmaLoc, Action, StringRef(), Mode);
211 template<typename ValueType>
212 void Sema::PragmaStack<ValueType>::Act(SourceLocation PragmaLocation,
213 PragmaMsStackAction Action,
214 llvm::StringRef StackSlotLabel,
216 if (Action == PSK_Reset) {
217 CurrentValue = DefaultValue;
218 CurrentPragmaLocation = PragmaLocation;
221 if (Action & PSK_Push)
222 Stack.push_back(Slot(StackSlotLabel, CurrentValue, CurrentPragmaLocation));
223 else if (Action & PSK_Pop) {
224 if (!StackSlotLabel.empty()) {
225 // If we've got a label, try to find it and jump there.
226 auto I = llvm::find_if(llvm::reverse(Stack), [&](const Slot &x) {
227 return x.StackSlotLabel == StackSlotLabel;
229 // If we found the label so pop from there.
230 if (I != Stack.rend()) {
231 CurrentValue = I->Value;
232 CurrentPragmaLocation = I->PragmaLocation;
233 Stack.erase(std::prev(I.base()), Stack.end());
235 } else if (!Stack.empty()) {
236 // We don't have a label, just pop the last entry.
237 CurrentValue = Stack.back().Value;
238 CurrentPragmaLocation = Stack.back().PragmaLocation;
242 if (Action & PSK_Set) {
243 CurrentValue = Value;
244 CurrentPragmaLocation = PragmaLocation;
248 bool Sema::UnifySection(StringRef SectionName,
250 DeclaratorDecl *Decl) {
251 auto Section = Context.SectionInfos.find(SectionName);
252 if (Section == Context.SectionInfos.end()) {
253 Context.SectionInfos[SectionName] =
254 ASTContext::SectionInfo(Decl, SourceLocation(), SectionFlags);
257 // A pre-declared section takes precedence w/o diagnostic.
258 if (Section->second.SectionFlags == SectionFlags ||
259 !(Section->second.SectionFlags & ASTContext::PSF_Implicit))
261 auto OtherDecl = Section->second.Decl;
262 Diag(Decl->getLocation(), diag::err_section_conflict)
263 << Decl << OtherDecl;
264 Diag(OtherDecl->getLocation(), diag::note_declared_at)
265 << OtherDecl->getName();
266 if (auto A = Decl->getAttr<SectionAttr>())
268 Diag(A->getLocation(), diag::note_pragma_entered_here);
269 if (auto A = OtherDecl->getAttr<SectionAttr>())
271 Diag(A->getLocation(), diag::note_pragma_entered_here);
275 bool Sema::UnifySection(StringRef SectionName,
277 SourceLocation PragmaSectionLocation) {
278 auto Section = Context.SectionInfos.find(SectionName);
279 if (Section != Context.SectionInfos.end()) {
280 if (Section->second.SectionFlags == SectionFlags)
282 if (!(Section->second.SectionFlags & ASTContext::PSF_Implicit)) {
283 Diag(PragmaSectionLocation, diag::err_section_conflict)
284 << "this" << "a prior #pragma section";
285 Diag(Section->second.PragmaSectionLocation,
286 diag::note_pragma_entered_here);
290 Context.SectionInfos[SectionName] =
291 ASTContext::SectionInfo(nullptr, PragmaSectionLocation, SectionFlags);
295 /// \brief Called on well formed \#pragma bss_seg().
296 void Sema::ActOnPragmaMSSeg(SourceLocation PragmaLocation,
297 PragmaMsStackAction Action,
298 llvm::StringRef StackSlotLabel,
299 StringLiteral *SegmentName,
300 llvm::StringRef PragmaName) {
301 PragmaStack<StringLiteral *> *Stack =
302 llvm::StringSwitch<PragmaStack<StringLiteral *> *>(PragmaName)
303 .Case("data_seg", &DataSegStack)
304 .Case("bss_seg", &BSSSegStack)
305 .Case("const_seg", &ConstSegStack)
306 .Case("code_seg", &CodeSegStack);
307 if (Action & PSK_Pop && Stack->Stack.empty())
308 Diag(PragmaLocation, diag::warn_pragma_pop_failed) << PragmaName
311 !checkSectionName(SegmentName->getLocStart(), SegmentName->getString()))
313 Stack->Act(PragmaLocation, Action, StackSlotLabel, SegmentName);
316 /// \brief Called on well formed \#pragma bss_seg().
317 void Sema::ActOnPragmaMSSection(SourceLocation PragmaLocation,
318 int SectionFlags, StringLiteral *SegmentName) {
319 UnifySection(SegmentName->getString(), SectionFlags, PragmaLocation);
322 void Sema::ActOnPragmaMSInitSeg(SourceLocation PragmaLocation,
323 StringLiteral *SegmentName) {
324 // There's no stack to maintain, so we just have a current section. When we
325 // see the default section, reset our current section back to null so we stop
326 // tacking on unnecessary attributes.
327 CurInitSeg = SegmentName->getString() == ".CRT$XCU" ? nullptr : SegmentName;
328 CurInitSegLoc = PragmaLocation;
331 void Sema::ActOnPragmaUnused(const Token &IdTok, Scope *curScope,
332 SourceLocation PragmaLoc) {
334 IdentifierInfo *Name = IdTok.getIdentifierInfo();
335 LookupResult Lookup(*this, Name, IdTok.getLocation(), LookupOrdinaryName);
336 LookupParsedName(Lookup, curScope, nullptr, true);
338 if (Lookup.empty()) {
339 Diag(PragmaLoc, diag::warn_pragma_unused_undeclared_var)
340 << Name << SourceRange(IdTok.getLocation());
344 VarDecl *VD = Lookup.getAsSingle<VarDecl>();
346 Diag(PragmaLoc, diag::warn_pragma_unused_expected_var_arg)
347 << Name << SourceRange(IdTok.getLocation());
351 // Warn if this was used before being marked unused.
353 Diag(PragmaLoc, diag::warn_used_but_marked_unused) << Name;
355 VD->addAttr(UnusedAttr::CreateImplicit(Context, UnusedAttr::GNU_unused,
356 IdTok.getLocation()));
359 void Sema::AddCFAuditedAttribute(Decl *D) {
360 SourceLocation Loc = PP.getPragmaARCCFCodeAuditedLoc();
361 if (!Loc.isValid()) return;
363 // Don't add a redundant or conflicting attribute.
364 if (D->hasAttr<CFAuditedTransferAttr>() ||
365 D->hasAttr<CFUnknownTransferAttr>())
368 D->addAttr(CFAuditedTransferAttr::CreateImplicit(Context, Loc));
373 Optional<attr::SubjectMatchRule>
374 getParentAttrMatcherRule(attr::SubjectMatchRule Rule) {
375 using namespace attr;
379 #define ATTR_MATCH_RULE(Value, Spelling, IsAbstract)
380 #define ATTR_MATCH_SUB_RULE(Value, Spelling, IsAbstract, Parent, IsNegated) \
383 #include "clang/Basic/AttrSubMatchRulesList.inc"
387 bool isNegatedAttrMatcherSubRule(attr::SubjectMatchRule Rule) {
388 using namespace attr;
392 #define ATTR_MATCH_RULE(Value, Spelling, IsAbstract)
393 #define ATTR_MATCH_SUB_RULE(Value, Spelling, IsAbstract, Parent, IsNegated) \
396 #include "clang/Basic/AttrSubMatchRulesList.inc"
400 CharSourceRange replacementRangeForListElement(const Sema &S,
402 // Make sure that the ',' is removed as well.
403 SourceLocation AfterCommaLoc = Lexer::findLocationAfterToken(
404 Range.getEnd(), tok::comma, S.getSourceManager(), S.getLangOpts(),
405 /*SkipTrailingWhitespaceAndNewLine=*/false);
406 if (AfterCommaLoc.isValid())
407 return CharSourceRange::getCharRange(Range.getBegin(), AfterCommaLoc);
409 return CharSourceRange::getTokenRange(Range);
413 attrMatcherRuleListToString(ArrayRef<attr::SubjectMatchRule> Rules) {
415 llvm::raw_string_ostream OS(Result);
416 for (const auto &I : llvm::enumerate(Rules)) {
418 OS << (I.index() == Rules.size() - 1 ? ", and " : ", ");
419 OS << "'" << attr::getSubjectMatchRuleSpelling(I.value()) << "'";
424 } // end anonymous namespace
426 void Sema::ActOnPragmaAttributePush(AttributeList &Attribute,
427 SourceLocation PragmaLoc,
428 attr::ParsedSubjectMatchRuleSet Rules) {
429 SmallVector<attr::SubjectMatchRule, 4> SubjectMatchRules;
430 // Gather the subject match rules that are supported by the attribute.
431 SmallVector<std::pair<attr::SubjectMatchRule, bool>, 4>
432 StrictSubjectMatchRuleSet;
433 Attribute.getMatchRules(LangOpts, StrictSubjectMatchRuleSet);
435 // Figure out which subject matching rules are valid.
436 if (StrictSubjectMatchRuleSet.empty()) {
437 // Check for contradicting match rules. Contradicting match rules are
439 // - a top-level rule and one of its sub-rules. E.g. variable and
440 // variable(is_parameter).
441 // - a sub-rule and a sibling that's negated. E.g.
442 // variable(is_thread_local) and variable(unless(is_parameter))
443 llvm::SmallDenseMap<int, std::pair<int, SourceRange>, 2>
444 RulesToFirstSpecifiedNegatedSubRule;
445 for (const auto &Rule : Rules) {
446 attr::SubjectMatchRule MatchRule = attr::SubjectMatchRule(Rule.first);
447 Optional<attr::SubjectMatchRule> ParentRule =
448 getParentAttrMatcherRule(MatchRule);
451 auto It = Rules.find(*ParentRule);
452 if (It != Rules.end()) {
453 // A sub-rule contradicts a parent rule.
454 Diag(Rule.second.getBegin(),
455 diag::err_pragma_attribute_matcher_subrule_contradicts_rule)
456 << attr::getSubjectMatchRuleSpelling(MatchRule)
457 << attr::getSubjectMatchRuleSpelling(*ParentRule) << It->second
458 << FixItHint::CreateRemoval(
459 replacementRangeForListElement(*this, Rule.second));
460 // Keep going without removing this rule as it won't change the set of
461 // declarations that receive the attribute.
464 if (isNegatedAttrMatcherSubRule(MatchRule))
465 RulesToFirstSpecifiedNegatedSubRule.insert(
466 std::make_pair(*ParentRule, Rule));
468 bool IgnoreNegatedSubRules = false;
469 for (const auto &Rule : Rules) {
470 attr::SubjectMatchRule MatchRule = attr::SubjectMatchRule(Rule.first);
471 Optional<attr::SubjectMatchRule> ParentRule =
472 getParentAttrMatcherRule(MatchRule);
475 auto It = RulesToFirstSpecifiedNegatedSubRule.find(*ParentRule);
476 if (It != RulesToFirstSpecifiedNegatedSubRule.end() &&
477 It->second != Rule) {
478 // Negated sub-rule contradicts another sub-rule.
480 It->second.second.getBegin(),
482 err_pragma_attribute_matcher_negated_subrule_contradicts_subrule)
483 << attr::getSubjectMatchRuleSpelling(
484 attr::SubjectMatchRule(It->second.first))
485 << attr::getSubjectMatchRuleSpelling(MatchRule) << Rule.second
486 << FixItHint::CreateRemoval(
487 replacementRangeForListElement(*this, It->second.second));
488 // Keep going but ignore all of the negated sub-rules.
489 IgnoreNegatedSubRules = true;
490 RulesToFirstSpecifiedNegatedSubRule.erase(It);
494 if (!IgnoreNegatedSubRules) {
495 for (const auto &Rule : Rules)
496 SubjectMatchRules.push_back(attr::SubjectMatchRule(Rule.first));
498 for (const auto &Rule : Rules) {
499 if (!isNegatedAttrMatcherSubRule(attr::SubjectMatchRule(Rule.first)))
500 SubjectMatchRules.push_back(attr::SubjectMatchRule(Rule.first));
505 for (const auto &Rule : StrictSubjectMatchRuleSet) {
506 if (Rules.erase(Rule.first)) {
507 // Add the rule to the set of attribute receivers only if it's supported
508 // in the current language mode.
510 SubjectMatchRules.push_back(Rule.first);
515 if (!Rules.empty()) {
517 Diag(PragmaLoc, diag::err_pragma_attribute_invalid_matchers)
518 << Attribute.getName();
519 SmallVector<attr::SubjectMatchRule, 2> ExtraRules;
520 for (const auto &Rule : Rules) {
521 ExtraRules.push_back(attr::SubjectMatchRule(Rule.first));
522 Diagnostic << FixItHint::CreateRemoval(
523 replacementRangeForListElement(*this, Rule.second));
525 Diagnostic << attrMatcherRuleListToString(ExtraRules);
528 PragmaAttributeStack.push_back(
529 {PragmaLoc, &Attribute, std::move(SubjectMatchRules), /*IsUsed=*/false});
532 void Sema::ActOnPragmaAttributePop(SourceLocation PragmaLoc) {
533 if (PragmaAttributeStack.empty()) {
534 Diag(PragmaLoc, diag::err_pragma_attribute_stack_mismatch);
537 const PragmaAttributeEntry &Entry = PragmaAttributeStack.back();
539 assert(Entry.Attribute && "Expected an attribute");
540 Diag(Entry.Attribute->getLoc(), diag::warn_pragma_attribute_unused)
541 << Entry.Attribute->getName();
542 Diag(PragmaLoc, diag::note_pragma_attribute_region_ends_here);
544 PragmaAttributeStack.pop_back();
547 void Sema::AddPragmaAttributes(Scope *S, Decl *D) {
548 if (PragmaAttributeStack.empty())
550 for (auto &Entry : PragmaAttributeStack) {
551 const AttributeList *Attribute = Entry.Attribute;
552 assert(Attribute && "Expected an attribute");
554 // Ensure that the attribute can be applied to the given declaration.
555 bool Applies = false;
556 for (const auto &Rule : Entry.MatchRules) {
557 if (Attribute->appliesToDecl(D, Rule)) {
565 assert(!Attribute->getNext() && "Expected just one attribute");
566 PragmaAttributeCurrentTargetDecl = D;
567 ProcessDeclAttributeList(S, D, Attribute);
568 PragmaAttributeCurrentTargetDecl = nullptr;
572 void Sema::PrintPragmaAttributeInstantiationPoint() {
573 assert(PragmaAttributeCurrentTargetDecl && "Expected an active declaration");
574 Diags.Report(PragmaAttributeCurrentTargetDecl->getLocStart(),
575 diag::note_pragma_attribute_applied_decl_here);
578 void Sema::DiagnoseUnterminatedPragmaAttribute() {
579 if (PragmaAttributeStack.empty())
581 Diag(PragmaAttributeStack.back().Loc, diag::err_pragma_attribute_no_pop_eof);
584 void Sema::ActOnPragmaOptimize(bool On, SourceLocation PragmaLoc) {
586 OptimizeOffPragmaLocation = SourceLocation();
588 OptimizeOffPragmaLocation = PragmaLoc;
591 void Sema::AddRangeBasedOptnone(FunctionDecl *FD) {
592 // In the future, check other pragmas if they're implemented (e.g. pragma
593 // optimize 0 will probably map to this functionality too).
594 if(OptimizeOffPragmaLocation.isValid())
595 AddOptnoneAttributeIfNoConflicts(FD, OptimizeOffPragmaLocation);
598 void Sema::AddOptnoneAttributeIfNoConflicts(FunctionDecl *FD,
599 SourceLocation Loc) {
600 // Don't add a conflicting attribute. No diagnostic is needed.
601 if (FD->hasAttr<MinSizeAttr>() || FD->hasAttr<AlwaysInlineAttr>())
604 // Add attributes only if required. Optnone requires noinline as well, but if
605 // either is already present then don't bother adding them.
606 if (!FD->hasAttr<OptimizeNoneAttr>())
607 FD->addAttr(OptimizeNoneAttr::CreateImplicit(Context, Loc));
608 if (!FD->hasAttr<NoInlineAttr>())
609 FD->addAttr(NoInlineAttr::CreateImplicit(Context, Loc));
612 typedef std::vector<std::pair<unsigned, SourceLocation> > VisStack;
613 enum : unsigned { NoVisibility = ~0U };
615 void Sema::AddPushedVisibilityAttribute(Decl *D) {
619 NamedDecl *ND = dyn_cast<NamedDecl>(D);
620 if (ND && ND->getExplicitVisibility(NamedDecl::VisibilityForValue))
623 VisStack *Stack = static_cast<VisStack*>(VisContext);
624 unsigned rawType = Stack->back().first;
625 if (rawType == NoVisibility) return;
627 VisibilityAttr::VisibilityType type
628 = (VisibilityAttr::VisibilityType) rawType;
629 SourceLocation loc = Stack->back().second;
631 D->addAttr(VisibilityAttr::CreateImplicit(Context, type, loc));
634 /// FreeVisContext - Deallocate and null out VisContext.
635 void Sema::FreeVisContext() {
636 delete static_cast<VisStack*>(VisContext);
637 VisContext = nullptr;
640 static void PushPragmaVisibility(Sema &S, unsigned type, SourceLocation loc) {
641 // Put visibility on stack.
643 S.VisContext = new VisStack;
645 VisStack *Stack = static_cast<VisStack*>(S.VisContext);
646 Stack->push_back(std::make_pair(type, loc));
649 void Sema::ActOnPragmaVisibility(const IdentifierInfo* VisType,
650 SourceLocation PragmaLoc) {
652 // Compute visibility to use.
653 VisibilityAttr::VisibilityType T;
654 if (!VisibilityAttr::ConvertStrToVisibilityType(VisType->getName(), T)) {
655 Diag(PragmaLoc, diag::warn_attribute_unknown_visibility) << VisType;
658 PushPragmaVisibility(*this, T, PragmaLoc);
660 PopPragmaVisibility(false, PragmaLoc);
664 void Sema::ActOnPragmaFPContract(LangOptions::FPContractModeKind FPC) {
666 case LangOptions::FPC_On:
667 FPFeatures.setAllowFPContractWithinStatement();
669 case LangOptions::FPC_Fast:
670 FPFeatures.setAllowFPContractAcrossStatement();
672 case LangOptions::FPC_Off:
673 FPFeatures.setDisallowFPContract();
678 void Sema::PushNamespaceVisibilityAttr(const VisibilityAttr *Attr,
679 SourceLocation Loc) {
680 // Visibility calculations will consider the namespace's visibility.
681 // Here we just want to note that we're in a visibility context
682 // which overrides any enclosing #pragma context, but doesn't itself
683 // contribute visibility.
684 PushPragmaVisibility(*this, NoVisibility, Loc);
687 void Sema::PopPragmaVisibility(bool IsNamespaceEnd, SourceLocation EndLoc) {
689 Diag(EndLoc, diag::err_pragma_pop_visibility_mismatch);
693 // Pop visibility from stack
694 VisStack *Stack = static_cast<VisStack*>(VisContext);
696 const std::pair<unsigned, SourceLocation> *Back = &Stack->back();
697 bool StartsWithPragma = Back->first != NoVisibility;
698 if (StartsWithPragma && IsNamespaceEnd) {
699 Diag(Back->second, diag::err_pragma_push_visibility_mismatch);
700 Diag(EndLoc, diag::note_surrounding_namespace_ends_here);
702 // For better error recovery, eat all pushes inside the namespace.
705 Back = &Stack->back();
706 StartsWithPragma = Back->first != NoVisibility;
707 } while (StartsWithPragma);
708 } else if (!StartsWithPragma && !IsNamespaceEnd) {
709 Diag(EndLoc, diag::err_pragma_pop_visibility_mismatch);
710 Diag(Back->second, diag::note_surrounding_namespace_starts_here);
715 // To simplify the implementation, never keep around an empty stack.