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::ActOnPragmaClangSection(SourceLocation PragmaLoc, PragmaClangSectionAction Action,
130 PragmaClangSectionKind SecKind, StringRef SecName) {
131 PragmaClangSection *CSec;
133 case PragmaClangSectionKind::PCSK_BSS:
134 CSec = &PragmaClangBSSSection;
136 case PragmaClangSectionKind::PCSK_Data:
137 CSec = &PragmaClangDataSection;
139 case PragmaClangSectionKind::PCSK_Rodata:
140 CSec = &PragmaClangRodataSection;
142 case PragmaClangSectionKind::PCSK_Text:
143 CSec = &PragmaClangTextSection;
146 llvm_unreachable("invalid clang section kind");
149 if (Action == PragmaClangSectionAction::PCSA_Clear) {
155 CSec->SectionName = SecName;
156 CSec->PragmaLocation = PragmaLoc;
159 void Sema::ActOnPragmaPack(SourceLocation PragmaLoc, PragmaMsStackAction Action,
160 StringRef SlotLabel, Expr *alignment) {
161 Expr *Alignment = static_cast<Expr *>(alignment);
163 // If specified then alignment must be a "small" power of two.
164 unsigned AlignmentVal = 0;
168 // pack(0) is like pack(), which just works out since that is what
169 // we use 0 for in PackAttr.
170 if (Alignment->isTypeDependent() ||
171 Alignment->isValueDependent() ||
172 !Alignment->isIntegerConstantExpr(Val, Context) ||
173 !(Val == 0 || Val.isPowerOf2()) ||
174 Val.getZExtValue() > 16) {
175 Diag(PragmaLoc, diag::warn_pragma_pack_invalid_alignment);
179 AlignmentVal = (unsigned) Val.getZExtValue();
181 if (Action == Sema::PSK_Show) {
182 // Show the current alignment, making sure to show the right value
184 // FIXME: This should come from the target.
185 AlignmentVal = PackStack.CurrentValue;
186 if (AlignmentVal == 0)
188 if (AlignmentVal == Sema::kMac68kAlignmentSentinel)
189 Diag(PragmaLoc, diag::warn_pragma_pack_show) << "mac68k";
191 Diag(PragmaLoc, diag::warn_pragma_pack_show) << AlignmentVal;
193 // MSDN, C/C++ Preprocessor Reference > Pragma Directives > pack:
194 // "#pragma pack(pop, identifier, n) is undefined"
195 if (Action & Sema::PSK_Pop) {
196 if (Alignment && !SlotLabel.empty())
197 Diag(PragmaLoc, diag::warn_pragma_pack_pop_identifer_and_alignment);
198 if (PackStack.Stack.empty())
199 Diag(PragmaLoc, diag::warn_pragma_pop_failed) << "pack" << "stack empty";
202 PackStack.Act(PragmaLoc, Action, SlotLabel, AlignmentVal);
205 void Sema::ActOnPragmaMSStruct(PragmaMSStructKind Kind) {
206 MSStructPragmaOn = (Kind == PMSST_ON);
209 void Sema::ActOnPragmaMSComment(SourceLocation CommentLoc,
210 PragmaMSCommentKind Kind, StringRef Arg) {
211 auto *PCD = PragmaCommentDecl::Create(
212 Context, Context.getTranslationUnitDecl(), CommentLoc, Kind, Arg);
213 Context.getTranslationUnitDecl()->addDecl(PCD);
214 Consumer.HandleTopLevelDecl(DeclGroupRef(PCD));
217 void Sema::ActOnPragmaDetectMismatch(SourceLocation Loc, StringRef Name,
219 auto *PDMD = PragmaDetectMismatchDecl::Create(
220 Context, Context.getTranslationUnitDecl(), Loc, Name, Value);
221 Context.getTranslationUnitDecl()->addDecl(PDMD);
222 Consumer.HandleTopLevelDecl(DeclGroupRef(PDMD));
225 void Sema::ActOnPragmaMSPointersToMembers(
226 LangOptions::PragmaMSPointersToMembersKind RepresentationMethod,
227 SourceLocation PragmaLoc) {
228 MSPointerToMemberRepresentationMethod = RepresentationMethod;
229 ImplicitMSInheritanceAttrLoc = PragmaLoc;
232 void Sema::ActOnPragmaMSVtorDisp(PragmaMsStackAction Action,
233 SourceLocation PragmaLoc,
234 MSVtorDispAttr::Mode Mode) {
235 if (Action & PSK_Pop && VtorDispStack.Stack.empty())
236 Diag(PragmaLoc, diag::warn_pragma_pop_failed) << "vtordisp"
238 VtorDispStack.Act(PragmaLoc, Action, StringRef(), Mode);
241 template<typename ValueType>
242 void Sema::PragmaStack<ValueType>::Act(SourceLocation PragmaLocation,
243 PragmaMsStackAction Action,
244 llvm::StringRef StackSlotLabel,
246 if (Action == PSK_Reset) {
247 CurrentValue = DefaultValue;
248 CurrentPragmaLocation = PragmaLocation;
251 if (Action & PSK_Push)
252 Stack.push_back(Slot(StackSlotLabel, CurrentValue, CurrentPragmaLocation));
253 else if (Action & PSK_Pop) {
254 if (!StackSlotLabel.empty()) {
255 // If we've got a label, try to find it and jump there.
256 auto I = llvm::find_if(llvm::reverse(Stack), [&](const Slot &x) {
257 return x.StackSlotLabel == StackSlotLabel;
259 // If we found the label so pop from there.
260 if (I != Stack.rend()) {
261 CurrentValue = I->Value;
262 CurrentPragmaLocation = I->PragmaLocation;
263 Stack.erase(std::prev(I.base()), Stack.end());
265 } else if (!Stack.empty()) {
266 // We don't have a label, just pop the last entry.
267 CurrentValue = Stack.back().Value;
268 CurrentPragmaLocation = Stack.back().PragmaLocation;
272 if (Action & PSK_Set) {
273 CurrentValue = Value;
274 CurrentPragmaLocation = PragmaLocation;
278 bool Sema::UnifySection(StringRef SectionName,
280 DeclaratorDecl *Decl) {
281 auto Section = Context.SectionInfos.find(SectionName);
282 if (Section == Context.SectionInfos.end()) {
283 Context.SectionInfos[SectionName] =
284 ASTContext::SectionInfo(Decl, SourceLocation(), SectionFlags);
287 // A pre-declared section takes precedence w/o diagnostic.
288 if (Section->second.SectionFlags == SectionFlags ||
289 !(Section->second.SectionFlags & ASTContext::PSF_Implicit))
291 auto OtherDecl = Section->second.Decl;
292 Diag(Decl->getLocation(), diag::err_section_conflict)
293 << Decl << OtherDecl;
294 Diag(OtherDecl->getLocation(), diag::note_declared_at)
295 << OtherDecl->getName();
296 if (auto A = Decl->getAttr<SectionAttr>())
298 Diag(A->getLocation(), diag::note_pragma_entered_here);
299 if (auto A = OtherDecl->getAttr<SectionAttr>())
301 Diag(A->getLocation(), diag::note_pragma_entered_here);
305 bool Sema::UnifySection(StringRef SectionName,
307 SourceLocation PragmaSectionLocation) {
308 auto Section = Context.SectionInfos.find(SectionName);
309 if (Section != Context.SectionInfos.end()) {
310 if (Section->second.SectionFlags == SectionFlags)
312 if (!(Section->second.SectionFlags & ASTContext::PSF_Implicit)) {
313 Diag(PragmaSectionLocation, diag::err_section_conflict)
314 << "this" << "a prior #pragma section";
315 Diag(Section->second.PragmaSectionLocation,
316 diag::note_pragma_entered_here);
320 Context.SectionInfos[SectionName] =
321 ASTContext::SectionInfo(nullptr, PragmaSectionLocation, SectionFlags);
325 /// \brief Called on well formed \#pragma bss_seg().
326 void Sema::ActOnPragmaMSSeg(SourceLocation PragmaLocation,
327 PragmaMsStackAction Action,
328 llvm::StringRef StackSlotLabel,
329 StringLiteral *SegmentName,
330 llvm::StringRef PragmaName) {
331 PragmaStack<StringLiteral *> *Stack =
332 llvm::StringSwitch<PragmaStack<StringLiteral *> *>(PragmaName)
333 .Case("data_seg", &DataSegStack)
334 .Case("bss_seg", &BSSSegStack)
335 .Case("const_seg", &ConstSegStack)
336 .Case("code_seg", &CodeSegStack);
337 if (Action & PSK_Pop && Stack->Stack.empty())
338 Diag(PragmaLocation, diag::warn_pragma_pop_failed) << PragmaName
341 !checkSectionName(SegmentName->getLocStart(), SegmentName->getString()))
343 Stack->Act(PragmaLocation, Action, StackSlotLabel, SegmentName);
346 /// \brief Called on well formed \#pragma bss_seg().
347 void Sema::ActOnPragmaMSSection(SourceLocation PragmaLocation,
348 int SectionFlags, StringLiteral *SegmentName) {
349 UnifySection(SegmentName->getString(), SectionFlags, PragmaLocation);
352 void Sema::ActOnPragmaMSInitSeg(SourceLocation PragmaLocation,
353 StringLiteral *SegmentName) {
354 // There's no stack to maintain, so we just have a current section. When we
355 // see the default section, reset our current section back to null so we stop
356 // tacking on unnecessary attributes.
357 CurInitSeg = SegmentName->getString() == ".CRT$XCU" ? nullptr : SegmentName;
358 CurInitSegLoc = PragmaLocation;
361 void Sema::ActOnPragmaUnused(const Token &IdTok, Scope *curScope,
362 SourceLocation PragmaLoc) {
364 IdentifierInfo *Name = IdTok.getIdentifierInfo();
365 LookupResult Lookup(*this, Name, IdTok.getLocation(), LookupOrdinaryName);
366 LookupParsedName(Lookup, curScope, nullptr, true);
368 if (Lookup.empty()) {
369 Diag(PragmaLoc, diag::warn_pragma_unused_undeclared_var)
370 << Name << SourceRange(IdTok.getLocation());
374 VarDecl *VD = Lookup.getAsSingle<VarDecl>();
376 Diag(PragmaLoc, diag::warn_pragma_unused_expected_var_arg)
377 << Name << SourceRange(IdTok.getLocation());
381 // Warn if this was used before being marked unused.
383 Diag(PragmaLoc, diag::warn_used_but_marked_unused) << Name;
385 VD->addAttr(UnusedAttr::CreateImplicit(Context, UnusedAttr::GNU_unused,
386 IdTok.getLocation()));
389 void Sema::AddCFAuditedAttribute(Decl *D) {
390 SourceLocation Loc = PP.getPragmaARCCFCodeAuditedLoc();
391 if (!Loc.isValid()) return;
393 // Don't add a redundant or conflicting attribute.
394 if (D->hasAttr<CFAuditedTransferAttr>() ||
395 D->hasAttr<CFUnknownTransferAttr>())
398 D->addAttr(CFAuditedTransferAttr::CreateImplicit(Context, Loc));
403 Optional<attr::SubjectMatchRule>
404 getParentAttrMatcherRule(attr::SubjectMatchRule Rule) {
405 using namespace attr;
409 #define ATTR_MATCH_RULE(Value, Spelling, IsAbstract)
410 #define ATTR_MATCH_SUB_RULE(Value, Spelling, IsAbstract, Parent, IsNegated) \
413 #include "clang/Basic/AttrSubMatchRulesList.inc"
417 bool isNegatedAttrMatcherSubRule(attr::SubjectMatchRule Rule) {
418 using namespace attr;
422 #define ATTR_MATCH_RULE(Value, Spelling, IsAbstract)
423 #define ATTR_MATCH_SUB_RULE(Value, Spelling, IsAbstract, Parent, IsNegated) \
426 #include "clang/Basic/AttrSubMatchRulesList.inc"
430 CharSourceRange replacementRangeForListElement(const Sema &S,
432 // Make sure that the ',' is removed as well.
433 SourceLocation AfterCommaLoc = Lexer::findLocationAfterToken(
434 Range.getEnd(), tok::comma, S.getSourceManager(), S.getLangOpts(),
435 /*SkipTrailingWhitespaceAndNewLine=*/false);
436 if (AfterCommaLoc.isValid())
437 return CharSourceRange::getCharRange(Range.getBegin(), AfterCommaLoc);
439 return CharSourceRange::getTokenRange(Range);
443 attrMatcherRuleListToString(ArrayRef<attr::SubjectMatchRule> Rules) {
445 llvm::raw_string_ostream OS(Result);
446 for (const auto &I : llvm::enumerate(Rules)) {
448 OS << (I.index() == Rules.size() - 1 ? ", and " : ", ");
449 OS << "'" << attr::getSubjectMatchRuleSpelling(I.value()) << "'";
454 } // end anonymous namespace
456 void Sema::ActOnPragmaAttributePush(AttributeList &Attribute,
457 SourceLocation PragmaLoc,
458 attr::ParsedSubjectMatchRuleSet Rules) {
459 SmallVector<attr::SubjectMatchRule, 4> SubjectMatchRules;
460 // Gather the subject match rules that are supported by the attribute.
461 SmallVector<std::pair<attr::SubjectMatchRule, bool>, 4>
462 StrictSubjectMatchRuleSet;
463 Attribute.getMatchRules(LangOpts, StrictSubjectMatchRuleSet);
465 // Figure out which subject matching rules are valid.
466 if (StrictSubjectMatchRuleSet.empty()) {
467 // Check for contradicting match rules. Contradicting match rules are
469 // - a top-level rule and one of its sub-rules. E.g. variable and
470 // variable(is_parameter).
471 // - a sub-rule and a sibling that's negated. E.g.
472 // variable(is_thread_local) and variable(unless(is_parameter))
473 llvm::SmallDenseMap<int, std::pair<int, SourceRange>, 2>
474 RulesToFirstSpecifiedNegatedSubRule;
475 for (const auto &Rule : Rules) {
476 attr::SubjectMatchRule MatchRule = attr::SubjectMatchRule(Rule.first);
477 Optional<attr::SubjectMatchRule> ParentRule =
478 getParentAttrMatcherRule(MatchRule);
481 auto It = Rules.find(*ParentRule);
482 if (It != Rules.end()) {
483 // A sub-rule contradicts a parent rule.
484 Diag(Rule.second.getBegin(),
485 diag::err_pragma_attribute_matcher_subrule_contradicts_rule)
486 << attr::getSubjectMatchRuleSpelling(MatchRule)
487 << attr::getSubjectMatchRuleSpelling(*ParentRule) << It->second
488 << FixItHint::CreateRemoval(
489 replacementRangeForListElement(*this, Rule.second));
490 // Keep going without removing this rule as it won't change the set of
491 // declarations that receive the attribute.
494 if (isNegatedAttrMatcherSubRule(MatchRule))
495 RulesToFirstSpecifiedNegatedSubRule.insert(
496 std::make_pair(*ParentRule, Rule));
498 bool IgnoreNegatedSubRules = false;
499 for (const auto &Rule : Rules) {
500 attr::SubjectMatchRule MatchRule = attr::SubjectMatchRule(Rule.first);
501 Optional<attr::SubjectMatchRule> ParentRule =
502 getParentAttrMatcherRule(MatchRule);
505 auto It = RulesToFirstSpecifiedNegatedSubRule.find(*ParentRule);
506 if (It != RulesToFirstSpecifiedNegatedSubRule.end() &&
507 It->second != Rule) {
508 // Negated sub-rule contradicts another sub-rule.
510 It->second.second.getBegin(),
512 err_pragma_attribute_matcher_negated_subrule_contradicts_subrule)
513 << attr::getSubjectMatchRuleSpelling(
514 attr::SubjectMatchRule(It->second.first))
515 << attr::getSubjectMatchRuleSpelling(MatchRule) << Rule.second
516 << FixItHint::CreateRemoval(
517 replacementRangeForListElement(*this, It->second.second));
518 // Keep going but ignore all of the negated sub-rules.
519 IgnoreNegatedSubRules = true;
520 RulesToFirstSpecifiedNegatedSubRule.erase(It);
524 if (!IgnoreNegatedSubRules) {
525 for (const auto &Rule : Rules)
526 SubjectMatchRules.push_back(attr::SubjectMatchRule(Rule.first));
528 for (const auto &Rule : Rules) {
529 if (!isNegatedAttrMatcherSubRule(attr::SubjectMatchRule(Rule.first)))
530 SubjectMatchRules.push_back(attr::SubjectMatchRule(Rule.first));
535 for (const auto &Rule : StrictSubjectMatchRuleSet) {
536 if (Rules.erase(Rule.first)) {
537 // Add the rule to the set of attribute receivers only if it's supported
538 // in the current language mode.
540 SubjectMatchRules.push_back(Rule.first);
545 if (!Rules.empty()) {
547 Diag(PragmaLoc, diag::err_pragma_attribute_invalid_matchers)
548 << Attribute.getName();
549 SmallVector<attr::SubjectMatchRule, 2> ExtraRules;
550 for (const auto &Rule : Rules) {
551 ExtraRules.push_back(attr::SubjectMatchRule(Rule.first));
552 Diagnostic << FixItHint::CreateRemoval(
553 replacementRangeForListElement(*this, Rule.second));
555 Diagnostic << attrMatcherRuleListToString(ExtraRules);
558 PragmaAttributeStack.push_back(
559 {PragmaLoc, &Attribute, std::move(SubjectMatchRules), /*IsUsed=*/false});
562 void Sema::ActOnPragmaAttributePop(SourceLocation PragmaLoc) {
563 if (PragmaAttributeStack.empty()) {
564 Diag(PragmaLoc, diag::err_pragma_attribute_stack_mismatch);
567 const PragmaAttributeEntry &Entry = PragmaAttributeStack.back();
569 assert(Entry.Attribute && "Expected an attribute");
570 Diag(Entry.Attribute->getLoc(), diag::warn_pragma_attribute_unused)
571 << Entry.Attribute->getName();
572 Diag(PragmaLoc, diag::note_pragma_attribute_region_ends_here);
574 PragmaAttributeStack.pop_back();
577 void Sema::AddPragmaAttributes(Scope *S, Decl *D) {
578 if (PragmaAttributeStack.empty())
580 for (auto &Entry : PragmaAttributeStack) {
581 const AttributeList *Attribute = Entry.Attribute;
582 assert(Attribute && "Expected an attribute");
584 // Ensure that the attribute can be applied to the given declaration.
585 bool Applies = false;
586 for (const auto &Rule : Entry.MatchRules) {
587 if (Attribute->appliesToDecl(D, Rule)) {
595 assert(!Attribute->getNext() && "Expected just one attribute");
596 PragmaAttributeCurrentTargetDecl = D;
597 ProcessDeclAttributeList(S, D, Attribute);
598 PragmaAttributeCurrentTargetDecl = nullptr;
602 void Sema::PrintPragmaAttributeInstantiationPoint() {
603 assert(PragmaAttributeCurrentTargetDecl && "Expected an active declaration");
604 Diags.Report(PragmaAttributeCurrentTargetDecl->getLocStart(),
605 diag::note_pragma_attribute_applied_decl_here);
608 void Sema::DiagnoseUnterminatedPragmaAttribute() {
609 if (PragmaAttributeStack.empty())
611 Diag(PragmaAttributeStack.back().Loc, diag::err_pragma_attribute_no_pop_eof);
614 void Sema::ActOnPragmaOptimize(bool On, SourceLocation PragmaLoc) {
616 OptimizeOffPragmaLocation = SourceLocation();
618 OptimizeOffPragmaLocation = PragmaLoc;
621 void Sema::AddRangeBasedOptnone(FunctionDecl *FD) {
622 // In the future, check other pragmas if they're implemented (e.g. pragma
623 // optimize 0 will probably map to this functionality too).
624 if(OptimizeOffPragmaLocation.isValid())
625 AddOptnoneAttributeIfNoConflicts(FD, OptimizeOffPragmaLocation);
628 void Sema::AddOptnoneAttributeIfNoConflicts(FunctionDecl *FD,
629 SourceLocation Loc) {
630 // Don't add a conflicting attribute. No diagnostic is needed.
631 if (FD->hasAttr<MinSizeAttr>() || FD->hasAttr<AlwaysInlineAttr>())
634 // Add attributes only if required. Optnone requires noinline as well, but if
635 // either is already present then don't bother adding them.
636 if (!FD->hasAttr<OptimizeNoneAttr>())
637 FD->addAttr(OptimizeNoneAttr::CreateImplicit(Context, Loc));
638 if (!FD->hasAttr<NoInlineAttr>())
639 FD->addAttr(NoInlineAttr::CreateImplicit(Context, Loc));
642 typedef std::vector<std::pair<unsigned, SourceLocation> > VisStack;
643 enum : unsigned { NoVisibility = ~0U };
645 void Sema::AddPushedVisibilityAttribute(Decl *D) {
649 NamedDecl *ND = dyn_cast<NamedDecl>(D);
650 if (ND && ND->getExplicitVisibility(NamedDecl::VisibilityForValue))
653 VisStack *Stack = static_cast<VisStack*>(VisContext);
654 unsigned rawType = Stack->back().first;
655 if (rawType == NoVisibility) return;
657 VisibilityAttr::VisibilityType type
658 = (VisibilityAttr::VisibilityType) rawType;
659 SourceLocation loc = Stack->back().second;
661 D->addAttr(VisibilityAttr::CreateImplicit(Context, type, loc));
664 /// FreeVisContext - Deallocate and null out VisContext.
665 void Sema::FreeVisContext() {
666 delete static_cast<VisStack*>(VisContext);
667 VisContext = nullptr;
670 static void PushPragmaVisibility(Sema &S, unsigned type, SourceLocation loc) {
671 // Put visibility on stack.
673 S.VisContext = new VisStack;
675 VisStack *Stack = static_cast<VisStack*>(S.VisContext);
676 Stack->push_back(std::make_pair(type, loc));
679 void Sema::ActOnPragmaVisibility(const IdentifierInfo* VisType,
680 SourceLocation PragmaLoc) {
682 // Compute visibility to use.
683 VisibilityAttr::VisibilityType T;
684 if (!VisibilityAttr::ConvertStrToVisibilityType(VisType->getName(), T)) {
685 Diag(PragmaLoc, diag::warn_attribute_unknown_visibility) << VisType;
688 PushPragmaVisibility(*this, T, PragmaLoc);
690 PopPragmaVisibility(false, PragmaLoc);
694 void Sema::ActOnPragmaFPContract(LangOptions::FPContractModeKind FPC) {
696 case LangOptions::FPC_On:
697 FPFeatures.setAllowFPContractWithinStatement();
699 case LangOptions::FPC_Fast:
700 FPFeatures.setAllowFPContractAcrossStatement();
702 case LangOptions::FPC_Off:
703 FPFeatures.setDisallowFPContract();
708 void Sema::PushNamespaceVisibilityAttr(const VisibilityAttr *Attr,
709 SourceLocation Loc) {
710 // Visibility calculations will consider the namespace's visibility.
711 // Here we just want to note that we're in a visibility context
712 // which overrides any enclosing #pragma context, but doesn't itself
713 // contribute visibility.
714 PushPragmaVisibility(*this, NoVisibility, Loc);
717 void Sema::PopPragmaVisibility(bool IsNamespaceEnd, SourceLocation EndLoc) {
719 Diag(EndLoc, diag::err_pragma_pop_visibility_mismatch);
723 // Pop visibility from stack
724 VisStack *Stack = static_cast<VisStack*>(VisContext);
726 const std::pair<unsigned, SourceLocation> *Back = &Stack->back();
727 bool StartsWithPragma = Back->first != NoVisibility;
728 if (StartsWithPragma && IsNamespaceEnd) {
729 Diag(Back->second, diag::err_pragma_push_visibility_mismatch);
730 Diag(EndLoc, diag::note_surrounding_namespace_ends_here);
732 // For better error recovery, eat all pushes inside the namespace.
735 Back = &Stack->back();
736 StartsWithPragma = Back->first != NoVisibility;
737 } while (StartsWithPragma);
738 } else if (!StartsWithPragma && !IsNamespaceEnd) {
739 Diag(EndLoc, diag::err_pragma_pop_visibility_mismatch);
740 Diag(Back->second, diag::note_surrounding_namespace_starts_here);
745 // To simplify the implementation, never keep around an empty stack.