SemaAttr.cpp revision e737f5041a36d0befb39ffeed8d50ba15916d3da
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 "clang/Sema/Sema.h" 16#include "clang/Sema/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 return; // Ignore 201 } 202 203 AlignmentVal = (unsigned) Val.getZExtValue(); 204 } 205 206 if (PackContext == 0) 207 PackContext = new PragmaPackStack(); 208 209 PragmaPackStack *Context = static_cast<PragmaPackStack*>(PackContext); 210 211 switch (Kind) { 212 case Action::PPK_Default: // pack([n]) 213 Context->setAlignment(AlignmentVal); 214 break; 215 216 case Action::PPK_Show: // pack(show) 217 // Show the current alignment, making sure to show the right value 218 // for the default. 219 AlignmentVal = Context->getAlignment(); 220 // FIXME: This should come from the target. 221 if (AlignmentVal == 0) 222 AlignmentVal = 8; 223 if (AlignmentVal == PackStackEntry::kMac68kAlignmentSentinel) 224 Diag(PragmaLoc, diag::warn_pragma_pack_show) << "mac68k"; 225 else 226 Diag(PragmaLoc, diag::warn_pragma_pack_show) << AlignmentVal; 227 break; 228 229 case Action::PPK_Push: // pack(push [, id] [, [n]) 230 Context->push(Name); 231 // Set the new alignment if specified. 232 if (Alignment) 233 Context->setAlignment(AlignmentVal); 234 break; 235 236 case Action::PPK_Pop: // pack(pop [, id] [, n]) 237 // MSDN, C/C++ Preprocessor Reference > Pragma Directives > pack: 238 // "#pragma pack(pop, identifier, n) is undefined" 239 if (Alignment && Name) 240 Diag(PragmaLoc, diag::warn_pragma_pack_pop_identifer_and_alignment); 241 242 // Do the pop. 243 if (!Context->pop(Name, /*IsReset=*/false)) { 244 // If a name was specified then failure indicates the name 245 // wasn't found. Otherwise failure indicates the stack was 246 // empty. 247 Diag(PragmaLoc, diag::warn_pragma_pack_pop_failed) 248 << (Name ? "no record matching name" : "stack empty"); 249 250 // FIXME: Warn about popping named records as MSVC does. 251 } else { 252 // Pop succeeded, set the new alignment if specified. 253 if (Alignment) 254 Context->setAlignment(AlignmentVal); 255 } 256 break; 257 258 default: 259 assert(0 && "Invalid #pragma pack kind."); 260 } 261} 262 263void Sema::ActOnPragmaUnused(const Token *Identifiers, unsigned NumIdentifiers, 264 Scope *curScope, 265 SourceLocation PragmaLoc, 266 SourceLocation LParenLoc, 267 SourceLocation RParenLoc) { 268 269 for (unsigned i = 0; i < NumIdentifiers; ++i) { 270 const Token &Tok = Identifiers[i]; 271 IdentifierInfo *Name = Tok.getIdentifierInfo(); 272 LookupResult Lookup(*this, Name, Tok.getLocation(), LookupOrdinaryName); 273 LookupParsedName(Lookup, curScope, NULL, true); 274 275 if (Lookup.empty()) { 276 Diag(PragmaLoc, diag::warn_pragma_unused_undeclared_var) 277 << Name << SourceRange(Tok.getLocation()); 278 continue; 279 } 280 281 VarDecl *VD = Lookup.getAsSingle<VarDecl>(); 282 if (!VD || !VD->hasLocalStorage()) { 283 Diag(PragmaLoc, diag::warn_pragma_unused_expected_localvar) 284 << Name << SourceRange(Tok.getLocation()); 285 continue; 286 } 287 288 VD->addAttr(::new (Context) UnusedAttr()); 289 } 290} 291 292typedef std::vector<VisibilityAttr::VisibilityTypes> VisStack; 293 294void Sema::AddPushedVisibilityAttribute(Decl *D) { 295 if (!VisContext) 296 return; 297 298 if (D->hasAttr<VisibilityAttr>()) 299 return; 300 301 VisStack *Stack = static_cast<VisStack*>(VisContext); 302 VisibilityAttr::VisibilityTypes type = Stack->back(); 303 304 D->addAttr(::new (Context) VisibilityAttr(type, true)); 305} 306 307/// FreeVisContext - Deallocate and null out VisContext. 308void Sema::FreeVisContext() { 309 delete static_cast<VisStack*>(VisContext); 310 VisContext = 0; 311} 312 313void Sema::ActOnPragmaVisibility(bool IsPush, const IdentifierInfo* VisType, 314 SourceLocation PragmaLoc) { 315 if (IsPush) { 316 // Compute visibility to use. 317 VisibilityAttr::VisibilityTypes type; 318 if (VisType->isStr("default")) 319 type = VisibilityAttr::DefaultVisibility; 320 else if (VisType->isStr("hidden")) 321 type = VisibilityAttr::HiddenVisibility; 322 else if (VisType->isStr("internal")) 323 type = VisibilityAttr::HiddenVisibility; // FIXME 324 else if (VisType->isStr("protected")) 325 type = VisibilityAttr::ProtectedVisibility; 326 else { 327 Diag(PragmaLoc, diag::warn_attribute_unknown_visibility) << 328 VisType->getName(); 329 return; 330 } 331 PushPragmaVisibility(type); 332 } else { 333 PopPragmaVisibility(); 334 } 335} 336 337void Sema::PushPragmaVisibility(VisibilityAttr::VisibilityTypes type) { 338 // Put visibility on stack. 339 if (!VisContext) 340 VisContext = new VisStack; 341 342 VisStack *Stack = static_cast<VisStack*>(VisContext); 343 Stack->push_back(type); 344} 345 346void Sema::PopPragmaVisibility() { 347 // Pop visibility from stack, if there is one on the stack. 348 if (VisContext) { 349 VisStack *Stack = static_cast<VisStack*>(VisContext); 350 351 Stack->pop_back(); 352 // To simplify the implementation, never keep around an empty stack. 353 if (Stack->empty()) 354 FreeVisContext(); 355 } 356 // FIXME: Add diag for pop without push. 357} 358