SemaAttr.cpp revision 199482
135124Sjb//===--- SemaAttr.cpp - Semantic Analysis for Attributes ------------------===// 235124Sjb// 335124Sjb// The LLVM Compiler Infrastructure 435124Sjb// 535124Sjb// This file is distributed under the University of Illinois Open Source 635124Sjb// License. See LICENSE.TXT for details. 735124Sjb// 835124Sjb//===----------------------------------------------------------------------===// 935124Sjb// 1035124Sjb// This file implements semantic analysis for non-trivial attributes and 1135124Sjb// pragmas. 1235124Sjb// 13165968Simp//===----------------------------------------------------------------------===// 1435124Sjb 1535124Sjb#include "Sema.h" 1635124Sjb#include "Lookup.h" 1735124Sjb#include "clang/AST/Expr.h" 1835124Sjbusing namespace clang; 1935124Sjb 2035124Sjb//===----------------------------------------------------------------------===// 2135124Sjb// Pragma Packed 2235124Sjb//===----------------------------------------------------------------------===// 2335124Sjb 2435124Sjbnamespace { 2535124Sjb /// PragmaPackStack - Simple class to wrap the stack used by #pragma 2635124Sjb /// pack. 2735124Sjb class PragmaPackStack { 2835124Sjb typedef std::vector< std::pair<unsigned, IdentifierInfo*> > stack_ty; 2950476Speter 3035124Sjb /// Alignment - The current user specified alignment. 3135124Sjb unsigned Alignment; 3235124Sjb 3335124Sjb /// Stack - Entries in the #pragma pack stack, consisting of saved 3435124Sjb /// alignments and optional names. 3535124Sjb stack_ty Stack; 3635124Sjb 37199606Sjhb public: 3835124Sjb PragmaPackStack() : Alignment(0) {} 3935124Sjb 4035124Sjb void setAlignment(unsigned A) { Alignment = A; } 4135124Sjb unsigned getAlignment() { return Alignment; } 4235124Sjb 4335124Sjb /// push - Push the current alignment onto the stack, optionally 4435124Sjb /// using the given \arg Name for the record, if non-zero. 4535124Sjb void push(IdentifierInfo *Name) { 4635124Sjb Stack.push_back(std::make_pair(Alignment, Name)); 47231868Skib } 48231868Skib 49231868Skib /// pop - Pop a record from the stack and restore the current 50231868Skib /// alignment to the previous value. If \arg Name is non-zero then 51231868Skib /// the first such named record is popped, otherwise the top record 52231868Skib /// is popped. Returns true if the pop succeeded. 53231868Skib bool pop(IdentifierInfo *Name); 54231868Skib }; 55231868Skib} // end anonymous namespace. 56228843Scperciva 57228843Scpercivabool PragmaPackStack::pop(IdentifierInfo *Name) { 58228843Scperciva if (Stack.empty()) 59228843Scperciva return false; 60228843Scperciva 61228843Scperciva // If name is empty just pop top. 62228843Scperciva if (!Name) { 63228843Scperciva Alignment = Stack.back().first; 64228843Scperciva Stack.pop_back(); 65228843Scperciva return true; 66228843Scperciva } 6735124Sjb 6835124Sjb // Otherwise, find the named record. 6935124Sjb for (unsigned i = Stack.size(); i != 0; ) { 7035124Sjb --i; 7135124Sjb if (Stack[i].second == Name) { 7235124Sjb // Found it, pop up to and including this record. 7335124Sjb Alignment = Stack[i].first; 7471579Sdeischen Stack.erase(Stack.begin() + i, Stack.end()); 7535124Sjb return true; 7635124Sjb } 7735124Sjb } 7835124Sjb 7935124Sjb return false; 8035124Sjb} 8135124Sjb 8271579Sdeischen 8335124Sjb/// FreePackedContext - Deallocate and null out PackContext. 84234657Skibvoid Sema::FreePackedContext() { 85234657Skib delete static_cast<PragmaPackStack*>(PackContext); 86234657Skib PackContext = 0; 87234657Skib} 88234657Skib 89234657Skib/// getPragmaPackAlignment() - Return the current alignment as specified by 90234657Skib/// the current #pragma pack directive, or 0 if none is currently active. 91234657Skibunsigned Sema::getPragmaPackAlignment() const { 92234657Skib if (PackContext) 93234657Skib return static_cast<PragmaPackStack*>(PackContext)->getAlignment(); 94234657Skib return 0; 95234657Skib} 96234657Skib 9793399Smarkmvoid Sema::ActOnPragmaPack(PragmaPackKind Kind, IdentifierInfo *Name, 98106866Sdeischen ExprTy *alignment, SourceLocation PragmaLoc, 99106866Sdeischen SourceLocation LParenLoc, SourceLocation RParenLoc) { 100106866Sdeischen Expr *Alignment = static_cast<Expr *>(alignment); 101106866Sdeischen 102106866Sdeischen // If specified then alignment must be a "small" power of two. 103106866Sdeischen unsigned AlignmentVal = 0; 104156319Sdeischen if (Alignment) { 105156319Sdeischen llvm::APSInt Val; 106156319Sdeischen 107156319Sdeischen // pack(0) is like pack(), which just works out since that is what 108156319Sdeischen // we use 0 for in PackAttr. 109156319Sdeischen if (!Alignment->isIntegerConstantExpr(Val, Context) || 110156319Sdeischen !(Val == 0 || Val.isPowerOf2()) || 111156319Sdeischen Val.getZExtValue() > 16) { 112156319Sdeischen Diag(PragmaLoc, diag::warn_pragma_pack_invalid_alignment); 113156319Sdeischen Alignment->Destroy(Context); 114156319Sdeischen return; // Ignore 115156319Sdeischen } 116156319Sdeischen 117156319Sdeischen AlignmentVal = (unsigned) Val.getZExtValue(); 118156319Sdeischen } 119156319Sdeischen 120156319Sdeischen if (PackContext == 0) 121156319Sdeischen PackContext = new PragmaPackStack(); 122156319Sdeischen 123156319Sdeischen PragmaPackStack *Context = static_cast<PragmaPackStack*>(PackContext); 124156319Sdeischen 125156319Sdeischen switch (Kind) { 126106866Sdeischen case Action::PPK_Default: // pack([n]) 127106866Sdeischen Context->setAlignment(AlignmentVal); 128106866Sdeischen break; 129106866Sdeischen 130156319Sdeischen case Action::PPK_Show: // pack(show) 131106866Sdeischen // Show the current alignment, making sure to show the right value 132156319Sdeischen // for the default. 133156319Sdeischen AlignmentVal = Context->getAlignment(); 134156319Sdeischen // FIXME: This should come from the target. 135106866Sdeischen if (AlignmentVal == 0) 136156319Sdeischen AlignmentVal = 8; 137106866Sdeischen Diag(PragmaLoc, diag::warn_pragma_pack_show) << AlignmentVal; 138106866Sdeischen break; 139156319Sdeischen 140106866Sdeischen case Action::PPK_Push: // pack(push [, id] [, [n]) 141156319Sdeischen Context->push(Name); 142156319Sdeischen // Set the new alignment if specified. 143156319Sdeischen if (Alignment) 144106866Sdeischen Context->setAlignment(AlignmentVal); 145106866Sdeischen break; 146106866Sdeischen 147106866Sdeischen case Action::PPK_Pop: // pack(pop [, id] [, n]) 148106866Sdeischen // MSDN, C/C++ Preprocessor Reference > Pragma Directives > pack: 149106866Sdeischen // "#pragma pack(pop, identifier, n) is undefined" 150106866Sdeischen if (Alignment && Name) 151106866Sdeischen Diag(PragmaLoc, diag::warn_pragma_pack_pop_identifer_and_alignment); 152106866Sdeischen 153106866Sdeischen // Do the pop. 154106866Sdeischen if (!Context->pop(Name)) { 155106866Sdeischen // If a name was specified then failure indicates the name 156106866Sdeischen // wasn't found. Otherwise failure indicates the stack was 157106866Sdeischen // empty. 158156319Sdeischen Diag(PragmaLoc, diag::warn_pragma_pack_pop_failed) 159156319Sdeischen << (Name ? "no record matching name" : "stack empty"); 160106866Sdeischen 161106866Sdeischen // FIXME: Warn about popping named records as MSVC does. 162156319Sdeischen } else { 163201546Sdavidxu // Pop succeeded, set the new alignment if specified. 164201546Sdavidxu if (Alignment) 165213153Sdavidxu Context->setAlignment(AlignmentVal); 166213153Sdavidxu } 167106866Sdeischen break; 168106866Sdeischen 169106866Sdeischen default: 170106870Sdeischen assert(0 && "Invalid #pragma pack kind."); 171106880Sdeischen } 172106866Sdeischen} 173106880Sdeischen 174106866Sdeischenvoid Sema::ActOnPragmaUnused(const Token *Identifiers, unsigned NumIdentifiers, 175106866Sdeischen Scope *curScope, 176111618Snectar SourceLocation PragmaLoc, 177111618Snectar SourceLocation LParenLoc, 178111618Snectar SourceLocation RParenLoc) { 179111618Snectar 180111618Snectar for (unsigned i = 0; i < NumIdentifiers; ++i) { 181111618Snectar const Token &Tok = Identifiers[i]; 182133754Sdfr IdentifierInfo *Name = Tok.getIdentifierInfo(); 183133754Sdfr LookupResult Lookup(*this, Name, Tok.getLocation(), LookupOrdinaryName); 184133754Sdfr LookupParsedName(Lookup, curScope, NULL, true); 185133754Sdfr 186111618Snectar NamedDecl *ND = Lookup.getAsSingleDecl(Context); 187111618Snectar 188199606Sjhb if (!ND) { 189199606Sjhb Diag(PragmaLoc, diag::warn_pragma_unused_undeclared_var) 190199606Sjhb << Name << SourceRange(Tok.getLocation()); 191199606Sjhb continue; 192199606Sjhb } 193199606Sjhb 194133754Sdfr if (!isa<VarDecl>(ND) || !cast<VarDecl>(ND)->hasLocalStorage()) { 195133754Sdfr Diag(PragmaLoc, diag::warn_pragma_unused_expected_localvar) 196133754Sdfr << Name << SourceRange(Tok.getLocation()); 197133754Sdfr continue; 198133754Sdfr } 19993399Smarkm 20093399Smarkm ND->addAttr(::new (Context) UnusedAttr()); 20193399Smarkm } 20293399Smarkm} 20393399Smarkm