From: Steve Naroff Date: Thu, 25 Dec 2008 14:16:32 +0000 (+0000) Subject: Add parser support for __cdecl, __stdcall, and __fastcall. X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=239f07384fe5e7194e780d98a17553084efeeb44;p=clang Add parser support for __cdecl, __stdcall, and __fastcall. Change preprocessor implementation of _cdecl to reference __cdecl. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@61430 91177308-0d34-0410-b5e6-96231b3b80d8 --- diff --git a/include/clang/Basic/TokenKinds.def b/include/clang/Basic/TokenKinds.def index c0a448dfa7..686c1b5b2a 100644 --- a/include/clang/Basic/TokenKinds.def +++ b/include/clang/Basic/TokenKinds.def @@ -309,6 +309,9 @@ KEYWORD(__private_extern__ , EXTC90|EXTC99|NOTCPP) // Microsoft Extension. KEYWORD(__declspec , EXTC90|EXTC99|EXTCPP|EXTCPP0x) +KEYWORD(__cdecl , EXTC90|EXTC99|EXTCPP|EXTCPP0x) +KEYWORD(__stdcall , EXTC90|EXTC99|EXTCPP|EXTCPP0x) +KEYWORD(__fastcall , EXTC90|EXTC99|EXTCPP|EXTCPP0x) // Alternate spelling for various tokens. There are GCC extensions in all // languages, but should not be disabled in strict conformance mode. diff --git a/lib/Lex/Preprocessor.cpp b/lib/Lex/Preprocessor.cpp index 97ff07049f..e68a44c188 100644 --- a/lib/Lex/Preprocessor.cpp +++ b/lib/Lex/Preprocessor.cpp @@ -483,9 +483,7 @@ static void InitializePredefinedMacros(Preprocessor &PP, // Filter out some microsoft extensions when trying to parse in ms-compat // mode. if (PP.getLangOptions().Microsoft) { - DefineBuiltinMacro(Buf, "__stdcall="); - DefineBuiltinMacro(Buf, "__cdecl="); - DefineBuiltinMacro(Buf, "_cdecl="); + DefineBuiltinMacro(Buf, "_cdecl=__cdecl"); DefineBuiltinMacro(Buf, "__ptr64="); DefineBuiltinMacro(Buf, "__w64="); DefineBuiltinMacro(Buf, "__forceinline="); diff --git a/lib/Parse/ParseDecl.cpp b/lib/Parse/ParseDecl.cpp index a8052dc290..bf75ab0e93 100644 --- a/lib/Parse/ParseDecl.cpp +++ b/lib/Parse/ParseDecl.cpp @@ -560,6 +560,15 @@ void Parser::ParseDeclarationSpecifiers(DeclSpec &DS, FuzzyParseMicrosoftDeclSpec(); continue; + // Microsoft single token adornments. + case tok::kw___cdecl: + case tok::kw___stdcall: + case tok::kw___fastcall: + if (!PP.getLangOptions().Microsoft) + goto DoneWithDeclSpec; + // Just ignore it. + break; + // storage-class-specifier case tok::kw_typedef: isInvalid = DS.SetStorageClassSpec(DeclSpec::SCS_typedef, Loc, PrevSpec); @@ -798,6 +807,11 @@ bool Parser::MaybeParseTypeSpecifier(DeclSpec &DS, int& isInvalid, ParseTypeofSpecifier(DS); return true; + case tok::kw___cdecl: + case tok::kw___stdcall: + case tok::kw___fastcall: + return PP.getLangOptions().Microsoft; + default: // Not a type-specifier; do nothing. return false; @@ -1199,6 +1213,11 @@ bool Parser::isTypeSpecifierQualifier() { // GNU ObjC bizarre protocol extension: with implicit 'id'. case tok::less: return getLang().ObjC1; + + case tok::kw___cdecl: + case tok::kw___stdcall: + case tok::kw___fastcall: + return PP.getLangOptions().Microsoft; } } @@ -1268,6 +1287,11 @@ bool Parser::isDeclarationSpecifier() { // GNU ObjC bizarre protocol extension: with implicit 'id'. case tok::less: return getLang().ObjC1; + + case tok::kw___cdecl: + case tok::kw___stdcall: + case tok::kw___fastcall: + return PP.getLangOptions().Microsoft; } } @@ -1298,6 +1322,13 @@ void Parser::ParseTypeQualifierListOpt(DeclSpec &DS, bool AttributesAllowed) { isInvalid = DS.SetTypeQual(DeclSpec::TQ_restrict, Loc, PrevSpec, getLang())*2; break; + case tok::kw___cdecl: + case tok::kw___stdcall: + case tok::kw___fastcall: + if (!PP.getLangOptions().Microsoft) + goto DoneWithTypeQuals; + // Just ignore it. + break; case tok::kw___attribute: if (AttributesAllowed) { DS.AddAttributes(ParseAttributes()); @@ -1305,6 +1336,7 @@ void Parser::ParseTypeQualifierListOpt(DeclSpec &DS, bool AttributesAllowed) { } // otherwise, FALL THROUGH! default: + DoneWithTypeQuals: // If this is not a type-qualifier token, we're done reading type // qualifiers. First verify that DeclSpec's are consistent. DS.Finish(Diags, PP.getSourceManager(), getLang()); @@ -1632,6 +1664,10 @@ void Parser::ParseParenDeclarator(Declarator &D) { // present even if the attribute list was empty. RequiresArg = true; } + // Eat any Microsoft extensions. + if ((Tok.is(tok::kw___cdecl) || Tok.is(tok::kw___stdcall) || + (Tok.is(tok::kw___fastcall))) && PP.getLangOptions().Microsoft) + ConsumeToken(); // If we haven't past the identifier yet (or where the identifier would be // stored, if this is an abstract declarator), then this is probably just diff --git a/test/Parser/MicrosoftExtensions.c b/test/Parser/MicrosoftExtensions.c new file mode 100644 index 0000000000..dc26c57323 --- /dev/null +++ b/test/Parser/MicrosoftExtensions.c @@ -0,0 +1,8 @@ +// RUN: clang -fsyntax-only -verify -fms-extensions %s +__stdcall int func0(); +int __stdcall func(); +typedef int (__cdecl *tptr)(); +void (*__fastcall fastpfunc)(); +extern __declspec(dllimport) void __stdcall VarR4FromDec(); +__declspec(deprecated) __declspec(deprecated) char * __cdecl ltoa( long _Val, char * _DstBuf, int _Radix); +__declspec(noalias) __declspec(restrict) void * __cdecl xxx( void * _Memory );