Home | History | Annotate | Download | only in Sema
      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/SemaInternal.h"
     16 #include "clang/Sema/Lookup.h"
     17 #include "clang/AST/Attr.h"
     18 #include "clang/AST/Expr.h"
     19 #include "clang/Basic/TargetInfo.h"
     20 #include "clang/Lex/Preprocessor.h"
     21 using namespace clang;
     22 
     23 //===----------------------------------------------------------------------===//
     24 // Pragma 'pack' and 'options align'
     25 //===----------------------------------------------------------------------===//
     26 
     27 namespace {
     28   struct PackStackEntry {
     29     // We just use a sentinel to represent when the stack is set to mac68k
     30     // alignment.
     31     static const unsigned kMac68kAlignmentSentinel = ~0U;
     32 
     33     unsigned Alignment;
     34     IdentifierInfo *Name;
     35   };
     36 
     37   /// PragmaPackStack - Simple class to wrap the stack used by #pragma
     38   /// pack.
     39   class PragmaPackStack {
     40     typedef std::vector<PackStackEntry> stack_ty;
     41 
     42     /// Alignment - The current user specified alignment.
     43     unsigned Alignment;
     44 
     45     /// Stack - Entries in the #pragma pack stack, consisting of saved
     46     /// alignments and optional names.
     47     stack_ty Stack;
     48 
     49   public:
     50     PragmaPackStack() : Alignment(0) {}
     51 
     52     void setAlignment(unsigned A) { Alignment = A; }
     53     unsigned getAlignment() { return Alignment; }
     54 
     55     /// push - Push the current alignment onto the stack, optionally
     56     /// using the given \arg Name for the record, if non-zero.
     57     void push(IdentifierInfo *Name) {
     58       PackStackEntry PSE = { Alignment, Name };
     59       Stack.push_back(PSE);
     60     }
     61 
     62     /// pop - Pop a record from the stack and restore the current
     63     /// alignment to the previous value. If \arg Name is non-zero then
     64     /// the first such named record is popped, otherwise the top record
     65     /// is popped. Returns true if the pop succeeded.
     66     bool pop(IdentifierInfo *Name, bool IsReset);
     67   };
     68 }  // end anonymous namespace.
     69 
     70 bool PragmaPackStack::pop(IdentifierInfo *Name, bool IsReset) {
     71   // If name is empty just pop top.
     72   if (!Name) {
     73     // An empty stack is a special case...
     74     if (Stack.empty()) {
     75       // If this isn't a reset, it is always an error.
     76       if (!IsReset)
     77         return false;
     78 
     79       // Otherwise, it is an error only if some alignment has been set.
     80       if (!Alignment)
     81         return false;
     82 
     83       // Otherwise, reset to the default alignment.
     84       Alignment = 0;
     85     } else {
     86       Alignment = Stack.back().Alignment;
     87       Stack.pop_back();
     88     }
     89 
     90     return true;
     91   }
     92 
     93   // Otherwise, find the named record.
     94   for (unsigned i = Stack.size(); i != 0; ) {
     95     --i;
     96     if (Stack[i].Name == Name) {
     97       // Found it, pop up to and including this record.
     98       Alignment = Stack[i].Alignment;
     99       Stack.erase(Stack.begin() + i, Stack.end());
    100       return true;
    101     }
    102   }
    103 
    104   return false;
    105 }
    106 
    107 
    108 /// FreePackedContext - Deallocate and null out PackContext.
    109 void Sema::FreePackedContext() {
    110   delete static_cast<PragmaPackStack*>(PackContext);
    111   PackContext = 0;
    112 }
    113 
    114 void Sema::AddAlignmentAttributesForRecord(RecordDecl *RD) {
    115   // If there is no pack context, we don't need any attributes.
    116   if (!PackContext)
    117     return;
    118 
    119   PragmaPackStack *Stack = static_cast<PragmaPackStack*>(PackContext);
    120 
    121   // Otherwise, check to see if we need a max field alignment attribute.
    122   if (unsigned Alignment = Stack->getAlignment()) {
    123     if (Alignment == PackStackEntry::kMac68kAlignmentSentinel)
    124       RD->addAttr(::new (Context) AlignMac68kAttr(SourceLocation(), Context));
    125     else
    126       RD->addAttr(::new (Context) MaxFieldAlignmentAttr(SourceLocation(),
    127                                                         Context,
    128                                                         Alignment * 8));
    129   }
    130 }
    131 
    132 void Sema::AddMsStructLayoutForRecord(RecordDecl *RD) {
    133   if (!MSStructPragmaOn)
    134     return;
    135   RD->addAttr(::new (Context) MsStructAttr(SourceLocation(), Context));
    136 }
    137 
    138 void Sema::ActOnPragmaOptionsAlign(PragmaOptionsAlignKind Kind,
    139                                    SourceLocation PragmaLoc,
    140                                    SourceLocation KindLoc) {
    141   if (PackContext == 0)
    142     PackContext = new PragmaPackStack();
    143 
    144   PragmaPackStack *Context = static_cast<PragmaPackStack*>(PackContext);
    145 
    146   // Reset just pops the top of the stack, or resets the current alignment to
    147   // default.
    148   if (Kind == Sema::POAK_Reset) {
    149     if (!Context->pop(0, /*IsReset=*/true)) {
    150       Diag(PragmaLoc, diag::warn_pragma_options_align_reset_failed)
    151         << "stack empty";
    152     }
    153     return;
    154   }
    155 
    156   switch (Kind) {
    157     // For all targets we support native and natural are the same.
    158     //
    159     // FIXME: This is not true on Darwin/PPC.
    160   case POAK_Native:
    161   case POAK_Power:
    162   case POAK_Natural:
    163     Context->push(0);
    164     Context->setAlignment(0);
    165     break;
    166 
    167     // Note that '#pragma options align=packed' is not equivalent to attribute
    168     // packed, it has a different precedence relative to attribute aligned.
    169   case POAK_Packed:
    170     Context->push(0);
    171     Context->setAlignment(1);
    172     break;
    173 
    174   case POAK_Mac68k:
    175     // Check if the target supports this.
    176     if (!PP.getTargetInfo().hasAlignMac68kSupport()) {
    177       Diag(PragmaLoc, diag::err_pragma_options_align_mac68k_target_unsupported);
    178       return;
    179     }
    180     Context->push(0);
    181     Context->setAlignment(PackStackEntry::kMac68kAlignmentSentinel);
    182     break;
    183 
    184   default:
    185     Diag(PragmaLoc, diag::warn_pragma_options_align_unsupported_option)
    186       << KindLoc;
    187     break;
    188   }
    189 }
    190 
    191 void Sema::ActOnPragmaPack(PragmaPackKind Kind, IdentifierInfo *Name,
    192                            ExprTy *alignment, SourceLocation PragmaLoc,
    193                            SourceLocation LParenLoc, SourceLocation RParenLoc) {
    194   Expr *Alignment = static_cast<Expr *>(alignment);
    195 
    196   // If specified then alignment must be a "small" power of two.
    197   unsigned AlignmentVal = 0;
    198   if (Alignment) {
    199     llvm::APSInt Val;
    200 
    201     // pack(0) is like pack(), which just works out since that is what
    202     // we use 0 for in PackAttr.
    203     if (Alignment->isTypeDependent() ||
    204         Alignment->isValueDependent() ||
    205         !Alignment->isIntegerConstantExpr(Val, Context) ||
    206         !(Val == 0 || Val.isPowerOf2()) ||
    207         Val.getZExtValue() > 16) {
    208       Diag(PragmaLoc, diag::warn_pragma_pack_invalid_alignment);
    209       return; // Ignore
    210     }
    211 
    212     AlignmentVal = (unsigned) Val.getZExtValue();
    213   }
    214 
    215   if (PackContext == 0)
    216     PackContext = new PragmaPackStack();
    217 
    218   PragmaPackStack *Context = static_cast<PragmaPackStack*>(PackContext);
    219 
    220   switch (Kind) {
    221   case Sema::PPK_Default: // pack([n])
    222     Context->setAlignment(AlignmentVal);
    223     break;
    224 
    225   case Sema::PPK_Show: // pack(show)
    226     // Show the current alignment, making sure to show the right value
    227     // for the default.
    228     AlignmentVal = Context->getAlignment();
    229     // FIXME: This should come from the target.
    230     if (AlignmentVal == 0)
    231       AlignmentVal = 8;
    232     if (AlignmentVal == PackStackEntry::kMac68kAlignmentSentinel)
    233       Diag(PragmaLoc, diag::warn_pragma_pack_show) << "mac68k";
    234     else
    235       Diag(PragmaLoc, diag::warn_pragma_pack_show) << AlignmentVal;
    236     break;
    237 
    238   case Sema::PPK_Push: // pack(push [, id] [, [n])
    239     Context->push(Name);
    240     // Set the new alignment if specified.
    241     if (Alignment)
    242       Context->setAlignment(AlignmentVal);
    243     break;
    244 
    245   case Sema::PPK_Pop: // pack(pop [, id] [,  n])
    246     // MSDN, C/C++ Preprocessor Reference > Pragma Directives > pack:
    247     // "#pragma pack(pop, identifier, n) is undefined"
    248     if (Alignment && Name)
    249       Diag(PragmaLoc, diag::warn_pragma_pack_pop_identifer_and_alignment);
    250 
    251     // Do the pop.
    252     if (!Context->pop(Name, /*IsReset=*/false)) {
    253       // If a name was specified then failure indicates the name
    254       // wasn't found. Otherwise failure indicates the stack was
    255       // empty.
    256       Diag(PragmaLoc, diag::warn_pragma_pack_pop_failed)
    257         << (Name ? "no record matching name" : "stack empty");
    258 
    259       // FIXME: Warn about popping named records as MSVC does.
    260     } else {
    261       // Pop succeeded, set the new alignment if specified.
    262       if (Alignment)
    263         Context->setAlignment(AlignmentVal);
    264     }
    265     break;
    266 
    267   default:
    268     assert(0 && "Invalid #pragma pack kind.");
    269   }
    270 }
    271 
    272 void Sema::ActOnPragmaMSStruct(PragmaMSStructKind Kind) {
    273   MSStructPragmaOn = (Kind == PMSST_ON);
    274 }
    275 
    276 void Sema::ActOnPragmaUnused(const Token &IdTok, Scope *curScope,
    277                              SourceLocation PragmaLoc) {
    278 
    279   IdentifierInfo *Name = IdTok.getIdentifierInfo();
    280   LookupResult Lookup(*this, Name, IdTok.getLocation(), LookupOrdinaryName);
    281   LookupParsedName(Lookup, curScope, NULL, true);
    282 
    283   if (Lookup.empty()) {
    284     Diag(PragmaLoc, diag::warn_pragma_unused_undeclared_var)
    285       << Name << SourceRange(IdTok.getLocation());
    286     return;
    287   }
    288 
    289   VarDecl *VD = Lookup.getAsSingle<VarDecl>();
    290   if (!VD) {
    291     Diag(PragmaLoc, diag::warn_pragma_unused_expected_var_arg)
    292       << Name << SourceRange(IdTok.getLocation());
    293     return;
    294   }
    295 
    296   // Warn if this was used before being marked unused.
    297   if (VD->isUsed())
    298     Diag(PragmaLoc, diag::warn_used_but_marked_unused) << Name;
    299 
    300   VD->addAttr(::new (Context) UnusedAttr(IdTok.getLocation(), Context));
    301 }
    302 
    303 typedef std::vector<std::pair<unsigned, SourceLocation> > VisStack;
    304 enum { NoVisibility = (unsigned) -1 };
    305 
    306 void Sema::AddPushedVisibilityAttribute(Decl *D) {
    307   if (!VisContext)
    308     return;
    309 
    310   if (isa<NamedDecl>(D) && cast<NamedDecl>(D)->getExplicitVisibility())
    311     return;
    312 
    313   VisStack *Stack = static_cast<VisStack*>(VisContext);
    314   unsigned rawType = Stack->back().first;
    315   if (rawType == NoVisibility) return;
    316 
    317   VisibilityAttr::VisibilityType type
    318     = (VisibilityAttr::VisibilityType) rawType;
    319   SourceLocation loc = Stack->back().second;
    320 
    321   D->addAttr(::new (Context) VisibilityAttr(loc, Context, type));
    322 }
    323 
    324 /// FreeVisContext - Deallocate and null out VisContext.
    325 void Sema::FreeVisContext() {
    326   delete static_cast<VisStack*>(VisContext);
    327   VisContext = 0;
    328 }
    329 
    330 static void PushPragmaVisibility(Sema &S, unsigned type, SourceLocation loc) {
    331   // Put visibility on stack.
    332   if (!S.VisContext)
    333     S.VisContext = new VisStack;
    334 
    335   VisStack *Stack = static_cast<VisStack*>(S.VisContext);
    336   Stack->push_back(std::make_pair(type, loc));
    337 }
    338 
    339 void Sema::ActOnPragmaVisibility(bool IsPush, const IdentifierInfo* VisType,
    340                                  SourceLocation PragmaLoc) {
    341   if (IsPush) {
    342     // Compute visibility to use.
    343     VisibilityAttr::VisibilityType type;
    344     if (VisType->isStr("default"))
    345       type = VisibilityAttr::Default;
    346     else if (VisType->isStr("hidden"))
    347       type = VisibilityAttr::Hidden;
    348     else if (VisType->isStr("internal"))
    349       type = VisibilityAttr::Hidden; // FIXME
    350     else if (VisType->isStr("protected"))
    351       type = VisibilityAttr::Protected;
    352     else {
    353       Diag(PragmaLoc, diag::warn_attribute_unknown_visibility) <<
    354         VisType->getName();
    355       return;
    356     }
    357     PushPragmaVisibility(*this, type, PragmaLoc);
    358   } else {
    359     PopPragmaVisibility();
    360   }
    361 }
    362 
    363 void Sema::ActOnPragmaFPContract(tok::OnOffSwitch OOS) {
    364   switch (OOS) {
    365   case tok::OOS_ON:
    366     FPFeatures.fp_contract = 1;
    367     break;
    368   case tok::OOS_OFF:
    369     FPFeatures.fp_contract = 0;
    370     break;
    371   case tok::OOS_DEFAULT:
    372     FPFeatures.fp_contract = getLangOptions().DefaultFPContract;
    373     break;
    374   }
    375 }
    376 
    377 void Sema::PushNamespaceVisibilityAttr(const VisibilityAttr *Attr) {
    378   // Visibility calculations will consider the namespace's visibility.
    379   // Here we just want to note that we're in a visibility context
    380   // which overrides any enclosing #pragma context, but doesn't itself
    381   // contribute visibility.
    382   PushPragmaVisibility(*this, NoVisibility, SourceLocation());
    383 }
    384 
    385 void Sema::PopPragmaVisibility() {
    386   // Pop visibility from stack, if there is one on the stack.
    387   if (VisContext) {
    388     VisStack *Stack = static_cast<VisStack*>(VisContext);
    389 
    390     Stack->pop_back();
    391     // To simplify the implementation, never keep around an empty stack.
    392     if (Stack->empty())
    393       FreeVisContext();
    394   }
    395   // FIXME: Add diag for pop without push.
    396 }
    397