зеркало из https://github.com/microsoft/clang-1.git
Add Sema implementation of #pragma pack stack.
- Follows the MSVC (original) implementation, including support of pack(show) (useful for testing). - Implements support for named pack records which gcc seems to ignore (or implements incorrectly). - Not currently wired to anything, only functionality change is the type checking of the pragma. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@57476 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
Родитель
e15fa27364
Коммит
4cde927072
|
@ -571,6 +571,16 @@ DIAG(warn_pragma_pack_invalid_constant, WARNING,
|
|||
"invalid constant for '#pragma pack', expected %0 - ignored")
|
||||
DIAG(warn_pragma_pack_malformed, WARNING,
|
||||
"malformed '#pragma pack', expected '#pragma pack(%0 [, id] [, n])' - ignored")
|
||||
// Follow the MSVC implementation.
|
||||
DIAG(warn_pragma_pack_show, WARNING,
|
||||
"value of #pragma pack(show) == %0")
|
||||
// FIXME: Dehardcode.
|
||||
DIAG(warn_pragma_pack_invalid_alignment, WARNING,
|
||||
"expected #pragma pack parameter to be '1', '2', '4', '8', or '16'")
|
||||
DIAG(warn_pragma_pack_pop_identifer_and_alignment, WARNING,
|
||||
"specifying both a name and alignment to pragma pack(pop, ...) is undefined")
|
||||
DIAG(warn_pragma_pack_pop_failed, WARNING,
|
||||
"#pragma pack(pop, ...) failed: %0")
|
||||
|
||||
//===----------------------------------------------------------------------===//
|
||||
// Semantic Analysis
|
||||
|
|
|
@ -82,7 +82,7 @@ void Sema::ActOnTranslationUnitScope(SourceLocation Loc, Scope *S) {
|
|||
|
||||
Sema::Sema(Preprocessor &pp, ASTContext &ctxt, ASTConsumer &consumer)
|
||||
: PP(pp), Context(ctxt), Consumer(consumer), CurContext(0), CurBlock(0),
|
||||
IdResolver(pp.getLangOptions()) {
|
||||
PackContext(0), IdResolver(pp.getLangOptions()) {
|
||||
|
||||
// Get IdentifierInfo objects for known functions for which we
|
||||
// do extra checking.
|
||||
|
|
|
@ -66,6 +66,37 @@ namespace clang {
|
|||
class ObjCPropertyDecl;
|
||||
struct BlockSemaInfo;
|
||||
|
||||
/// PragmaPackStack - Simple class to wrap the stack used by #pragma
|
||||
/// pack.
|
||||
class PragmaPackStack {
|
||||
typedef std::vector< std::pair<unsigned, std::string> > stack_ty;
|
||||
|
||||
/// Alignment - The current user specified alignment.
|
||||
unsigned Alignment;
|
||||
|
||||
/// Stack - Entries in the #pragma pack stack.
|
||||
stack_ty Stack;
|
||||
|
||||
public:
|
||||
PragmaPackStack(unsigned A) : Alignment(A) {}
|
||||
|
||||
void setAlignment(unsigned A) { Alignment = A; }
|
||||
unsigned getAlignment() { return Alignment; }
|
||||
|
||||
/// push - Push the current alignment onto the stack, optionally
|
||||
/// using the given \arg Name for the record, if non-zero,
|
||||
void push(IdentifierInfo *Name) {
|
||||
Stack.push_back(std::make_pair(Alignment,
|
||||
std::string(Name ? Name->getName() : "")));
|
||||
}
|
||||
|
||||
/// pop - Pop a record from the stack and restore the current
|
||||
/// alignment to the previous value. If \arg Name is non-zero then
|
||||
/// the first such named record is popped, otherwise the top record
|
||||
/// is popped. Returns true if the pop succeeded.
|
||||
bool pop(IdentifierInfo *Name);
|
||||
};
|
||||
|
||||
/// Sema - This implements semantic analysis and AST building for C.
|
||||
class Sema : public Action {
|
||||
public:
|
||||
|
@ -80,6 +111,10 @@ public:
|
|||
/// the active block object that represents it.
|
||||
BlockSemaInfo *CurBlock;
|
||||
|
||||
/// PackContext - Manages the stack for #pragma pack. An alignment
|
||||
/// of 0 indicates default alignment.
|
||||
PragmaPackStack PackContext;
|
||||
|
||||
/// LabelMap - This is a mapping from label identifiers to the LabelStmt for
|
||||
/// it (which acts like the label decl in some ways). Forward referenced
|
||||
/// labels have a LabelStmt created for them with a null location & SubStmt.
|
||||
|
@ -809,6 +844,15 @@ public:
|
|||
ExprTy *receiver, Selector Sel,
|
||||
SourceLocation lbrac, SourceLocation rbrac,
|
||||
ExprTy **ArgExprs, unsigned NumArgs);
|
||||
|
||||
/// ActOnPragmaPack - Called on well formed #pragma pack(...).
|
||||
virtual void ActOnPragmaPack(PragmaPackKind Kind,
|
||||
IdentifierInfo *Name,
|
||||
ExprTy *Alignment,
|
||||
SourceLocation PragmaLoc,
|
||||
SourceLocation LParenLoc,
|
||||
SourceLocation RParenLoc);
|
||||
|
||||
private:
|
||||
/// ImpCastExprToType - If Expr is not of type 'Type', insert an implicit
|
||||
/// cast. If there is already an implicit cast, merge into the existing one.
|
||||
|
|
|
@ -25,6 +25,7 @@
|
|||
#include "clang/Lex/Preprocessor.h"
|
||||
#include "clang/Lex/HeaderSearch.h"
|
||||
#include "llvm/ADT/SmallSet.h"
|
||||
#include "llvm/ADT/StringExtras.h"
|
||||
using namespace clang;
|
||||
|
||||
Sema::TypeTy *Sema::isTypeName(const IdentifierInfo &II, Scope *S) {
|
||||
|
@ -2559,3 +2560,97 @@ Sema::DeclTy* Sema::ActOnLinkageSpec(SourceLocation Loc,
|
|||
// FIXME: Add all the various semantics of linkage specifications
|
||||
return LinkageSpecDecl::Create(Context, Loc, Language, dcl);
|
||||
}
|
||||
|
||||
void Sema::ActOnPragmaPack(PragmaPackKind Kind, IdentifierInfo *Name,
|
||||
ExprTy *alignment, SourceLocation PragmaLoc,
|
||||
SourceLocation LParenLoc, SourceLocation RParenLoc) {
|
||||
Expr *Alignment = static_cast<Expr *>(alignment);
|
||||
|
||||
// If specified then alignment must be a "small" power of two.
|
||||
unsigned AlignmentVal = 0;
|
||||
if (Alignment) {
|
||||
llvm::APSInt Val;
|
||||
if (!Alignment->isIntegerConstantExpr(Val, Context) ||
|
||||
!Val.isPowerOf2() ||
|
||||
Val.getZExtValue() > 16) {
|
||||
Diag(PragmaLoc, diag::warn_pragma_pack_invalid_alignment);
|
||||
delete Alignment;
|
||||
return; // Ignore
|
||||
}
|
||||
|
||||
AlignmentVal = (unsigned) Val.getZExtValue();
|
||||
}
|
||||
|
||||
switch (Kind) {
|
||||
case Action::PPK_Default: // pack([n])
|
||||
PackContext.setAlignment(AlignmentVal);
|
||||
break;
|
||||
|
||||
case Action::PPK_Show: // pack(show)
|
||||
// Show the current alignment, making sure to show the right value
|
||||
// for the default.
|
||||
AlignmentVal = PackContext.getAlignment();
|
||||
// FIXME: This should come from the target.
|
||||
if (AlignmentVal == 0)
|
||||
AlignmentVal = 8;
|
||||
Diag(PragmaLoc, diag::warn_pragma_pack_show, llvm::utostr(AlignmentVal));
|
||||
break;
|
||||
|
||||
case Action::PPK_Push: // pack(push [, id] [, [n])
|
||||
PackContext.push(Name);
|
||||
// Set the new alignment if specified.
|
||||
if (Alignment)
|
||||
PackContext.setAlignment(AlignmentVal);
|
||||
break;
|
||||
|
||||
case Action::PPK_Pop: // pack(pop [, id] [, n])
|
||||
// MSDN, C/C++ Preprocessor Reference > Pragma Directives > pack:
|
||||
// "#pragma pack(pop, identifier, n) is undefined"
|
||||
if (Alignment && Name)
|
||||
Diag(PragmaLoc, diag::warn_pragma_pack_pop_identifer_and_alignment);
|
||||
|
||||
// Do the pop.
|
||||
if (!PackContext.pop(Name)) {
|
||||
// If a name was specified then failure indicates the name
|
||||
// wasn't found. Otherwise failure indicates the stack was
|
||||
// empty.
|
||||
Diag(PragmaLoc, diag::warn_pragma_pack_pop_failed,
|
||||
Name ? "no record matching name" : "stack empty");
|
||||
|
||||
// FIXME: Warn about popping named records as MSVC does.
|
||||
} else {
|
||||
// Pop succeeded, set the new alignment if specified.
|
||||
if (Alignment)
|
||||
PackContext.setAlignment(AlignmentVal);
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
assert(0 && "Invalid #pragma pack kind.");
|
||||
}
|
||||
}
|
||||
|
||||
bool PragmaPackStack::pop(IdentifierInfo *Name) {
|
||||
if (Stack.empty())
|
||||
return false;
|
||||
|
||||
// If name is empty just pop top.
|
||||
if (!Name) {
|
||||
Alignment = Stack.back().first;
|
||||
Stack.pop_back();
|
||||
return true;
|
||||
}
|
||||
|
||||
// Otherwise, find the named record.
|
||||
for (unsigned i = Stack.size(); i != 0; ) {
|
||||
--i;
|
||||
if (strcmp(Stack[i].second.c_str(), Name->getName()) == 0) {
|
||||
// Found it, pop up to and including this record.
|
||||
Alignment = Stack[i].first;
|
||||
Stack.erase(Stack.begin() + i, Stack.end());
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
|
|
@ -0,0 +1,22 @@
|
|||
// RUN: clang -m -triple i686-apple-darwin9 -fsyntax-only -verify %s
|
||||
|
||||
/* expected-warning {{value of #pragma pack(show) == 8}} */ #pragma pack(show)
|
||||
/* expected-warning {{expected #pragma pack parameter to be}} */ #pragma pack(3)
|
||||
/* expected-warning {{value of #pragma pack(show) == 8}} */ #pragma pack(show)
|
||||
#pragma pack(4)
|
||||
/* expected-warning {{value of #pragma pack(show) == 4}} */ #pragma pack(show)
|
||||
#pragma pack() // resets to default
|
||||
/* expected-warning {{value of #pragma pack(show) == 8}} */ #pragma pack(show)
|
||||
#pragma pack(2)
|
||||
#pragma pack(push, eek, 16) // -> (eek, 2), 16
|
||||
/* expected-warning {{value of #pragma pack(show) == 16}} */ #pragma pack(show)
|
||||
#pragma pack(push) // -> (eek, 2), (, 2), 16
|
||||
/* expected-warning {{value of #pragma pack(show) == 16}} */ #pragma pack(show)
|
||||
#pragma pack(1)
|
||||
#pragma pack(push, 8) // -> (eek, 2), (, 2), (, 1), 8
|
||||
/* expected-warning {{value of #pragma pack(show) == 8}} */ #pragma pack(show)
|
||||
#pragma pack(pop) // -> (eek, 2), (,2), 1
|
||||
/* expected-warning {{value of #pragma pack(show) == 1}} */ #pragma pack(show)
|
||||
#pragma pack(pop, eek)
|
||||
/* expected-warning {{value of #pragma pack(show) == 2}} */ #pragma pack(show)
|
||||
/* expected-warning {{#pragma pack(pop, ...) failed: stack empty}} */ #pragma pack(pop)
|
Загрузка…
Ссылка в новой задаче