forked from OSchip/llvm-project
Handle "#pragma GCC visibility" in a few more places. Switch over "#pragma pack" to use the same handling that gcc does. Fixes <rdar://problem/10871094> and <rdar://problem/10893316>.
(Hopefully, common usage of these pragmas isn't irregular enough to break our current handling. Doug has ideas for a more crazy approach if necessary.) llvm-svn: 151307
This commit is contained in:
parent
6f298a6464
commit
ec52f92db3
|
@ -574,6 +574,11 @@ ANNOTATION(pragma_unused)
|
|||
// handles them.
|
||||
ANNOTATION(pragma_vis)
|
||||
|
||||
// Annotation for #pragma pack...
|
||||
// The lexer produces these so that they only take effect when the parser
|
||||
// handles them.
|
||||
ANNOTATION(pragma_pack)
|
||||
|
||||
#undef ANNOTATION
|
||||
#undef TESTING_KEYWORD
|
||||
#undef OBJC2_AT_KEYWORD
|
||||
|
|
|
@ -410,6 +410,10 @@ private:
|
|||
/// #pragma GCC visibility...
|
||||
void HandlePragmaVisibility();
|
||||
|
||||
/// \brief Handle the annotation token produced for
|
||||
/// #pragma pack...
|
||||
void HandlePragmaPack();
|
||||
|
||||
/// GetLookAheadToken - This peeks ahead N tokens and returns that token
|
||||
/// without consuming any tokens. LookAhead(0) returns 'Tok', LookAhead(1)
|
||||
/// returns the token after Tok, etc.
|
||||
|
|
|
@ -2251,6 +2251,16 @@ void Parser::ParseCXXMemberSpecification(SourceLocation RecordLoc,
|
|||
continue;
|
||||
}
|
||||
|
||||
if (Tok.is(tok::annot_pragma_vis)) {
|
||||
HandlePragmaVisibility();
|
||||
continue;
|
||||
}
|
||||
|
||||
if (Tok.is(tok::annot_pragma_pack)) {
|
||||
HandlePragmaPack();
|
||||
continue;
|
||||
}
|
||||
|
||||
AccessSpecifier AS = getAccessSpecifierIfPresent();
|
||||
if (AS != AS_none) {
|
||||
// Current token is a C++ access specifier.
|
||||
|
|
|
@ -37,6 +37,24 @@ void Parser::HandlePragmaVisibility() {
|
|||
Actions.ActOnPragmaVisibility(VisType, VisLoc);
|
||||
}
|
||||
|
||||
struct PragmaPackInfo {
|
||||
Sema::PragmaPackKind Kind;
|
||||
IdentifierInfo *Name;
|
||||
Expr *Alignment;
|
||||
SourceLocation LParenLoc;
|
||||
SourceLocation RParenLoc;
|
||||
};
|
||||
|
||||
void Parser::HandlePragmaPack() {
|
||||
assert(Tok.is(tok::annot_pragma_pack));
|
||||
PragmaPackInfo *Info =
|
||||
static_cast<PragmaPackInfo *>(Tok.getAnnotationValue());
|
||||
SourceLocation PragmaLoc = ConsumeToken();
|
||||
Actions.ActOnPragmaPack(Info->Kind, Info->Name, Info->Alignment, PragmaLoc,
|
||||
Info->LParenLoc, Info->RParenLoc);
|
||||
delete Info;
|
||||
}
|
||||
|
||||
// #pragma GCC visibility comes in two variants:
|
||||
// 'push' '(' [visibility] ')'
|
||||
// 'pop'
|
||||
|
@ -196,8 +214,20 @@ void PragmaPackHandler::HandlePragma(Preprocessor &PP,
|
|||
return;
|
||||
}
|
||||
|
||||
Actions.ActOnPragmaPack(Kind, Name, Alignment.release(), PackLoc,
|
||||
LParenLoc, RParenLoc);
|
||||
PragmaPackInfo *Info = new PragmaPackInfo;
|
||||
Info->Kind = Kind;
|
||||
Info->Name = Name;
|
||||
Info->Alignment = Alignment.release();
|
||||
Info->LParenLoc = LParenLoc;
|
||||
Info->RParenLoc = RParenLoc;
|
||||
|
||||
Token *Toks = new Token[1];
|
||||
Toks[0].startToken();
|
||||
Toks[0].setKind(tok::annot_pragma_pack);
|
||||
Toks[0].setLocation(PackLoc);
|
||||
Toks[0].setAnnotationValue(static_cast<void*>(Info));
|
||||
PP.EnterTokenStream(Toks, 1, /*DisableMacroExpansion=*/true,
|
||||
/*OwnsTokens=*/true);
|
||||
}
|
||||
|
||||
// #pragma ms_struct on
|
||||
|
|
|
@ -280,6 +280,14 @@ Retry:
|
|||
|
||||
case tok::kw___try:
|
||||
return ParseSEHTryBlock(attrs);
|
||||
|
||||
case tok::annot_pragma_vis:
|
||||
HandlePragmaVisibility();
|
||||
return StmtEmpty();
|
||||
|
||||
case tok::annot_pragma_pack:
|
||||
HandlePragmaPack();
|
||||
return StmtEmpty();
|
||||
}
|
||||
|
||||
// If we reached this code, the statement must end in a semicolon.
|
||||
|
|
|
@ -549,6 +549,9 @@ Parser::ParseExternalDeclaration(ParsedAttributesWithRange &attrs,
|
|||
case tok::annot_pragma_vis:
|
||||
HandlePragmaVisibility();
|
||||
return DeclGroupPtrTy();
|
||||
case tok::annot_pragma_pack:
|
||||
HandlePragmaPack();
|
||||
return DeclGroupPtrTy();
|
||||
case tok::semi:
|
||||
Diag(Tok, getLang().CPlusPlus0x ?
|
||||
diag::warn_cxx98_compat_top_level_semi : diag::ext_top_level_semi)
|
||||
|
|
|
@ -22,32 +22,32 @@ extern int a1[offsetof(struct s1, f1) == 2 ? 1 : -1];
|
|||
// Test scope of definition
|
||||
|
||||
#pragma pack(push, 2)
|
||||
struct s2_0 {
|
||||
#pragma pack(pop)
|
||||
struct s2_0 { // expected-error {{expected ';'}}
|
||||
#pragma pack(pop) // expected-error {{type name}} expected-error {{member name}} expected-warning {{type specifier}}
|
||||
char f0;
|
||||
int f1;
|
||||
};
|
||||
extern int a2_0[offsetof(struct s2_0, f1) == 2 ? 1 : -1];
|
||||
|
||||
struct s2_1 {
|
||||
char f0;
|
||||
#pragma pack(push, 2)
|
||||
int f1;
|
||||
#pragma pack(pop)
|
||||
char f0; // expected-error {{expected ';'}}
|
||||
#pragma pack(push, 2) // expected-error {{type name}} expected-error {{member name}} expected-warning {{type specifier}}
|
||||
int f1; // expected-error {{expected ';'}}
|
||||
#pragma pack(pop) // expected-error {{type name}} expected-error {{member name}} expected-warning {{type specifier}}
|
||||
};
|
||||
extern int a2_1[offsetof(struct s2_1, f1) == 4 ? 1 : -1];
|
||||
|
||||
struct s2_2 {
|
||||
char f0;
|
||||
int f1;
|
||||
#pragma pack(push, 2)
|
||||
int f1; // expected-error {{expected ';'}}
|
||||
#pragma pack(push, 2) // expected-error {{type name}} expected-error {{member name}} expected-warning {{type specifier}}
|
||||
};
|
||||
#pragma pack(pop)
|
||||
extern int a2_2[offsetof(struct s2_2, f1) == 4 ? 1 : -1];
|
||||
|
||||
struct s2_3 {
|
||||
char f0;
|
||||
#pragma pack(push, 2)
|
||||
char f0; // expected-error {{expected ';'}}
|
||||
#pragma pack(push, 2) // expected-error {{type name}} expected-error {{member name}} expected-warning {{type specifier}}
|
||||
struct s2_3_0 {
|
||||
#pragma pack(pop)
|
||||
int f0;
|
||||
|
@ -58,10 +58,10 @@ extern int a2_3[offsetof(struct s2_3, f1) == 2 ? 1 : -1];
|
|||
struct s2_4 {
|
||||
char f0;
|
||||
struct s2_4_0 {
|
||||
int f0;
|
||||
#pragma pack(push, 2)
|
||||
} f1;
|
||||
#pragma pack(pop)
|
||||
int f0; // expected-error {{expected ';'}}
|
||||
#pragma pack(push, 2) // expected-error {{type name}} expected-error {{member name}} expected-warning {{type specifier}}
|
||||
} f1; // expected-error {{expected ';'}}
|
||||
#pragma pack(pop) // expected-error {{type name}} expected-error {{member name}} expected-warning {{type specifier}}
|
||||
};
|
||||
extern int a2_4[offsetof(struct s2_4, f1) == 4 ? 1 : -1];
|
||||
|
||||
|
@ -91,3 +91,15 @@ struct s4_1 {
|
|||
};
|
||||
extern int a4_0[offsetof(struct s4_0, f1) == 1 ? 1 : -1];
|
||||
extern int a4_1[offsetof(struct s4_1, f1) == 4 ? 1 : -1];
|
||||
|
||||
void f() {
|
||||
#pragma pack(push, 2)
|
||||
struct s5_0 {
|
||||
char f0;
|
||||
struct s2_4_0 {
|
||||
int f0;
|
||||
} f1;
|
||||
};
|
||||
#pragma pack(pop)
|
||||
extern int s5_0[offsetof(struct s5_0, f1) == 2 ? 1 : -1];
|
||||
}
|
||||
|
|
|
@ -10,3 +10,14 @@ namespace test2 __attribute__((visibility("hidden"))) {
|
|||
} // expected-note{{surrounding namespace with visibility attribute ends here}}
|
||||
|
||||
#pragma GCC visibility pop // expected-error{{#pragma visibility pop with no matching #pragma visibility push}}
|
||||
|
||||
// <rdar://problem/10871094>
|
||||
struct A {
|
||||
#pragma GCC visibility push(protected)
|
||||
#pragma GCC visibility pop
|
||||
};
|
||||
|
||||
void f() {
|
||||
#pragma GCC visibility push(protected)
|
||||
#pragma GCC visibility pop
|
||||
}
|
||||
|
|
|
@ -0,0 +1,16 @@
|
|||
// RUN: %clang_cc1 -triple i686-apple-darwin9 -fsyntax-only -verify %s
|
||||
|
||||
// Make sure pragma pack works inside ObjC methods. <rdar://problem/10893316>
|
||||
@interface X
|
||||
@end
|
||||
@implementation X
|
||||
- (void)Y {
|
||||
#pragma pack(push, 1)
|
||||
struct x {
|
||||
char a;
|
||||
int b;
|
||||
};
|
||||
#pragma pack(pop)
|
||||
typedef char check_[sizeof (struct x) == 5 ? 1 : -1];
|
||||
}
|
||||
@end
|
Loading…
Reference in New Issue