forked from OSchip/llvm-project
183 lines
5.4 KiB
C++
183 lines
5.4 KiB
C++
//===--- ParsePragma.cpp - Language specific pragma parsing ---------------===//
|
|
//
|
|
// The LLVM Compiler Infrastructure
|
|
//
|
|
// This file is distributed under the University of Illinois Open Source
|
|
// License. See LICENSE.TXT for details.
|
|
//
|
|
//===----------------------------------------------------------------------===//
|
|
//
|
|
// This file implements the language specific #pragma handlers.
|
|
//
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
#include "ParsePragma.h"
|
|
#include "clang/Parse/ParseDiagnostic.h"
|
|
#include "clang/Lex/Preprocessor.h"
|
|
#include "clang/Parse/Action.h"
|
|
#include "clang/Parse/Parser.h"
|
|
using namespace clang;
|
|
|
|
// #pragma pack(...) comes in the following delicious flavors:
|
|
// pack '(' [integer] ')'
|
|
// pack '(' 'show' ')'
|
|
// pack '(' ('push' | 'pop') [',' identifier] [, integer] ')'
|
|
void PragmaPackHandler::HandlePragma(Preprocessor &PP, Token &PackTok) {
|
|
// FIXME: Should we be expanding macros here? My guess is no.
|
|
SourceLocation PackLoc = PackTok.getLocation();
|
|
|
|
Token Tok;
|
|
PP.Lex(Tok);
|
|
if (Tok.isNot(tok::l_paren)) {
|
|
PP.Diag(Tok.getLocation(), diag::warn_pragma_expected_lparen) << "pack";
|
|
return;
|
|
}
|
|
|
|
Action::PragmaPackKind Kind = Action::PPK_Default;
|
|
IdentifierInfo *Name = 0;
|
|
Action::OwningExprResult Alignment(Actions);
|
|
SourceLocation LParenLoc = Tok.getLocation();
|
|
PP.Lex(Tok);
|
|
if (Tok.is(tok::numeric_constant)) {
|
|
Alignment = Actions.ActOnNumericConstant(Tok);
|
|
if (Alignment.isInvalid())
|
|
return;
|
|
|
|
PP.Lex(Tok);
|
|
} else if (Tok.is(tok::identifier)) {
|
|
const IdentifierInfo *II = Tok.getIdentifierInfo();
|
|
if (II->isStr("show")) {
|
|
Kind = Action::PPK_Show;
|
|
PP.Lex(Tok);
|
|
} else {
|
|
if (II->isStr("push")) {
|
|
Kind = Action::PPK_Push;
|
|
} else if (II->isStr("pop")) {
|
|
Kind = Action::PPK_Pop;
|
|
} else {
|
|
PP.Diag(Tok.getLocation(), diag::warn_pragma_pack_invalid_action);
|
|
return;
|
|
}
|
|
PP.Lex(Tok);
|
|
|
|
if (Tok.is(tok::comma)) {
|
|
PP.Lex(Tok);
|
|
|
|
if (Tok.is(tok::numeric_constant)) {
|
|
Alignment = Actions.ActOnNumericConstant(Tok);
|
|
if (Alignment.isInvalid())
|
|
return;
|
|
|
|
PP.Lex(Tok);
|
|
} else if (Tok.is(tok::identifier)) {
|
|
Name = Tok.getIdentifierInfo();
|
|
PP.Lex(Tok);
|
|
|
|
if (Tok.is(tok::comma)) {
|
|
PP.Lex(Tok);
|
|
|
|
if (Tok.isNot(tok::numeric_constant)) {
|
|
PP.Diag(Tok.getLocation(), diag::warn_pragma_pack_malformed);
|
|
return;
|
|
}
|
|
|
|
Alignment = Actions.ActOnNumericConstant(Tok);
|
|
if (Alignment.isInvalid())
|
|
return;
|
|
|
|
PP.Lex(Tok);
|
|
}
|
|
} else {
|
|
PP.Diag(Tok.getLocation(), diag::warn_pragma_pack_malformed);
|
|
return;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
if (Tok.isNot(tok::r_paren)) {
|
|
PP.Diag(Tok.getLocation(), diag::warn_pragma_expected_rparen) << "pack";
|
|
return;
|
|
}
|
|
|
|
SourceLocation RParenLoc = Tok.getLocation();
|
|
Actions.ActOnPragmaPack(Kind, Name, Alignment.release(), PackLoc,
|
|
LParenLoc, RParenLoc);
|
|
}
|
|
|
|
// #pragma unused(identifier)
|
|
void PragmaUnusedHandler::HandlePragma(Preprocessor &PP, Token &UnusedTok) {
|
|
// FIXME: Should we be expanding macros here? My guess is no.
|
|
SourceLocation UnusedLoc = UnusedTok.getLocation();
|
|
|
|
// Lex the left '('.
|
|
Token Tok;
|
|
PP.Lex(Tok);
|
|
if (Tok.isNot(tok::l_paren)) {
|
|
PP.Diag(Tok.getLocation(), diag::warn_pragma_expected_lparen) << "unused";
|
|
return;
|
|
}
|
|
SourceLocation LParenLoc = Tok.getLocation();
|
|
|
|
// Lex the declaration reference(s).
|
|
llvm::SmallVector<Action::ExprTy*, 5> Ex;
|
|
SourceLocation RParenLoc;
|
|
bool LexID = true;
|
|
|
|
while (true) {
|
|
PP.Lex(Tok);
|
|
|
|
if (LexID) {
|
|
if (Tok.is(tok::identifier)) {
|
|
Action::OwningExprResult Name =
|
|
Actions.ActOnIdentifierExpr(parser.CurScope, Tok.getLocation(),
|
|
*Tok.getIdentifierInfo(), false);
|
|
|
|
if (Name.isInvalid()) {
|
|
if (!Ex.empty())
|
|
Action::MultiExprArg Release(Actions, &Ex[0], Ex.size());
|
|
return;
|
|
}
|
|
|
|
Ex.push_back(Name.release());
|
|
LexID = false;
|
|
continue;
|
|
}
|
|
|
|
// Illegal token! Release the parsed expressions (if any) and emit
|
|
// a warning.
|
|
if (!Ex.empty())
|
|
Action::MultiExprArg Release(Actions, &Ex[0], Ex.size());
|
|
|
|
PP.Diag(Tok.getLocation(), diag::warn_pragma_unused_expected_var);
|
|
return;
|
|
}
|
|
|
|
// We are execting a ')' or a ','.
|
|
if (Tok.is(tok::comma)) {
|
|
LexID = true;
|
|
continue;
|
|
}
|
|
|
|
if (Tok.is(tok::r_paren)) {
|
|
RParenLoc = Tok.getLocation();
|
|
break;
|
|
}
|
|
|
|
// Illegal token! Release the parsed expressions (if any) and emit
|
|
// a warning.
|
|
if (!Ex.empty())
|
|
Action::MultiExprArg Release(Actions, &Ex[0], Ex.size());
|
|
|
|
PP.Diag(Tok.getLocation(), diag::warn_pragma_unused_expected_punc);
|
|
return;
|
|
}
|
|
|
|
// Verify that we have a location for the right parenthesis.
|
|
assert(RParenLoc.isValid() && "Valid '#pragma unused' must have ')'");
|
|
assert(!Ex.empty() && "Valid '#pragma unused' must have arguments");
|
|
|
|
// Perform the action to handle the pragma.
|
|
Actions.ActOnPragmaUnused(&Ex[0], Ex.size(), UnusedLoc, LParenLoc, RParenLoc);
|
|
}
|