blob: 2075f9aa9359c5ea8a7ec9740f0611301b6bbdf8 [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 {
28 unsigned Alignment;
29 IdentifierInfo *Name;
30 };
31
Chris Lattner574aa402009-02-17 01:09:29 +000032 /// PragmaPackStack - Simple class to wrap the stack used by #pragma
33 /// pack.
34 class PragmaPackStack {
Daniel Dunbarae2232b2010-05-27 02:25:27 +000035 typedef std::vector<PackStackEntry> stack_ty;
Chris Lattner574aa402009-02-17 01:09:29 +000036
37 /// Alignment - The current user specified alignment.
38 unsigned Alignment;
39
40 /// Stack - Entries in the #pragma pack stack, consisting of saved
41 /// alignments and optional names.
42 stack_ty Stack;
Mike Stump1eb44332009-09-09 15:08:12 +000043
44 public:
Chris Lattner574aa402009-02-17 01:09:29 +000045 PragmaPackStack() : Alignment(0) {}
46
47 void setAlignment(unsigned A) { Alignment = A; }
48 unsigned getAlignment() { return Alignment; }
49
50 /// push - Push the current alignment onto the stack, optionally
51 /// using the given \arg Name for the record, if non-zero.
52 void push(IdentifierInfo *Name) {
Daniel Dunbarae2232b2010-05-27 02:25:27 +000053 PackStackEntry PSE = { Alignment, Name };
54 Stack.push_back(PSE);
Chris Lattner574aa402009-02-17 01:09:29 +000055 }
56
57 /// pop - Pop a record from the stack and restore the current
58 /// alignment to the previous value. If \arg Name is non-zero then
59 /// the first such named record is popped, otherwise the top record
60 /// is popped. Returns true if the pop succeeded.
61 bool pop(IdentifierInfo *Name);
62 };
63} // end anonymous namespace.
64
65bool PragmaPackStack::pop(IdentifierInfo *Name) {
66 if (Stack.empty())
67 return false;
Mike Stump1eb44332009-09-09 15:08:12 +000068
Chris Lattner574aa402009-02-17 01:09:29 +000069 // If name is empty just pop top.
70 if (!Name) {
Daniel Dunbarae2232b2010-05-27 02:25:27 +000071 Alignment = Stack.back().Alignment;
Chris Lattner574aa402009-02-17 01:09:29 +000072 Stack.pop_back();
73 return true;
Mike Stump1eb44332009-09-09 15:08:12 +000074 }
75
Chris Lattner574aa402009-02-17 01:09:29 +000076 // Otherwise, find the named record.
77 for (unsigned i = Stack.size(); i != 0; ) {
78 --i;
Daniel Dunbarae2232b2010-05-27 02:25:27 +000079 if (Stack[i].Name == Name) {
Chris Lattner574aa402009-02-17 01:09:29 +000080 // Found it, pop up to and including this record.
Daniel Dunbarae2232b2010-05-27 02:25:27 +000081 Alignment = Stack[i].Alignment;
Chris Lattner574aa402009-02-17 01:09:29 +000082 Stack.erase(Stack.begin() + i, Stack.end());
83 return true;
84 }
85 }
Mike Stump1eb44332009-09-09 15:08:12 +000086
Chris Lattner574aa402009-02-17 01:09:29 +000087 return false;
88}
89
90
91/// FreePackedContext - Deallocate and null out PackContext.
92void Sema::FreePackedContext() {
93 delete static_cast<PragmaPackStack*>(PackContext);
94 PackContext = 0;
95}
96
Daniel Dunbar9f21f892010-05-27 01:53:40 +000097void Sema::AddAlignmentAttributesForRecord(RecordDecl *RD) {
98 // If there is no pack context, we don't need any attributes.
99 if (!PackContext)
100 return;
101
102 PragmaPackStack *Stack = static_cast<PragmaPackStack*>(PackContext);
103
104 // Otherwise, check to see if we need a max field alignment attribute.
105 if (unsigned Alignment = Stack->getAlignment())
106 RD->addAttr(::new (Context) MaxFieldAlignmentAttr(Alignment * 8));
Chris Lattner574aa402009-02-17 01:09:29 +0000107}
108
Daniel Dunbarea75a822010-05-27 00:04:40 +0000109void Sema::ActOnPragmaOptionsAlign(PragmaOptionsAlignKind Kind,
110 SourceLocation PragmaLoc,
111 SourceLocation KindLoc) {
112 if (PackContext == 0)
113 PackContext = new PragmaPackStack();
114
115 PragmaPackStack *Context = static_cast<PragmaPackStack*>(PackContext);
116
117 // Reset just pops the top of the stack.
118 if (Kind == Action::POAK_Reset) {
119 // Do the pop.
120 if (!Context->pop(0)) {
121 // If a name was specified then failure indicates the name
122 // wasn't found. Otherwise failure indicates the stack was
123 // empty.
124 Diag(PragmaLoc, diag::warn_pragma_options_align_reset_failed)
125 << "stack empty";
126 }
127 return;
128 }
129
130 // We don't support #pragma options align=power.
131 switch (Kind) {
132 case POAK_Natural:
133 Context->push(0);
134 Context->setAlignment(0);
135 break;
136
Daniel Dunbar613fd672010-05-27 00:35:16 +0000137 case POAK_Mac68k:
138 // Check if the target supports this.
139 if (!PP.getTargetInfo().hasAlignMac68kSupport()) {
140 Diag(PragmaLoc, diag::err_pragma_options_align_mac68k_target_unsupported);
141 return;
142 } else {
143 // Otherwise, just warn about it for now.
144 Diag(PragmaLoc, diag::warn_pragma_options_align_unsupported_option)
145 << KindLoc;
146 }
147 break;
148
Daniel Dunbarea75a822010-05-27 00:04:40 +0000149 default:
150 Diag(PragmaLoc, diag::warn_pragma_options_align_unsupported_option)
151 << KindLoc;
152 break;
153 }
154}
155
Mike Stump1eb44332009-09-09 15:08:12 +0000156void Sema::ActOnPragmaPack(PragmaPackKind Kind, IdentifierInfo *Name,
157 ExprTy *alignment, SourceLocation PragmaLoc,
Chris Lattner5a0c3512009-02-17 00:57:29 +0000158 SourceLocation LParenLoc, SourceLocation RParenLoc) {
159 Expr *Alignment = static_cast<Expr *>(alignment);
160
161 // If specified then alignment must be a "small" power of two.
162 unsigned AlignmentVal = 0;
163 if (Alignment) {
164 llvm::APSInt Val;
Mike Stump1eb44332009-09-09 15:08:12 +0000165
Daniel Dunbar79cd1162009-03-06 20:45:54 +0000166 // pack(0) is like pack(), which just works out since that is what
167 // we use 0 for in PackAttr.
Douglas Gregorac06a0e2010-05-18 23:01:22 +0000168 if (Alignment->isTypeDependent() ||
169 Alignment->isValueDependent() ||
170 !Alignment->isIntegerConstantExpr(Val, Context) ||
Daniel Dunbar79cd1162009-03-06 20:45:54 +0000171 !(Val == 0 || Val.isPowerOf2()) ||
Chris Lattner5a0c3512009-02-17 00:57:29 +0000172 Val.getZExtValue() > 16) {
173 Diag(PragmaLoc, diag::warn_pragma_pack_invalid_alignment);
174 Alignment->Destroy(Context);
175 return; // Ignore
176 }
177
178 AlignmentVal = (unsigned) Val.getZExtValue();
179 }
Mike Stump1eb44332009-09-09 15:08:12 +0000180
Chris Lattner574aa402009-02-17 01:09:29 +0000181 if (PackContext == 0)
182 PackContext = new PragmaPackStack();
Mike Stump1eb44332009-09-09 15:08:12 +0000183
Chris Lattner574aa402009-02-17 01:09:29 +0000184 PragmaPackStack *Context = static_cast<PragmaPackStack*>(PackContext);
Mike Stump1eb44332009-09-09 15:08:12 +0000185
Chris Lattner5a0c3512009-02-17 00:57:29 +0000186 switch (Kind) {
187 case Action::PPK_Default: // pack([n])
Chris Lattner574aa402009-02-17 01:09:29 +0000188 Context->setAlignment(AlignmentVal);
Chris Lattner5a0c3512009-02-17 00:57:29 +0000189 break;
190
191 case Action::PPK_Show: // pack(show)
192 // Show the current alignment, making sure to show the right value
193 // for the default.
Chris Lattner574aa402009-02-17 01:09:29 +0000194 AlignmentVal = Context->getAlignment();
Chris Lattner5a0c3512009-02-17 00:57:29 +0000195 // FIXME: This should come from the target.
196 if (AlignmentVal == 0)
197 AlignmentVal = 8;
198 Diag(PragmaLoc, diag::warn_pragma_pack_show) << AlignmentVal;
199 break;
200
201 case Action::PPK_Push: // pack(push [, id] [, [n])
Chris Lattner574aa402009-02-17 01:09:29 +0000202 Context->push(Name);
Chris Lattner5a0c3512009-02-17 00:57:29 +0000203 // Set the new alignment if specified.
204 if (Alignment)
Mike Stump1eb44332009-09-09 15:08:12 +0000205 Context->setAlignment(AlignmentVal);
Chris Lattner5a0c3512009-02-17 00:57:29 +0000206 break;
207
208 case Action::PPK_Pop: // pack(pop [, id] [, n])
209 // MSDN, C/C++ Preprocessor Reference > Pragma Directives > pack:
210 // "#pragma pack(pop, identifier, n) is undefined"
211 if (Alignment && Name)
Mike Stump1eb44332009-09-09 15:08:12 +0000212 Diag(PragmaLoc, diag::warn_pragma_pack_pop_identifer_and_alignment);
213
Chris Lattner5a0c3512009-02-17 00:57:29 +0000214 // Do the pop.
Chris Lattner574aa402009-02-17 01:09:29 +0000215 if (!Context->pop(Name)) {
Chris Lattner5a0c3512009-02-17 00:57:29 +0000216 // If a name was specified then failure indicates the name
217 // wasn't found. Otherwise failure indicates the stack was
218 // empty.
219 Diag(PragmaLoc, diag::warn_pragma_pack_pop_failed)
220 << (Name ? "no record matching name" : "stack empty");
221
222 // FIXME: Warn about popping named records as MSVC does.
223 } else {
224 // Pop succeeded, set the new alignment if specified.
225 if (Alignment)
Chris Lattner574aa402009-02-17 01:09:29 +0000226 Context->setAlignment(AlignmentVal);
Chris Lattner5a0c3512009-02-17 00:57:29 +0000227 }
228 break;
229
230 default:
231 assert(0 && "Invalid #pragma pack kind.");
232 }
233}
234
Ted Kremenek7a02a372009-08-03 23:24:57 +0000235void Sema::ActOnPragmaUnused(const Token *Identifiers, unsigned NumIdentifiers,
236 Scope *curScope,
Ted Kremenek4726d032009-03-23 22:28:25 +0000237 SourceLocation PragmaLoc,
238 SourceLocation LParenLoc,
239 SourceLocation RParenLoc) {
Ted Kremenek4726d032009-03-23 22:28:25 +0000240
Ted Kremenek7a02a372009-08-03 23:24:57 +0000241 for (unsigned i = 0; i < NumIdentifiers; ++i) {
242 const Token &Tok = Identifiers[i];
Mike Stump1eb44332009-09-09 15:08:12 +0000243 IdentifierInfo *Name = Tok.getIdentifierInfo();
John McCalla24dc2e2009-11-17 02:14:36 +0000244 LookupResult Lookup(*this, Name, Tok.getLocation(), LookupOrdinaryName);
245 LookupParsedName(Lookup, curScope, NULL, true);
Ted Kremenek4726d032009-03-23 22:28:25 +0000246
John McCall1bcee0a2009-12-02 08:25:40 +0000247 if (Lookup.empty()) {
Ted Kremenek7a02a372009-08-03 23:24:57 +0000248 Diag(PragmaLoc, diag::warn_pragma_unused_undeclared_var)
249 << Name << SourceRange(Tok.getLocation());
250 continue;
Ted Kremenek4726d032009-03-23 22:28:25 +0000251 }
Mike Stump1eb44332009-09-09 15:08:12 +0000252
John McCall1bcee0a2009-12-02 08:25:40 +0000253 VarDecl *VD = Lookup.getAsSingle<VarDecl>();
254 if (!VD || !VD->hasLocalStorage()) {
Ted Kremenek7a02a372009-08-03 23:24:57 +0000255 Diag(PragmaLoc, diag::warn_pragma_unused_expected_localvar)
256 << Name << SourceRange(Tok.getLocation());
257 continue;
258 }
Mike Stump1eb44332009-09-09 15:08:12 +0000259
John McCall1bcee0a2009-12-02 08:25:40 +0000260 VD->addAttr(::new (Context) UnusedAttr());
Ted Kremenek4726d032009-03-23 22:28:25 +0000261 }
262}