SemaAttr.cpp revision 210299
1193326Sed//===--- SemaAttr.cpp - Semantic Analysis for Attributes ------------------===// 2193326Sed// 3193326Sed// The LLVM Compiler Infrastructure 4193326Sed// 5193326Sed// This file is distributed under the University of Illinois Open Source 6193326Sed// License. See LICENSE.TXT for details. 7193326Sed// 8193326Sed//===----------------------------------------------------------------------===// 9193326Sed// 10193326Sed// This file implements semantic analysis for non-trivial attributes and 11193326Sed// pragmas. 12193326Sed// 13193326Sed//===----------------------------------------------------------------------===// 14193326Sed 15193326Sed#include "Sema.h" 16199482Srdivacky#include "Lookup.h" 17193326Sed#include "clang/AST/Expr.h" 18208600Srdivacky#include "clang/Basic/TargetInfo.h" 19208600Srdivacky#include "clang/Lex/Preprocessor.h" 20193326Sedusing namespace clang; 21193326Sed 22193326Sed//===----------------------------------------------------------------------===// 23208600Srdivacky// Pragma 'pack' and 'options align' 24193326Sed//===----------------------------------------------------------------------===// 25193326Sed 26193326Sednamespace { 27208600Srdivacky struct PackStackEntry { 28208600Srdivacky // We just use a sentinel to represent when the stack is set to mac68k 29208600Srdivacky // alignment. 30208600Srdivacky static const unsigned kMac68kAlignmentSentinel = ~0U; 31208600Srdivacky 32208600Srdivacky unsigned Alignment; 33208600Srdivacky IdentifierInfo *Name; 34208600Srdivacky }; 35208600Srdivacky 36193326Sed /// PragmaPackStack - Simple class to wrap the stack used by #pragma 37193326Sed /// pack. 38193326Sed class PragmaPackStack { 39208600Srdivacky typedef std::vector<PackStackEntry> stack_ty; 40193326Sed 41193326Sed /// Alignment - The current user specified alignment. 42193326Sed unsigned Alignment; 43193326Sed 44193326Sed /// Stack - Entries in the #pragma pack stack, consisting of saved 45193326Sed /// alignments and optional names. 46193326Sed stack_ty Stack; 47198092Srdivacky 48198092Srdivacky public: 49193326Sed PragmaPackStack() : Alignment(0) {} 50193326Sed 51193326Sed void setAlignment(unsigned A) { Alignment = A; } 52193326Sed unsigned getAlignment() { return Alignment; } 53193326Sed 54193326Sed /// push - Push the current alignment onto the stack, optionally 55193326Sed /// using the given \arg Name for the record, if non-zero. 56193326Sed void push(IdentifierInfo *Name) { 57208600Srdivacky PackStackEntry PSE = { Alignment, Name }; 58208600Srdivacky Stack.push_back(PSE); 59193326Sed } 60193326Sed 61193326Sed /// pop - Pop a record from the stack and restore the current 62193326Sed /// alignment to the previous value. If \arg Name is non-zero then 63193326Sed /// the first such named record is popped, otherwise the top record 64193326Sed /// is popped. Returns true if the pop succeeded. 65193326Sed bool pop(IdentifierInfo *Name); 66193326Sed }; 67193326Sed} // end anonymous namespace. 68193326Sed 69193326Sedbool PragmaPackStack::pop(IdentifierInfo *Name) { 70193326Sed if (Stack.empty()) 71193326Sed return false; 72198092Srdivacky 73193326Sed // If name is empty just pop top. 74193326Sed if (!Name) { 75208600Srdivacky Alignment = Stack.back().Alignment; 76193326Sed Stack.pop_back(); 77193326Sed return true; 78198092Srdivacky } 79198092Srdivacky 80193326Sed // Otherwise, find the named record. 81193326Sed for (unsigned i = Stack.size(); i != 0; ) { 82193326Sed --i; 83208600Srdivacky if (Stack[i].Name == Name) { 84193326Sed // Found it, pop up to and including this record. 85208600Srdivacky Alignment = Stack[i].Alignment; 86193326Sed Stack.erase(Stack.begin() + i, Stack.end()); 87193326Sed return true; 88193326Sed } 89193326Sed } 90198092Srdivacky 91193326Sed return false; 92193326Sed} 93193326Sed 94193326Sed 95193326Sed/// FreePackedContext - Deallocate and null out PackContext. 96193326Sedvoid Sema::FreePackedContext() { 97193326Sed delete static_cast<PragmaPackStack*>(PackContext); 98193326Sed PackContext = 0; 99193326Sed} 100193326Sed 101208600Srdivackyvoid Sema::AddAlignmentAttributesForRecord(RecordDecl *RD) { 102208600Srdivacky // If there is no pack context, we don't need any attributes. 103208600Srdivacky if (!PackContext) 104208600Srdivacky return; 105208600Srdivacky 106208600Srdivacky PragmaPackStack *Stack = static_cast<PragmaPackStack*>(PackContext); 107208600Srdivacky 108208600Srdivacky // Otherwise, check to see if we need a max field alignment attribute. 109208600Srdivacky if (unsigned Alignment = Stack->getAlignment()) { 110208600Srdivacky if (Alignment == PackStackEntry::kMac68kAlignmentSentinel) 111208600Srdivacky RD->addAttr(::new (Context) AlignMac68kAttr()); 112208600Srdivacky else 113208600Srdivacky RD->addAttr(::new (Context) MaxFieldAlignmentAttr(Alignment * 8)); 114208600Srdivacky } 115193326Sed} 116193326Sed 117208600Srdivackyvoid Sema::ActOnPragmaOptionsAlign(PragmaOptionsAlignKind Kind, 118208600Srdivacky SourceLocation PragmaLoc, 119208600Srdivacky SourceLocation KindLoc) { 120208600Srdivacky if (PackContext == 0) 121208600Srdivacky PackContext = new PragmaPackStack(); 122208600Srdivacky 123208600Srdivacky PragmaPackStack *Context = static_cast<PragmaPackStack*>(PackContext); 124208600Srdivacky 125208600Srdivacky // Reset just pops the top of the stack. 126208600Srdivacky if (Kind == Action::POAK_Reset) { 127208600Srdivacky // Do the pop. 128208600Srdivacky if (!Context->pop(0)) { 129208600Srdivacky // If a name was specified then failure indicates the name 130208600Srdivacky // wasn't found. Otherwise failure indicates the stack was 131208600Srdivacky // empty. 132208600Srdivacky Diag(PragmaLoc, diag::warn_pragma_options_align_reset_failed) 133208600Srdivacky << "stack empty"; 134208600Srdivacky } 135208600Srdivacky return; 136208600Srdivacky } 137208600Srdivacky 138208600Srdivacky switch (Kind) { 139210299Sed // For all targets we support native and natural are the same. 140210299Sed // 141210299Sed // FIXME: This is not true on Darwin/PPC. 142210299Sed case POAK_Native: 143210299Sed case POAK_Power: 144208600Srdivacky case POAK_Natural: 145208600Srdivacky Context->push(0); 146208600Srdivacky Context->setAlignment(0); 147208600Srdivacky break; 148208600Srdivacky 149210299Sed // Note that '#pragma options align=packed' is not equivalent to attribute 150210299Sed // packed, it has a different precedence relative to attribute aligned. 151210299Sed case POAK_Packed: 152210299Sed Context->push(0); 153210299Sed Context->setAlignment(1); 154210299Sed break; 155210299Sed 156208600Srdivacky case POAK_Mac68k: 157208600Srdivacky // Check if the target supports this. 158208600Srdivacky if (!PP.getTargetInfo().hasAlignMac68kSupport()) { 159208600Srdivacky Diag(PragmaLoc, diag::err_pragma_options_align_mac68k_target_unsupported); 160208600Srdivacky return; 161208600Srdivacky } 162208600Srdivacky Context->push(0); 163208600Srdivacky Context->setAlignment(PackStackEntry::kMac68kAlignmentSentinel); 164208600Srdivacky break; 165208600Srdivacky 166208600Srdivacky default: 167208600Srdivacky Diag(PragmaLoc, diag::warn_pragma_options_align_unsupported_option) 168208600Srdivacky << KindLoc; 169208600Srdivacky break; 170208600Srdivacky } 171208600Srdivacky} 172208600Srdivacky 173198092Srdivackyvoid Sema::ActOnPragmaPack(PragmaPackKind Kind, IdentifierInfo *Name, 174198092Srdivacky ExprTy *alignment, SourceLocation PragmaLoc, 175193326Sed SourceLocation LParenLoc, SourceLocation RParenLoc) { 176193326Sed Expr *Alignment = static_cast<Expr *>(alignment); 177193326Sed 178193326Sed // If specified then alignment must be a "small" power of two. 179193326Sed unsigned AlignmentVal = 0; 180193326Sed if (Alignment) { 181193326Sed llvm::APSInt Val; 182198092Srdivacky 183193326Sed // pack(0) is like pack(), which just works out since that is what 184193326Sed // we use 0 for in PackAttr. 185208600Srdivacky if (Alignment->isTypeDependent() || 186208600Srdivacky Alignment->isValueDependent() || 187208600Srdivacky !Alignment->isIntegerConstantExpr(Val, Context) || 188193326Sed !(Val == 0 || Val.isPowerOf2()) || 189193326Sed Val.getZExtValue() > 16) { 190193326Sed Diag(PragmaLoc, diag::warn_pragma_pack_invalid_alignment); 191193326Sed Alignment->Destroy(Context); 192193326Sed return; // Ignore 193193326Sed } 194193326Sed 195193326Sed AlignmentVal = (unsigned) Val.getZExtValue(); 196193326Sed } 197198092Srdivacky 198193326Sed if (PackContext == 0) 199193326Sed PackContext = new PragmaPackStack(); 200198092Srdivacky 201193326Sed PragmaPackStack *Context = static_cast<PragmaPackStack*>(PackContext); 202198092Srdivacky 203193326Sed switch (Kind) { 204193326Sed case Action::PPK_Default: // pack([n]) 205193326Sed Context->setAlignment(AlignmentVal); 206193326Sed break; 207193326Sed 208193326Sed case Action::PPK_Show: // pack(show) 209193326Sed // Show the current alignment, making sure to show the right value 210193326Sed // for the default. 211193326Sed AlignmentVal = Context->getAlignment(); 212193326Sed // FIXME: This should come from the target. 213193326Sed if (AlignmentVal == 0) 214193326Sed AlignmentVal = 8; 215208600Srdivacky if (AlignmentVal == PackStackEntry::kMac68kAlignmentSentinel) 216208600Srdivacky Diag(PragmaLoc, diag::warn_pragma_pack_show) << "mac68k"; 217208600Srdivacky else 218208600Srdivacky Diag(PragmaLoc, diag::warn_pragma_pack_show) << AlignmentVal; 219193326Sed break; 220193326Sed 221193326Sed case Action::PPK_Push: // pack(push [, id] [, [n]) 222193326Sed Context->push(Name); 223193326Sed // Set the new alignment if specified. 224193326Sed if (Alignment) 225198092Srdivacky Context->setAlignment(AlignmentVal); 226193326Sed break; 227193326Sed 228193326Sed case Action::PPK_Pop: // pack(pop [, id] [, n]) 229193326Sed // MSDN, C/C++ Preprocessor Reference > Pragma Directives > pack: 230193326Sed // "#pragma pack(pop, identifier, n) is undefined" 231193326Sed if (Alignment && Name) 232198092Srdivacky Diag(PragmaLoc, diag::warn_pragma_pack_pop_identifer_and_alignment); 233198092Srdivacky 234193326Sed // Do the pop. 235193326Sed if (!Context->pop(Name)) { 236193326Sed // If a name was specified then failure indicates the name 237193326Sed // wasn't found. Otherwise failure indicates the stack was 238193326Sed // empty. 239193326Sed Diag(PragmaLoc, diag::warn_pragma_pack_pop_failed) 240193326Sed << (Name ? "no record matching name" : "stack empty"); 241193326Sed 242193326Sed // FIXME: Warn about popping named records as MSVC does. 243193326Sed } else { 244193326Sed // Pop succeeded, set the new alignment if specified. 245193326Sed if (Alignment) 246193326Sed Context->setAlignment(AlignmentVal); 247193326Sed } 248193326Sed break; 249193326Sed 250193326Sed default: 251193326Sed assert(0 && "Invalid #pragma pack kind."); 252193326Sed } 253193326Sed} 254193326Sed 255198092Srdivackyvoid Sema::ActOnPragmaUnused(const Token *Identifiers, unsigned NumIdentifiers, 256198092Srdivacky Scope *curScope, 257193326Sed SourceLocation PragmaLoc, 258193326Sed SourceLocation LParenLoc, 259193326Sed SourceLocation RParenLoc) { 260198092Srdivacky 261198092Srdivacky for (unsigned i = 0; i < NumIdentifiers; ++i) { 262198092Srdivacky const Token &Tok = Identifiers[i]; 263198092Srdivacky IdentifierInfo *Name = Tok.getIdentifierInfo(); 264199482Srdivacky LookupResult Lookup(*this, Name, Tok.getLocation(), LookupOrdinaryName); 265199482Srdivacky LookupParsedName(Lookup, curScope, NULL, true); 266198092Srdivacky 267200583Srdivacky if (Lookup.empty()) { 268198092Srdivacky Diag(PragmaLoc, diag::warn_pragma_unused_undeclared_var) 269198092Srdivacky << Name << SourceRange(Tok.getLocation()); 270198092Srdivacky continue; 271193326Sed } 272193326Sed 273200583Srdivacky VarDecl *VD = Lookup.getAsSingle<VarDecl>(); 274200583Srdivacky if (!VD || !VD->hasLocalStorage()) { 275198092Srdivacky Diag(PragmaLoc, diag::warn_pragma_unused_expected_localvar) 276198092Srdivacky << Name << SourceRange(Tok.getLocation()); 277198092Srdivacky continue; 278198092Srdivacky } 279193326Sed 280200583Srdivacky VD->addAttr(::new (Context) UnusedAttr()); 281193326Sed } 282193326Sed} 283