Properly implement pointer types

- special DCD pointer symbols are actually inserted now
- they are implicitly dereferenced (max 1 deref) for member access
- index accessing them yields proper types (one pointer removed)
- they return standard type properties on pointer pointers
This commit is contained in:
WebFreak001 2023-03-16 04:45:20 +01:00 committed by Jan Jurzitza
parent 795ea87f80
commit 690d6254db
8 changed files with 113 additions and 23 deletions

View File

@ -40,6 +40,11 @@ TTree!(DSymbol*, SymbolsAllocator, true, "a < b") classSymbols;
*/
TTree!(DSymbol*, SymbolsAllocator, true, "a < b") enumSymbols;
/**
* Pointer properties (when not implicitly dereferencing)
*/
TTree!(DSymbol*, SymbolsAllocator, true, "a < b") pointerSymbols;
/**
* Variadic template parameters properties
*/
@ -191,6 +196,12 @@ static this()
aggregateSymbols.insert(stringof_);
aggregateSymbols.insert(init);
pointerSymbols.insert(mangleof_);
pointerSymbols.insert(alignof_);
pointerSymbols.insert(sizeof_);
pointerSymbols.insert(stringof_);
pointerSymbols.insert(init);
classSymbols.insert(makeSymbol("classinfo", CompletionKind.variableName));
classSymbols.insert(tupleof);
classSymbols.insert(makeSymbol("__vptr", CompletionKind.variableName));
@ -283,6 +294,7 @@ static ~this()
destroy(aggregateSymbols);
destroy(classSymbols);
destroy(enumSymbols);
destroy(pointerSymbols);
foreach (sym; symbolsMadeHere[])
destroy(*sym);

View File

