forked from OSchip/llvm-project
Implement -fms-extensions. This allows us to fuzzy parse non-standard MS constructs used in "windows.h".
llvm-svn: 46838
This commit is contained in:
parent
a56c08a2e4
commit
b2c80c7c7b
|
@ -309,6 +309,11 @@ static llvm::cl::opt<bool>
|
|||
PascalStrings("fpascal-strings",
|
||||
llvm::cl::desc("Recognize and construct Pascal-style "
|
||||
"string literals"));
|
||||
|
||||
static llvm::cl::opt<bool>
|
||||
MSExtensions("fms-extensions",
|
||||
llvm::cl::desc("Accept some non-standard constructs used in "
|
||||
"Microsoft header files. "));
|
||||
|
||||
static llvm::cl::opt<bool>
|
||||
WritableStrings("fwritable-strings",
|
||||
|
@ -376,6 +381,7 @@ static void InitializeLanguageStandard(LangOptions &Options, LangKind LK) {
|
|||
Options.Trigraphs = 1; // -trigraphs or -ansi
|
||||
Options.DollarIdents = 1; // FIXME: Really a target property.
|
||||
Options.PascalStrings = PascalStrings;
|
||||
Options.Microsoft = MSExtensions;
|
||||
Options.WritableStrings = WritableStrings;
|
||||
Options.LaxVectorConversions = LaxVectorConversions;
|
||||
}
|
||||
|
|
|
@ -424,7 +424,13 @@ static void InitializePredefinedMacros(Preprocessor &PP,
|
|||
DefineBuiltinMacro(Buf, "__cplusplus=1");
|
||||
DefineBuiltinMacro(Buf, "__private_extern__=extern");
|
||||
}
|
||||
|
||||
if (PP.getLangOptions().Microsoft) {
|
||||
DefineBuiltinMacro(Buf, "__stdcall=");
|
||||
DefineBuiltinMacro(Buf, "__cdecl=");
|
||||
DefineBuiltinMacro(Buf, "_cdecl=");
|
||||
DefineBuiltinMacro(Buf, "__ptr64=");
|
||||
DefineBuiltinMacro(Buf, "__forceinline=");
|
||||
}
|
||||
// FIXME: Should emit a #line directive here.
|
||||
}
|
||||
|
||||
|
|
|
@ -36,6 +36,48 @@ Parser::TypeTy *Parser::ParseTypeName() {
|
|||
return Actions.ActOnTypeName(CurScope, DeclaratorInfo).Val;
|
||||
}
|
||||
|
||||
/// FuzzyParseMicrosoftDeclspec. The following construct is Microsoft's
|
||||
/// equivalent of GCC's __attribute__. The grammar below is taken from
|
||||
/// Microsoft's website. Unfortunately, it is incomplete. FIXME: If/when we
|
||||
/// parse this for real, we will need to get a real/current grammar.
|
||||
///
|
||||
/// decl-specifier:
|
||||
/// '__declspec' '(' extended-decl-modifier-seq ')'
|
||||
///
|
||||
/// extended-decl-modifier-seq:
|
||||
/// extended-decl-modifier opt
|
||||
/// extended-decl-modifier extended-decl-modifier-seq
|
||||
///
|
||||
/// extended-decl-modifier:
|
||||
/// align( # )
|
||||
/// allocate(" segname ")
|
||||
/// appdomain
|
||||
/// deprecated
|
||||
/// dllimport
|
||||
/// dllexport
|
||||
/// jitintrinsic
|
||||
/// naked
|
||||
/// noalias
|
||||
/// noinline
|
||||
/// noreturn
|
||||
/// nothrow
|
||||
/// novtable
|
||||
/// process
|
||||
/// property({get=get_func_name|,put=put_func_name})
|
||||
/// restrict
|
||||
/// selectany
|
||||
/// thread
|
||||
/// uuid(" ComObjectGUID ")
|
||||
///
|
||||
void Parser::FuzzyParseMicrosoftDeclspec() {
|
||||
assert(Tok.is(tok::kw___declspec) && "Not an declspec!");
|
||||
ConsumeToken();
|
||||
do {
|
||||
ConsumeAnyToken();
|
||||
} while (ParenCount > 0 && Tok.isNot(tok::eof));
|
||||
return;
|
||||
}
|
||||
|
||||
/// ParseAttributes - Parse a non-empty attributes list.
|
||||
///
|
||||
/// [GNU] attributes:
|
||||
|
@ -441,6 +483,15 @@ void Parser::ParseDeclarationSpecifiers(DeclSpec &DS) {
|
|||
case tok::kw_typedef:
|
||||
isInvalid = DS.SetStorageClassSpec(DeclSpec::SCS_typedef, Loc, PrevSpec);
|
||||
break;
|
||||
case tok::kw___w64: // ignore Microsoft specifier
|
||||
break;
|
||||
case tok::kw___declspec:
|
||||
FuzzyParseMicrosoftDeclspec();
|
||||
// Don't consume the next token, __declspec's can appear one after
|
||||
// another. For example:
|
||||
// __declspec(deprecated("comment1"))
|
||||
// __declspec(deprecated("comment2")) extern unsigned int _winmajor;
|
||||
continue;
|
||||
case tok::kw_extern:
|
||||
if (DS.isThreadSpecified())
|
||||
Diag(Tok, diag::ext_thread_before, "extern");
|
||||
|
@ -465,9 +516,11 @@ void Parser::ParseDeclarationSpecifiers(DeclSpec &DS) {
|
|||
break;
|
||||
|
||||
// type-specifiers
|
||||
case tok::kw___int16:
|
||||
case tok::kw_short:
|
||||
isInvalid = DS.SetTypeSpecWidth(DeclSpec::TSW_short, Loc, PrevSpec);
|
||||
break;
|
||||
case tok::kw___int64:
|
||||
case tok::kw_long:
|
||||
if (DS.getTypeSpecWidth() != DeclSpec::TSW_long)
|
||||
isInvalid = DS.SetTypeSpecWidth(DeclSpec::TSW_long, Loc, PrevSpec);
|
||||
|
@ -489,9 +542,11 @@ void Parser::ParseDeclarationSpecifiers(DeclSpec &DS) {
|
|||
case tok::kw_void:
|
||||
isInvalid = DS.SetTypeSpecType(DeclSpec::TST_void, Loc, PrevSpec);
|
||||
break;
|
||||
case tok::kw___int8:
|
||||
case tok::kw_char:
|
||||
isInvalid = DS.SetTypeSpecType(DeclSpec::TST_char, Loc, PrevSpec);
|
||||
break;
|
||||
case tok::kw___int32:
|
||||
case tok::kw_int:
|
||||
isInvalid = DS.SetTypeSpecType(DeclSpec::TST_int, Loc, PrevSpec);
|
||||
break;
|
||||
|
@ -625,6 +680,9 @@ void Parser::ParseStructUnionSpecifier(DeclSpec &DS) {
|
|||
Tok.is(tok::kw_union) ? DeclSpec::TST_union : DeclSpec::TST_struct;
|
||||
SourceLocation StartLoc = ConsumeToken();
|
||||
|
||||
if (getLang().Microsoft && Tok.is(tok::kw___declspec))
|
||||
FuzzyParseMicrosoftDeclspec();
|
||||
|
||||
// Parse the tag portion of this.
|
||||
DeclTy *TagDecl;
|
||||
if (ParseTag(TagDecl, TagType, StartLoc))
|
||||
|
@ -671,7 +729,8 @@ void Parser::ParseStructDeclaration(DeclTy *TagDecl,
|
|||
|
||||
// If there are no declarators, issue a warning.
|
||||
if (Tok.is(tok::semi)) {
|
||||
Diag(SpecQualLoc, diag::w_no_declarators);
|
||||
if (!getLang().Microsoft) // MS allows unnamed struct/union fields.
|
||||
Diag(SpecQualLoc, diag::w_no_declarators);
|
||||
return;
|
||||
}
|
||||
|
||||
|
|
|
@ -153,7 +153,9 @@ Parser::StmtResult Parser::ParseStatementOrDeclaration(bool OnlyStatement) {
|
|||
break;
|
||||
|
||||
case tok::kw_asm:
|
||||
Res = ParseAsmStatement();
|
||||
bool msAsm = false;
|
||||
Res = ParseAsmStatement(msAsm);
|
||||
if (msAsm) return Res;
|
||||
SemiError = "asm statement";
|
||||
break;
|
||||
}
|
||||
|
@ -908,6 +910,14 @@ Parser::StmtResult Parser::ParseReturnStatement() {
|
|||
return Actions.ActOnReturnStmt(ReturnLoc, R.Val);
|
||||
}
|
||||
|
||||
Parser::StmtResult Parser::FuzzyParseMicrosoftAsmStatement() {
|
||||
unsigned short savedBraceCount = BraceCount;
|
||||
do {
|
||||
ConsumeAnyToken();
|
||||
} while (BraceCount > savedBraceCount && Tok.isNot(tok::eof));
|
||||
return false;
|
||||
}
|
||||
|
||||
/// ParseAsmStatement - Parse a GNU extended asm statement.
|
||||
/// [GNU] asm-statement:
|
||||
/// 'asm' type-qualifier[opt] '(' asm-argument ')' ';'
|
||||
|
@ -923,10 +933,14 @@ Parser::StmtResult Parser::ParseReturnStatement() {
|
|||
/// asm-string-literal
|
||||
/// asm-clobbers ',' asm-string-literal
|
||||
///
|
||||
Parser::StmtResult Parser::ParseAsmStatement() {
|
||||
Parser::StmtResult Parser::ParseAsmStatement(bool &msAsm) {
|
||||
assert(Tok.is(tok::kw_asm) && "Not an asm stmt");
|
||||
SourceLocation AsmLoc = ConsumeToken();
|
||||
|
||||
if (Tok.is(tok::l_brace)) {
|
||||
msAsm = true;
|
||||
return FuzzyParseMicrosoftAsmStatement();
|
||||
}
|
||||
DeclSpec DS;
|
||||
SourceLocation Loc = Tok.getLocation();
|
||||
ParseTypeQualifierListOpt(DS);
|
||||
|
|
|
@ -228,8 +228,9 @@ TypedefDecl *Sema::MergeTypeDefDecl(TypedefDecl *New, ScopedDecl *OldD) {
|
|||
DirectoryLookup::DirType OldDirType = HdrInfo.getFileDirFlavor(OldDeclFile);
|
||||
DirectoryLookup::DirType NewDirType = HdrInfo.getFileDirFlavor(NewDeclFile);
|
||||
|
||||
if (OldDirType == DirectoryLookup::ExternCSystemHeaderDir ||
|
||||
NewDirType == DirectoryLookup::ExternCSystemHeaderDir)
|
||||
if ((OldDirType == DirectoryLookup::ExternCSystemHeaderDir ||
|
||||
NewDirType == DirectoryLookup::ExternCSystemHeaderDir) ||
|
||||
getLangOptions().Microsoft)
|
||||
return New;
|
||||
|
||||
// TODO: CHECK FOR CONFLICTS, multiple decls with same name in one scope.
|
||||
|
|
|
@ -302,6 +302,14 @@ KEYWORD(__thread , EXTC90|EXTC99|EXTCPP|EXTCPP0x)
|
|||
// Apple Extension.
|
||||
KEYWORD(__private_extern__ , EXTC90|EXTC99|NOTCPP)
|
||||
|
||||
// Microsoft Extensions.
|
||||
KEYWORD(__w64 , EXTC90|EXTC99|NOTCPP)
|
||||
KEYWORD(__declspec , EXTC90|EXTC99|NOTCPP)
|
||||
KEYWORD(__int8 , EXTC90|EXTC99|NOTCPP)
|
||||
KEYWORD(__int16 , EXTC90|EXTC99|NOTCPP)
|
||||
KEYWORD(__int32 , EXTC90|EXTC99|NOTCPP)
|
||||
KEYWORD(__int64 , EXTC90|EXTC99|NOTCPP)
|
||||
|
||||
// Alternate spelling for various tokens. There are GCC extensions in all
|
||||
// languages, but should not be disabled in strict conformance mode.
|
||||
ALIAS("__attribute__", __attribute)
|
||||
|
|
|
@ -130,6 +130,8 @@ private:
|
|||
return ConsumeBracket();
|
||||
else if (isTokenBrace())
|
||||
return ConsumeBrace();
|
||||
else if (isTokenStringLiteral())
|
||||
return ConsumeStringToken();
|
||||
else
|
||||
return ConsumeToken();
|
||||
}
|
||||
|
@ -402,7 +404,8 @@ private:
|
|||
StmtResult ParseContinueStatement();
|
||||
StmtResult ParseBreakStatement();
|
||||
StmtResult ParseReturnStatement();
|
||||
StmtResult ParseAsmStatement();
|
||||
StmtResult ParseAsmStatement(bool &msAsm);
|
||||
StmtResult FuzzyParseMicrosoftAsmStatement();
|
||||
StmtResult ParseObjCAtStatement(SourceLocation atLoc);
|
||||
StmtResult ParseObjCTryStmt(SourceLocation atLoc, bool &processAtKeyword);
|
||||
StmtResult ParseObjCThrowStmt(SourceLocation atLoc);
|
||||
|
@ -438,6 +441,7 @@ private:
|
|||
bool isTypeSpecifierQualifier() const;
|
||||
|
||||
TypeTy *ParseTypeName();
|
||||
void FuzzyParseMicrosoftDeclspec();
|
||||
AttributeList *ParseAttributes();
|
||||
void ParseTypeofSpecifier(DeclSpec &DS);
|
||||
|
||||
|
|
Loading…
Reference in New Issue