SemaAttr.cpp revision 200583
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" 18193326Sedusing namespace clang; 19193326Sed 20193326Sed//===----------------------------------------------------------------------===// 21193326Sed// Pragma Packed 22193326Sed//===----------------------------------------------------------------------===// 23193326Sed 24193326Sednamespace { 25193326Sed /// PragmaPackStack - Simple class to wrap the stack used by #pragma 26193326Sed /// pack. 27193326Sed class PragmaPackStack { 28193326Sed typedef std::vector< std::pair<unsigned, IdentifierInfo*> > stack_ty; 29193326Sed 30193326Sed /// Alignment - The current user specified alignment. 31193326Sed unsigned Alignment; 32193326Sed 33193326Sed /// Stack - Entries in the #pragma pack stack, consisting of saved 34193326Sed /// alignments and optional names. 35193326Sed stack_ty Stack; 36198092Srdivacky 37198092Srdivacky public: 38193326Sed PragmaPackStack() : Alignment(0) {} 39193326Sed 40193326Sed void setAlignment(unsigned A) { Alignment = A; } 41193326Sed unsigned getAlignment() { return Alignment; } 42193326Sed 43193326Sed /// push - Push the current alignment onto the stack, optionally 44193326Sed /// using the given \arg Name for the record, if non-zero. 45193326Sed void push(IdentifierInfo *Name) { 46193326Sed Stack.push_back(std::make_pair(Alignment, Name)); 47193326Sed } 48193326Sed 49193326Sed /// pop - Pop a record from the stack and restore the current 50193326Sed /// alignment to the previous value. If \arg Name is non-zero then 51193326Sed /// the first such named record is popped, otherwise the top record 52193326Sed /// is popped. Returns true if the pop succeeded. 53193326Sed bool pop(IdentifierInfo *Name); 54193326Sed }; 55193326Sed} // end anonymous namespace. 56193326Sed 57193326Sedbool PragmaPackStack::pop(IdentifierInfo *Name) { 58193326Sed if (Stack.empty()) 59193326Sed return false; 60198092Srdivacky 61193326Sed // If name is empty just pop top. 62193326Sed if (!Name) { 63193326Sed Alignment = Stack.back().first; 64193326Sed Stack.pop_back(); 65193326Sed return true; 66198092Srdivacky } 67198092Srdivacky 68193326Sed // Otherwise, find the named record. 69193326Sed for (unsigned i = Stack.size(); i != 0; ) { 70193326Sed --i; 71193326Sed if (Stack[i].second == Name) { 72193326Sed // Found it, pop up to and including this record. 73193326Sed Alignment = Stack[i].first; 74193326Sed Stack.erase(Stack.begin() + i, Stack.end()); 75193326Sed return true; 76193326Sed } 77193326Sed } 78198092Srdivacky 79193326Sed return false; 80193326Sed} 81193326Sed 82193326Sed 83193326Sed/// FreePackedContext - Deallocate and null out PackContext. 84193326Sedvoid Sema::FreePackedContext() { 85193326Sed delete static_cast<PragmaPackStack*>(PackContext); 86193326Sed PackContext = 0; 87193326Sed} 88193326Sed 89193326Sed/// getPragmaPackAlignment() - Return the current alignment as specified by 90193326Sed/// the current #pragma pack directive, or 0 if none is currently active. 91193326Sedunsigned Sema::getPragmaPackAlignment() const { 92193326Sed if (PackContext) 93193326Sed return static_cast<PragmaPackStack*>(PackContext)->getAlignment(); 94193326Sed return 0; 95193326Sed} 96193326Sed 97198092Srdivackyvoid Sema::ActOnPragmaPack(PragmaPackKind Kind, IdentifierInfo *Name, 98198092Srdivacky ExprTy *alignment, SourceLocation PragmaLoc, 99193326Sed SourceLocation LParenLoc, SourceLocation RParenLoc) { 100193326Sed Expr *Alignment = static_cast<Expr *>(alignment); 101193326Sed 102193326Sed // If specified then alignment must be a "small" power of two. 103193326Sed unsigned AlignmentVal = 0; 104193326Sed if (Alignment) { 105193326Sed llvm::APSInt Val; 106198092Srdivacky 107193326Sed // pack(0) is like pack(), which just works out since that is what 108193326Sed // we use 0 for in PackAttr. 109193326Sed if (!Alignment->isIntegerConstantExpr(Val, Context) || 110193326Sed !(Val == 0 || Val.isPowerOf2()) || 111193326Sed Val.getZExtValue() > 16) { 112193326Sed Diag(PragmaLoc, diag::warn_pragma_pack_invalid_alignment); 113193326Sed Alignment->Destroy(Context); 114193326Sed return; // Ignore 115193326Sed } 116193326Sed 117193326Sed AlignmentVal = (unsigned) Val.getZExtValue(); 118193326Sed } 119198092Srdivacky 120193326Sed if (PackContext == 0) 121193326Sed PackContext = new PragmaPackStack(); 122198092Srdivacky 123193326Sed PragmaPackStack *Context = static_cast<PragmaPackStack*>(PackContext); 124198092Srdivacky 125193326Sed switch (Kind) { 126193326Sed case Action::PPK_Default: // pack([n]) 127193326Sed Context->setAlignment(AlignmentVal); 128193326Sed break; 129193326Sed 130193326Sed case Action::PPK_Show: // pack(show) 131193326Sed // Show the current alignment, making sure to show the right value 132193326Sed // for the default. 133193326Sed AlignmentVal = Context->getAlignment(); 134193326Sed // FIXME: This should come from the target. 135193326Sed if (AlignmentVal == 0) 136193326Sed AlignmentVal = 8; 137193326Sed Diag(PragmaLoc, diag::warn_pragma_pack_show) << AlignmentVal; 138193326Sed break; 139193326Sed 140193326Sed case Action::PPK_Push: // pack(push [, id] [, [n]) 141193326Sed Context->push(Name); 142193326Sed // Set the new alignment if specified. 143193326Sed if (Alignment) 144198092Srdivacky Context->setAlignment(AlignmentVal); 145193326Sed break; 146193326Sed 147193326Sed case Action::PPK_Pop: // pack(pop [, id] [, n]) 148193326Sed // MSDN, C/C++ Preprocessor Reference > Pragma Directives > pack: 149193326Sed // "#pragma pack(pop, identifier, n) is undefined" 150193326Sed if (Alignment && Name) 151198092Srdivacky Diag(PragmaLoc, diag::warn_pragma_pack_pop_identifer_and_alignment); 152198092Srdivacky 153193326Sed // Do the pop. 154193326Sed if (!Context->pop(Name)) { 155193326Sed // If a name was specified then failure indicates the name 156193326Sed // wasn't found. Otherwise failure indicates the stack was 157193326Sed // empty. 158193326Sed Diag(PragmaLoc, diag::warn_pragma_pack_pop_failed) 159193326Sed << (Name ? "no record matching name" : "stack empty"); 160193326Sed 161193326Sed // FIXME: Warn about popping named records as MSVC does. 162193326Sed } else { 163193326Sed // Pop succeeded, set the new alignment if specified. 164193326Sed if (Alignment) 165193326Sed Context->setAlignment(AlignmentVal); 166193326Sed } 167193326Sed break; 168193326Sed 169193326Sed default: 170193326Sed assert(0 && "Invalid #pragma pack kind."); 171193326Sed } 172193326Sed} 173193326Sed 174198092Srdivackyvoid Sema::ActOnPragmaUnused(const Token *Identifiers, unsigned NumIdentifiers, 175198092Srdivacky Scope *curScope, 176193326Sed SourceLocation PragmaLoc, 177193326Sed SourceLocation LParenLoc, 178193326Sed SourceLocation RParenLoc) { 179198092Srdivacky 180198092Srdivacky for (unsigned i = 0; i < NumIdentifiers; ++i) { 181198092Srdivacky const Token &Tok = Identifiers[i]; 182198092Srdivacky IdentifierInfo *Name = Tok.getIdentifierInfo(); 183199482Srdivacky LookupResult Lookup(*this, Name, Tok.getLocation(), LookupOrdinaryName); 184199482Srdivacky LookupParsedName(Lookup, curScope, NULL, true); 185198092Srdivacky 186200583Srdivacky if (Lookup.empty()) { 187198092Srdivacky Diag(PragmaLoc, diag::warn_pragma_unused_undeclared_var) 188198092Srdivacky << Name << SourceRange(Tok.getLocation()); 189198092Srdivacky continue; 190193326Sed } 191193326Sed 192200583Srdivacky VarDecl *VD = Lookup.getAsSingle<VarDecl>(); 193200583Srdivacky if (!VD || !VD->hasLocalStorage()) { 194198092Srdivacky Diag(PragmaLoc, diag::warn_pragma_unused_expected_localvar) 195198092Srdivacky << Name << SourceRange(Tok.getLocation()); 196198092Srdivacky continue; 197198092Srdivacky } 198193326Sed 199200583Srdivacky VD->addAttr(::new (Context) UnusedAttr()); 200193326Sed } 201193326Sed} 202