xref: /minix3/external/bsd/llvm/dist/clang/lib/Sema/SemaAttr.cpp (revision f4a2713ac843a11c696ec80c0a5e3e5d80b4d338)
1*f4a2713aSLionel Sambuc //===--- SemaAttr.cpp - Semantic Analysis for Attributes ------------------===//
2*f4a2713aSLionel Sambuc //
3*f4a2713aSLionel Sambuc //                     The LLVM Compiler Infrastructure
4*f4a2713aSLionel Sambuc //
5*f4a2713aSLionel Sambuc // This file is distributed under the University of Illinois Open Source
6*f4a2713aSLionel Sambuc // License. See LICENSE.TXT for details.
7*f4a2713aSLionel Sambuc //
8*f4a2713aSLionel Sambuc //===----------------------------------------------------------------------===//
9*f4a2713aSLionel Sambuc //
10*f4a2713aSLionel Sambuc // This file implements semantic analysis for non-trivial attributes and
11*f4a2713aSLionel Sambuc // pragmas.
12*f4a2713aSLionel Sambuc //
13*f4a2713aSLionel Sambuc //===----------------------------------------------------------------------===//
14*f4a2713aSLionel Sambuc 
15*f4a2713aSLionel Sambuc #include "clang/Sema/SemaInternal.h"
16*f4a2713aSLionel Sambuc #include "clang/AST/ASTConsumer.h"
17*f4a2713aSLionel Sambuc #include "clang/AST/Attr.h"
18*f4a2713aSLionel Sambuc #include "clang/AST/Expr.h"
19*f4a2713aSLionel Sambuc #include "clang/Basic/TargetInfo.h"
20*f4a2713aSLionel Sambuc #include "clang/Lex/Preprocessor.h"
21*f4a2713aSLionel Sambuc #include "clang/Sema/Lookup.h"
22*f4a2713aSLionel Sambuc using namespace clang;
23*f4a2713aSLionel Sambuc 
24*f4a2713aSLionel Sambuc //===----------------------------------------------------------------------===//
25*f4a2713aSLionel Sambuc // Pragma 'pack' and 'options align'
26*f4a2713aSLionel Sambuc //===----------------------------------------------------------------------===//
27*f4a2713aSLionel Sambuc 
28*f4a2713aSLionel Sambuc namespace {
29*f4a2713aSLionel Sambuc   struct PackStackEntry {
30*f4a2713aSLionel Sambuc     // We just use a sentinel to represent when the stack is set to mac68k
31*f4a2713aSLionel Sambuc     // alignment.
32*f4a2713aSLionel Sambuc     static const unsigned kMac68kAlignmentSentinel = ~0U;
33*f4a2713aSLionel Sambuc 
34*f4a2713aSLionel Sambuc     unsigned Alignment;
35*f4a2713aSLionel Sambuc     IdentifierInfo *Name;
36*f4a2713aSLionel Sambuc   };
37*f4a2713aSLionel Sambuc 
38*f4a2713aSLionel Sambuc   /// PragmaPackStack - Simple class to wrap the stack used by #pragma
39*f4a2713aSLionel Sambuc   /// pack.
40*f4a2713aSLionel Sambuc   class PragmaPackStack {
41*f4a2713aSLionel Sambuc     typedef std::vector<PackStackEntry> stack_ty;
42*f4a2713aSLionel Sambuc 
43*f4a2713aSLionel Sambuc     /// Alignment - The current user specified alignment.
44*f4a2713aSLionel Sambuc     unsigned Alignment;
45*f4a2713aSLionel Sambuc 
46*f4a2713aSLionel Sambuc     /// Stack - Entries in the #pragma pack stack, consisting of saved
47*f4a2713aSLionel Sambuc     /// alignments and optional names.
48*f4a2713aSLionel Sambuc     stack_ty Stack;
49*f4a2713aSLionel Sambuc 
50*f4a2713aSLionel Sambuc   public:
51*f4a2713aSLionel Sambuc     PragmaPackStack() : Alignment(0) {}
52*f4a2713aSLionel Sambuc 
53*f4a2713aSLionel Sambuc     void setAlignment(unsigned A) { Alignment = A; }
54*f4a2713aSLionel Sambuc     unsigned getAlignment() { return Alignment; }
55*f4a2713aSLionel Sambuc 
56*f4a2713aSLionel Sambuc     /// push - Push the current alignment onto the stack, optionally
57*f4a2713aSLionel Sambuc     /// using the given \arg Name for the record, if non-zero.
58*f4a2713aSLionel Sambuc     void push(IdentifierInfo *Name) {
59*f4a2713aSLionel Sambuc       PackStackEntry PSE = { Alignment, Name };
60*f4a2713aSLionel Sambuc       Stack.push_back(PSE);
61*f4a2713aSLionel Sambuc     }
62*f4a2713aSLionel Sambuc 
63*f4a2713aSLionel Sambuc     /// pop - Pop a record from the stack and restore the current
64*f4a2713aSLionel Sambuc     /// alignment to the previous value. If \arg Name is non-zero then
65*f4a2713aSLionel Sambuc     /// the first such named record is popped, otherwise the top record
66*f4a2713aSLionel Sambuc     /// is popped. Returns true if the pop succeeded.
67*f4a2713aSLionel Sambuc     bool pop(IdentifierInfo *Name, bool IsReset);
68*f4a2713aSLionel Sambuc   };
69*f4a2713aSLionel Sambuc }  // end anonymous namespace.
70*f4a2713aSLionel Sambuc 
71*f4a2713aSLionel Sambuc bool PragmaPackStack::pop(IdentifierInfo *Name, bool IsReset) {
72*f4a2713aSLionel Sambuc   // If name is empty just pop top.
73*f4a2713aSLionel Sambuc   if (!Name) {
74*f4a2713aSLionel Sambuc     // An empty stack is a special case...
75*f4a2713aSLionel Sambuc     if (Stack.empty()) {
76*f4a2713aSLionel Sambuc       // If this isn't a reset, it is always an error.
77*f4a2713aSLionel Sambuc       if (!IsReset)
78*f4a2713aSLionel Sambuc         return false;
79*f4a2713aSLionel Sambuc 
80*f4a2713aSLionel Sambuc       // Otherwise, it is an error only if some alignment has been set.
81*f4a2713aSLionel Sambuc       if (!Alignment)
82*f4a2713aSLionel Sambuc         return false;
83*f4a2713aSLionel Sambuc 
84*f4a2713aSLionel Sambuc       // Otherwise, reset to the default alignment.
85*f4a2713aSLionel Sambuc       Alignment = 0;
86*f4a2713aSLionel Sambuc     } else {
87*f4a2713aSLionel Sambuc       Alignment = Stack.back().Alignment;
88*f4a2713aSLionel Sambuc       Stack.pop_back();
89*f4a2713aSLionel Sambuc     }
90*f4a2713aSLionel Sambuc 
91*f4a2713aSLionel Sambuc     return true;
92*f4a2713aSLionel Sambuc   }
93*f4a2713aSLionel Sambuc 
94*f4a2713aSLionel Sambuc   // Otherwise, find the named record.
95*f4a2713aSLionel Sambuc   for (unsigned i = Stack.size(); i != 0; ) {
96*f4a2713aSLionel Sambuc     --i;
97*f4a2713aSLionel Sambuc     if (Stack[i].Name == Name) {
98*f4a2713aSLionel Sambuc       // Found it, pop up to and including this record.
99*f4a2713aSLionel Sambuc       Alignment = Stack[i].Alignment;
100*f4a2713aSLionel Sambuc       Stack.erase(Stack.begin() + i, Stack.end());
101*f4a2713aSLionel Sambuc       return true;
102*f4a2713aSLionel Sambuc     }
103*f4a2713aSLionel Sambuc   }
104*f4a2713aSLionel Sambuc 
105*f4a2713aSLionel Sambuc   return false;
106*f4a2713aSLionel Sambuc }
107*f4a2713aSLionel Sambuc 
108*f4a2713aSLionel Sambuc 
109*f4a2713aSLionel Sambuc /// FreePackedContext - Deallocate and null out PackContext.
110*f4a2713aSLionel Sambuc void Sema::FreePackedContext() {
111*f4a2713aSLionel Sambuc   delete static_cast<PragmaPackStack*>(PackContext);
112*f4a2713aSLionel Sambuc   PackContext = 0;
113*f4a2713aSLionel Sambuc }
114*f4a2713aSLionel Sambuc 
115*f4a2713aSLionel Sambuc void Sema::AddAlignmentAttributesForRecord(RecordDecl *RD) {
116*f4a2713aSLionel Sambuc   // If there is no pack context, we don't need any attributes.
117*f4a2713aSLionel Sambuc   if (!PackContext)
118*f4a2713aSLionel Sambuc     return;
119*f4a2713aSLionel Sambuc 
120*f4a2713aSLionel Sambuc   PragmaPackStack *Stack = static_cast<PragmaPackStack*>(PackContext);
121*f4a2713aSLionel Sambuc 
122*f4a2713aSLionel Sambuc   // Otherwise, check to see if we need a max field alignment attribute.
123*f4a2713aSLionel Sambuc   if (unsigned Alignment = Stack->getAlignment()) {
124*f4a2713aSLionel Sambuc     if (Alignment == PackStackEntry::kMac68kAlignmentSentinel)
125*f4a2713aSLionel Sambuc       RD->addAttr(::new (Context) AlignMac68kAttr(SourceLocation(), Context));
126*f4a2713aSLionel Sambuc     else
127*f4a2713aSLionel Sambuc       RD->addAttr(::new (Context) MaxFieldAlignmentAttr(SourceLocation(),
128*f4a2713aSLionel Sambuc                                                         Context,
129*f4a2713aSLionel Sambuc                                                         Alignment * 8));
130*f4a2713aSLionel Sambuc   }
131*f4a2713aSLionel Sambuc }
132*f4a2713aSLionel Sambuc 
133*f4a2713aSLionel Sambuc void Sema::AddMsStructLayoutForRecord(RecordDecl *RD) {
134*f4a2713aSLionel Sambuc   if (!MSStructPragmaOn)
135*f4a2713aSLionel Sambuc     return;
136*f4a2713aSLionel Sambuc   RD->addAttr(::new (Context) MsStructAttr(SourceLocation(), Context));
137*f4a2713aSLionel Sambuc }
138*f4a2713aSLionel Sambuc 
139*f4a2713aSLionel Sambuc void Sema::ActOnPragmaOptionsAlign(PragmaOptionsAlignKind Kind,
140*f4a2713aSLionel Sambuc                                    SourceLocation PragmaLoc) {
141*f4a2713aSLionel Sambuc   if (PackContext == 0)
142*f4a2713aSLionel Sambuc     PackContext = new PragmaPackStack();
143*f4a2713aSLionel Sambuc 
144*f4a2713aSLionel Sambuc   PragmaPackStack *Context = static_cast<PragmaPackStack*>(PackContext);
145*f4a2713aSLionel Sambuc 
146*f4a2713aSLionel Sambuc   switch (Kind) {
147*f4a2713aSLionel Sambuc     // For all targets we support native and natural are the same.
148*f4a2713aSLionel Sambuc     //
149*f4a2713aSLionel Sambuc     // FIXME: This is not true on Darwin/PPC.
150*f4a2713aSLionel Sambuc   case POAK_Native:
151*f4a2713aSLionel Sambuc   case POAK_Power:
152*f4a2713aSLionel Sambuc   case POAK_Natural:
153*f4a2713aSLionel Sambuc     Context->push(0);
154*f4a2713aSLionel Sambuc     Context->setAlignment(0);
155*f4a2713aSLionel Sambuc     break;
156*f4a2713aSLionel Sambuc 
157*f4a2713aSLionel Sambuc     // Note that '#pragma options align=packed' is not equivalent to attribute
158*f4a2713aSLionel Sambuc     // packed, it has a different precedence relative to attribute aligned.
159*f4a2713aSLionel Sambuc   case POAK_Packed:
160*f4a2713aSLionel Sambuc     Context->push(0);
161*f4a2713aSLionel Sambuc     Context->setAlignment(1);
162*f4a2713aSLionel Sambuc     break;
163*f4a2713aSLionel Sambuc 
164*f4a2713aSLionel Sambuc   case POAK_Mac68k:
165*f4a2713aSLionel Sambuc     // Check if the target supports this.
166*f4a2713aSLionel Sambuc     if (!PP.getTargetInfo().hasAlignMac68kSupport()) {
167*f4a2713aSLionel Sambuc       Diag(PragmaLoc, diag::err_pragma_options_align_mac68k_target_unsupported);
168*f4a2713aSLionel Sambuc       return;
169*f4a2713aSLionel Sambuc     }
170*f4a2713aSLionel Sambuc     Context->push(0);
171*f4a2713aSLionel Sambuc     Context->setAlignment(PackStackEntry::kMac68kAlignmentSentinel);
172*f4a2713aSLionel Sambuc     break;
173*f4a2713aSLionel Sambuc 
174*f4a2713aSLionel Sambuc   case POAK_Reset:
175*f4a2713aSLionel Sambuc     // Reset just pops the top of the stack, or resets the current alignment to
176*f4a2713aSLionel Sambuc     // default.
177*f4a2713aSLionel Sambuc     if (!Context->pop(0, /*IsReset=*/true)) {
178*f4a2713aSLionel Sambuc       Diag(PragmaLoc, diag::warn_pragma_options_align_reset_failed)
179*f4a2713aSLionel Sambuc         << "stack empty";
180*f4a2713aSLionel Sambuc     }
181*f4a2713aSLionel Sambuc     break;
182*f4a2713aSLionel Sambuc   }
183*f4a2713aSLionel Sambuc }
184*f4a2713aSLionel Sambuc 
185*f4a2713aSLionel Sambuc void Sema::ActOnPragmaPack(PragmaPackKind Kind, IdentifierInfo *Name,
186*f4a2713aSLionel Sambuc                            Expr *alignment, SourceLocation PragmaLoc,
187*f4a2713aSLionel Sambuc                            SourceLocation LParenLoc, SourceLocation RParenLoc) {
188*f4a2713aSLionel Sambuc   Expr *Alignment = static_cast<Expr *>(alignment);
189*f4a2713aSLionel Sambuc 
190*f4a2713aSLionel Sambuc   // If specified then alignment must be a "small" power of two.
191*f4a2713aSLionel Sambuc   unsigned AlignmentVal = 0;
192*f4a2713aSLionel Sambuc   if (Alignment) {
193*f4a2713aSLionel Sambuc     llvm::APSInt Val;
194*f4a2713aSLionel Sambuc 
195*f4a2713aSLionel Sambuc     // pack(0) is like pack(), which just works out since that is what
196*f4a2713aSLionel Sambuc     // we use 0 for in PackAttr.
197*f4a2713aSLionel Sambuc     if (Alignment->isTypeDependent() ||
198*f4a2713aSLionel Sambuc         Alignment->isValueDependent() ||
199*f4a2713aSLionel Sambuc         !Alignment->isIntegerConstantExpr(Val, Context) ||
200*f4a2713aSLionel Sambuc         !(Val == 0 || Val.isPowerOf2()) ||
201*f4a2713aSLionel Sambuc         Val.getZExtValue() > 16) {
202*f4a2713aSLionel Sambuc       Diag(PragmaLoc, diag::warn_pragma_pack_invalid_alignment);
203*f4a2713aSLionel Sambuc       return; // Ignore
204*f4a2713aSLionel Sambuc     }
205*f4a2713aSLionel Sambuc 
206*f4a2713aSLionel Sambuc     AlignmentVal = (unsigned) Val.getZExtValue();
207*f4a2713aSLionel Sambuc   }
208*f4a2713aSLionel Sambuc 
209*f4a2713aSLionel Sambuc   if (PackContext == 0)
210*f4a2713aSLionel Sambuc     PackContext = new PragmaPackStack();
211*f4a2713aSLionel Sambuc 
212*f4a2713aSLionel Sambuc   PragmaPackStack *Context = static_cast<PragmaPackStack*>(PackContext);
213*f4a2713aSLionel Sambuc 
214*f4a2713aSLionel Sambuc   switch (Kind) {
215*f4a2713aSLionel Sambuc   case Sema::PPK_Default: // pack([n])
216*f4a2713aSLionel Sambuc     Context->setAlignment(AlignmentVal);
217*f4a2713aSLionel Sambuc     break;
218*f4a2713aSLionel Sambuc 
219*f4a2713aSLionel Sambuc   case Sema::PPK_Show: // pack(show)
220*f4a2713aSLionel Sambuc     // Show the current alignment, making sure to show the right value
221*f4a2713aSLionel Sambuc     // for the default.
222*f4a2713aSLionel Sambuc     AlignmentVal = Context->getAlignment();
223*f4a2713aSLionel Sambuc     // FIXME: This should come from the target.
224*f4a2713aSLionel Sambuc     if (AlignmentVal == 0)
225*f4a2713aSLionel Sambuc       AlignmentVal = 8;
226*f4a2713aSLionel Sambuc     if (AlignmentVal == PackStackEntry::kMac68kAlignmentSentinel)
227*f4a2713aSLionel Sambuc       Diag(PragmaLoc, diag::warn_pragma_pack_show) << "mac68k";
228*f4a2713aSLionel Sambuc     else
229*f4a2713aSLionel Sambuc       Diag(PragmaLoc, diag::warn_pragma_pack_show) << AlignmentVal;
230*f4a2713aSLionel Sambuc     break;
231*f4a2713aSLionel Sambuc 
232*f4a2713aSLionel Sambuc   case Sema::PPK_Push: // pack(push [, id] [, [n])
233*f4a2713aSLionel Sambuc     Context->push(Name);
234*f4a2713aSLionel Sambuc     // Set the new alignment if specified.
235*f4a2713aSLionel Sambuc     if (Alignment)
236*f4a2713aSLionel Sambuc       Context->setAlignment(AlignmentVal);
237*f4a2713aSLionel Sambuc     break;
238*f4a2713aSLionel Sambuc 
239*f4a2713aSLionel Sambuc   case Sema::PPK_Pop: // pack(pop [, id] [,  n])
240*f4a2713aSLionel Sambuc     // MSDN, C/C++ Preprocessor Reference > Pragma Directives > pack:
241*f4a2713aSLionel Sambuc     // "#pragma pack(pop, identifier, n) is undefined"
242*f4a2713aSLionel Sambuc     if (Alignment && Name)
243*f4a2713aSLionel Sambuc       Diag(PragmaLoc, diag::warn_pragma_pack_pop_identifer_and_alignment);
244*f4a2713aSLionel Sambuc 
245*f4a2713aSLionel Sambuc     // Do the pop.
246*f4a2713aSLionel Sambuc     if (!Context->pop(Name, /*IsReset=*/false)) {
247*f4a2713aSLionel Sambuc       // If a name was specified then failure indicates the name
248*f4a2713aSLionel Sambuc       // wasn't found. Otherwise failure indicates the stack was
249*f4a2713aSLionel Sambuc       // empty.
250*f4a2713aSLionel Sambuc       Diag(PragmaLoc, diag::warn_pragma_pack_pop_failed)
251*f4a2713aSLionel Sambuc         << (Name ? "no record matching name" : "stack empty");
252*f4a2713aSLionel Sambuc 
253*f4a2713aSLionel Sambuc       // FIXME: Warn about popping named records as MSVC does.
254*f4a2713aSLionel Sambuc     } else {
255*f4a2713aSLionel Sambuc       // Pop succeeded, set the new alignment if specified.
256*f4a2713aSLionel Sambuc       if (Alignment)
257*f4a2713aSLionel Sambuc         Context->setAlignment(AlignmentVal);
258*f4a2713aSLionel Sambuc     }
259*f4a2713aSLionel Sambuc     break;
260*f4a2713aSLionel Sambuc   }
261*f4a2713aSLionel Sambuc }
262*f4a2713aSLionel Sambuc 
263*f4a2713aSLionel Sambuc void Sema::ActOnPragmaMSStruct(PragmaMSStructKind Kind) {
264*f4a2713aSLionel Sambuc   MSStructPragmaOn = (Kind == PMSST_ON);
265*f4a2713aSLionel Sambuc }
266*f4a2713aSLionel Sambuc 
267*f4a2713aSLionel Sambuc void Sema::ActOnPragmaMSComment(PragmaMSCommentKind Kind, StringRef Arg) {
268*f4a2713aSLionel Sambuc   // FIXME: Serialize this.
269*f4a2713aSLionel Sambuc   switch (Kind) {
270*f4a2713aSLionel Sambuc   case PCK_Unknown:
271*f4a2713aSLionel Sambuc     llvm_unreachable("unexpected pragma comment kind");
272*f4a2713aSLionel Sambuc   case PCK_Linker:
273*f4a2713aSLionel Sambuc     Consumer.HandleLinkerOptionPragma(Arg);
274*f4a2713aSLionel Sambuc     return;
275*f4a2713aSLionel Sambuc   case PCK_Lib:
276*f4a2713aSLionel Sambuc     Consumer.HandleDependentLibrary(Arg);
277*f4a2713aSLionel Sambuc     return;
278*f4a2713aSLionel Sambuc   case PCK_Compiler:
279*f4a2713aSLionel Sambuc   case PCK_ExeStr:
280*f4a2713aSLionel Sambuc   case PCK_User:
281*f4a2713aSLionel Sambuc     return;  // We ignore all of these.
282*f4a2713aSLionel Sambuc   }
283*f4a2713aSLionel Sambuc   llvm_unreachable("invalid pragma comment kind");
284*f4a2713aSLionel Sambuc }
285*f4a2713aSLionel Sambuc 
286*f4a2713aSLionel Sambuc void Sema::ActOnPragmaDetectMismatch(StringRef Name, StringRef Value) {
287*f4a2713aSLionel Sambuc   // FIXME: Serialize this.
288*f4a2713aSLionel Sambuc   Consumer.HandleDetectMismatch(Name, Value);
289*f4a2713aSLionel Sambuc }
290*f4a2713aSLionel Sambuc 
291*f4a2713aSLionel Sambuc void Sema::ActOnPragmaUnused(const Token &IdTok, Scope *curScope,
292*f4a2713aSLionel Sambuc                              SourceLocation PragmaLoc) {
293*f4a2713aSLionel Sambuc 
294*f4a2713aSLionel Sambuc   IdentifierInfo *Name = IdTok.getIdentifierInfo();
295*f4a2713aSLionel Sambuc   LookupResult Lookup(*this, Name, IdTok.getLocation(), LookupOrdinaryName);
296*f4a2713aSLionel Sambuc   LookupParsedName(Lookup, curScope, NULL, true);
297*f4a2713aSLionel Sambuc 
298*f4a2713aSLionel Sambuc   if (Lookup.empty()) {
299*f4a2713aSLionel Sambuc     Diag(PragmaLoc, diag::warn_pragma_unused_undeclared_var)
300*f4a2713aSLionel Sambuc       << Name << SourceRange(IdTok.getLocation());
301*f4a2713aSLionel Sambuc     return;
302*f4a2713aSLionel Sambuc   }
303*f4a2713aSLionel Sambuc 
304*f4a2713aSLionel Sambuc   VarDecl *VD = Lookup.getAsSingle<VarDecl>();
305*f4a2713aSLionel Sambuc   if (!VD) {
306*f4a2713aSLionel Sambuc     Diag(PragmaLoc, diag::warn_pragma_unused_expected_var_arg)
307*f4a2713aSLionel Sambuc       << Name << SourceRange(IdTok.getLocation());
308*f4a2713aSLionel Sambuc     return;
309*f4a2713aSLionel Sambuc   }
310*f4a2713aSLionel Sambuc 
311*f4a2713aSLionel Sambuc   // Warn if this was used before being marked unused.
312*f4a2713aSLionel Sambuc   if (VD->isUsed())
313*f4a2713aSLionel Sambuc     Diag(PragmaLoc, diag::warn_used_but_marked_unused) << Name;
314*f4a2713aSLionel Sambuc 
315*f4a2713aSLionel Sambuc   VD->addAttr(::new (Context) UnusedAttr(IdTok.getLocation(), Context));
316*f4a2713aSLionel Sambuc }
317*f4a2713aSLionel Sambuc 
318*f4a2713aSLionel Sambuc void Sema::AddCFAuditedAttribute(Decl *D) {
319*f4a2713aSLionel Sambuc   SourceLocation Loc = PP.getPragmaARCCFCodeAuditedLoc();
320*f4a2713aSLionel Sambuc   if (!Loc.isValid()) return;
321*f4a2713aSLionel Sambuc 
322*f4a2713aSLionel Sambuc   // Don't add a redundant or conflicting attribute.
323*f4a2713aSLionel Sambuc   if (D->hasAttr<CFAuditedTransferAttr>() ||
324*f4a2713aSLionel Sambuc       D->hasAttr<CFUnknownTransferAttr>())
325*f4a2713aSLionel Sambuc     return;
326*f4a2713aSLionel Sambuc 
327*f4a2713aSLionel Sambuc   D->addAttr(::new (Context) CFAuditedTransferAttr(Loc, Context));
328*f4a2713aSLionel Sambuc }
329*f4a2713aSLionel Sambuc 
330*f4a2713aSLionel Sambuc typedef std::vector<std::pair<unsigned, SourceLocation> > VisStack;
331*f4a2713aSLionel Sambuc enum { NoVisibility = (unsigned) -1 };
332*f4a2713aSLionel Sambuc 
333*f4a2713aSLionel Sambuc void Sema::AddPushedVisibilityAttribute(Decl *D) {
334*f4a2713aSLionel Sambuc   if (!VisContext)
335*f4a2713aSLionel Sambuc     return;
336*f4a2713aSLionel Sambuc 
337*f4a2713aSLionel Sambuc   NamedDecl *ND = dyn_cast<NamedDecl>(D);
338*f4a2713aSLionel Sambuc   if (ND && ND->getExplicitVisibility(NamedDecl::VisibilityForValue))
339*f4a2713aSLionel Sambuc     return;
340*f4a2713aSLionel Sambuc 
341*f4a2713aSLionel Sambuc   VisStack *Stack = static_cast<VisStack*>(VisContext);
342*f4a2713aSLionel Sambuc   unsigned rawType = Stack->back().first;
343*f4a2713aSLionel Sambuc   if (rawType == NoVisibility) return;
344*f4a2713aSLionel Sambuc 
345*f4a2713aSLionel Sambuc   VisibilityAttr::VisibilityType type
346*f4a2713aSLionel Sambuc     = (VisibilityAttr::VisibilityType) rawType;
347*f4a2713aSLionel Sambuc   SourceLocation loc = Stack->back().second;
348*f4a2713aSLionel Sambuc 
349*f4a2713aSLionel Sambuc   D->addAttr(::new (Context) VisibilityAttr(loc, Context, type));
350*f4a2713aSLionel Sambuc }
351*f4a2713aSLionel Sambuc 
352*f4a2713aSLionel Sambuc /// FreeVisContext - Deallocate and null out VisContext.
353*f4a2713aSLionel Sambuc void Sema::FreeVisContext() {
354*f4a2713aSLionel Sambuc   delete static_cast<VisStack*>(VisContext);
355*f4a2713aSLionel Sambuc   VisContext = 0;
356*f4a2713aSLionel Sambuc }
357*f4a2713aSLionel Sambuc 
358*f4a2713aSLionel Sambuc static void PushPragmaVisibility(Sema &S, unsigned type, SourceLocation loc) {
359*f4a2713aSLionel Sambuc   // Put visibility on stack.
360*f4a2713aSLionel Sambuc   if (!S.VisContext)
361*f4a2713aSLionel Sambuc     S.VisContext = new VisStack;
362*f4a2713aSLionel Sambuc 
363*f4a2713aSLionel Sambuc   VisStack *Stack = static_cast<VisStack*>(S.VisContext);
364*f4a2713aSLionel Sambuc   Stack->push_back(std::make_pair(type, loc));
365*f4a2713aSLionel Sambuc }
366*f4a2713aSLionel Sambuc 
367*f4a2713aSLionel Sambuc void Sema::ActOnPragmaVisibility(const IdentifierInfo* VisType,
368*f4a2713aSLionel Sambuc                                  SourceLocation PragmaLoc) {
369*f4a2713aSLionel Sambuc   if (VisType) {
370*f4a2713aSLionel Sambuc     // Compute visibility to use.
371*f4a2713aSLionel Sambuc     VisibilityAttr::VisibilityType T;
372*f4a2713aSLionel Sambuc     if (!VisibilityAttr::ConvertStrToVisibilityType(VisType->getName(), T)) {
373*f4a2713aSLionel Sambuc       Diag(PragmaLoc, diag::warn_attribute_unknown_visibility) << VisType;
374*f4a2713aSLionel Sambuc       return;
375*f4a2713aSLionel Sambuc     }
376*f4a2713aSLionel Sambuc     PushPragmaVisibility(*this, T, PragmaLoc);
377*f4a2713aSLionel Sambuc   } else {
378*f4a2713aSLionel Sambuc     PopPragmaVisibility(false, PragmaLoc);
379*f4a2713aSLionel Sambuc   }
380*f4a2713aSLionel Sambuc }
381*f4a2713aSLionel Sambuc 
382*f4a2713aSLionel Sambuc void Sema::ActOnPragmaFPContract(tok::OnOffSwitch OOS) {
383*f4a2713aSLionel Sambuc   switch (OOS) {
384*f4a2713aSLionel Sambuc   case tok::OOS_ON:
385*f4a2713aSLionel Sambuc     FPFeatures.fp_contract = 1;
386*f4a2713aSLionel Sambuc     break;
387*f4a2713aSLionel Sambuc   case tok::OOS_OFF:
388*f4a2713aSLionel Sambuc     FPFeatures.fp_contract = 0;
389*f4a2713aSLionel Sambuc     break;
390*f4a2713aSLionel Sambuc   case tok::OOS_DEFAULT:
391*f4a2713aSLionel Sambuc     FPFeatures.fp_contract = getLangOpts().DefaultFPContract;
392*f4a2713aSLionel Sambuc     break;
393*f4a2713aSLionel Sambuc   }
394*f4a2713aSLionel Sambuc }
395*f4a2713aSLionel Sambuc 
396*f4a2713aSLionel Sambuc void Sema::PushNamespaceVisibilityAttr(const VisibilityAttr *Attr,
397*f4a2713aSLionel Sambuc                                        SourceLocation Loc) {
398*f4a2713aSLionel Sambuc   // Visibility calculations will consider the namespace's visibility.
399*f4a2713aSLionel Sambuc   // Here we just want to note that we're in a visibility context
400*f4a2713aSLionel Sambuc   // which overrides any enclosing #pragma context, but doesn't itself
401*f4a2713aSLionel Sambuc   // contribute visibility.
402*f4a2713aSLionel Sambuc   PushPragmaVisibility(*this, NoVisibility, Loc);
403*f4a2713aSLionel Sambuc }
404*f4a2713aSLionel Sambuc 
405*f4a2713aSLionel Sambuc void Sema::PopPragmaVisibility(bool IsNamespaceEnd, SourceLocation EndLoc) {
406*f4a2713aSLionel Sambuc   if (!VisContext) {
407*f4a2713aSLionel Sambuc     Diag(EndLoc, diag::err_pragma_pop_visibility_mismatch);
408*f4a2713aSLionel Sambuc     return;
409*f4a2713aSLionel Sambuc   }
410*f4a2713aSLionel Sambuc 
411*f4a2713aSLionel Sambuc   // Pop visibility from stack
412*f4a2713aSLionel Sambuc   VisStack *Stack = static_cast<VisStack*>(VisContext);
413*f4a2713aSLionel Sambuc 
414*f4a2713aSLionel Sambuc   const std::pair<unsigned, SourceLocation> *Back = &Stack->back();
415*f4a2713aSLionel Sambuc   bool StartsWithPragma = Back->first != NoVisibility;
416*f4a2713aSLionel Sambuc   if (StartsWithPragma && IsNamespaceEnd) {
417*f4a2713aSLionel Sambuc     Diag(Back->second, diag::err_pragma_push_visibility_mismatch);
418*f4a2713aSLionel Sambuc     Diag(EndLoc, diag::note_surrounding_namespace_ends_here);
419*f4a2713aSLionel Sambuc 
420*f4a2713aSLionel Sambuc     // For better error recovery, eat all pushes inside the namespace.
421*f4a2713aSLionel Sambuc     do {
422*f4a2713aSLionel Sambuc       Stack->pop_back();
423*f4a2713aSLionel Sambuc       Back = &Stack->back();
424*f4a2713aSLionel Sambuc       StartsWithPragma = Back->first != NoVisibility;
425*f4a2713aSLionel Sambuc     } while (StartsWithPragma);
426*f4a2713aSLionel Sambuc   } else if (!StartsWithPragma && !IsNamespaceEnd) {
427*f4a2713aSLionel Sambuc     Diag(EndLoc, diag::err_pragma_pop_visibility_mismatch);
428*f4a2713aSLionel Sambuc     Diag(Back->second, diag::note_surrounding_namespace_starts_here);
429*f4a2713aSLionel Sambuc     return;
430*f4a2713aSLionel Sambuc   }
431*f4a2713aSLionel Sambuc 
432*f4a2713aSLionel Sambuc   Stack->pop_back();
433*f4a2713aSLionel Sambuc   // To simplify the implementation, never keep around an empty stack.
434*f4a2713aSLionel Sambuc   if (Stack->empty())
435*f4a2713aSLionel Sambuc     FreeVisContext();
436*f4a2713aSLionel Sambuc }
437