blob: a3978ac32c372b9d7cb31e5e0ff8a5e9f25513bd [file] [log] [blame]
Chris Lattner5a0c3512009-02-17 00:57:29 +00001//===--- 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.
11//
12//===----------------------------------------------------------------------===//
13
14#include "Sema.h"
15#include "clang/AST/Expr.h"
16using namespace clang;
17
18void Sema::ActOnPragmaPack(PragmaPackKind Kind, IdentifierInfo *Name,
19 ExprTy *alignment, SourceLocation PragmaLoc,
20 SourceLocation LParenLoc, SourceLocation RParenLoc) {
21 Expr *Alignment = static_cast<Expr *>(alignment);
22
23 // If specified then alignment must be a "small" power of two.
24 unsigned AlignmentVal = 0;
25 if (Alignment) {
26 llvm::APSInt Val;
27 if (!Alignment->isIntegerConstantExpr(Val, Context) ||
28 !Val.isPowerOf2() ||
29 Val.getZExtValue() > 16) {
30 Diag(PragmaLoc, diag::warn_pragma_pack_invalid_alignment);
31 Alignment->Destroy(Context);
32 return; // Ignore
33 }
34
35 AlignmentVal = (unsigned) Val.getZExtValue();
36 }
37
38 switch (Kind) {
39 case Action::PPK_Default: // pack([n])
40 PackContext.setAlignment(AlignmentVal);
41 break;
42
43 case Action::PPK_Show: // pack(show)
44 // Show the current alignment, making sure to show the right value
45 // for the default.
46 AlignmentVal = PackContext.getAlignment();
47 // FIXME: This should come from the target.
48 if (AlignmentVal == 0)
49 AlignmentVal = 8;
50 Diag(PragmaLoc, diag::warn_pragma_pack_show) << AlignmentVal;
51 break;
52
53 case Action::PPK_Push: // pack(push [, id] [, [n])
54 PackContext.push(Name);
55 // Set the new alignment if specified.
56 if (Alignment)
57 PackContext.setAlignment(AlignmentVal);
58 break;
59
60 case Action::PPK_Pop: // pack(pop [, id] [, n])
61 // MSDN, C/C++ Preprocessor Reference > Pragma Directives > pack:
62 // "#pragma pack(pop, identifier, n) is undefined"
63 if (Alignment && Name)
64 Diag(PragmaLoc, diag::warn_pragma_pack_pop_identifer_and_alignment);
65
66 // Do the pop.
67 if (!PackContext.pop(Name)) {
68 // If a name was specified then failure indicates the name
69 // wasn't found. Otherwise failure indicates the stack was
70 // empty.
71 Diag(PragmaLoc, diag::warn_pragma_pack_pop_failed)
72 << (Name ? "no record matching name" : "stack empty");
73
74 // FIXME: Warn about popping named records as MSVC does.
75 } else {
76 // Pop succeeded, set the new alignment if specified.
77 if (Alignment)
78 PackContext.setAlignment(AlignmentVal);
79 }
80 break;
81
82 default:
83 assert(0 && "Invalid #pragma pack kind.");
84 }
85}
86
87bool PragmaPackStack::pop(IdentifierInfo *Name) {
88 if (Stack.empty())
89 return false;
90
91 // If name is empty just pop top.
92 if (!Name) {
93 Alignment = Stack.back().first;
94 Stack.pop_back();
95 return true;
96 }
97
98 // Otherwise, find the named record.
99 for (unsigned i = Stack.size(); i != 0; ) {
100 --i;
101 if (Stack[i].second == Name) {
102 // Found it, pop up to and including this record.
103 Alignment = Stack[i].first;
104 Stack.erase(Stack.begin() + i, Stack.end());
105 return true;
106 }
107 }
108
109 return false;
110}