blob: 770bd218d1929ff76e713fd781df446c99f5e8e8 [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"
18using namespace clang;
19
Chris Lattner574aa402009-02-17 01:09:29 +000020//===----------------------------------------------------------------------===//
Daniel Dunbarea75a822010-05-27 00:04:40 +000021// Pragma 'pack' and 'options align'
Chris Lattner574aa402009-02-17 01:09:29 +000022//===----------------------------------------------------------------------===//
23
24namespace {
25 /// PragmaPackStack - Simple class to wrap the stack used by #pragma
26 /// pack.
27 class PragmaPackStack {
28 typedef std::vector< std::pair<unsigned, IdentifierInfo*> > stack_ty;
29
30 /// Alignment - The current user specified alignment.
31 unsigned Alignment;
32
33 /// Stack - Entries in the #pragma pack stack, consisting of saved
34 /// alignments and optional names.
35 stack_ty Stack;
Mike Stump1eb44332009-09-09 15:08:12 +000036
37 public:
Chris Lattner574aa402009-02-17 01:09:29 +000038 PragmaPackStack() : Alignment(0) {}
39
40 void setAlignment(unsigned A) { Alignment = A; }
41 unsigned getAlignment() { return Alignment; }
42
43 /// push - Push the current alignment onto the stack, optionally
44 /// using the given \arg Name for the record, if non-zero.
45 void push(IdentifierInfo *Name) {
46 Stack.push_back(std::make_pair(Alignment, Name));
47 }
48
49 /// pop - Pop a record from the stack and restore the current
50 /// alignment to the previous value. If \arg Name is non-zero then
51 /// the first such named record is popped, otherwise the top record
52 /// is popped. Returns true if the pop succeeded.
53 bool pop(IdentifierInfo *Name);
54 };
55} // end anonymous namespace.
56
57bool PragmaPackStack::pop(IdentifierInfo *Name) {
58 if (Stack.empty())
59 return false;
Mike Stump1eb44332009-09-09 15:08:12 +000060
Chris Lattner574aa402009-02-17 01:09:29 +000061 // If name is empty just pop top.
62 if (!Name) {
63 Alignment = Stack.back().first;
64 Stack.pop_back();
65 return true;
Mike Stump1eb44332009-09-09 15:08:12 +000066 }
67
Chris Lattner574aa402009-02-17 01:09:29 +000068 // Otherwise, find the named record.
69 for (unsigned i = Stack.size(); i != 0; ) {
70 --i;
71 if (Stack[i].second == Name) {
72 // Found it, pop up to and including this record.
73 Alignment = Stack[i].first;
74 Stack.erase(Stack.begin() + i, Stack.end());
75 return true;
76 }
77 }
Mike Stump1eb44332009-09-09 15:08:12 +000078
Chris Lattner574aa402009-02-17 01:09:29 +000079 return false;
80}
81
82
83/// FreePackedContext - Deallocate and null out PackContext.
84void Sema::FreePackedContext() {
85 delete static_cast<PragmaPackStack*>(PackContext);
86 PackContext = 0;
87}
88
89/// getPragmaPackAlignment() - Return the current alignment as specified by
90/// the current #pragma pack directive, or 0 if none is currently active.
91unsigned Sema::getPragmaPackAlignment() const {
92 if (PackContext)
93 return static_cast<PragmaPackStack*>(PackContext)->getAlignment();
94 return 0;
95}
96
Daniel Dunbarea75a822010-05-27 00:04:40 +000097void Sema::ActOnPragmaOptionsAlign(PragmaOptionsAlignKind Kind,
98 SourceLocation PragmaLoc,
99 SourceLocation KindLoc) {
100 if (PackContext == 0)
101 PackContext = new PragmaPackStack();
102
103 PragmaPackStack *Context = static_cast<PragmaPackStack*>(PackContext);
104
105 // Reset just pops the top of the stack.
106 if (Kind == Action::POAK_Reset) {
107 // Do the pop.
108 if (!Context->pop(0)) {
109 // If a name was specified then failure indicates the name
110 // wasn't found. Otherwise failure indicates the stack was
111 // empty.
112 Diag(PragmaLoc, diag::warn_pragma_options_align_reset_failed)
113 << "stack empty";
114 }
115 return;
116 }
117
118 // We don't support #pragma options align=power.
119 switch (Kind) {
120 case POAK_Natural:
121 Context->push(0);
122 Context->setAlignment(0);
123 break;
124
125 default:
126 Diag(PragmaLoc, diag::warn_pragma_options_align_unsupported_option)
127 << KindLoc;
128 break;
129 }
130}
131
Mike Stump1eb44332009-09-09 15:08:12 +0000132void Sema::ActOnPragmaPack(PragmaPackKind Kind, IdentifierInfo *Name,
133 ExprTy *alignment, SourceLocation PragmaLoc,
Chris Lattner5a0c3512009-02-17 00:57:29 +0000134 SourceLocation LParenLoc, SourceLocation RParenLoc) {
135 Expr *Alignment = static_cast<Expr *>(alignment);
136
137 // If specified then alignment must be a "small" power of two.
138 unsigned AlignmentVal = 0;
139 if (Alignment) {
140 llvm::APSInt Val;
Mike Stump1eb44332009-09-09 15:08:12 +0000141
Daniel Dunbar79cd1162009-03-06 20:45:54 +0000142 // pack(0) is like pack(), which just works out since that is what
143 // we use 0 for in PackAttr.
Douglas Gregorac06a0e2010-05-18 23:01:22 +0000144 if (Alignment->isTypeDependent() ||
145 Alignment->isValueDependent() ||
146 !Alignment->isIntegerConstantExpr(Val, Context) ||
Daniel Dunbar79cd1162009-03-06 20:45:54 +0000147 !(Val == 0 || Val.isPowerOf2()) ||
Chris Lattner5a0c3512009-02-17 00:57:29 +0000148 Val.getZExtValue() > 16) {
149 Diag(PragmaLoc, diag::warn_pragma_pack_invalid_alignment);
150 Alignment->Destroy(Context);
151 return; // Ignore
152 }
153
154 AlignmentVal = (unsigned) Val.getZExtValue();
155 }
Mike Stump1eb44332009-09-09 15:08:12 +0000156
Chris Lattner574aa402009-02-17 01:09:29 +0000157 if (PackContext == 0)
158 PackContext = new PragmaPackStack();
Mike Stump1eb44332009-09-09 15:08:12 +0000159
Chris Lattner574aa402009-02-17 01:09:29 +0000160 PragmaPackStack *Context = static_cast<PragmaPackStack*>(PackContext);
Mike Stump1eb44332009-09-09 15:08:12 +0000161
Chris Lattner5a0c3512009-02-17 00:57:29 +0000162 switch (Kind) {
163 case Action::PPK_Default: // pack([n])
Chris Lattner574aa402009-02-17 01:09:29 +0000164 Context->setAlignment(AlignmentVal);
Chris Lattner5a0c3512009-02-17 00:57:29 +0000165 break;
166
167 case Action::PPK_Show: // pack(show)
168 // Show the current alignment, making sure to show the right value
169 // for the default.
Chris Lattner574aa402009-02-17 01:09:29 +0000170 AlignmentVal = Context->getAlignment();
Chris Lattner5a0c3512009-02-17 00:57:29 +0000171 // FIXME: This should come from the target.
172 if (AlignmentVal == 0)
173 AlignmentVal = 8;
174 Diag(PragmaLoc, diag::warn_pragma_pack_show) << AlignmentVal;
175 break;
176
177 case Action::PPK_Push: // pack(push [, id] [, [n])
Chris Lattner574aa402009-02-17 01:09:29 +0000178 Context->push(Name);
Chris Lattner5a0c3512009-02-17 00:57:29 +0000179 // Set the new alignment if specified.
180 if (Alignment)
Mike Stump1eb44332009-09-09 15:08:12 +0000181 Context->setAlignment(AlignmentVal);
Chris Lattner5a0c3512009-02-17 00:57:29 +0000182 break;
183
184 case Action::PPK_Pop: // pack(pop [, id] [, n])
185 // MSDN, C/C++ Preprocessor Reference > Pragma Directives > pack:
186 // "#pragma pack(pop, identifier, n) is undefined"
187 if (Alignment && Name)
Mike Stump1eb44332009-09-09 15:08:12 +0000188 Diag(PragmaLoc, diag::warn_pragma_pack_pop_identifer_and_alignment);
189
Chris Lattner5a0c3512009-02-17 00:57:29 +0000190 // Do the pop.
Chris Lattner574aa402009-02-17 01:09:29 +0000191 if (!Context->pop(Name)) {
Chris Lattner5a0c3512009-02-17 00:57:29 +0000192 // If a name was specified then failure indicates the name
193 // wasn't found. Otherwise failure indicates the stack was
194 // empty.
195 Diag(PragmaLoc, diag::warn_pragma_pack_pop_failed)
196 << (Name ? "no record matching name" : "stack empty");
197
198 // FIXME: Warn about popping named records as MSVC does.
199 } else {
200 // Pop succeeded, set the new alignment if specified.
201 if (Alignment)
Chris Lattner574aa402009-02-17 01:09:29 +0000202 Context->setAlignment(AlignmentVal);
Chris Lattner5a0c3512009-02-17 00:57:29 +0000203 }
204 break;
205
206 default:
207 assert(0 && "Invalid #pragma pack kind.");
208 }
209}
210
Ted Kremenek7a02a372009-08-03 23:24:57 +0000211void Sema::ActOnPragmaUnused(const Token *Identifiers, unsigned NumIdentifiers,
212 Scope *curScope,
Ted Kremenek4726d032009-03-23 22:28:25 +0000213 SourceLocation PragmaLoc,
214 SourceLocation LParenLoc,
215 SourceLocation RParenLoc) {
Ted Kremenek4726d032009-03-23 22:28:25 +0000216
Ted Kremenek7a02a372009-08-03 23:24:57 +0000217 for (unsigned i = 0; i < NumIdentifiers; ++i) {
218 const Token &Tok = Identifiers[i];
Mike Stump1eb44332009-09-09 15:08:12 +0000219 IdentifierInfo *Name = Tok.getIdentifierInfo();
John McCalla24dc2e2009-11-17 02:14:36 +0000220 LookupResult Lookup(*this, Name, Tok.getLocation(), LookupOrdinaryName);
221 LookupParsedName(Lookup, curScope, NULL, true);
Ted Kremenek4726d032009-03-23 22:28:25 +0000222
John McCall1bcee0a2009-12-02 08:25:40 +0000223 if (Lookup.empty()) {
Ted Kremenek7a02a372009-08-03 23:24:57 +0000224 Diag(PragmaLoc, diag::warn_pragma_unused_undeclared_var)
225 << Name << SourceRange(Tok.getLocation());
226 continue;
Ted Kremenek4726d032009-03-23 22:28:25 +0000227 }
Mike Stump1eb44332009-09-09 15:08:12 +0000228
John McCall1bcee0a2009-12-02 08:25:40 +0000229 VarDecl *VD = Lookup.getAsSingle<VarDecl>();
230 if (!VD || !VD->hasLocalStorage()) {
Ted Kremenek7a02a372009-08-03 23:24:57 +0000231 Diag(PragmaLoc, diag::warn_pragma_unused_expected_localvar)
232 << Name << SourceRange(Tok.getLocation());
233 continue;
234 }
Mike Stump1eb44332009-09-09 15:08:12 +0000235
John McCall1bcee0a2009-12-02 08:25:40 +0000236 VD->addAttr(::new (Context) UnusedAttr());
Ted Kremenek4726d032009-03-23 22:28:25 +0000237 }
238}