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/AST/Attr.h"
     17 #include "clang/AST/Expr.h"
     18 #include "clang/Basic/TargetInfo.h"
     19 #include "clang/Lex/Preprocessor.h"
     20 #include "clang/Sema/Lookup.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   if (PackContext == 0)
    141     PackContext = new PragmaPackStack();
    142 
    143   PragmaPackStack *Context = static_cast<PragmaPackStack*>(PackContext);
    144 
    145   switch (Kind) {
    146     // For all targets we support native and natural are the same.
    147     //
    148     // FIXME: This is not true on Darwin/PPC.
    149   case POAK_Native:
    150   case POAK_Power:
    151   case POAK_Natural:
    152     Context->push(0);
    153     Context->setAlignment(0);
    154     break;
    155 
    156     // Note that '#pragma options align=packed' is not equivalent to attribute
    157     // packed, it has a different precedence relative to attribute aligned.
    158   case POAK_Packed:
    159     Context->push(0);
    160     Context->setAlignment(1);
    161     break;
    162 
    163   case POAK_Mac68k:
    164     // Check if the target supports this.
    165     if (!PP.getTargetInfo().hasAlignMac68kSupport()) {
    166       Diag(PragmaLoc, diag::err_pragma_options_align_mac68k_target_unsupported);
    167       return;
    168     }
    169     Context->push(0);
    170     Context->setAlignment(PackStackEntry::kMac68kAlignmentSentinel);
    171     break;
    172 
    173   case POAK_Reset:
    174     // Reset just pops the top of the stack, or resets the current alignment to
    175     // default.
    176     if (!Context->pop(0, /*IsReset=*/true)) {
    177       Diag(PragmaLoc, diag::warn_pragma_options_align_reset_failed)
    178         << "stack empty";
    179     }
    180     break;
    181   }
    182 }
    183 
    184 void Sema::ActOnPragmaPack(PragmaPackKind Kind, IdentifierInfo *Name,
    185                            Expr *alignment, SourceLocation PragmaLoc,
    186                            SourceLocation LParenLoc, SourceLocation RParenLoc) {
    187   Expr *Alignment = static_cast<Expr *>(alignment);
    188 
    189   // If specified then alignment must be a "small" power of two.
    190   unsigned AlignmentVal = 0;
    191   if (Alignment) {
    192     llvm::APSInt Val;
    193 
    194     // pack(0) is like pack(), which just works out since that is what
    195     // we use 0 for in PackAttr.
    196     if (Alignment->isTypeDependent() ||
    197         Alignment->isValueDependent() ||
    198         !Alignment->isIntegerConstantExpr(Val, Context) ||
    199         !(Val == 0 || Val.isPowerOf2()) ||
    200         Val.getZExtValue() > 16) {
    201       Diag(PragmaLoc, diag::warn_pragma_pack_invalid_alignment);
    202       return; // Ignore
    203     }
    204 
    205     AlignmentVal = (unsigned) Val.getZExtValue();
    206   }
    207 
    208   if (PackContext == 0)
    209     PackContext = new PragmaPackStack();
    210 
    211   PragmaPackStack *Context = static_cast<PragmaPackStack*>(PackContext);
    212 
    213   switch (Kind) {
    214   case Sema::PPK_Default: // pack([n])
    215     Context->setAlignment(AlignmentVal);
    216     break;
    217 
    218   case Sema::PPK_Show: // pack(show)
    219     // Show the current alignment, making sure to show the right value
    220     // for the default.
    221     AlignmentVal = Context->getAlignment();
    222     // FIXME: This should come from the target.
    223     if (AlignmentVal == 0)
    224       AlignmentVal = 8;
    225     if (AlignmentVal == PackStackEntry::kMac68kAlignmentSentinel)
    226       Diag(PragmaLoc, diag::warn_pragma_pack_show) << "mac68k";
    227     else
    228       Diag(PragmaLoc, diag::warn_pragma_pack_show) << AlignmentVal;
    229     break;
    230 
    231   case Sema::PPK_Push: // pack(push [, id] [, [n])
    232     Context->push(Name);
    233     // Set the new alignment if specified.
    234     if (Alignment)
    235       Context->setAlignment(AlignmentVal);
    236     break;
    237 
    238   case Sema::PPK_Pop: // pack(pop [, id] [,  n])
    239     // MSDN, C/C++ Preprocessor Reference > Pragma Directives > pack:
    240     // "#pragma pack(pop, identifier, n) is undefined"
    241     if (Alignment && Name)
    242       Diag(PragmaLoc, diag::warn_pragma_pack_pop_identifer_and_alignment);
    243 
    244     // Do the pop.
    245     if (!Context->pop(Name, /*IsReset=*/false)) {
    246       // If a name was specified then failure indicates the name
    247       // wasn't found. Otherwise failure indicates the stack was
    248       // empty.
    249       Diag(PragmaLoc, diag::warn_pragma_pack_pop_failed)
    250         << (Name ? "no record matching name" : "stack empty");
    251 
    252       // FIXME: Warn about popping named records as MSVC does.
    253     } else {
    254       // Pop succeeded, set the new alignment if specified.
    255       if (Alignment)
    256         Context->setAlignment(AlignmentVal);
    257     }
    258     break;
    259   }
    260 }
    261 
    262 void Sema::ActOnPragmaMSStruct(PragmaMSStructKind Kind) {
    263   MSStructPragmaOn = (Kind == PMSST_ON);
    264 }
    265 
    266 void Sema::ActOnPragmaUnused(const Token &IdTok, Scope *curScope,
    267                              SourceLocation PragmaLoc) {
    268 
    269   IdentifierInfo *Name = IdTok.getIdentifierInfo();
    270   LookupResult Lookup(*this, Name, IdTok.getLocation(), LookupOrdinaryName);
    271   LookupParsedName(Lookup, curScope, NULL, true);
    272 
    273   if (Lookup.empty()) {
    274     Diag(PragmaLoc, diag::warn_pragma_unused_undeclared_var)
    275       << Name << SourceRange(IdTok.getLocation());
    276     return;
    277   }
    278 
    279   VarDecl *VD = Lookup.getAsSingle<VarDecl>();
    280   if (!VD) {
    281     Diag(PragmaLoc, diag::warn_pragma_unused_expected_var_arg)
    282       << Name << SourceRange(IdTok.getLocation());
    283     return;
    284   }
    285 
    286   // Warn if this was used before being marked unused.
    287   if (VD->isUsed())
    288     Diag(PragmaLoc, diag::warn_used_but_marked_unused) << Name;
    289 
    290   VD->addAttr(::new (Context) UnusedAttr(IdTok.getLocation(), Context));
    291 }
    292 
    293 void Sema::AddCFAuditedAttribute(Decl *D) {
    294   SourceLocation Loc = PP.getPragmaARCCFCodeAuditedLoc();
    295   if (!Loc.isValid()) return;
    296 
    297   // Don't add a redundant or conflicting attribute.
    298   if (D->hasAttr<CFAuditedTransferAttr>() ||
    299       D->hasAttr<CFUnknownTransferAttr>())
    300     return;
    301 
    302   D->addAttr(::new (Context) CFAuditedTransferAttr(Loc, Context));
    303 }
    304 
    305 typedef std::vector<std::pair<unsigned, SourceLocation> > VisStack;
    306 enum { NoVisibility = (unsigned) -1 };
    307 
    308 void Sema::AddPushedVisibilityAttribute(Decl *D) {
    309   if (!VisContext)
    310     return;
    311 
    312   NamedDecl *ND = dyn_cast<NamedDecl>(D);
    313   if (ND && ND->getExplicitVisibility(NamedDecl::VisibilityForValue))
    314     return;
    315 
    316   VisStack *Stack = static_cast<VisStack*>(VisContext);
    317   unsigned rawType = Stack->back().first;
    318   if (rawType == NoVisibility) return;
    319 
    320   VisibilityAttr::VisibilityType type
    321     = (VisibilityAttr::VisibilityType) rawType;
    322   SourceLocation loc = Stack->back().second;
    323 
    324   D->addAttr(::new (Context) VisibilityAttr(loc, Context, type));
    325 }
    326 
    327 /// FreeVisContext - Deallocate and null out VisContext.
    328 void Sema::FreeVisContext() {
    329   delete static_cast<VisStack*>(VisContext);
    330   VisContext = 0;
    331 }
    332 
    333 static void PushPragmaVisibility(Sema &S, unsigned type, SourceLocation loc) {
    334   // Put visibility on stack.
    335   if (!S.VisContext)
    336     S.VisContext = new VisStack;
    337 
    338   VisStack *Stack = static_cast<VisStack*>(S.VisContext);
    339   Stack->push_back(std::make_pair(type, loc));
    340 }
    341 
    342 void Sema::ActOnPragmaVisibility(const IdentifierInfo* VisType,
    343                                  SourceLocation PragmaLoc) {
    344   if (VisType) {
    345     // Compute visibility to use.
    346     VisibilityAttr::VisibilityType type;
    347     if (VisType->isStr("default"))
    348       type = VisibilityAttr::Default;
    349     else if (VisType->isStr("hidden"))
    350       type = VisibilityAttr::Hidden;
    351     else if (VisType->isStr("internal"))
    352       type = VisibilityAttr::Hidden; // FIXME
    353     else if (VisType->isStr("protected"))
    354       type = VisibilityAttr::Protected;
    355     else {
    356       Diag(PragmaLoc, diag::warn_attribute_unknown_visibility) <<
    357         VisType->getName();
    358       return;
    359     }
    360     PushPragmaVisibility(*this, type, PragmaLoc);
    361   } else {
    362     PopPragmaVisibility(false, PragmaLoc);
    363   }
    364 }
    365 
    366 void Sema::ActOnPragmaFPContract(tok::OnOffSwitch OOS) {
    367   switch (OOS) {
    368   case tok::OOS_ON:
    369     FPFeatures.fp_contract = 1;
    370     break;
    371   case tok::OOS_OFF:
    372     FPFeatures.fp_contract = 0;
    373     break;
    374   case tok::OOS_DEFAULT:
    375     FPFeatures.fp_contract = getLangOpts().DefaultFPContract;
    376     break;
    377   }
    378 }
    379 
    380 void Sema::PushNamespaceVisibilityAttr(const VisibilityAttr *Attr,
    381                                        SourceLocation Loc) {
    382   // Visibility calculations will consider the namespace's visibility.
    383   // Here we just want to note that we're in a visibility context
    384   // which overrides any enclosing #pragma context, but doesn't itself
    385   // contribute visibility.
    386   PushPragmaVisibility(*this, NoVisibility, Loc);
    387 }
    388 
    389 void Sema::PopPragmaVisibility(bool IsNamespaceEnd, SourceLocation EndLoc) {
    390   if (!VisContext) {
    391     Diag(EndLoc, diag::err_pragma_pop_visibility_mismatch);
    392     return;
    393   }
    394 
    395   // Pop visibility from stack
    396   VisStack *Stack = static_cast<VisStack*>(VisContext);
    397 
    398   const std::pair<unsigned, SourceLocation> *Back = &Stack->back();
    399   bool StartsWithPragma = Back->first != NoVisibility;
    400   if (StartsWithPragma && IsNamespaceEnd) {
    401     Diag(Back->second, diag::err_pragma_push_visibility_mismatch);
    402     Diag(EndLoc, diag::note_surrounding_namespace_ends_here);
    403 
    404     // For better error recovery, eat all pushes inside the namespace.
    405     do {
    406       Stack->pop_back();
    407       Back = &Stack->back();
    408       StartsWithPragma = Back->first != NoVisibility;
    409     } while (StartsWithPragma);
    410   } else if (!StartsWithPragma && !IsNamespaceEnd) {
    411     Diag(EndLoc, diag::err_pragma_pop_visibility_mismatch);
    412     Diag(Back->second, diag::note_surrounding_namespace_starts_here);
    413     return;
    414   }
    415 
    416   Stack->pop_back();
    417   // To simplify the implementation, never keep around an empty stack.
    418   if (Stack->empty())
    419     FreeVisContext();
    420 }
    421