Skip to content

Commit

Permalink
Merge pull request #3621 from masatake/cxx--typeof
Browse files Browse the repository at this point in the history
Cxx: support typeof and __typeof__ keywords of the gcc extension
  • Loading branch information
masatake committed Jan 8, 2023
2 parents dfdabb5 + 8a6c482 commit 129d7e2
Show file tree
Hide file tree
Showing 10 changed files with 122 additions and 11 deletions.
5 changes: 5 additions & 0 deletions Units/parser-c.r/macroexpand-typeof.d/args.ctags
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
--sort=no
--param-CPreProcessor._expand=true
--fields-C=+{macrodef}
--fields=+{signature}
--kinds-C=+x
5 changes: 5 additions & 0 deletions Units/parser-c.r/macroexpand-typeof.d/expected.tags
Original file line number Diff line number Diff line change
@@ -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)
14 changes: 14 additions & 0 deletions Units/parser-c.r/macroexpand-typeof.d/input.c
Original file line number Diff line number Diff line change
@@ -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)
2 changes: 2 additions & 0 deletions Units/parser-cxx.r/more-decltypes.d/args.ctags
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
--sort=no
--fields-C++={properties}
17 changes: 17 additions & 0 deletions Units/parser-cxx.r/more-decltypes.d/expected.tags
Original file line number Diff line number Diff line change
@@ -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
21 changes: 21 additions & 0 deletions Units/parser-cxx.r/more-decltypes.d/input.cxx
Original file line number Diff line number Diff line change
@@ -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;
27 changes: 25 additions & 2 deletions parsers/cxx/cxx_keyword.c
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -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,
Expand Down Expand Up @@ -250,7 +262,7 @@ static CXXKeywordDescriptor g_aCXXKeywordTable[] = {
{
"decltype",
CXXLanguageCPP,
CXXKeywordMayAppearInVariableDeclaration | CXXKeywordFlagMayBePartOfTypeName
CXXKeywordIsDecltype | CXXKeywordMayAppearInVariableDeclaration | CXXKeywordFlagMayBePartOfTypeName
},
{
"default",
Expand Down Expand Up @@ -518,6 +530,11 @@ static CXXKeywordDescriptor g_aCXXKeywordTable[] = {
CXXKeywordMayAppearInVariableDeclaration | CXXKeywordFlagMayBePartOfTypeName |
CXXKeywordIsTypeRefMarker
},
{
"typeof",
CXXLanguageC | CXXLanguageCPP,
CXXKeywordIsDecltype | CXXKeywordMayAppearInVariableDeclaration | CXXKeywordFlagMayBePartOfTypeName
},
{
"union",
CXXLanguageC | CXXLanguageCPP | CXXLanguageCUDA,
Expand Down Expand Up @@ -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 =
Expand Down
4 changes: 4 additions & 0 deletions parsers/cxx/cxx_keyword.h
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand Down Expand Up @@ -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,
Expand All @@ -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);
Expand Down
26 changes: 19 additions & 7 deletions parsers/cxx/cxx_parser_variable.c
Original file line number Diff line number Diff line change
Expand Up @@ -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)
)
) &&
(
Expand All @@ -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;
}
Expand Down Expand Up @@ -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)
)
)
)
{
Expand Down
12 changes: 10 additions & 2 deletions parsers/cxx/cxx_token_chain.c
Original file line number Diff line number Diff line change
Expand Up @@ -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 |
Expand Down

0 comments on commit 129d7e2

Please sign in to comment.