diff --git a/Units/parser-c.r/macroexpand-typeof.d/args.ctags b/Units/parser-c.r/macroexpand-typeof.d/args.ctags new file mode 100644 index 0000000000..753ac8a04f --- /dev/null +++ b/Units/parser-c.r/macroexpand-typeof.d/args.ctags @@ -0,0 +1,5 @@ +--sort=no +--param-CPreProcessor._expand=true +--fields-C=+{macrodef} +--fields=+{signature} +--kinds-C=+x diff --git a/Units/parser-c.r/macroexpand-typeof.d/expected.tags b/Units/parser-c.r/macroexpand-typeof.d/expected.tags new file mode 100644 index 0000000000..04be048204 --- /dev/null +++ b/Units/parser-c.r/macroexpand-typeof.d/expected.tags @@ -0,0 +1,5 @@ +__attribute_copy__ input.c /^# define __attribute_copy__(/;" d file: signature:(arg) macrodef:__attribute__ ((__copy__ (arg))) +weak_alias input.c /^# define weak_alias(name, aliasname) _weak_alias /;" d file: signature:(name,aliasname) macrodef:_weak_alias (name, aliasname) +_weak_alias input.c /^# define _weak_alias(/;" d file: signature:(name,aliasname) macrodef:extern __typeof (name) aliasname __attribute__ ((weak, alias (#name))) __attribute_copy__ (name); +__brk input.c /^__brk (void *addr)$/;" f typeref:typename:int signature:(void * addr) +brk input.c /^weak_alias (__brk, brk)$/;" x typeref:typename:__typeof(__brk) diff --git a/Units/parser-c.r/macroexpand-typeof.d/input.c b/Units/parser-c.r/macroexpand-typeof.d/input.c new file mode 100644 index 0000000000..320ecd6f8a --- /dev/null +++ b/Units/parser-c.r/macroexpand-typeof.d/input.c @@ -0,0 +1,14 @@ +// Derrived from glibc +# define __attribute_copy__(arg) __attribute__ ((__copy__ (arg))) +# define weak_alias(name, aliasname) _weak_alias (name, aliasname) +# define _weak_alias(name, aliasname) \ + extern __typeof (name) aliasname __attribute__ ((weak, alias (#name))) \ + __attribute_copy__ (name); + +int +__brk (void *addr) +{ + /* ... */ + return 0; +} +weak_alias (__brk, brk) diff --git a/Units/parser-cxx.r/more-decltypes.d/args.ctags b/Units/parser-cxx.r/more-decltypes.d/args.ctags new file mode 100644 index 0000000000..429cff8069 --- /dev/null +++ b/Units/parser-cxx.r/more-decltypes.d/args.ctags @@ -0,0 +1,2 @@ +--sort=no +--fields-C++={properties} diff --git a/Units/parser-cxx.r/more-decltypes.d/expected.tags b/Units/parser-cxx.r/more-decltypes.d/expected.tags new file mode 100644 index 0000000000..aa77c7a7f6 --- /dev/null +++ b/Units/parser-cxx.r/more-decltypes.d/expected.tags @@ -0,0 +1,17 @@ +a input.cxx /^int a;$/;" v typeref:typename:int +b input.cxx /^decltype(a) b;$/;" v typeref:typename:decltype(a) +c input.cxx /^typeof(a) c;$/;" v typeref:typename:typeof(a) +d input.cxx /^__typeof__(a) d;$/;" v typeref:typename:__typeof__(a) +d0 input.cxx /^__typeof(a) d0;$/;" v typeref:typename:__typeof(a) +e input.cxx /^decltype(a) const e = 1;$/;" v typeref:typename:decltype(a) const +f input.cxx /^typeof(a) const f = 2;$/;" v typeref:typename:typeof(a) const +g input.cxx /^__typeof__(a) const g = 3;$/;" v typeref:typename:__typeof__(a) const +g0 input.cxx /^__typeof(a) const g0 = 3;$/;" v typeref:typename:__typeof(a) const +h input.cxx /^static decltype(a) const h = 4;$/;" v typeref:typename:decltype(a) const file: properties:static +i input.cxx /^static typeof(a) const i = 5;$/;" v typeref:typename:typeof(a) const file: properties:static +j input.cxx /^static __typeof__(a) const j = 6;$/;" v typeref:typename:__typeof__(a) const file: properties:static +j0 input.cxx /^static __typeof(a) const j0 = 6;$/;" v typeref:typename:__typeof(a) const file: properties:static +k input.cxx /^static const decltype(a) k = 7;$/;" v typeref:typename:const decltype(a) file: properties:static +l input.cxx /^static const typeof(a) l = 8;$/;" v typeref:typename:const typeof(a) file: properties:static +m input.cxx /^static const __typeof__(a) m = 9;$/;" v typeref:typename:const __typeof__(a) file: properties:static +m0 input.cxx /^static const __typeof(a) m0 = 10;$/;" v typeref:typename:const __typeof(a) file: properties:static diff --git a/Units/parser-cxx.r/more-decltypes.d/input.cxx b/Units/parser-cxx.r/more-decltypes.d/input.cxx new file mode 100644 index 0000000000..b99ddee0aa --- /dev/null +++ b/Units/parser-cxx.r/more-decltypes.d/input.cxx @@ -0,0 +1,21 @@ +int a; + +decltype(a) b; +typeof(a) c; +__typeof__(a) d; +__typeof(a) d0; + +decltype(a) const e = 1; +typeof(a) const f = 2; +__typeof__(a) const g = 3; +__typeof(a) const g0 = 3; + +static decltype(a) const h = 4; +static typeof(a) const i = 5; +static __typeof__(a) const j = 6; +static __typeof(a) const j0 = 6; + +static const decltype(a) k = 7; +static const typeof(a) l = 8; +static const __typeof__(a) m = 9; +static const __typeof(a) m0 = 10; diff --git a/parsers/cxx/cxx_keyword.c b/parsers/cxx/cxx_keyword.c index 0e34c24919..be17fc6581 100644 --- a/parsers/cxx/cxx_keyword.c +++ b/parsers/cxx/cxx_keyword.c @@ -34,7 +34,9 @@ enum CXXKeywordFlag // of the type itself. Keywords that do NOT have this flag simply cannot appear // in a variable declaration. // Examples: __global__, __host__, restrict, register... - CXXKeywordMayAppearInVariableDeclaration = (1 << 5) + CXXKeywordMayAppearInVariableDeclaration = (1 << 5), + // decltype, __typeof, __typeof__, and typeof + CXXKeywordIsDecltype = (1 << 6), }; typedef struct _CXXKeywordDescriptor @@ -141,6 +143,16 @@ static CXXKeywordDescriptor g_aCXXKeywordTable[] = { CXXLanguageC | CXXLanguageCPP, CXXKeywordMayAppearInVariableDeclaration | CXXKeywordExcludeFromTypeNames, }, + { + "__typeof", + CXXLanguageC | CXXLanguageCPP, + CXXKeywordIsDecltype | CXXKeywordMayAppearInVariableDeclaration | CXXKeywordFlagMayBePartOfTypeName + }, + { + "__typeof__", + CXXLanguageC | CXXLanguageCPP, + CXXKeywordIsDecltype | CXXKeywordMayAppearInVariableDeclaration | CXXKeywordFlagMayBePartOfTypeName + }, { "_Thread_local", CXXLanguageC, @@ -250,7 +262,7 @@ static CXXKeywordDescriptor g_aCXXKeywordTable[] = { { "decltype", CXXLanguageCPP, - CXXKeywordMayAppearInVariableDeclaration | CXXKeywordFlagMayBePartOfTypeName + CXXKeywordIsDecltype | CXXKeywordMayAppearInVariableDeclaration | CXXKeywordFlagMayBePartOfTypeName }, { "default", @@ -518,6 +530,11 @@ static CXXKeywordDescriptor g_aCXXKeywordTable[] = { CXXKeywordMayAppearInVariableDeclaration | CXXKeywordFlagMayBePartOfTypeName | CXXKeywordIsTypeRefMarker }, + { + "typeof", + CXXLanguageC | CXXLanguageCPP, + CXXKeywordIsDecltype | CXXKeywordMayAppearInVariableDeclaration | CXXKeywordFlagMayBePartOfTypeName + }, { "union", CXXLanguageC | CXXLanguageCPP | CXXLanguageCUDA, @@ -609,6 +626,12 @@ bool cxxKeywordIsDisabled(CXXKeyword eKeywordId) CXXKeywordIsDisabled; } +bool cxxKeywordIsDecltype(CXXKeyword eKeywordId) +{ + return g_aCXXKeywordTable[eKeywordId].uFlags & + CXXKeywordIsDecltype; +} + bool cxxKeywordEnablePublicProtectedPrivate(bool bEnableIt) { bool bEnabledNow = diff --git a/parsers/cxx/cxx_keyword.h b/parsers/cxx/cxx_keyword.h index c8697e7801..ad1440f275 100644 --- a/parsers/cxx/cxx_keyword.h +++ b/parsers/cxx/cxx_keyword.h @@ -34,6 +34,8 @@ typedef enum _CXXKeyword CXXKeyword__STDCALL, // Microsoft C/C++ CXXKeyword__THISCALL, // Microsoft C/C++ CXXKeyword__THREAD, // GCC (https://gcc.gnu.org/onlinedocs/gcc-3.3.1/gcc/Thread-Local.html#Thread-Local) + CXXKeyword__TYPEOF, // GCC accepts this. + CXXKeyword__TYPEOF__, // GCC (https://gcc.gnu.org/onlinedocs/gcc-3.3.1/gcc/Typeof.html#Typeof) CXXKeyword_THREAD_LOCAL, // C11 CXXKeywordALIGNAS, // (since C++11) CXXKeywordALIGNOF, // (since C++11) @@ -116,6 +118,7 @@ typedef enum _CXXKeyword CXXKeywordTYPEDEF, CXXKeywordTYPEID, CXXKeywordTYPENAME, + CXXKeywordTYPEOF, // GCC (https://gcc.gnu.org/onlinedocs/gcc-3.3.1/gcc/Typeof.html#Typeof) CXXKeywordUNION, CXXKeywordUNSIGNED, CXXKeywordUSING, @@ -135,6 +138,7 @@ bool cxxKeywordIsTypeRefMarker(CXXKeyword eKeywordId); bool cxxKeywordExcludeFromTypeNames(CXXKeyword eKeywordId); bool cxxKeywordMayAppearInVariableDeclaration(CXXKeyword eKeywordId); bool cxxKeywordIsCPPSpecific(CXXKeyword eKeywordId); +bool cxxKeywordIsDecltype(CXXKeyword eKeywordId); const char * cxxKeywordName(CXXKeyword eKeywordId); diff --git a/parsers/cxx/cxx_parser_variable.c b/parsers/cxx/cxx_parser_variable.c index e9a5183391..c63476cdad 100644 --- a/parsers/cxx/cxx_parser_variable.c +++ b/parsers/cxx/cxx_parser_variable.c @@ -339,7 +339,7 @@ bool cxxParserExtractVariableDeclarations(CXXTokenChain * pChain,unsigned int uF cxxTokenTypeIs(t->pPrev,CXXTokenTypeKeyword) && cxxKeywordMayBePartOfTypeName(t->pPrev->eKeyword) && // but not decltype(var)! - (t->pPrev->eKeyword != CXXKeywordDECLTYPE) + !cxxKeywordIsDecltype(t->pPrev->eKeyword) ) ) && ( @@ -348,19 +348,20 @@ bool cxxParserExtractVariableDeclarations(CXXTokenChain * pChain,unsigned int uF ) ) { - CXX_DEBUG_LEAVE_TEXT("Parenthesis seems to surround a variable definition"); + CXX_DEBUG_PRINT("Parenthesis seems to surround a variable definition"); pTokenBefore = t->pPrev; t = t->pNext; goto got_identifier; } if( - cxxTokenIsKeyword(t->pPrev,CXXKeywordDECLTYPE) && + cxxTokenTypeIs(t->pPrev,CXXTokenTypeKeyword) && + cxxKeywordIsDecltype(t->pPrev->eKeyword) && t->pNext ) { // part of typename -> skip ahead - CXX_DEBUG_LEAVE_TEXT("Parenthesis follows decltype(), skipping"); + CXX_DEBUG_PRINT("Parenthesis follows decltype(), skipping"); t = t->pNext; continue; } @@ -598,14 +599,25 @@ bool cxxParserExtractVariableDeclarations(CXXTokenChain * pChain,unsigned int uF // Possibly one of: // MACRO(whatever) variable; // decltype(whatever) variable; + // __typeof(whatever) variable; + // __typeof__(whatever) variable; + // typeof(whatever) variable; cxxTokenTypeIs(pTokenBefore,CXXTokenTypeParenthesisChain) && pTokenBefore->pPrev && - !pTokenBefore->pPrev->pPrev && + (!pTokenBefore->pPrev->pPrev || + ( + cxxTokenTypeIs(pTokenBefore->pPrev->pPrev,CXXTokenTypeKeyword) && + cxxKeywordMayAppearInVariableDeclaration(pTokenBefore->pPrev->pPrev->eKeyword) + ) + ) && ( // macro cxxTokenTypeIs(pTokenBefore->pPrev,CXXTokenTypeIdentifier) || - // decltype - cxxTokenIsKeyword(pTokenBefore->pPrev,CXXKeywordDECLTYPE) + // decltype or typeof + ( + cxxTokenTypeIs(pTokenBefore->pPrev,CXXTokenTypeKeyword) && + cxxKeywordIsDecltype(pTokenBefore->pPrev->eKeyword) + ) ) ) { diff --git a/parsers/cxx/cxx_token_chain.c b/parsers/cxx/cxx_token_chain.c index 0baac78841..dbeaaf0dda 100644 --- a/parsers/cxx/cxx_token_chain.c +++ b/parsers/cxx/cxx_token_chain.c @@ -1200,12 +1200,20 @@ void cxxTokenChainNormalizeTypeNameSpacingInRange(CXXToken * pFrom,CXXToken * pT CXXTokenTypeParenthesisChain | CXXTokenTypeSquareParenthesisChain )) { + // decltype(a) const + // -----------^ + // In this case, a space is needed. + bool bFollowedBySpace = ( + t->pPrev && + cxxTokenTypeIs(t->pPrev,CXXTokenTypeKeyword) && + cxxKeywordIsDecltype(t->pPrev->eKeyword) + ); cxxTokenChainNormalizeTypeNameSpacing(t->pChain); - t->bFollowedBySpace = false; + t->bFollowedBySpace = bFollowedBySpace; } else if(cxxTokenTypeIs(t,CXXTokenTypeKeyword)) { t->bFollowedBySpace = t->pNext && - (t->eKeyword != CXXKeywordDECLTYPE) && + (!cxxKeywordIsDecltype(t->eKeyword)) && cxxTokenTypeIsOneOf( t->pNext, CXXTokenTypeParenthesisChain | CXXTokenTypeIdentifier |