xref: /aosp_15_r20/external/clang/lib/Sema/SemaAttr.cpp (revision 67e74705e28f6214e480b399dd47ea732279e315)
1*67e74705SXin Li //===--- SemaAttr.cpp - Semantic Analysis for Attributes ------------------===//
2*67e74705SXin Li //
3*67e74705SXin Li //                     The LLVM Compiler Infrastructure
4*67e74705SXin Li //
5*67e74705SXin Li // This file is distributed under the University of Illinois Open Source
6*67e74705SXin Li // License. See LICENSE.TXT for details.
7*67e74705SXin Li //
8*67e74705SXin Li //===----------------------------------------------------------------------===//
9*67e74705SXin Li //
10*67e74705SXin Li // This file implements semantic analysis for non-trivial attributes and
11*67e74705SXin Li // pragmas.
12*67e74705SXin Li //
13*67e74705SXin Li //===----------------------------------------------------------------------===//
14*67e74705SXin Li 
15*67e74705SXin Li #include "clang/Sema/SemaInternal.h"
16*67e74705SXin Li #include "clang/AST/ASTConsumer.h"
17*67e74705SXin Li #include "clang/AST/Attr.h"
18*67e74705SXin Li #include "clang/AST/Expr.h"
19*67e74705SXin Li #include "clang/Basic/TargetInfo.h"
20*67e74705SXin Li #include "clang/Lex/Preprocessor.h"
21*67e74705SXin Li #include "clang/Sema/Lookup.h"
22*67e74705SXin Li using namespace clang;
23*67e74705SXin Li 
24*67e74705SXin Li //===----------------------------------------------------------------------===//
25*67e74705SXin Li // Pragma 'pack' and 'options align'
26*67e74705SXin Li //===----------------------------------------------------------------------===//
27*67e74705SXin Li 
PragmaStackSentinelRAII(Sema & S,StringRef SlotLabel,bool ShouldAct)28*67e74705SXin Li Sema::PragmaStackSentinelRAII::PragmaStackSentinelRAII(Sema &S,
29*67e74705SXin Li                                                        StringRef SlotLabel,
30*67e74705SXin Li                                                        bool ShouldAct)
31*67e74705SXin Li     : S(S), SlotLabel(SlotLabel), ShouldAct(ShouldAct) {
32*67e74705SXin Li   if (ShouldAct) {
33*67e74705SXin Li     S.VtorDispStack.SentinelAction(PSK_Push, SlotLabel);
34*67e74705SXin Li     S.DataSegStack.SentinelAction(PSK_Push, SlotLabel);
35*67e74705SXin Li     S.BSSSegStack.SentinelAction(PSK_Push, SlotLabel);
36*67e74705SXin Li     S.ConstSegStack.SentinelAction(PSK_Push, SlotLabel);
37*67e74705SXin Li     S.CodeSegStack.SentinelAction(PSK_Push, SlotLabel);
38*67e74705SXin Li   }
39*67e74705SXin Li }
40*67e74705SXin Li 
~PragmaStackSentinelRAII()41*67e74705SXin Li Sema::PragmaStackSentinelRAII::~PragmaStackSentinelRAII() {
42*67e74705SXin Li   if (ShouldAct) {
43*67e74705SXin Li     S.VtorDispStack.SentinelAction(PSK_Pop, SlotLabel);
44*67e74705SXin Li     S.DataSegStack.SentinelAction(PSK_Pop, SlotLabel);
45*67e74705SXin Li     S.BSSSegStack.SentinelAction(PSK_Pop, SlotLabel);
46*67e74705SXin Li     S.ConstSegStack.SentinelAction(PSK_Pop, SlotLabel);
47*67e74705SXin Li     S.CodeSegStack.SentinelAction(PSK_Pop, SlotLabel);
48*67e74705SXin Li   }
49*67e74705SXin Li }
50*67e74705SXin Li 
AddAlignmentAttributesForRecord(RecordDecl * RD)51*67e74705SXin Li void Sema::AddAlignmentAttributesForRecord(RecordDecl *RD) {
52*67e74705SXin Li   // If there is no pack value, we don't need any attributes.
53*67e74705SXin Li   if (!PackStack.CurrentValue)
54*67e74705SXin Li     return;
55*67e74705SXin Li 
56*67e74705SXin Li   // Otherwise, check to see if we need a max field alignment attribute.
57*67e74705SXin Li   if (unsigned Alignment = PackStack.CurrentValue) {
58*67e74705SXin Li     if (Alignment == Sema::kMac68kAlignmentSentinel)
59*67e74705SXin Li       RD->addAttr(AlignMac68kAttr::CreateImplicit(Context));
60*67e74705SXin Li     else
61*67e74705SXin Li       RD->addAttr(MaxFieldAlignmentAttr::CreateImplicit(Context,
62*67e74705SXin Li                                                         Alignment * 8));
63*67e74705SXin Li   }
64*67e74705SXin Li }
65*67e74705SXin Li 
AddMsStructLayoutForRecord(RecordDecl * RD)66*67e74705SXin Li void Sema::AddMsStructLayoutForRecord(RecordDecl *RD) {
67*67e74705SXin Li   if (MSStructPragmaOn)
68*67e74705SXin Li     RD->addAttr(MSStructAttr::CreateImplicit(Context));
69*67e74705SXin Li 
70*67e74705SXin Li   // FIXME: We should merge AddAlignmentAttributesForRecord with
71*67e74705SXin Li   // AddMsStructLayoutForRecord into AddPragmaAttributesForRecord, which takes
72*67e74705SXin Li   // all active pragmas and applies them as attributes to class definitions.
73*67e74705SXin Li   if (VtorDispStack.CurrentValue != getLangOpts().VtorDispMode)
74*67e74705SXin Li     RD->addAttr(
75*67e74705SXin Li         MSVtorDispAttr::CreateImplicit(Context, VtorDispStack.CurrentValue));
76*67e74705SXin Li }
77*67e74705SXin Li 
ActOnPragmaOptionsAlign(PragmaOptionsAlignKind Kind,SourceLocation PragmaLoc)78*67e74705SXin Li void Sema::ActOnPragmaOptionsAlign(PragmaOptionsAlignKind Kind,
79*67e74705SXin Li                                    SourceLocation PragmaLoc) {
80*67e74705SXin Li   PragmaMsStackAction Action = Sema::PSK_Reset;
81*67e74705SXin Li   unsigned Alignment = 0;
82*67e74705SXin Li   switch (Kind) {
83*67e74705SXin Li     // For all targets we support native and natural are the same.
84*67e74705SXin Li     //
85*67e74705SXin Li     // FIXME: This is not true on Darwin/PPC.
86*67e74705SXin Li   case POAK_Native:
87*67e74705SXin Li   case POAK_Power:
88*67e74705SXin Li   case POAK_Natural:
89*67e74705SXin Li     Action = Sema::PSK_Push_Set;
90*67e74705SXin Li     Alignment = 0;
91*67e74705SXin Li     break;
92*67e74705SXin Li 
93*67e74705SXin Li     // Note that '#pragma options align=packed' is not equivalent to attribute
94*67e74705SXin Li     // packed, it has a different precedence relative to attribute aligned.
95*67e74705SXin Li   case POAK_Packed:
96*67e74705SXin Li     Action = Sema::PSK_Push_Set;
97*67e74705SXin Li     Alignment = 1;
98*67e74705SXin Li     break;
99*67e74705SXin Li 
100*67e74705SXin Li   case POAK_Mac68k:
101*67e74705SXin Li     // Check if the target supports this.
102*67e74705SXin Li     if (!this->Context.getTargetInfo().hasAlignMac68kSupport()) {
103*67e74705SXin Li       Diag(PragmaLoc, diag::err_pragma_options_align_mac68k_target_unsupported);
104*67e74705SXin Li       return;
105*67e74705SXin Li     }
106*67e74705SXin Li     Action = Sema::PSK_Push_Set;
107*67e74705SXin Li     Alignment = Sema::kMac68kAlignmentSentinel;
108*67e74705SXin Li     break;
109*67e74705SXin Li 
110*67e74705SXin Li   case POAK_Reset:
111*67e74705SXin Li     // Reset just pops the top of the stack, or resets the current alignment to
112*67e74705SXin Li     // default.
113*67e74705SXin Li     Action = Sema::PSK_Pop;
114*67e74705SXin Li     if (PackStack.Stack.empty()) {
115*67e74705SXin Li       if (PackStack.CurrentValue) {
116*67e74705SXin Li         Action = Sema::PSK_Reset;
117*67e74705SXin Li       } else {
118*67e74705SXin Li         Diag(PragmaLoc, diag::warn_pragma_options_align_reset_failed)
119*67e74705SXin Li             << "stack empty";
120*67e74705SXin Li         return;
121*67e74705SXin Li       }
122*67e74705SXin Li     }
123*67e74705SXin Li     break;
124*67e74705SXin Li   }
125*67e74705SXin Li 
126*67e74705SXin Li   PackStack.Act(PragmaLoc, Action, StringRef(), Alignment);
127*67e74705SXin Li }
128*67e74705SXin Li 
ActOnPragmaPack(SourceLocation PragmaLoc,PragmaMsStackAction Action,StringRef SlotLabel,Expr * alignment)129*67e74705SXin Li void Sema::ActOnPragmaPack(SourceLocation PragmaLoc, PragmaMsStackAction Action,
130*67e74705SXin Li                            StringRef SlotLabel, Expr *alignment) {
131*67e74705SXin Li   Expr *Alignment = static_cast<Expr *>(alignment);
132*67e74705SXin Li 
133*67e74705SXin Li   // If specified then alignment must be a "small" power of two.
134*67e74705SXin Li   unsigned AlignmentVal = 0;
135*67e74705SXin Li   if (Alignment) {
136*67e74705SXin Li     llvm::APSInt Val;
137*67e74705SXin Li 
138*67e74705SXin Li     // pack(0) is like pack(), which just works out since that is what
139*67e74705SXin Li     // we use 0 for in PackAttr.
140*67e74705SXin Li     if (Alignment->isTypeDependent() ||
141*67e74705SXin Li         Alignment->isValueDependent() ||
142*67e74705SXin Li         !Alignment->isIntegerConstantExpr(Val, Context) ||
143*67e74705SXin Li         !(Val == 0 || Val.isPowerOf2()) ||
144*67e74705SXin Li         Val.getZExtValue() > 16) {
145*67e74705SXin Li       Diag(PragmaLoc, diag::warn_pragma_pack_invalid_alignment);
146*67e74705SXin Li       return; // Ignore
147*67e74705SXin Li     }
148*67e74705SXin Li 
149*67e74705SXin Li     AlignmentVal = (unsigned) Val.getZExtValue();
150*67e74705SXin Li   }
151*67e74705SXin Li   if (Action == Sema::PSK_Show) {
152*67e74705SXin Li     // Show the current alignment, making sure to show the right value
153*67e74705SXin Li     // for the default.
154*67e74705SXin Li     // FIXME: This should come from the target.
155*67e74705SXin Li     AlignmentVal = PackStack.CurrentValue;
156*67e74705SXin Li     if (AlignmentVal == 0)
157*67e74705SXin Li       AlignmentVal = 8;
158*67e74705SXin Li     if (AlignmentVal == Sema::kMac68kAlignmentSentinel)
159*67e74705SXin Li       Diag(PragmaLoc, diag::warn_pragma_pack_show) << "mac68k";
160*67e74705SXin Li     else
161*67e74705SXin Li       Diag(PragmaLoc, diag::warn_pragma_pack_show) << AlignmentVal;
162*67e74705SXin Li   }
163*67e74705SXin Li   // MSDN, C/C++ Preprocessor Reference > Pragma Directives > pack:
164*67e74705SXin Li   // "#pragma pack(pop, identifier, n) is undefined"
165*67e74705SXin Li   if (Action & Sema::PSK_Pop) {
166*67e74705SXin Li     if (Alignment && !SlotLabel.empty())
167*67e74705SXin Li       Diag(PragmaLoc, diag::warn_pragma_pack_pop_identifer_and_alignment);
168*67e74705SXin Li     if (PackStack.Stack.empty())
169*67e74705SXin Li       Diag(PragmaLoc, diag::warn_pragma_pop_failed) << "pack" << "stack empty";
170*67e74705SXin Li   }
171*67e74705SXin Li 
172*67e74705SXin Li   PackStack.Act(PragmaLoc, Action, SlotLabel, AlignmentVal);
173*67e74705SXin Li }
174*67e74705SXin Li 
ActOnPragmaMSStruct(PragmaMSStructKind Kind)175*67e74705SXin Li void Sema::ActOnPragmaMSStruct(PragmaMSStructKind Kind) {
176*67e74705SXin Li   MSStructPragmaOn = (Kind == PMSST_ON);
177*67e74705SXin Li }
178*67e74705SXin Li 
ActOnPragmaMSComment(SourceLocation CommentLoc,PragmaMSCommentKind Kind,StringRef Arg)179*67e74705SXin Li void Sema::ActOnPragmaMSComment(SourceLocation CommentLoc,
180*67e74705SXin Li                                 PragmaMSCommentKind Kind, StringRef Arg) {
181*67e74705SXin Li   auto *PCD = PragmaCommentDecl::Create(
182*67e74705SXin Li       Context, Context.getTranslationUnitDecl(), CommentLoc, Kind, Arg);
183*67e74705SXin Li   Context.getTranslationUnitDecl()->addDecl(PCD);
184*67e74705SXin Li   Consumer.HandleTopLevelDecl(DeclGroupRef(PCD));
185*67e74705SXin Li }
186*67e74705SXin Li 
ActOnPragmaDetectMismatch(SourceLocation Loc,StringRef Name,StringRef Value)187*67e74705SXin Li void Sema::ActOnPragmaDetectMismatch(SourceLocation Loc, StringRef Name,
188*67e74705SXin Li                                      StringRef Value) {
189*67e74705SXin Li   auto *PDMD = PragmaDetectMismatchDecl::Create(
190*67e74705SXin Li       Context, Context.getTranslationUnitDecl(), Loc, Name, Value);
191*67e74705SXin Li   Context.getTranslationUnitDecl()->addDecl(PDMD);
192*67e74705SXin Li   Consumer.HandleTopLevelDecl(DeclGroupRef(PDMD));
193*67e74705SXin Li }
194*67e74705SXin Li 
ActOnPragmaMSPointersToMembers(LangOptions::PragmaMSPointersToMembersKind RepresentationMethod,SourceLocation PragmaLoc)195*67e74705SXin Li void Sema::ActOnPragmaMSPointersToMembers(
196*67e74705SXin Li     LangOptions::PragmaMSPointersToMembersKind RepresentationMethod,
197*67e74705SXin Li     SourceLocation PragmaLoc) {
198*67e74705SXin Li   MSPointerToMemberRepresentationMethod = RepresentationMethod;
199*67e74705SXin Li   ImplicitMSInheritanceAttrLoc = PragmaLoc;
200*67e74705SXin Li }
201*67e74705SXin Li 
ActOnPragmaMSVtorDisp(PragmaMsStackAction Action,SourceLocation PragmaLoc,MSVtorDispAttr::Mode Mode)202*67e74705SXin Li void Sema::ActOnPragmaMSVtorDisp(PragmaMsStackAction Action,
203*67e74705SXin Li                                  SourceLocation PragmaLoc,
204*67e74705SXin Li                                  MSVtorDispAttr::Mode Mode) {
205*67e74705SXin Li   if (Action & PSK_Pop && VtorDispStack.Stack.empty())
206*67e74705SXin Li     Diag(PragmaLoc, diag::warn_pragma_pop_failed) << "vtordisp"
207*67e74705SXin Li                                                   << "stack empty";
208*67e74705SXin Li   VtorDispStack.Act(PragmaLoc, Action, StringRef(), Mode);
209*67e74705SXin Li }
210*67e74705SXin Li 
211*67e74705SXin Li template<typename ValueType>
Act(SourceLocation PragmaLocation,PragmaMsStackAction Action,llvm::StringRef StackSlotLabel,ValueType Value)212*67e74705SXin Li void Sema::PragmaStack<ValueType>::Act(SourceLocation PragmaLocation,
213*67e74705SXin Li                                        PragmaMsStackAction Action,
214*67e74705SXin Li                                        llvm::StringRef StackSlotLabel,
215*67e74705SXin Li                                        ValueType Value) {
216*67e74705SXin Li   if (Action == PSK_Reset) {
217*67e74705SXin Li     CurrentValue = DefaultValue;
218*67e74705SXin Li     return;
219*67e74705SXin Li   }
220*67e74705SXin Li   if (Action & PSK_Push)
221*67e74705SXin Li     Stack.push_back(Slot(StackSlotLabel, CurrentValue, CurrentPragmaLocation));
222*67e74705SXin Li   else if (Action & PSK_Pop) {
223*67e74705SXin Li     if (!StackSlotLabel.empty()) {
224*67e74705SXin Li       // If we've got a label, try to find it and jump there.
225*67e74705SXin Li       auto I = llvm::find_if(llvm::reverse(Stack), [&](const Slot &x) {
226*67e74705SXin Li         return x.StackSlotLabel == StackSlotLabel;
227*67e74705SXin Li       });
228*67e74705SXin Li       // If we found the label so pop from there.
229*67e74705SXin Li       if (I != Stack.rend()) {
230*67e74705SXin Li         CurrentValue = I->Value;
231*67e74705SXin Li         CurrentPragmaLocation = I->PragmaLocation;
232*67e74705SXin Li         Stack.erase(std::prev(I.base()), Stack.end());
233*67e74705SXin Li       }
234*67e74705SXin Li     } else if (!Stack.empty()) {
235*67e74705SXin Li       // We don't have a label, just pop the last entry.
236*67e74705SXin Li       CurrentValue = Stack.back().Value;
237*67e74705SXin Li       CurrentPragmaLocation = Stack.back().PragmaLocation;
238*67e74705SXin Li       Stack.pop_back();
239*67e74705SXin Li     }
240*67e74705SXin Li   }
241*67e74705SXin Li   if (Action & PSK_Set) {
242*67e74705SXin Li     CurrentValue = Value;
243*67e74705SXin Li     CurrentPragmaLocation = PragmaLocation;
244*67e74705SXin Li   }
245*67e74705SXin Li }
246*67e74705SXin Li 
UnifySection(StringRef SectionName,int SectionFlags,DeclaratorDecl * Decl)247*67e74705SXin Li bool Sema::UnifySection(StringRef SectionName,
248*67e74705SXin Li                         int SectionFlags,
249*67e74705SXin Li                         DeclaratorDecl *Decl) {
250*67e74705SXin Li   auto Section = Context.SectionInfos.find(SectionName);
251*67e74705SXin Li   if (Section == Context.SectionInfos.end()) {
252*67e74705SXin Li     Context.SectionInfos[SectionName] =
253*67e74705SXin Li         ASTContext::SectionInfo(Decl, SourceLocation(), SectionFlags);
254*67e74705SXin Li     return false;
255*67e74705SXin Li   }
256*67e74705SXin Li   // A pre-declared section takes precedence w/o diagnostic.
257*67e74705SXin Li   if (Section->second.SectionFlags == SectionFlags ||
258*67e74705SXin Li       !(Section->second.SectionFlags & ASTContext::PSF_Implicit))
259*67e74705SXin Li     return false;
260*67e74705SXin Li   auto OtherDecl = Section->second.Decl;
261*67e74705SXin Li   Diag(Decl->getLocation(), diag::err_section_conflict)
262*67e74705SXin Li       << Decl << OtherDecl;
263*67e74705SXin Li   Diag(OtherDecl->getLocation(), diag::note_declared_at)
264*67e74705SXin Li       << OtherDecl->getName();
265*67e74705SXin Li   if (auto A = Decl->getAttr<SectionAttr>())
266*67e74705SXin Li     if (A->isImplicit())
267*67e74705SXin Li       Diag(A->getLocation(), diag::note_pragma_entered_here);
268*67e74705SXin Li   if (auto A = OtherDecl->getAttr<SectionAttr>())
269*67e74705SXin Li     if (A->isImplicit())
270*67e74705SXin Li       Diag(A->getLocation(), diag::note_pragma_entered_here);
271*67e74705SXin Li   return true;
272*67e74705SXin Li }
273*67e74705SXin Li 
UnifySection(StringRef SectionName,int SectionFlags,SourceLocation PragmaSectionLocation)274*67e74705SXin Li bool Sema::UnifySection(StringRef SectionName,
275*67e74705SXin Li                         int SectionFlags,
276*67e74705SXin Li                         SourceLocation PragmaSectionLocation) {
277*67e74705SXin Li   auto Section = Context.SectionInfos.find(SectionName);
278*67e74705SXin Li   if (Section != Context.SectionInfos.end()) {
279*67e74705SXin Li     if (Section->second.SectionFlags == SectionFlags)
280*67e74705SXin Li       return false;
281*67e74705SXin Li     if (!(Section->second.SectionFlags & ASTContext::PSF_Implicit)) {
282*67e74705SXin Li       Diag(PragmaSectionLocation, diag::err_section_conflict)
283*67e74705SXin Li           << "this" << "a prior #pragma section";
284*67e74705SXin Li       Diag(Section->second.PragmaSectionLocation,
285*67e74705SXin Li            diag::note_pragma_entered_here);
286*67e74705SXin Li       return true;
287*67e74705SXin Li     }
288*67e74705SXin Li   }
289*67e74705SXin Li   Context.SectionInfos[SectionName] =
290*67e74705SXin Li       ASTContext::SectionInfo(nullptr, PragmaSectionLocation, SectionFlags);
291*67e74705SXin Li   return false;
292*67e74705SXin Li }
293*67e74705SXin Li 
294*67e74705SXin Li /// \brief Called on well formed \#pragma bss_seg().
ActOnPragmaMSSeg(SourceLocation PragmaLocation,PragmaMsStackAction Action,llvm::StringRef StackSlotLabel,StringLiteral * SegmentName,llvm::StringRef PragmaName)295*67e74705SXin Li void Sema::ActOnPragmaMSSeg(SourceLocation PragmaLocation,
296*67e74705SXin Li                             PragmaMsStackAction Action,
297*67e74705SXin Li                             llvm::StringRef StackSlotLabel,
298*67e74705SXin Li                             StringLiteral *SegmentName,
299*67e74705SXin Li                             llvm::StringRef PragmaName) {
300*67e74705SXin Li   PragmaStack<StringLiteral *> *Stack =
301*67e74705SXin Li     llvm::StringSwitch<PragmaStack<StringLiteral *> *>(PragmaName)
302*67e74705SXin Li         .Case("data_seg", &DataSegStack)
303*67e74705SXin Li         .Case("bss_seg", &BSSSegStack)
304*67e74705SXin Li         .Case("const_seg", &ConstSegStack)
305*67e74705SXin Li         .Case("code_seg", &CodeSegStack);
306*67e74705SXin Li   if (Action & PSK_Pop && Stack->Stack.empty())
307*67e74705SXin Li     Diag(PragmaLocation, diag::warn_pragma_pop_failed) << PragmaName
308*67e74705SXin Li         << "stack empty";
309*67e74705SXin Li   if (SegmentName &&
310*67e74705SXin Li       !checkSectionName(SegmentName->getLocStart(), SegmentName->getString()))
311*67e74705SXin Li     return;
312*67e74705SXin Li   Stack->Act(PragmaLocation, Action, StackSlotLabel, SegmentName);
313*67e74705SXin Li }
314*67e74705SXin Li 
315*67e74705SXin Li /// \brief Called on well formed \#pragma bss_seg().
ActOnPragmaMSSection(SourceLocation PragmaLocation,int SectionFlags,StringLiteral * SegmentName)316*67e74705SXin Li void Sema::ActOnPragmaMSSection(SourceLocation PragmaLocation,
317*67e74705SXin Li                                 int SectionFlags, StringLiteral *SegmentName) {
318*67e74705SXin Li   UnifySection(SegmentName->getString(), SectionFlags, PragmaLocation);
319*67e74705SXin Li }
320*67e74705SXin Li 
ActOnPragmaMSInitSeg(SourceLocation PragmaLocation,StringLiteral * SegmentName)321*67e74705SXin Li void Sema::ActOnPragmaMSInitSeg(SourceLocation PragmaLocation,
322*67e74705SXin Li                                 StringLiteral *SegmentName) {
323*67e74705SXin Li   // There's no stack to maintain, so we just have a current section.  When we
324*67e74705SXin Li   // see the default section, reset our current section back to null so we stop
325*67e74705SXin Li   // tacking on unnecessary attributes.
326*67e74705SXin Li   CurInitSeg = SegmentName->getString() == ".CRT$XCU" ? nullptr : SegmentName;
327*67e74705SXin Li   CurInitSegLoc = PragmaLocation;
328*67e74705SXin Li }
329*67e74705SXin Li 
ActOnPragmaUnused(const Token & IdTok,Scope * curScope,SourceLocation PragmaLoc)330*67e74705SXin Li void Sema::ActOnPragmaUnused(const Token &IdTok, Scope *curScope,
331*67e74705SXin Li                              SourceLocation PragmaLoc) {
332*67e74705SXin Li 
333*67e74705SXin Li   IdentifierInfo *Name = IdTok.getIdentifierInfo();
334*67e74705SXin Li   LookupResult Lookup(*this, Name, IdTok.getLocation(), LookupOrdinaryName);
335*67e74705SXin Li   LookupParsedName(Lookup, curScope, nullptr, true);
336*67e74705SXin Li 
337*67e74705SXin Li   if (Lookup.empty()) {
338*67e74705SXin Li     Diag(PragmaLoc, diag::warn_pragma_unused_undeclared_var)
339*67e74705SXin Li       << Name << SourceRange(IdTok.getLocation());
340*67e74705SXin Li     return;
341*67e74705SXin Li   }
342*67e74705SXin Li 
343*67e74705SXin Li   VarDecl *VD = Lookup.getAsSingle<VarDecl>();
344*67e74705SXin Li   if (!VD) {
345*67e74705SXin Li     Diag(PragmaLoc, diag::warn_pragma_unused_expected_var_arg)
346*67e74705SXin Li       << Name << SourceRange(IdTok.getLocation());
347*67e74705SXin Li     return;
348*67e74705SXin Li   }
349*67e74705SXin Li 
350*67e74705SXin Li   // Warn if this was used before being marked unused.
351*67e74705SXin Li   if (VD->isUsed())
352*67e74705SXin Li     Diag(PragmaLoc, diag::warn_used_but_marked_unused) << Name;
353*67e74705SXin Li 
354*67e74705SXin Li   VD->addAttr(UnusedAttr::CreateImplicit(Context, UnusedAttr::GNU_unused,
355*67e74705SXin Li                                          IdTok.getLocation()));
356*67e74705SXin Li }
357*67e74705SXin Li 
AddCFAuditedAttribute(Decl * D)358*67e74705SXin Li void Sema::AddCFAuditedAttribute(Decl *D) {
359*67e74705SXin Li   SourceLocation Loc = PP.getPragmaARCCFCodeAuditedLoc();
360*67e74705SXin Li   if (!Loc.isValid()) return;
361*67e74705SXin Li 
362*67e74705SXin Li   // Don't add a redundant or conflicting attribute.
363*67e74705SXin Li   if (D->hasAttr<CFAuditedTransferAttr>() ||
364*67e74705SXin Li       D->hasAttr<CFUnknownTransferAttr>())
365*67e74705SXin Li     return;
366*67e74705SXin Li 
367*67e74705SXin Li   D->addAttr(CFAuditedTransferAttr::CreateImplicit(Context, Loc));
368*67e74705SXin Li }
369*67e74705SXin Li 
ActOnPragmaOptimize(bool On,SourceLocation PragmaLoc)370*67e74705SXin Li void Sema::ActOnPragmaOptimize(bool On, SourceLocation PragmaLoc) {
371*67e74705SXin Li   if(On)
372*67e74705SXin Li     OptimizeOffPragmaLocation = SourceLocation();
373*67e74705SXin Li   else
374*67e74705SXin Li     OptimizeOffPragmaLocation = PragmaLoc;
375*67e74705SXin Li }
376*67e74705SXin Li 
AddRangeBasedOptnone(FunctionDecl * FD)377*67e74705SXin Li void Sema::AddRangeBasedOptnone(FunctionDecl *FD) {
378*67e74705SXin Li   // In the future, check other pragmas if they're implemented (e.g. pragma
379*67e74705SXin Li   // optimize 0 will probably map to this functionality too).
380*67e74705SXin Li   if(OptimizeOffPragmaLocation.isValid())
381*67e74705SXin Li     AddOptnoneAttributeIfNoConflicts(FD, OptimizeOffPragmaLocation);
382*67e74705SXin Li }
383*67e74705SXin Li 
AddOptnoneAttributeIfNoConflicts(FunctionDecl * FD,SourceLocation Loc)384*67e74705SXin Li void Sema::AddOptnoneAttributeIfNoConflicts(FunctionDecl *FD,
385*67e74705SXin Li                                             SourceLocation Loc) {
386*67e74705SXin Li   // Don't add a conflicting attribute. No diagnostic is needed.
387*67e74705SXin Li   if (FD->hasAttr<MinSizeAttr>() || FD->hasAttr<AlwaysInlineAttr>())
388*67e74705SXin Li     return;
389*67e74705SXin Li 
390*67e74705SXin Li   // Add attributes only if required. Optnone requires noinline as well, but if
391*67e74705SXin Li   // either is already present then don't bother adding them.
392*67e74705SXin Li   if (!FD->hasAttr<OptimizeNoneAttr>())
393*67e74705SXin Li     FD->addAttr(OptimizeNoneAttr::CreateImplicit(Context, Loc));
394*67e74705SXin Li   if (!FD->hasAttr<NoInlineAttr>())
395*67e74705SXin Li     FD->addAttr(NoInlineAttr::CreateImplicit(Context, Loc));
396*67e74705SXin Li }
397*67e74705SXin Li 
398*67e74705SXin Li typedef std::vector<std::pair<unsigned, SourceLocation> > VisStack;
399*67e74705SXin Li enum : unsigned { NoVisibility = ~0U };
400*67e74705SXin Li 
AddPushedVisibilityAttribute(Decl * D)401*67e74705SXin Li void Sema::AddPushedVisibilityAttribute(Decl *D) {
402*67e74705SXin Li   if (!VisContext)
403*67e74705SXin Li     return;
404*67e74705SXin Li 
405*67e74705SXin Li   NamedDecl *ND = dyn_cast<NamedDecl>(D);
406*67e74705SXin Li   if (ND && ND->getExplicitVisibility(NamedDecl::VisibilityForValue))
407*67e74705SXin Li     return;
408*67e74705SXin Li 
409*67e74705SXin Li   VisStack *Stack = static_cast<VisStack*>(VisContext);
410*67e74705SXin Li   unsigned rawType = Stack->back().first;
411*67e74705SXin Li   if (rawType == NoVisibility) return;
412*67e74705SXin Li 
413*67e74705SXin Li   VisibilityAttr::VisibilityType type
414*67e74705SXin Li     = (VisibilityAttr::VisibilityType) rawType;
415*67e74705SXin Li   SourceLocation loc = Stack->back().second;
416*67e74705SXin Li 
417*67e74705SXin Li   D->addAttr(VisibilityAttr::CreateImplicit(Context, type, loc));
418*67e74705SXin Li }
419*67e74705SXin Li 
420*67e74705SXin Li /// FreeVisContext - Deallocate and null out VisContext.
FreeVisContext()421*67e74705SXin Li void Sema::FreeVisContext() {
422*67e74705SXin Li   delete static_cast<VisStack*>(VisContext);
423*67e74705SXin Li   VisContext = nullptr;
424*67e74705SXin Li }
425*67e74705SXin Li 
PushPragmaVisibility(Sema & S,unsigned type,SourceLocation loc)426*67e74705SXin Li static void PushPragmaVisibility(Sema &S, unsigned type, SourceLocation loc) {
427*67e74705SXin Li   // Put visibility on stack.
428*67e74705SXin Li   if (!S.VisContext)
429*67e74705SXin Li     S.VisContext = new VisStack;
430*67e74705SXin Li 
431*67e74705SXin Li   VisStack *Stack = static_cast<VisStack*>(S.VisContext);
432*67e74705SXin Li   Stack->push_back(std::make_pair(type, loc));
433*67e74705SXin Li }
434*67e74705SXin Li 
ActOnPragmaVisibility(const IdentifierInfo * VisType,SourceLocation PragmaLoc)435*67e74705SXin Li void Sema::ActOnPragmaVisibility(const IdentifierInfo* VisType,
436*67e74705SXin Li                                  SourceLocation PragmaLoc) {
437*67e74705SXin Li   if (VisType) {
438*67e74705SXin Li     // Compute visibility to use.
439*67e74705SXin Li     VisibilityAttr::VisibilityType T;
440*67e74705SXin Li     if (!VisibilityAttr::ConvertStrToVisibilityType(VisType->getName(), T)) {
441*67e74705SXin Li       Diag(PragmaLoc, diag::warn_attribute_unknown_visibility) << VisType;
442*67e74705SXin Li       return;
443*67e74705SXin Li     }
444*67e74705SXin Li     PushPragmaVisibility(*this, T, PragmaLoc);
445*67e74705SXin Li   } else {
446*67e74705SXin Li     PopPragmaVisibility(false, PragmaLoc);
447*67e74705SXin Li   }
448*67e74705SXin Li }
449*67e74705SXin Li 
ActOnPragmaFPContract(tok::OnOffSwitch OOS)450*67e74705SXin Li void Sema::ActOnPragmaFPContract(tok::OnOffSwitch OOS) {
451*67e74705SXin Li   switch (OOS) {
452*67e74705SXin Li   case tok::OOS_ON:
453*67e74705SXin Li     FPFeatures.fp_contract = 1;
454*67e74705SXin Li     break;
455*67e74705SXin Li   case tok::OOS_OFF:
456*67e74705SXin Li     FPFeatures.fp_contract = 0;
457*67e74705SXin Li     break;
458*67e74705SXin Li   case tok::OOS_DEFAULT:
459*67e74705SXin Li     FPFeatures.fp_contract = getLangOpts().DefaultFPContract;
460*67e74705SXin Li     break;
461*67e74705SXin Li   }
462*67e74705SXin Li }
463*67e74705SXin Li 
PushNamespaceVisibilityAttr(const VisibilityAttr * Attr,SourceLocation Loc)464*67e74705SXin Li void Sema::PushNamespaceVisibilityAttr(const VisibilityAttr *Attr,
465*67e74705SXin Li                                        SourceLocation Loc) {
466*67e74705SXin Li   // Visibility calculations will consider the namespace's visibility.
467*67e74705SXin Li   // Here we just want to note that we're in a visibility context
468*67e74705SXin Li   // which overrides any enclosing #pragma context, but doesn't itself
469*67e74705SXin Li   // contribute visibility.
470*67e74705SXin Li   PushPragmaVisibility(*this, NoVisibility, Loc);
471*67e74705SXin Li }
472*67e74705SXin Li 
PopPragmaVisibility(bool IsNamespaceEnd,SourceLocation EndLoc)473*67e74705SXin Li void Sema::PopPragmaVisibility(bool IsNamespaceEnd, SourceLocation EndLoc) {
474*67e74705SXin Li   if (!VisContext) {
475*67e74705SXin Li     Diag(EndLoc, diag::err_pragma_pop_visibility_mismatch);
476*67e74705SXin Li     return;
477*67e74705SXin Li   }
478*67e74705SXin Li 
479*67e74705SXin Li   // Pop visibility from stack
480*67e74705SXin Li   VisStack *Stack = static_cast<VisStack*>(VisContext);
481*67e74705SXin Li 
482*67e74705SXin Li   const std::pair<unsigned, SourceLocation> *Back = &Stack->back();
483*67e74705SXin Li   bool StartsWithPragma = Back->first != NoVisibility;
484*67e74705SXin Li   if (StartsWithPragma && IsNamespaceEnd) {
485*67e74705SXin Li     Diag(Back->second, diag::err_pragma_push_visibility_mismatch);
486*67e74705SXin Li     Diag(EndLoc, diag::note_surrounding_namespace_ends_here);
487*67e74705SXin Li 
488*67e74705SXin Li     // For better error recovery, eat all pushes inside the namespace.
489*67e74705SXin Li     do {
490*67e74705SXin Li       Stack->pop_back();
491*67e74705SXin Li       Back = &Stack->back();
492*67e74705SXin Li       StartsWithPragma = Back->first != NoVisibility;
493*67e74705SXin Li     } while (StartsWithPragma);
494*67e74705SXin Li   } else if (!StartsWithPragma && !IsNamespaceEnd) {
495*67e74705SXin Li     Diag(EndLoc, diag::err_pragma_pop_visibility_mismatch);
496*67e74705SXin Li     Diag(Back->second, diag::note_surrounding_namespace_starts_here);
497*67e74705SXin Li     return;
498*67e74705SXin Li   }
499*67e74705SXin Li 
500*67e74705SXin Li   Stack->pop_back();
501*67e74705SXin Li   // To simplify the implementation, never keep around an empty stack.
502*67e74705SXin Li   if (Stack->empty())
503*67e74705SXin Li     FreeVisContext();
504*67e74705SXin Li }
505