blob: 430bd4d6be7cc676c0ef0b9ee7de782c0b1bb962 [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
91/// getPragmaPackAlignment() - Return the current alignment as specified by
92/// the current #pragma pack directive, or 0 if none is currently active.
93unsigned Sema::getPragmaPackAlignment() const {
94 if (PackContext)
95 return static_cast<PragmaPackStack*>(PackContext)->getAlignment();
96 return 0;
97}
98
Daniel Dunbarea75a822010-05-27 00:04:40 +000099void Sema::ActOnPragmaOptionsAlign(PragmaOptionsAlignKind Kind,
100 SourceLocation PragmaLoc,
101 SourceLocation KindLoc) {
102 if (PackContext == 0)
103 PackContext = new PragmaPackStack();
104
105 PragmaPackStack *Context = static_cast<PragmaPackStack*>(PackContext);
106
107 // Reset just pops the top of the stack.
108 if (Kind == Action::POAK_Reset) {
109 // Do the pop.
110 if (!Context->pop(0)) {
111 // If a name was specified then failure indicates the name
112 // wasn't found. Otherwise failure indicates the stack was
113 // empty.
114 Diag(PragmaLoc, diag::warn_pragma_options_align_reset_failed)
115 << "stack empty";
116 }
117 return;
118 }
119
120 // We don't support #pragma options align=power.
121 switch (Kind) {
122 case POAK_Natural:
123 Context->push(0);
124 Context->setAlignment(0);
125 break;
126
Daniel Dunbar613fd672010-05-27 00:35:16 +0000127 case POAK_Mac68k:
128 // Check if the target supports this.
129 if (!PP.getTargetInfo().hasAlignMac68kSupport()) {
130 Diag(PragmaLoc, diag::err_pragma_options_align_mac68k_target_unsupported);
131 return;
132 } else {
133 // Otherwise, just warn about it for now.
134 Diag(PragmaLoc, diag::warn_pragma_options_align_unsupported_option)
135 << KindLoc;
136 }
137 break;
138
Daniel Dunbarea75a822010-05-27 00:04:40 +0000139 default:
140 Diag(PragmaLoc, diag::warn_pragma_options_align_unsupported_option)
141 << KindLoc;
142 break;
143 }
144}
145
Mike Stump1eb44332009-09-09 15:08:12 +0000146void Sema::ActOnPragmaPack(PragmaPackKind Kind, IdentifierInfo *Name,
147 ExprTy *alignment, SourceLocation PragmaLoc,
Chris Lattner5a0c3512009-02-17 00:57:29 +0000148 SourceLocation LParenLoc, SourceLocation RParenLoc) {
149 Expr *Alignment = static_cast<Expr *>(alignment);
150
151 // If specified then alignment must be a "small" power of two.
152 unsigned AlignmentVal = 0;
153 if (Alignment) {
154 llvm::APSInt Val;
Mike Stump1eb44332009-09-09 15:08:12 +0000155
Daniel Dunbar79cd1162009-03-06 20:45:54 +0000156 // pack(0) is like pack(), which just works out since that is what
157 // we use 0 for in PackAttr.
Douglas Gregorac06a0e2010-05-18 23:01:22 +0000158 if (Alignment->isTypeDependent() ||
159 Alignment->isValueDependent() ||
160 !Alignment->isIntegerConstantExpr(Val, Context) ||
Daniel Dunbar79cd1162009-03-06 20:45:54 +0000161 !(Val == 0 || Val.isPowerOf2()) ||
Chris Lattner5a0c3512009-02-17 00:57:29 +0000162 Val.getZExtValue() > 16) {
163 Diag(PragmaLoc, diag::warn_pragma_pack_invalid_alignment);
164 Alignment->Destroy(Context);
165 return; // Ignore
166 }
167
168 AlignmentVal = (unsigned) Val.getZExtValue();
169 }
Mike Stump1eb44332009-09-09 15:08:12 +0000170
Chris Lattner574aa402009-02-17 01:09:29 +0000171 if (PackContext == 0)
172 PackContext = new PragmaPackStack();
Mike Stump1eb44332009-09-09 15:08:12 +0000173
Chris Lattner574aa402009-02-17 01:09:29 +0000174 PragmaPackStack *Context = static_cast<PragmaPackStack*>(PackContext);
Mike Stump1eb44332009-09-09 15:08:12 +0000175
Chris Lattner5a0c3512009-02-17 00:57:29 +0000176 switch (Kind) {
177 case Action::PPK_Default: // pack([n])
Chris Lattner574aa402009-02-17 01:09:29 +0000178 Context->setAlignment(AlignmentVal);
Chris Lattner5a0c3512009-02-17 00:57:29 +0000179 break;
180
181 case Action::PPK_Show: // pack(show)
182 // Show the current alignment, making sure to show the right value
183 // for the default.
Chris Lattner574aa402009-02-17 01:09:29 +0000184 AlignmentVal = Context->getAlignment();
Chris Lattner5a0c3512009-02-17 00:57:29 +0000185 // FIXME: This should come from the target.
186 if (AlignmentVal == 0)
187 AlignmentVal = 8;
188 Diag(PragmaLoc, diag::warn_pragma_pack_show) << AlignmentVal;
189 break;
190
191 case Action::PPK_Push: // pack(push [, id] [, [n])
Chris Lattner574aa402009-02-17 01:09:29 +0000192 Context->push(Name);
Chris Lattner5a0c3512009-02-17 00:57:29 +0000193 // Set the new alignment if specified.
194 if (Alignment)
Mike Stump1eb44332009-09-09 15:08:12 +0000195 Context->setAlignment(AlignmentVal);
Chris Lattner5a0c3512009-02-17 00:57:29 +0000196 break;
197
198 case Action::PPK_Pop: // pack(pop [, id] [, n])
199 // MSDN, C/C++ Preprocessor Reference > Pragma Directives > pack:
200 // "#pragma pack(pop, identifier, n) is undefined"
201 if (Alignment && Name)
Mike Stump1eb44332009-09-09 15:08:12 +0000202 Diag(PragmaLoc, diag::warn_pragma_pack_pop_identifer_and_alignment);
203
Chris Lattner5a0c3512009-02-17 00:57:29 +0000204 // Do the pop.
Chris Lattner574aa402009-02-17 01:09:29 +0000205 if (!Context->pop(Name)) {
Chris Lattner5a0c3512009-02-17 00:57:29 +0000206 // If a name was specified then failure indicates the name
207 // wasn't found. Otherwise failure indicates the stack was
208 // empty.
209 Diag(PragmaLoc, diag::warn_pragma_pack_pop_failed)
210 << (Name ? "no record matching name" : "stack empty");
211
212 // FIXME: Warn about popping named records as MSVC does.
213 } else {
214 // Pop succeeded, set the new alignment if specified.
215 if (Alignment)
Chris Lattner574aa402009-02-17 01:09:29 +0000216 Context->setAlignment(AlignmentVal);
Chris Lattner5a0c3512009-02-17 00:57:29 +0000217 }
218 break;
219
220 default:
221 assert(0 && "Invalid #pragma pack kind.");
222 }
223}
224
Ted Kremenek7a02a372009-08-03 23:24:57 +0000225void Sema::ActOnPragmaUnused(const Token *Identifiers, unsigned NumIdentifiers,
226 Scope *curScope,
Ted Kremenek4726d032009-03-23 22:28:25 +0000227 SourceLocation PragmaLoc,
228 SourceLocation LParenLoc,
229 SourceLocation RParenLoc) {
Ted Kremenek4726d032009-03-23 22:28:25 +0000230
Ted Kremenek7a02a372009-08-03 23:24:57 +0000231 for (unsigned i = 0; i < NumIdentifiers; ++i) {
232 const Token &Tok = Identifiers[i];
Mike Stump1eb44332009-09-09 15:08:12 +0000233 IdentifierInfo *Name = Tok.getIdentifierInfo();
John McCalla24dc2e2009-11-17 02:14:36 +0000234 LookupResult Lookup(*this, Name, Tok.getLocation(), LookupOrdinaryName);
235 LookupParsedName(Lookup, curScope, NULL, true);
Ted Kremenek4726d032009-03-23 22:28:25 +0000236
John McCall1bcee0a2009-12-02 08:25:40 +0000237 if (Lookup.empty()) {
Ted Kremenek7a02a372009-08-03 23:24:57 +0000238 Diag(PragmaLoc, diag::warn_pragma_unused_undeclared_var)
239 << Name << SourceRange(Tok.getLocation());
240 continue;
Ted Kremenek4726d032009-03-23 22:28:25 +0000241 }
Mike Stump1eb44332009-09-09 15:08:12 +0000242
John McCall1bcee0a2009-12-02 08:25:40 +0000243 VarDecl *VD = Lookup.getAsSingle<VarDecl>();
244 if (!VD || !VD->hasLocalStorage()) {
Ted Kremenek7a02a372009-08-03 23:24:57 +0000245 Diag(PragmaLoc, diag::warn_pragma_unused_expected_localvar)
246 << Name << SourceRange(Tok.getLocation());
247 continue;
248 }
Mike Stump1eb44332009-09-09 15:08:12 +0000249
John McCall1bcee0a2009-12-02 08:25:40 +0000250 VD->addAttr(::new (Context) UnusedAttr());
Ted Kremenek4726d032009-03-23 22:28:25 +0000251 }
252}