blob: 69f27b0ada7da7196a3763ec35728b2f039a61a0 [file] [log] [blame]
Chris Lattner5a0c3512009-02-17 00:57:29 +00001//===--- SemaAttr.cpp - Semantic Analysis for Attributes ------------------===//
2//
3// The LLVM Compiler Infrastructure
4//
5// This file is distributed under the University of Illinois Open Source
6// License. See LICENSE.TXT for details.
7//
8//===----------------------------------------------------------------------===//
9//
Chris Lattner574aa402009-02-17 01:09:29 +000010// This file implements semantic analysis for non-trivial attributes and
11// pragmas.
Chris Lattner5a0c3512009-02-17 00:57:29 +000012//
13//===----------------------------------------------------------------------===//
14
15#include "Sema.h"
John McCall7d384dd2009-11-18 07:57:50 +000016#include "Lookup.h"
Chris Lattner5a0c3512009-02-17 00:57:29 +000017#include "clang/AST/Expr.h"
Daniel Dunbar613fd672010-05-27 00:35:16 +000018#include "clang/Basic/TargetInfo.h"
19#include "clang/Lex/Preprocessor.h"
Chris Lattner5a0c3512009-02-17 00:57:29 +000020using namespace clang;
21
Chris Lattner574aa402009-02-17 01:09:29 +000022//===----------------------------------------------------------------------===//
Daniel Dunbarea75a822010-05-27 00:04:40 +000023// Pragma 'pack' and 'options align'
Chris Lattner574aa402009-02-17 01:09:29 +000024//===----------------------------------------------------------------------===//
25
26namespace {
Daniel Dunbarae2232b2010-05-27 02:25:27 +000027 struct PackStackEntry {
Daniel Dunbarc6082fe2010-05-27 05:45:51 +000028 // We just use a sentinel to represent when the stack is set to mac68k
29 // alignment.
30 static const unsigned kMac68kAlignmentSentinel = ~0U;
31
Daniel Dunbarae2232b2010-05-27 02:25:27 +000032 unsigned Alignment;
33 IdentifierInfo *Name;
34 };
35
Chris Lattner574aa402009-02-17 01:09:29 +000036 /// PragmaPackStack - Simple class to wrap the stack used by #pragma
37 /// pack.
38 class PragmaPackStack {
Daniel Dunbarae2232b2010-05-27 02:25:27 +000039 typedef std::vector<PackStackEntry> stack_ty;
Chris Lattner574aa402009-02-17 01:09:29 +000040
41 /// Alignment - The current user specified alignment.
42 unsigned Alignment;
43
44 /// Stack - Entries in the #pragma pack stack, consisting of saved
45 /// alignments and optional names.
46 stack_ty Stack;
Mike Stump1eb44332009-09-09 15:08:12 +000047
48 public:
Chris Lattner574aa402009-02-17 01:09:29 +000049 PragmaPackStack() : Alignment(0) {}
50
51 void setAlignment(unsigned A) { Alignment = A; }
52 unsigned getAlignment() { return Alignment; }
53
54 /// push - Push the current alignment onto the stack, optionally
55 /// using the given \arg Name for the record, if non-zero.
56 void push(IdentifierInfo *Name) {
Daniel Dunbarae2232b2010-05-27 02:25:27 +000057 PackStackEntry PSE = { Alignment, Name };
58 Stack.push_back(PSE);
Chris Lattner574aa402009-02-17 01:09:29 +000059 }
60
61 /// pop - Pop a record from the stack and restore the current
62 /// alignment to the previous value. If \arg Name is non-zero then
63 /// the first such named record is popped, otherwise the top record
64 /// is popped. Returns true if the pop succeeded.
65 bool pop(IdentifierInfo *Name);
66 };
67} // end anonymous namespace.
68
69bool PragmaPackStack::pop(IdentifierInfo *Name) {
70 if (Stack.empty())
71 return false;
Mike Stump1eb44332009-09-09 15:08:12 +000072
Chris Lattner574aa402009-02-17 01:09:29 +000073 // If name is empty just pop top.
74 if (!Name) {
Daniel Dunbarae2232b2010-05-27 02:25:27 +000075 Alignment = Stack.back().Alignment;
Chris Lattner574aa402009-02-17 01:09:29 +000076 Stack.pop_back();
77 return true;
Mike Stump1eb44332009-09-09 15:08:12 +000078 }
79
Chris Lattner574aa402009-02-17 01:09:29 +000080 // Otherwise, find the named record.
81 for (unsigned i = Stack.size(); i != 0; ) {
82 --i;
Daniel Dunbarae2232b2010-05-27 02:25:27 +000083 if (Stack[i].Name == Name) {
Chris Lattner574aa402009-02-17 01:09:29 +000084 // Found it, pop up to and including this record.
Daniel Dunbarae2232b2010-05-27 02:25:27 +000085 Alignment = Stack[i].Alignment;
Chris Lattner574aa402009-02-17 01:09:29 +000086 Stack.erase(Stack.begin() + i, Stack.end());
87 return true;
88 }
89 }
Mike Stump1eb44332009-09-09 15:08:12 +000090
Chris Lattner574aa402009-02-17 01:09:29 +000091 return false;
92}
93
94
95/// FreePackedContext - Deallocate and null out PackContext.
96void Sema::FreePackedContext() {
97 delete static_cast<PragmaPackStack*>(PackContext);
98 PackContext = 0;
99}
100
Daniel Dunbar9f21f892010-05-27 01:53:40 +0000101void Sema::AddAlignmentAttributesForRecord(RecordDecl *RD) {
102 // If there is no pack context, we don't need any attributes.
103 if (!PackContext)
104 return;
105
106 PragmaPackStack *Stack = static_cast<PragmaPackStack*>(PackContext);
107
108 // Otherwise, check to see if we need a max field alignment attribute.
Daniel Dunbarc6082fe2010-05-27 05:45:51 +0000109 if (unsigned Alignment = Stack->getAlignment()) {
110 if (Alignment == PackStackEntry::kMac68kAlignmentSentinel)
111 RD->addAttr(::new (Context) AlignMac68kAttr());
112 else
113 RD->addAttr(::new (Context) MaxFieldAlignmentAttr(Alignment * 8));
114 }
Chris Lattner574aa402009-02-17 01:09:29 +0000115}
116
Daniel Dunbarea75a822010-05-27 00:04:40 +0000117void Sema::ActOnPragmaOptionsAlign(PragmaOptionsAlignKind Kind,
118 SourceLocation PragmaLoc,
119 SourceLocation KindLoc) {
120 if (PackContext == 0)
121 PackContext = new PragmaPackStack();
122
123 PragmaPackStack *Context = static_cast<PragmaPackStack*>(PackContext);
124
125 // Reset just pops the top of the stack.
126 if (Kind == Action::POAK_Reset) {
127 // Do the pop.
128 if (!Context->pop(0)) {
129 // If a name was specified then failure indicates the name
130 // wasn't found. Otherwise failure indicates the stack was
131 // empty.
132 Diag(PragmaLoc, diag::warn_pragma_options_align_reset_failed)
133 << "stack empty";
134 }
135 return;
136 }
137
Daniel Dunbarea75a822010-05-27 00:04:40 +0000138 switch (Kind) {
Daniel Dunbar638e7cf2010-05-27 18:42:09 +0000139 // For all targets we support native and natural are the same.
140 //
141 // FIXME: This is not true on Darwin/PPC.
142 case POAK_Native:
Daniel Dunbar450f7932010-05-28 19:43:33 +0000143 case POAK_Power:
Daniel Dunbard6b305d2010-05-28 20:08:00 +0000144 case POAK_Natural:
Daniel Dunbar450f7932010-05-28 19:43:33 +0000145 Context->push(0);
146 Context->setAlignment(0);
147 break;
148
Daniel Dunbar6f739142010-05-27 18:42:17 +0000149 // Note that '#pragma options align=packed' is not equivalent to attribute
150 // packed, it has a different precedence relative to attribute aligned.
151 case POAK_Packed:
152 Context->push(0);
153 Context->setAlignment(1);
154 break;
155
Daniel Dunbar613fd672010-05-27 00:35:16 +0000156 case POAK_Mac68k:
157 // Check if the target supports this.
158 if (!PP.getTargetInfo().hasAlignMac68kSupport()) {
159 Diag(PragmaLoc, diag::err_pragma_options_align_mac68k_target_unsupported);
160 return;
Daniel Dunbar613fd672010-05-27 00:35:16 +0000161 }
Daniel Dunbarc6082fe2010-05-27 05:45:51 +0000162 Context->push(0);
163 Context->setAlignment(PackStackEntry::kMac68kAlignmentSentinel);
Daniel Dunbar613fd672010-05-27 00:35:16 +0000164 break;
165
Daniel Dunbarea75a822010-05-27 00:04:40 +0000166 default:
167 Diag(PragmaLoc, diag::warn_pragma_options_align_unsupported_option)
168 << KindLoc;
169 break;
170 }
171}
172
Mike Stump1eb44332009-09-09 15:08:12 +0000173void Sema::ActOnPragmaPack(PragmaPackKind Kind, IdentifierInfo *Name,
174 ExprTy *alignment, SourceLocation PragmaLoc,
Chris Lattner5a0c3512009-02-17 00:57:29 +0000175 SourceLocation LParenLoc, SourceLocation RParenLoc) {
176 Expr *Alignment = static_cast<Expr *>(alignment);
177
178 // If specified then alignment must be a "small" power of two.
179 unsigned AlignmentVal = 0;
180 if (Alignment) {
181 llvm::APSInt Val;
Mike Stump1eb44332009-09-09 15:08:12 +0000182
Daniel Dunbar79cd1162009-03-06 20:45:54 +0000183 // pack(0) is like pack(), which just works out since that is what
184 // we use 0 for in PackAttr.
Douglas Gregorac06a0e2010-05-18 23:01:22 +0000185 if (Alignment->isTypeDependent() ||
186 Alignment->isValueDependent() ||
187 !Alignment->isIntegerConstantExpr(Val, Context) ||
Daniel Dunbar79cd1162009-03-06 20:45:54 +0000188 !(Val == 0 || Val.isPowerOf2()) ||
Chris Lattner5a0c3512009-02-17 00:57:29 +0000189 Val.getZExtValue() > 16) {
190 Diag(PragmaLoc, diag::warn_pragma_pack_invalid_alignment);
191 Alignment->Destroy(Context);
192 return; // Ignore
193 }
194
195 AlignmentVal = (unsigned) Val.getZExtValue();
196 }
Mike Stump1eb44332009-09-09 15:08:12 +0000197
Chris Lattner574aa402009-02-17 01:09:29 +0000198 if (PackContext == 0)
199 PackContext = new PragmaPackStack();
Mike Stump1eb44332009-09-09 15:08:12 +0000200
Chris Lattner574aa402009-02-17 01:09:29 +0000201 PragmaPackStack *Context = static_cast<PragmaPackStack*>(PackContext);
Mike Stump1eb44332009-09-09 15:08:12 +0000202
Chris Lattner5a0c3512009-02-17 00:57:29 +0000203 switch (Kind) {
204 case Action::PPK_Default: // pack([n])
Chris Lattner574aa402009-02-17 01:09:29 +0000205 Context->setAlignment(AlignmentVal);
Chris Lattner5a0c3512009-02-17 00:57:29 +0000206 break;
207
208 case Action::PPK_Show: // pack(show)
209 // Show the current alignment, making sure to show the right value
210 // for the default.
Chris Lattner574aa402009-02-17 01:09:29 +0000211 AlignmentVal = Context->getAlignment();
Chris Lattner5a0c3512009-02-17 00:57:29 +0000212 // FIXME: This should come from the target.
213 if (AlignmentVal == 0)
214 AlignmentVal = 8;
Daniel Dunbarc6082fe2010-05-27 05:45:51 +0000215 if (AlignmentVal == PackStackEntry::kMac68kAlignmentSentinel)
216 Diag(PragmaLoc, diag::warn_pragma_pack_show) << "mac68k";
217 else
218 Diag(PragmaLoc, diag::warn_pragma_pack_show) << AlignmentVal;
Chris Lattner5a0c3512009-02-17 00:57:29 +0000219 break;
220
221 case Action::PPK_Push: // pack(push [, id] [, [n])
Chris Lattner574aa402009-02-17 01:09:29 +0000222 Context->push(Name);
Chris Lattner5a0c3512009-02-17 00:57:29 +0000223 // Set the new alignment if specified.
224 if (Alignment)
Mike Stump1eb44332009-09-09 15:08:12 +0000225 Context->setAlignment(AlignmentVal);
Chris Lattner5a0c3512009-02-17 00:57:29 +0000226 break;
227
228 case Action::PPK_Pop: // pack(pop [, id] [, n])
229 // MSDN, C/C++ Preprocessor Reference > Pragma Directives > pack:
230 // "#pragma pack(pop, identifier, n) is undefined"
231 if (Alignment && Name)
Mike Stump1eb44332009-09-09 15:08:12 +0000232 Diag(PragmaLoc, diag::warn_pragma_pack_pop_identifer_and_alignment);
233
Chris Lattner5a0c3512009-02-17 00:57:29 +0000234 // Do the pop.
Chris Lattner574aa402009-02-17 01:09:29 +0000235 if (!Context->pop(Name)) {
Chris Lattner5a0c3512009-02-17 00:57:29 +0000236 // If a name was specified then failure indicates the name
237 // wasn't found. Otherwise failure indicates the stack was
238 // empty.
239 Diag(PragmaLoc, diag::warn_pragma_pack_pop_failed)
240 << (Name ? "no record matching name" : "stack empty");
241
242 // FIXME: Warn about popping named records as MSVC does.
243 } else {
244 // Pop succeeded, set the new alignment if specified.
245 if (Alignment)
Chris Lattner574aa402009-02-17 01:09:29 +0000246 Context->setAlignment(AlignmentVal);
Chris Lattner5a0c3512009-02-17 00:57:29 +0000247 }
248 break;
249
250 default:
251 assert(0 && "Invalid #pragma pack kind.");
252 }
253}
254
Ted Kremenek7a02a372009-08-03 23:24:57 +0000255void Sema::ActOnPragmaUnused(const Token *Identifiers, unsigned NumIdentifiers,
256 Scope *curScope,
Ted Kremenek4726d032009-03-23 22:28:25 +0000257 SourceLocation PragmaLoc,
258 SourceLocation LParenLoc,
259 SourceLocation RParenLoc) {
Ted Kremenek4726d032009-03-23 22:28:25 +0000260
Ted Kremenek7a02a372009-08-03 23:24:57 +0000261 for (unsigned i = 0; i < NumIdentifiers; ++i) {
262 const Token &Tok = Identifiers[i];
Mike Stump1eb44332009-09-09 15:08:12 +0000263 IdentifierInfo *Name = Tok.getIdentifierInfo();
John McCalla24dc2e2009-11-17 02:14:36 +0000264 LookupResult Lookup(*this, Name, Tok.getLocation(), LookupOrdinaryName);
265 LookupParsedName(Lookup, curScope, NULL, true);
Ted Kremenek4726d032009-03-23 22:28:25 +0000266
John McCall1bcee0a2009-12-02 08:25:40 +0000267 if (Lookup.empty()) {
Ted Kremenek7a02a372009-08-03 23:24:57 +0000268 Diag(PragmaLoc, diag::warn_pragma_unused_undeclared_var)
269 << Name << SourceRange(Tok.getLocation());
270 continue;
Ted Kremenek4726d032009-03-23 22:28:25 +0000271 }
Mike Stump1eb44332009-09-09 15:08:12 +0000272
John McCall1bcee0a2009-12-02 08:25:40 +0000273 VarDecl *VD = Lookup.getAsSingle<VarDecl>();
274 if (!VD || !VD->hasLocalStorage()) {
Ted Kremenek7a02a372009-08-03 23:24:57 +0000275 Diag(PragmaLoc, diag::warn_pragma_unused_expected_localvar)
276 << Name << SourceRange(Tok.getLocation());
277 continue;
278 }
Mike Stump1eb44332009-09-09 15:08:12 +0000279
John McCall1bcee0a2009-12-02 08:25:40 +0000280 VD->addAttr(::new (Context) UnusedAttr());
Ted Kremenek4726d032009-03-23 22:28:25 +0000281 }
282}