Skip to content

Commit d42c320

Browse files
authored
Merge pull request checkedc#1081 from correctcomputation/clangd-typevariabletypeloc-init
Add missing initialization of TypeVariableTypeLoc's SourceLocation.
2 parents 3d9acd6 + 7df5ca8 commit d42c320

File tree

3 files changed

+59
-0
lines changed

3 files changed

+59
-0
lines changed
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
_For_any(T) void my_free(_Ptr<T> p);
Lines changed: 57 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,57 @@
1+
# Regression test for a bug where Parser::ParseForanySpecifierHelper left the
2+
# memory representing the SourceLocation of the TypeVariableTypeLoc
3+
# uninitialized (the second sub-issue of
4+
# https://github.com/microsoft/checkedc-clang/issues/1066).
5+
6+
# The original symptom was that when a C file includes a header containing a
7+
# _For_any or _Itype_for_any construct, clangd writes out a precompiled header
8+
# with a garbage value for the SourceLocation, and when clangd reads the
9+
# precompiled header back in, the bad SourceLocation causes an "offset overflow"
10+
# assertion failure with TypeLocReader::VisitTypeVariableTypeLoc on the call
11+
# stack. However, this is nondeterministic depending on the content of the
12+
# uninitialized memory. To write a test that consistently catches the problem,
13+
# we run clangd under valgrind memcheck and check for an uninitialized memory
14+
# error. Alternatively, there might be a way to query the SourceLocation from
15+
# clangd so we can check that it is actually correct, although conceivably this
16+
# could falsely pass if the uninitialized memory coincidentally contained the
17+
# correct value.
18+
19+
# Note that lit has a --vg command-line option to run test(s) under `valgrind
20+
# --error-exitcode`, but there doesn't seem to be a way that we can force that
21+
# option to be enabled just for this test, so we hard-code the valgrind command
22+
# here. If valgrind isn't available on the system, the test will fail;
23+
# effectively, we're requiring the user to install valgrind in order to run the
24+
# clangd test suite. We consider this a lesser evil than automatically skipping
25+
# the test if valgrind is unavailable, in which case users might not pay
26+
# attention to the fact that they should run it at all.
27+
28+
# This test won't work correctly when run under a second level of valgrind via
29+
# `lit --vg`, so treat it as unsupported in that case. Hopefully users don't run
30+
# the test suite _only_ with --vg and forget to run this test.
31+
# UNSUPPORTED: valgrind
32+
33+
# No good drop-in replacement for valgrind is currently available for Windows.
34+
# UNSUPPORTED: system-windows
35+
36+
# Notes about command-line arguments:
37+
#
38+
# - Without --compile_args_from=lsp, clangd seems to automatically take
39+
# undesired compiler options from the LLVM monorepo's own compilation
40+
# database.
41+
#
42+
# - --path-mappings seems to be the easiest way to get the `#include` to resolve
43+
# to our desired header file in the Inputs directory, since lit expands %S
44+
# there but not in the uri in the actual LSP message. This is modeled on
45+
# path-mappings.test, although the purpose of path-mappings.test is actually
46+
# to test the path mapping, while here, we just use it to facilitate the
47+
# TypeVariableTypeLoc test.
48+
49+
# RUN: valgrind --error-exitcode=1 clangd --compile_args_from=lsp --path-mappings '/test-workspace=%S/Inputs' -lit-test < %s
50+
51+
{"jsonrpc":"2.0","id":0,"method":"initialize","params":{"processId":123,"rootPath":"clangd","capabilities":{},"trace":"off"}}
52+
---
53+
{"jsonrpc":"2.0","method":"textDocument/didOpen","params":{"textDocument":{"uri":"file:///test-workspace/checkedc-typevariabletypeloc-uninit.c","languageId":"c","version":1,"text":"#include \"checkedc-typevariabletypeloc-uninit.h\""}}}
54+
---
55+
{"jsonrpc":"2.0","id":2,"method":"shutdown"}
56+
---
57+
{"jsonrpc":"2.0","method":"exit"}

clang/lib/Parse/ParseDecl.cpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7999,6 +7999,7 @@ bool Parser::ParseForanySpecifierHelper(DeclSpec &DS,
79997999
// TypeVariableType.
80008000
QualType R = Actions.Context.getTypeVariableType(Depth, typeVariableIndex, S == Scope::ItypeforanyScope);
80018001
TypeSourceInfo *TInfo = Actions.Context.CreateTypeSourceInfo(R);
8002+
TInfo->getTypeLoc().castAs<TypeVariableTypeLoc>().setNameLoc(Tok.getLocation());
80028003
TypedefDecl *NewTD = TypedefDecl::Create(Actions.Context, Actions.CurContext,
80038004
Loc,
80048005
Tok.getLocation(),

0 commit comments

Comments
 (0)