@ -1129,9 +1129,7 @@ private:
foreach (suffix; type.typeSuffixes)
{
if (suffix.star != tok!"")
continue;
else if (suffix.type)
if (suffix.type)
lookup.breadcrumbs.insert(ASSOC_ARRAY_SYMBOL_NAME);
else if (suffix.array)
lookup.breadcrumbs.insert(ARRAY_SYMBOL_NAME);

View File

@ -180,29 +180,30 @@ do
while (!lookup.breadcrumbs.empty)
{
auto back = lookup.breadcrumbs.back;
immutable bool isArr = back == ARRAY_SYMBOL_NAME;
immutable bool isAssoc = back == ASSOC_ARRAY_SYMBOL_NAME;
immutable bool isFunction = back == FUNCTION_SYMBOL_NAME;
if (back == POINTER_SYMBOL_NAME)
{
lastSuffix.isPointer = true;
lookup.breadcrumbs.popBack();
continue;
}
if (!isArr && !isAssoc && !isFunction)
break;
immutable qualifier = isAssoc ? SymbolQualifier.assocArray
: (isFunction ? SymbolQualifier.func : SymbolQualifier.array);
SymbolQualifier qualifier;
if (back == ARRAY_SYMBOL_NAME) qualifier = SymbolQualifier.array;
else if (back == ASSOC_ARRAY_SYMBOL_NAME) qualifier = SymbolQualifier.assocArray;
else if (back == FUNCTION_SYMBOL_NAME) qualifier = SymbolQualifier.func;
else if (back == POINTER_SYMBOL_NAME) qualifier = SymbolQualifier.pointer;
else break;
lastSuffix = GCAllocator.instance.make!DSymbol(back, CompletionKind.dummy, lastSuffix);
lastSuffix.qualifier = qualifier;
lastSuffix.ownType = true;
if (isFunction)
final switch (qualifier)
{
case SymbolQualifier.none:
case SymbolQualifier.selectiveImport:
assert(false, "this should never be generated");
case SymbolQualifier.func:
lookup.breadcrumbs.popBack();
lastSuffix.callTip = lookup.breadcrumbs.back();
break;
case SymbolQualifier.array: lastSuffix.addChildren(arraySymbols[], false); break;
case SymbolQualifier.assocArray: lastSuffix.addChildren(assocArraySymbols[], false); break;
case SymbolQualifier.pointer: lastSuffix.addChildren(pointerSymbols[], false); break;
}
else
lastSuffix.addChildren(isArr ? arraySymbols[] : assocArraySymbols[], false);
if (suffix is null)
suffix = lastSuffix;
@ -454,9 +455,10 @@ void resolveTypeFromInitializer(DSymbol* symbol, TypeLookup* lookup,
if (currentSymbol is null)
return;
// Index expressions can be an array index or an AA index
// Index expressions can be on a pointer, an array or an AA
if (currentSymbol.qualifier == SymbolQualifier.array
|| currentSymbol.qualifier == SymbolQualifier.assocArray
|| currentSymbol.qualifier == SymbolQualifier.pointer
|| currentSymbol.kind == CompletionKind.aliasName)
{
if (currentSymbol.type !is null)

View File

@ -131,6 +131,8 @@ enum SymbolQualifier : ubyte
func,
/// Selective import
selectiveImport,
/// The symbol is a pointer
pointer,
}
/**
@ -228,6 +230,11 @@ struct DSymbol
return;
visited.insert(cast(size_t) &this);
// pointers are implicitly dereferenced on members (a single layer)
if (qualifier == SymbolQualifier.pointer
&& this.type.qualifier != SymbolQualifier.pointer)
return type.getParts!OR(name, app, visited, onlyOne);
if (name is null)
{
foreach (part; parts[].filter!(a => a.name != IMPORT_SYMBOL_NAME))
@ -427,10 +434,14 @@ struct DSymbol
// dfmt off
mixin(bitfields!(bool, "ownType", 1,
bool, "skipOver", 1,
bool, "isPointer", 1,
ubyte, "", 5));
ubyte, "", 6));
// dfmt on
deprecated bool isPointer()
{
return qualifier == SymbolQualifier.pointer;
}
/// Protection level for this symbol
IdType protection;

View File

@ -381,7 +381,8 @@ DSymbol*[] getSymbolsByTokenChain(T)(Scope* completionScope,
case tok!"[":
if (symbols.length == 0)
break loop;
if (symbols[0].qualifier == SymbolQualifier.array)
if (symbols[0].qualifier == SymbolQualifier.array
|| symbols[0].qualifier == SymbolQualifier.pointer)
{
skip(tok!"[", tok!"]");
if (!isSliceExpression(tokens, i))

View File

@ -0,0 +1,30 @@
identifiers
alignof k
init k
mangleof k
member v int member stdin 16 int
sizeof k
stringof k
tupleof k
identifiers
alignof k
init k
mangleof k
member v int member stdin 16 int
sizeof k
stringof k
tupleof k
identifiers
alignof k
init k
mangleof k
sizeof k
stringof k
identifiers
alignof k
init k
mangleof k
member v int member stdin 16 int
sizeof k
stringof k
tupleof k

28
tests/tc_pointers/file.d Normal file
View File

@ -0,0 +1,28 @@
struct S
{
int member;
}
void test()
{
S itemA;
itemA.
}
void test2()
{
S* itemPtr = &itemA;
itemPtr.
}
void test3()
{
S** itemPtrPtr = &itemA;
itemPtrPtr.
}
void test3()
{
S** itemPtrPtr = &itemA;
itemPtrPtr[10].
}

8
tests/tc_pointers/run.sh Executable file
View File

@ -0,0 +1,8 @@
set -e
set -u
../../bin/dcd-client $1 file.d -x -c58 > actual1.txt
../../bin/dcd-client $1 file.d -x -c108 >> actual1.txt
../../bin/dcd-client $1 file.d -x -c165 >> actual1.txt
../../bin/dcd-client $1 file.d -x -c226 >> actual1.txt
diff actual1.txt expected1.txt --strip-trailing-cr