blob: ee6aef06299ef22d981a18af2f0da0904452d6bf [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 {
27 /// PragmaPackStack - Simple class to wrap the stack used by #pragma
28 /// pack.
29 class PragmaPackStack {
30 typedef std::vector< std::pair<unsigned, IdentifierInfo*> > stack_ty;
31
32 /// Alignment - The current user specified alignment.
33 unsigned Alignment;
34
35 /// Stack - Entries in the #pragma pack stack, consisting of saved
36 /// alignments and optional names.
37 stack_ty Stack;
Mike Stump1eb44332009-09-09 15:08:12 +000038
39 public:
Chris Lattner574aa402009-02-17 01:09:29 +000040 PragmaPackStack() : Alignment(0) {}
41
42 void setAlignment(unsigned A) { Alignment = A; }
43 unsigned getAlignment() { return Alignment; }
44
45 /// push - Push the current alignment onto the stack, optionally
46 /// using the given \arg Name for the record, if non-zero.
47 void push(IdentifierInfo *Name) {
48 Stack.push_back(std::make_pair(Alignment, Name));
49 }
50
51 /// pop - Pop a record from the stack and restore the current
52 /// alignment to the previous value. If \arg Name is non-zero then
53 /// the first such named record is popped, otherwise the top record
54 /// is popped. Returns true if the pop succeeded.
55 bool pop(IdentifierInfo *Name);
56 };
57} // end anonymous namespace.
58
59bool PragmaPackStack::pop(IdentifierInfo *Name) {
60 if (Stack.empty())
61 return false;
Mike Stump1eb44332009-09-09 15:08:12 +000062
Chris Lattner574aa402009-02-17 01:09:29 +000063 // If name is empty just pop top.
64 if (!Name) {
65 Alignment = Stack.back().first;
66 Stack.pop_back();
67 return true;
Mike Stump1eb44332009-09-09 15:08:12 +000068 }
69
Chris Lattner574aa402009-02-17 01:09:29 +000070 // Otherwise, find the named record.
71 for (unsigned i = Stack.size(); i != 0; ) {
72 --i;
73 if (Stack[i].second == Name) {
74 // Found it, pop up to and including this record.
75 Alignment = Stack[i].first;
76 Stack.erase(Stack.begin() + i, Stack.end());
77 return true;
78 }
79 }
Mike Stump1eb44332009-09-09 15:08:12 +000080
Chris Lattner574aa402009-02-17 01:09:29 +000081 return false;
82}
83
84
85/// FreePackedContext - Deallocate and null out PackContext.
86void Sema::FreePackedContext() {
87 delete static_cast<PragmaPackStack*>(PackContext);
88 PackContext = 0;
89}
90
Daniel Dunbar9f21f892010-05-27 01:53:40 +000091void Sema::AddAlignmentAttributesForRecord(RecordDecl *RD) {
92 // If there is no pack context, we don't need any attributes.
93 if (!PackContext)
94 return;
95
96 PragmaPackStack *Stack = static_cast<PragmaPackStack*>(PackContext);
97
98 // Otherwise, check to see if we need a max field alignment attribute.
99 if (unsigned Alignment = Stack->getAlignment())
100 RD->addAttr(::new (Context) MaxFieldAlignmentAttr(Alignment * 8));
Chris Lattner574aa402009-02-17 01:09:29 +0000101}
102
Daniel Dunbarea75a822010-05-27 00:04:40 +0000103void Sema::ActOnPragmaOptionsAlign(PragmaOptionsAlignKind Kind,
104 SourceLocation PragmaLoc,
105 SourceLocation KindLoc) {
106 if (PackContext == 0)
107 PackContext = new PragmaPackStack();
108
109 PragmaPackStack *Context = static_cast<PragmaPackStack*>(PackContext);
110
111 // Reset just pops the top of the stack.
112 if (Kind == Action::POAK_Reset) {
113 // Do the pop.
114 if (!Context->pop(0)) {
115 // If a name was specified then failure indicates the name
116 // wasn't found. Otherwise failure indicates the stack was
117 // empty.
118 Diag(PragmaLoc, diag::warn_pragma_options_align_reset_failed)
119 << "stack empty";
120 }
121 return;
122 }
123
124 // We don't support #pragma options align=power.
125 switch (Kind) {
126 case POAK_Natural:
127 Context->push(0);
128 Context->setAlignment(0);
129 break;
130
Daniel Dunbar613fd672010-05-27 00:35:16 +0000131 case POAK_Mac68k:
132 // Check if the target supports this.
133 if (!PP.getTargetInfo().hasAlignMac68kSupport()) {
134 Diag(PragmaLoc, diag::err_pragma_options_align_mac68k_target_unsupported);
135 return;
136 } else {
137 // Otherwise, just warn about it for now.
138 Diag(PragmaLoc, diag::warn_pragma_options_align_unsupported_option)
139 << KindLoc;
140 }
141 break;
142
Daniel Dunbarea75a822010-05-27 00:04:40 +0000143 default:
144 Diag(PragmaLoc, diag::warn_pragma_options_align_unsupported_option)
145 << KindLoc;
146 break;
147 }
148}
149
Mike Stump1eb44332009-09-09 15:08:12 +0000150void Sema::ActOnPragmaPack(PragmaPackKind Kind, IdentifierInfo *Name,
151 ExprTy *alignment, SourceLocation PragmaLoc,
Chris Lattner5a0c3512009-02-17 00:57:29 +0000152 SourceLocation LParenLoc, SourceLocation RParenLoc) {
153 Expr *Alignment = static_cast<Expr *>(alignment);
154
155 // If specified then alignment must be a "small" power of two.
156 unsigned AlignmentVal = 0;
157 if (Alignment) {
158 llvm::APSInt Val;
Mike Stump1eb44332009-09-09 15:08:12 +0000159
Daniel Dunbar79cd1162009-03-06 20:45:54 +0000160 // pack(0) is like pack(), which just works out since that is what
161 // we use 0 for in PackAttr.
Douglas Gregorac06a0e2010-05-18 23:01:22 +0000162 if (Alignment->isTypeDependent() ||
163 Alignment->isValueDependent() ||
164 !Alignment->isIntegerConstantExpr(Val, Context) ||
Daniel Dunbar79cd1162009-03-06 20:45:54 +0000165 !(Val == 0 || Val.isPowerOf2()) ||
Chris Lattner5a0c3512009-02-17 00:57:29 +0000166 Val.getZExtValue() > 16) {
167 Diag(PragmaLoc, diag::warn_pragma_pack_invalid_alignment);
168 Alignment->Destroy(Context);
169 return; // Ignore
170 }
171
172 AlignmentVal = (unsigned) Val.getZExtValue();
173 }
Mike Stump1eb44332009-09-09 15:08:12 +0000174
Chris Lattner574aa402009-02-17 01:09:29 +0000175 if (PackContext == 0)
176 PackContext = new PragmaPackStack();
Mike Stump1eb44332009-09-09 15:08:12 +0000177
Chris Lattner574aa402009-02-17 01:09:29 +0000178 PragmaPackStack *Context = static_cast<PragmaPackStack*>(PackContext);
Mike Stump1eb44332009-09-09 15:08:12 +0000179
Chris Lattner5a0c3512009-02-17 00:57:29 +0000180 switch (Kind) {
181 case Action::PPK_Default: // pack([n])
Chris Lattner574aa402009-02-17 01:09:29 +0000182 Context->setAlignment(AlignmentVal);
Chris Lattner5a0c3512009-02-17 00:57:29 +0000183 break;
184
185 case Action::PPK_Show: // pack(show)
186 // Show the current alignment, making sure to show the right value
187 // for the default.
Chris Lattner574aa402009-02-17 01:09:29 +0000188 AlignmentVal = Context->getAlignment();
Chris Lattner5a0c3512009-02-17 00:57:29 +0000189 // FIXME: This should come from the target.
190 if (AlignmentVal == 0)
191 AlignmentVal = 8;
192 Diag(PragmaLoc, diag::warn_pragma_pack_show) << AlignmentVal;
193 break;
194
195 case Action::PPK_Push: // pack(push [, id] [, [n])
Chris Lattner574aa402009-02-17 01:09:29 +0000196 Context->push(Name);
Chris Lattner5a0c3512009-02-17 00:57:29 +0000197 // Set the new alignment if specified.
198 if (Alignment)
Mike Stump1eb44332009-09-09 15:08:12 +0000199 Context->setAlignment(AlignmentVal);
Chris Lattner5a0c3512009-02-17 00:57:29 +0000200 break;
201
202 case Action::PPK_Pop: // pack(pop [, id] [, n])
203 // MSDN, C/C++ Preprocessor Reference > Pragma Directives > pack:
204 // "#pragma pack(pop, identifier, n) is undefined"
205 if (Alignment && Name)
Mike Stump1eb44332009-09-09 15:08:12 +0000206 Diag(PragmaLoc, diag::warn_pragma_pack_pop_identifer_and_alignment);
207
Chris Lattner5a0c3512009-02-17 00:57:29 +0000208 // Do the pop.
Chris Lattner574aa402009-02-17 01:09:29 +0000209 if (!Context->pop(Name)) {
Chris Lattner5a0c3512009-02-17 00:57:29 +0000210 // If a name was specified then failure indicates the name
211 // wasn't found. Otherwise failure indicates the stack was
212 // empty.
213 Diag(PragmaLoc, diag::warn_pragma_pack_pop_failed)
214 << (Name ? "no record matching name" : "stack empty");
215
216 // FIXME: Warn about popping named records as MSVC does.
217 } else {
218 // Pop succeeded, set the new alignment if specified.
219 if (Alignment)
Chris Lattner574aa402009-02-17 01:09:29 +0000220 Context->setAlignment(AlignmentVal);
Chris Lattner5a0c3512009-02-17 00:57:29 +0000221 }
222 break;
223
224 default:
225 assert(0 && "Invalid #pragma pack kind.");
226 }
227}
228
Ted Kremenek7a02a372009-08-03 23:24:57 +0000229void Sema::ActOnPragmaUnused(const Token *Identifiers, unsigned NumIdentifiers,
230 Scope *curScope,
Ted Kremenek4726d032009-03-23 22:28:25 +0000231 SourceLocation PragmaLoc,
232 SourceLocation LParenLoc,
233 SourceLocation RParenLoc) {
Ted Kremenek4726d032009-03-23 22:28:25 +0000234
Ted Kremenek7a02a372009-08-03 23:24:57 +0000235 for (unsigned i = 0; i < NumIdentifiers; ++i) {
236 const Token &Tok = Identifiers[i];
Mike Stump1eb44332009-09-09 15:08:12 +0000237 IdentifierInfo *Name = Tok.getIdentifierInfo();
John McCalla24dc2e2009-11-17 02:14:36 +0000238 LookupResult Lookup(*this, Name, Tok.getLocation(), LookupOrdinaryName);
239 LookupParsedName(Lookup, curScope, NULL, true);
Ted Kremenek4726d032009-03-23 22:28:25 +0000240
John McCall1bcee0a2009-12-02 08:25:40 +0000241 if (Lookup.empty()) {
Ted Kremenek7a02a372009-08-03 23:24:57 +0000242 Diag(PragmaLoc, diag::warn_pragma_unused_undeclared_var)
243 << Name << SourceRange(Tok.getLocation());
244 continue;
Ted Kremenek4726d032009-03-23 22:28:25 +0000245 }
Mike Stump1eb44332009-09-09 15:08:12 +0000246
John McCall1bcee0a2009-12-02 08:25:40 +0000247 VarDecl *VD = Lookup.getAsSingle<VarDecl>();
248 if (!VD || !VD->hasLocalStorage()) {
Ted Kremenek7a02a372009-08-03 23:24:57 +0000249 Diag(PragmaLoc, diag::warn_pragma_unused_expected_localvar)
250 << Name << SourceRange(Tok.getLocation());
251 continue;
252 }
Mike Stump1eb44332009-09-09 15:08:12 +0000253
John McCall1bcee0a2009-12-02 08:25:40 +0000254 VD->addAttr(::new (Context) UnusedAttr());
Ted Kremenek4726d032009-03-23 22:28:25 +0000255 }
256}