SemaAttr.cpp revision ddc6ff6b9aff656504c1e84ee7dc9f617a20f866
1//===--- 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// 10// This file implements semantic analysis for non-trivial attributes and 11// pragmas. 12// 13//===----------------------------------------------------------------------===// 14 15#include "Sema.h" 16#include "Lookup.h" 17#include "clang/AST/Expr.h" 18#include "clang/Basic/TargetInfo.h" 19#include "clang/Lex/Preprocessor.h" 20using namespace clang; 21 22//===----------------------------------------------------------------------===// 23// Pragma 'pack' and 'options align' 24//===----------------------------------------------------------------------===// 25 26namespace { 27 struct PackStackEntry { 28 // We just use a sentinel to represent when the stack is set to mac68k 29 // alignment. 30 static const unsigned kMac68kAlignmentSentinel = ~0U; 31 32 unsigned Alignment; 33 IdentifierInfo *Name; 34 }; 35 36 /// PragmaPackStack - Simple class to wrap the stack used by #pragma 37 /// pack. 38 class PragmaPackStack { 39 typedef std::vector<PackStackEntry> stack_ty; 40 41 /// Alignment - The current user specified alignment. 42 unsigned Alignment; 43 44 /// Stack - Entries in the #pragma pack stack, consisting of saved 45 /// alignments and optional names. 46 stack_ty Stack; 47 48 public: 49 PragmaPackStack() : Alignment(0) {} 50 51 void setAlignment(unsigned A) { Alignment = A; } 52 unsigned getAlignment() { return Alignment; } 53 54 /// push - Push the current alignment onto the stack, optionally 55 /// using the given \arg Name for the record, if non-zero. 56 void push(IdentifierInfo *Name) { 57 PackStackEntry PSE = { Alignment, Name }; 58 Stack.push_back(PSE); 59 } 60 61 /// pop - Pop a record from the stack and restore the current 62 /// alignment to the previous value. If \arg Name is non-zero then 63 /// the first such named record is popped, otherwise the top record 64 /// is popped. Returns true if the pop succeeded. 65 bool pop(IdentifierInfo *Name, bool IsReset); 66 }; 67} // end anonymous namespace. 68 69bool PragmaPackStack::pop(IdentifierInfo *Name, bool IsReset) { 70 // If name is empty just pop top. 71 if (!Name) { 72 // An empty stack is a special case... 73 if (Stack.empty()) { 74 // If this isn't a reset, it is always an error. 75 if (!IsReset) 76 return false; 77 78 // Otherwise, it is an error only if some alignment has been set. 79 if (!Alignment) 80 return false; 81 82 // Otherwise, reset to the default alignment. 83 Alignment = 0; 84 } else { 85 Alignment = Stack.back().Alignment; 86 Stack.pop_back(); 87 } 88 89 return true; 90 } 91 92 // Otherwise, find the named record. 93 for (unsigned i = Stack.size(); i != 0; ) { 94 --i; 95 if (Stack[i].Name == Name) { 96 // Found it, pop up to and including this record. 97 Alignment = Stack[i].Alignment; 98 Stack.erase(Stack.begin() + i, Stack.end()); 99 return true; 100 } 101 } 102 103 return false; 104} 105 106 107/// FreePackedContext - Deallocate and null out PackContext. 108void Sema::FreePackedContext() { 109 delete static_cast<PragmaPackStack*>(PackContext); 110 PackContext = 0; 111} 112 113void Sema::AddAlignmentAttributesForRecord(RecordDecl *RD) { 114 // If there is no pack context, we don't need any attributes. 115 if (!PackContext) 116 return; 117 118 PragmaPackStack *Stack = static_cast<PragmaPackStack*>(PackContext); 119 120 // Otherwise, check to see if we need a max field alignment attribute. 121 if (unsigned Alignment = Stack->getAlignment()) { 122 if (Alignment == PackStackEntry::kMac68kAlignmentSentinel) 123 RD->addAttr(::new (Context) AlignMac68kAttr()); 124 else 125 RD->addAttr(::new (Context) MaxFieldAlignmentAttr(Alignment * 8)); 126 } 127} 128 129void Sema::ActOnPragmaOptionsAlign(PragmaOptionsAlignKind Kind, 130 SourceLocation PragmaLoc, 131 SourceLocation KindLoc) { 132 if (PackContext == 0) 133 PackContext = new PragmaPackStack(); 134 135 PragmaPackStack *Context = static_cast<PragmaPackStack*>(PackContext); 136 137 // Reset just pops the top of the stack, or resets the current alignment to 138 // default. 139 if (Kind == Action::POAK_Reset) { 140 if (!Context->pop(0, /*IsReset=*/true)) { 141 Diag(PragmaLoc, diag::warn_pragma_options_align_reset_failed) 142 << "stack empty"; 143 } 144 return; 145 } 146 147 switch (Kind) { 148 // For all targets we support native and natural are the same. 149 // 150 // FIXME: This is not true on Darwin/PPC. 151 case POAK_Native: 152 case POAK_Power: 153 case POAK_Natural: 154 Context->push(0); 155 Context->setAlignment(0); 156 break; 157 158 // Note that '#pragma options align=packed' is not equivalent to attribute 159 // packed, it has a different precedence relative to attribute aligned. 160 case POAK_Packed: 161 Context->push(0); 162 Context->setAlignment(1); 163 break; 164 165 case POAK_Mac68k: 166 // Check if the target supports this. 167 if (!PP.getTargetInfo().hasAlignMac68kSupport()) { 168 Diag(PragmaLoc, diag::err_pragma_options_align_mac68k_target_unsupported); 169 return; 170 } 171 Context->push(0); 172 Context->setAlignment(PackStackEntry::kMac68kAlignmentSentinel); 173 break; 174 175 default: 176 Diag(PragmaLoc, diag::warn_pragma_options_align_unsupported_option) 177 << KindLoc; 178 break; 179 } 180} 181 182void Sema::ActOnPragmaPack(PragmaPackKind Kind, IdentifierInfo *Name, 183 ExprTy *alignment, SourceLocation PragmaLoc, 184 SourceLocation LParenLoc, SourceLocation RParenLoc) { 185 Expr *Alignment = static_cast<Expr *>(alignment); 186 187 // If specified then alignment must be a "small" power of two. 188 unsigned AlignmentVal = 0; 189 if (Alignment) { 190 llvm::APSInt Val; 191 192 // pack(0) is like pack(), which just works out since that is what 193 // we use 0 for in PackAttr. 194 if (Alignment->isTypeDependent() || 195 Alignment->isValueDependent() || 196 !Alignment->isIntegerConstantExpr(Val, Context) || 197 !(Val == 0 || Val.isPowerOf2()) || 198 Val.getZExtValue() > 16) { 199 Diag(PragmaLoc, diag::warn_pragma_pack_invalid_alignment); 200 Alignment->Destroy(Context); 201 return; // Ignore 202 } 203 204 AlignmentVal = (unsigned) Val.getZExtValue(); 205 } 206 207 if (PackContext == 0) 208 PackContext = new PragmaPackStack(); 209 210 PragmaPackStack *Context = static_cast<PragmaPackStack*>(PackContext); 211 212 switch (Kind) { 213 case Action::PPK_Default: // pack([n]) 214 Context->setAlignment(AlignmentVal); 215 break; 216 217 case Action::PPK_Show: // pack(show) 218 // Show the current alignment, making sure to show the right value 219 // for the default. 220 AlignmentVal = Context->getAlignment(); 221 // FIXME: This should come from the target. 222 if (AlignmentVal == 0) 223 AlignmentVal = 8; 224 if (AlignmentVal == PackStackEntry::kMac68kAlignmentSentinel) 225 Diag(PragmaLoc, diag::warn_pragma_pack_show) << "mac68k"; 226 else 227 Diag(PragmaLoc, diag::warn_pragma_pack_show) << AlignmentVal; 228 break; 229 230 case Action::PPK_Push: // pack(push [, id] [, [n]) 231 Context->push(Name); 232 // Set the new alignment if specified. 233 if (Alignment) 234 Context->setAlignment(AlignmentVal); 235 break; 236 237 case Action::PPK_Pop: // pack(pop [, id] [, n]) 238 // MSDN, C/C++ Preprocessor Reference > Pragma Directives > pack: 239 // "#pragma pack(pop, identifier, n) is undefined" 240 if (Alignment && Name) 241 Diag(PragmaLoc, diag::warn_pragma_pack_pop_identifer_and_alignment); 242 243 // Do the pop. 244 if (!Context->pop(Name, /*IsReset=*/false)) { 245 // If a name was specified then failure indicates the name 246 // wasn't found. Otherwise failure indicates the stack was 247 // empty. 248 Diag(PragmaLoc, diag::warn_pragma_pack_pop_failed) 249 << (Name ? "no record matching name" : "stack empty"); 250 251 // FIXME: Warn about popping named records as MSVC does. 252 } else { 253 // Pop succeeded, set the new alignment if specified. 254 if (Alignment) 255 Context->setAlignment(AlignmentVal); 256 } 257 break; 258 259 default: 260 assert(0 && "Invalid #pragma pack kind."); 261 } 262} 263 264void Sema::ActOnPragmaUnused(const Token *Identifiers, unsigned NumIdentifiers, 265 Scope *curScope, 266 SourceLocation PragmaLoc, 267 SourceLocation LParenLoc, 268 SourceLocation RParenLoc) { 269 270 for (unsigned i = 0; i < NumIdentifiers; ++i) { 271 const Token &Tok = Identifiers[i]; 272 IdentifierInfo *Name = Tok.getIdentifierInfo(); 273 LookupResult Lookup(*this, Name, Tok.getLocation(), LookupOrdinaryName); 274 LookupParsedName(Lookup, curScope, NULL, true); 275 276 if (Lookup.empty()) { 277 Diag(PragmaLoc, diag::warn_pragma_unused_undeclared_var) 278 << Name << SourceRange(Tok.getLocation()); 279 continue; 280 } 281 282 VarDecl *VD = Lookup.getAsSingle<VarDecl>(); 283 if (!VD || !VD->hasLocalStorage()) { 284 Diag(PragmaLoc, diag::warn_pragma_unused_expected_localvar) 285 << Name << SourceRange(Tok.getLocation()); 286 continue; 287 } 288 289 VD->addAttr(::new (Context) UnusedAttr()); 290 } 291} 292