blob: dc7815fa6435fe8e558cbad2e965afae199c98c5 [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//===----------------------------------------------------------------------===//
21// Pragma Packed
22//===----------------------------------------------------------------------===//
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
Mike Stump1eb44332009-09-09 15:08:12 +000097void Sema::ActOnPragmaPack(PragmaPackKind Kind, IdentifierInfo *Name,
98 ExprTy *alignment, SourceLocation PragmaLoc,
Chris Lattner5a0c3512009-02-17 00:57:29 +000099 SourceLocation LParenLoc, SourceLocation RParenLoc) {
100 Expr *Alignment = static_cast<Expr *>(alignment);
101
102 // If specified then alignment must be a "small" power of two.
103 unsigned AlignmentVal = 0;
104 if (Alignment) {
105 llvm::APSInt Val;
Mike Stump1eb44332009-09-09 15:08:12 +0000106
Daniel Dunbar79cd1162009-03-06 20:45:54 +0000107 // pack(0) is like pack(), which just works out since that is what
108 // we use 0 for in PackAttr.
Douglas Gregorac06a0e2010-05-18 23:01:22 +0000109 if (Alignment->isTypeDependent() ||
110 Alignment->isValueDependent() ||
111 !Alignment->isIntegerConstantExpr(Val, Context) ||
Daniel Dunbar79cd1162009-03-06 20:45:54 +0000112 !(Val == 0 || Val.isPowerOf2()) ||
Chris Lattner5a0c3512009-02-17 00:57:29 +0000113 Val.getZExtValue() > 16) {
114 Diag(PragmaLoc, diag::warn_pragma_pack_invalid_alignment);
115 Alignment->Destroy(Context);
116 return; // Ignore
117 }
118
119 AlignmentVal = (unsigned) Val.getZExtValue();
120 }
Mike Stump1eb44332009-09-09 15:08:12 +0000121
Chris Lattner574aa402009-02-17 01:09:29 +0000122 if (PackContext == 0)
123 PackContext = new PragmaPackStack();
Mike Stump1eb44332009-09-09 15:08:12 +0000124
Chris Lattner574aa402009-02-17 01:09:29 +0000125 PragmaPackStack *Context = static_cast<PragmaPackStack*>(PackContext);
Mike Stump1eb44332009-09-09 15:08:12 +0000126
Chris Lattner5a0c3512009-02-17 00:57:29 +0000127 switch (Kind) {
128 case Action::PPK_Default: // pack([n])
Chris Lattner574aa402009-02-17 01:09:29 +0000129 Context->setAlignment(AlignmentVal);
Chris Lattner5a0c3512009-02-17 00:57:29 +0000130 break;
131
132 case Action::PPK_Show: // pack(show)
133 // Show the current alignment, making sure to show the right value
134 // for the default.
Chris Lattner574aa402009-02-17 01:09:29 +0000135 AlignmentVal = Context->getAlignment();
Chris Lattner5a0c3512009-02-17 00:57:29 +0000136 // FIXME: This should come from the target.
137 if (AlignmentVal == 0)
138 AlignmentVal = 8;
139 Diag(PragmaLoc, diag::warn_pragma_pack_show) << AlignmentVal;
140 break;
141
142 case Action::PPK_Push: // pack(push [, id] [, [n])
Chris Lattner574aa402009-02-17 01:09:29 +0000143 Context->push(Name);
Chris Lattner5a0c3512009-02-17 00:57:29 +0000144 // Set the new alignment if specified.
145 if (Alignment)
Mike Stump1eb44332009-09-09 15:08:12 +0000146 Context->setAlignment(AlignmentVal);
Chris Lattner5a0c3512009-02-17 00:57:29 +0000147 break;
148
149 case Action::PPK_Pop: // pack(pop [, id] [, n])
150 // MSDN, C/C++ Preprocessor Reference > Pragma Directives > pack:
151 // "#pragma pack(pop, identifier, n) is undefined"
152 if (Alignment && Name)
Mike Stump1eb44332009-09-09 15:08:12 +0000153 Diag(PragmaLoc, diag::warn_pragma_pack_pop_identifer_and_alignment);
154
Chris Lattner5a0c3512009-02-17 00:57:29 +0000155 // Do the pop.
Chris Lattner574aa402009-02-17 01:09:29 +0000156 if (!Context->pop(Name)) {
Chris Lattner5a0c3512009-02-17 00:57:29 +0000157 // If a name was specified then failure indicates the name
158 // wasn't found. Otherwise failure indicates the stack was
159 // empty.
160 Diag(PragmaLoc, diag::warn_pragma_pack_pop_failed)
161 << (Name ? "no record matching name" : "stack empty");
162
163 // FIXME: Warn about popping named records as MSVC does.
164 } else {
165 // Pop succeeded, set the new alignment if specified.
166 if (Alignment)
Chris Lattner574aa402009-02-17 01:09:29 +0000167 Context->setAlignment(AlignmentVal);
Chris Lattner5a0c3512009-02-17 00:57:29 +0000168 }
169 break;
170
171 default:
172 assert(0 && "Invalid #pragma pack kind.");
173 }
174}
175
Ted Kremenek7a02a372009-08-03 23:24:57 +0000176void Sema::ActOnPragmaUnused(const Token *Identifiers, unsigned NumIdentifiers,
177 Scope *curScope,
Ted Kremenek4726d032009-03-23 22:28:25 +0000178 SourceLocation PragmaLoc,
179 SourceLocation LParenLoc,
180 SourceLocation RParenLoc) {
Ted Kremenek4726d032009-03-23 22:28:25 +0000181
Ted Kremenek7a02a372009-08-03 23:24:57 +0000182 for (unsigned i = 0; i < NumIdentifiers; ++i) {
183 const Token &Tok = Identifiers[i];
Mike Stump1eb44332009-09-09 15:08:12 +0000184 IdentifierInfo *Name = Tok.getIdentifierInfo();
John McCalla24dc2e2009-11-17 02:14:36 +0000185 LookupResult Lookup(*this, Name, Tok.getLocation(), LookupOrdinaryName);
186 LookupParsedName(Lookup, curScope, NULL, true);
Ted Kremenek4726d032009-03-23 22:28:25 +0000187
John McCall1bcee0a2009-12-02 08:25:40 +0000188 if (Lookup.empty()) {
Ted Kremenek7a02a372009-08-03 23:24:57 +0000189 Diag(PragmaLoc, diag::warn_pragma_unused_undeclared_var)
190 << Name << SourceRange(Tok.getLocation());
191 continue;
Ted Kremenek4726d032009-03-23 22:28:25 +0000192 }
Mike Stump1eb44332009-09-09 15:08:12 +0000193
John McCall1bcee0a2009-12-02 08:25:40 +0000194 VarDecl *VD = Lookup.getAsSingle<VarDecl>();
195 if (!VD || !VD->hasLocalStorage()) {
Ted Kremenek7a02a372009-08-03 23:24:57 +0000196 Diag(PragmaLoc, diag::warn_pragma_unused_expected_localvar)
197 << Name << SourceRange(Tok.getLocation());
198 continue;
199 }
Mike Stump1eb44332009-09-09 15:08:12 +0000200
John McCall1bcee0a2009-12-02 08:25:40 +0000201 VD->addAttr(::new (Context) UnusedAttr());
Ted Kremenek4726d032009-03-23 22:28:25 +0000202 }
203}