Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Cxx: support typeof and __typeof__ keywords of the gcc extension #3621

Merged
merged 4 commits into from
Jan 8, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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