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