ParsePragma.cpp revision 0e9eabca263e8922bec0e2b38c8670eba9a39a1f
1//===--- ParsePragma.cpp - Language specific pragma parsing ---------------===//
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 the language specific #pragma handlers.
11//
12//===----------------------------------------------------------------------===//
13
14#include "ParsePragma.h"
15#include "AstGuard.h"
16#include "clang/Basic/Diagnostic.h"
17#include "clang/Lex/Preprocessor.h"
18#include "clang/Parse/Action.h"
19using namespace clang;
20
21// #pragma pack(...) comes in the following delicious flavors:
22//   pack '(' [integer] ')'
23//   pack '(' 'show' ')'
24//   pack '(' ('push' | 'pop') [',' identifier] [, integer] ')'
25void PragmaPackHandler::HandlePragma(Preprocessor &PP, Token &PackTok) {
26  // FIXME: Should we be expanding macros here? My guess is no.
27  SourceLocation PackLoc = PackTok.getLocation();
28
29  Token Tok;
30  PP.Lex(Tok);
31  if (Tok.isNot(tok::l_paren)) {
32    PP.Diag(Tok.getLocation(), diag::warn_pragma_pack_expected_lparen);
33    return;
34  }
35
36  Action::PragmaPackKind Kind = Action::PPK_Default;
37  IdentifierInfo *Name = 0;
38  ExprOwner Alignment(Actions);
39  SourceLocation LParenLoc = Tok.getLocation();
40  PP.Lex(Tok);
41  if (Tok.is(tok::numeric_constant)) {
42    Alignment = Actions.ActOnNumericConstant(Tok);
43    if (Alignment.isInvalid())
44      return;
45
46    PP.Lex(Tok);
47  } else if (Tok.is(tok::identifier)) {
48    const IdentifierInfo *II = Tok.getIdentifierInfo();
49    if (II->isStr("show")) {
50      Kind = Action::PPK_Show;
51      PP.Lex(Tok);
52    } else {
53      if (II->isStr("push")) {
54        Kind = Action::PPK_Push;
55      } else if (II->isStr("pop")) {
56        Kind = Action::PPK_Pop;
57      } else {
58        PP.Diag(Tok.getLocation(), diag::warn_pragma_pack_invalid_action);
59        return;
60      }
61      PP.Lex(Tok);
62
63      if (Tok.is(tok::comma)) {
64        PP.Lex(Tok);
65
66        if (Tok.is(tok::numeric_constant)) {
67          Alignment = Actions.ActOnNumericConstant(Tok);
68          if (Alignment.isInvalid())
69            return;
70
71          PP.Lex(Tok);
72        } else if (Tok.is(tok::identifier)) {
73          Name = Tok.getIdentifierInfo();
74          PP.Lex(Tok);
75
76          if (Tok.is(tok::comma)) {
77            PP.Lex(Tok);
78
79            if (Tok.isNot(tok::numeric_constant)) {
80              PP.Diag(Tok.getLocation(), diag::warn_pragma_pack_malformed);
81              return;
82            }
83
84            Alignment = Actions.ActOnNumericConstant(Tok);
85            if (Alignment.isInvalid())
86              return;
87
88            PP.Lex(Tok);
89          }
90        } else {
91          PP.Diag(Tok.getLocation(), diag::warn_pragma_pack_malformed);
92          return;
93        }
94      }
95    }
96  }
97
98  if (Tok.isNot(tok::r_paren)) {
99    PP.Diag(Tok.getLocation(), diag::warn_pragma_pack_expected_rparen);
100    return;
101  }
102
103  SourceLocation RParenLoc = Tok.getLocation();
104  Actions.ActOnPragmaPack(Kind, Name, Alignment.move(), PackLoc,
105                          LParenLoc, RParenLoc);
106}
107
108