[analyzer] operator new: Add a new ProgramPoint for check::NewAllocator.

Add PostAllocatorCall program point to represent the moment in the analysis
between the operator new() call and the constructor call. Pointer cast from
"void *" to the correct object pointer type has already happened by this point.

The new program point, unlike the previously used PostImplicitCall, contains a
reference to the new-expression, which allows adding path diagnostics over it.

Differential Revision: https://reviews.llvm.org/D41800
rdar://problem/12180598

llvm-svn: 322796
This commit is contained in:
Artem Dergachev 2018-01-18 00:50:19 +00:00
parent 0c79eab03d
commit 1c64e617f5
5 changed files with 70 additions and 56 deletions

View File

@ -73,8 +73,9 @@ public:
PostStoreKind, PostStoreKind,
PostConditionKind, PostConditionKind,
PostLValueKind, PostLValueKind,
PostAllocatorCallKind,
MinPostStmtKind = PostStmtKind, MinPostStmtKind = PostStmtKind,
MaxPostStmtKind = PostLValueKind, MaxPostStmtKind = PostAllocatorCallKind,
PostInitializerKind, PostInitializerKind,
CallEnterKind, CallEnterKind,
CallExitBeginKind, CallExitBeginKind,
@ -580,6 +581,20 @@ private:
} }
}; };
class PostAllocatorCall : public StmtPoint {
public:
PostAllocatorCall(const Stmt *S, const LocationContext *L,
const ProgramPointTag *Tag = nullptr)
: StmtPoint(S, nullptr, PostAllocatorCallKind, L, Tag) {}
private:
friend class ProgramPoint;
PostAllocatorCall() {}
static bool isKind(const ProgramPoint &Location) {
return Location.getKind() == PostAllocatorCallKind;
}
};
/// Represents a point when we begin processing an inlined call. /// Represents a point when we begin processing an inlined call.
/// CallEnter uses the caller's location context. /// CallEnter uses the caller's location context.
class CallEnter : public ProgramPoint { class CallEnter : public ProgramPoint {

View File

@ -488,12 +488,7 @@ namespace {
void runChecker(CheckerManager::CheckNewAllocatorFunc checkFn, void runChecker(CheckerManager::CheckNewAllocatorFunc checkFn,
NodeBuilder &Bldr, ExplodedNode *Pred) { NodeBuilder &Bldr, ExplodedNode *Pred) {
// TODO: Does this deserve a custom program point? For now we're re-using ProgramPoint L = PostAllocatorCall(NE, Pred->getLocationContext());
// PostImplicitCall because we're guaranteed to use the non-implicit
// PostStmt for the PostCall callback, because we have some sort of
// call site (CXXNewExpr) in this scenario.
ProgramPoint L = PostImplicitCall(NE->getOperatorNew(), NE->getLocStart(),
Pred->getLocationContext());
CheckerContext C(Bldr, Eng, Pred, L, WasInlined); CheckerContext C(Bldr, Eng, Pred, L, WasInlined);
checkFn(NE, Target, C); checkFn(NE, Target, C);
} }

View File

@ -275,7 +275,8 @@ void CoreEngine::dispatchWorkItem(ExplodedNode* Pred, ProgramPoint Loc,
Loc.getAs<PostInitializer>() || Loc.getAs<PostInitializer>() ||
Loc.getAs<PostImplicitCall>() || Loc.getAs<PostImplicitCall>() ||
Loc.getAs<CallExitEnd>() || Loc.getAs<CallExitEnd>() ||
Loc.getAs<LoopExit>()); Loc.getAs<LoopExit>() ||
Loc.getAs<PostAllocatorCall>());
HandlePostStmt(WU.getBlock(), WU.getIndex(), Pred); HandlePostStmt(WU.getBlock(), WU.getIndex(), Pred);
break; break;
} }

View File

@ -2930,6 +2930,8 @@ struct DOTGraphTraits<ExplodedNode*> :
Out << "\\lPostStore\\l"; Out << "\\lPostStore\\l";
else if (Loc.getAs<PostLValue>()) else if (Loc.getAs<PostLValue>())
Out << "\\lPostLValue\\l"; Out << "\\lPostLValue\\l";
else if (Loc.getAs<PostAllocatorCall>())
Out << "\\lPostAllocatorCall\\l";
break; break;
} }

View File

@ -1,4 +1,5 @@
// RUN: %clang_analyze_cc1 -analyzer-checker=cplusplus.NewDelete,unix.Malloc -analyzer-output=text -verify %s // RUN: %clang_analyze_cc1 -analyzer-checker=cplusplus.NewDelete,unix.Malloc -analyzer-output=text -verify %s
// RUN: %clang_analyze_cc1 -analyzer-checker=cplusplus.NewDelete,unix.Malloc -analyzer-output=text -analyzer-config c++-allocator-inlining=true -verify %s
// RUN: %clang_analyze_cc1 -analyzer-checker=cplusplus.NewDelete,unix.Malloc -analyzer-output=plist -analyzer-config path-diagnostics-alternate=false %s -o %t.plist // RUN: %clang_analyze_cc1 -analyzer-checker=cplusplus.NewDelete,unix.Malloc -analyzer-output=plist -analyzer-config path-diagnostics-alternate=false %s -o %t.plist
// RUN: FileCheck --input-file=%t.plist %s // RUN: FileCheck --input-file=%t.plist %s
@ -40,12 +41,12 @@ void test(Odd *odd) {
// CHECK-NEXT: <key>start</key> // CHECK-NEXT: <key>start</key>
// CHECK-NEXT: <array> // CHECK-NEXT: <array>
// CHECK-NEXT: <dict> // CHECK-NEXT: <dict>
// CHECK-NEXT: <key>line</key><integer>6</integer> // CHECK-NEXT: <key>line</key><integer>7</integer>
// CHECK-NEXT: <key>col</key><integer>3</integer> // CHECK-NEXT: <key>col</key><integer>3</integer>
// CHECK-NEXT: <key>file</key><integer>0</integer> // CHECK-NEXT: <key>file</key><integer>0</integer>
// CHECK-NEXT: </dict> // CHECK-NEXT: </dict>
// CHECK-NEXT: <dict> // CHECK-NEXT: <dict>
// CHECK-NEXT: <key>line</key><integer>6</integer> // CHECK-NEXT: <key>line</key><integer>7</integer>
// CHECK-NEXT: <key>col</key><integer>5</integer> // CHECK-NEXT: <key>col</key><integer>5</integer>
// CHECK-NEXT: <key>file</key><integer>0</integer> // CHECK-NEXT: <key>file</key><integer>0</integer>
// CHECK-NEXT: </dict> // CHECK-NEXT: </dict>
@ -53,12 +54,12 @@ void test(Odd *odd) {
// CHECK-NEXT: <key>end</key> // CHECK-NEXT: <key>end</key>
// CHECK-NEXT: <array> // CHECK-NEXT: <array>
// CHECK-NEXT: <dict> // CHECK-NEXT: <dict>
// CHECK-NEXT: <key>line</key><integer>6</integer> // CHECK-NEXT: <key>line</key><integer>7</integer>
// CHECK-NEXT: <key>col</key><integer>12</integer> // CHECK-NEXT: <key>col</key><integer>12</integer>
// CHECK-NEXT: <key>file</key><integer>0</integer> // CHECK-NEXT: <key>file</key><integer>0</integer>
// CHECK-NEXT: </dict> // CHECK-NEXT: </dict>
// CHECK-NEXT: <dict> // CHECK-NEXT: <dict>
// CHECK-NEXT: <key>line</key><integer>6</integer> // CHECK-NEXT: <key>line</key><integer>7</integer>
// CHECK-NEXT: <key>col</key><integer>14</integer> // CHECK-NEXT: <key>col</key><integer>14</integer>
// CHECK-NEXT: <key>file</key><integer>0</integer> // CHECK-NEXT: <key>file</key><integer>0</integer>
// CHECK-NEXT: </dict> // CHECK-NEXT: </dict>
@ -70,7 +71,7 @@ void test(Odd *odd) {
// CHECK-NEXT: <key>kind</key><string>event</string> // CHECK-NEXT: <key>kind</key><string>event</string>
// CHECK-NEXT: <key>location</key> // CHECK-NEXT: <key>location</key>
// CHECK-NEXT: <dict> // CHECK-NEXT: <dict>
// CHECK-NEXT: <key>line</key><integer>6</integer> // CHECK-NEXT: <key>line</key><integer>7</integer>
// CHECK-NEXT: <key>col</key><integer>12</integer> // CHECK-NEXT: <key>col</key><integer>12</integer>
// CHECK-NEXT: <key>file</key><integer>0</integer> // CHECK-NEXT: <key>file</key><integer>0</integer>
// CHECK-NEXT: </dict> // CHECK-NEXT: </dict>
@ -78,12 +79,12 @@ void test(Odd *odd) {
// CHECK-NEXT: <array> // CHECK-NEXT: <array>
// CHECK-NEXT: <array> // CHECK-NEXT: <array>
// CHECK-NEXT: <dict> // CHECK-NEXT: <dict>
// CHECK-NEXT: <key>line</key><integer>6</integer> // CHECK-NEXT: <key>line</key><integer>7</integer>
// CHECK-NEXT: <key>col</key><integer>12</integer> // CHECK-NEXT: <key>col</key><integer>12</integer>
// CHECK-NEXT: <key>file</key><integer>0</integer> // CHECK-NEXT: <key>file</key><integer>0</integer>
// CHECK-NEXT: </dict> // CHECK-NEXT: </dict>
// CHECK-NEXT: <dict> // CHECK-NEXT: <dict>
// CHECK-NEXT: <key>line</key><integer>6</integer> // CHECK-NEXT: <key>line</key><integer>7</integer>
// CHECK-NEXT: <key>col</key><integer>18</integer> // CHECK-NEXT: <key>col</key><integer>18</integer>
// CHECK-NEXT: <key>file</key><integer>0</integer> // CHECK-NEXT: <key>file</key><integer>0</integer>
// CHECK-NEXT: </dict> // CHECK-NEXT: </dict>
@ -103,12 +104,12 @@ void test(Odd *odd) {
// CHECK-NEXT: <key>start</key> // CHECK-NEXT: <key>start</key>
// CHECK-NEXT: <array> // CHECK-NEXT: <array>
// CHECK-NEXT: <dict> // CHECK-NEXT: <dict>
// CHECK-NEXT: <key>line</key><integer>6</integer> // CHECK-NEXT: <key>line</key><integer>7</integer>
// CHECK-NEXT: <key>col</key><integer>12</integer> // CHECK-NEXT: <key>col</key><integer>12</integer>
// CHECK-NEXT: <key>file</key><integer>0</integer> // CHECK-NEXT: <key>file</key><integer>0</integer>
// CHECK-NEXT: </dict> // CHECK-NEXT: </dict>
// CHECK-NEXT: <dict> // CHECK-NEXT: <dict>
// CHECK-NEXT: <key>line</key><integer>6</integer> // CHECK-NEXT: <key>line</key><integer>7</integer>
// CHECK-NEXT: <key>col</key><integer>14</integer> // CHECK-NEXT: <key>col</key><integer>14</integer>
// CHECK-NEXT: <key>file</key><integer>0</integer> // CHECK-NEXT: <key>file</key><integer>0</integer>
// CHECK-NEXT: </dict> // CHECK-NEXT: </dict>
@ -116,12 +117,12 @@ void test(Odd *odd) {
// CHECK-NEXT: <key>end</key> // CHECK-NEXT: <key>end</key>
// CHECK-NEXT: <array> // CHECK-NEXT: <array>
// CHECK-NEXT: <dict> // CHECK-NEXT: <dict>
// CHECK-NEXT: <key>line</key><integer>8</integer> // CHECK-NEXT: <key>line</key><integer>9</integer>
// CHECK-NEXT: <key>col</key><integer>3</integer> // CHECK-NEXT: <key>col</key><integer>3</integer>
// CHECK-NEXT: <key>file</key><integer>0</integer> // CHECK-NEXT: <key>file</key><integer>0</integer>
// CHECK-NEXT: </dict> // CHECK-NEXT: </dict>
// CHECK-NEXT: <dict> // CHECK-NEXT: <dict>
// CHECK-NEXT: <key>line</key><integer>8</integer> // CHECK-NEXT: <key>line</key><integer>9</integer>
// CHECK-NEXT: <key>col</key><integer>4</integer> // CHECK-NEXT: <key>col</key><integer>4</integer>
// CHECK-NEXT: <key>file</key><integer>0</integer> // CHECK-NEXT: <key>file</key><integer>0</integer>
// CHECK-NEXT: </dict> // CHECK-NEXT: </dict>
@ -137,12 +138,12 @@ void test(Odd *odd) {
// CHECK-NEXT: <key>start</key> // CHECK-NEXT: <key>start</key>
// CHECK-NEXT: <array> // CHECK-NEXT: <array>
// CHECK-NEXT: <dict> // CHECK-NEXT: <dict>
// CHECK-NEXT: <key>line</key><integer>8</integer> // CHECK-NEXT: <key>line</key><integer>9</integer>
// CHECK-NEXT: <key>col</key><integer>3</integer> // CHECK-NEXT: <key>col</key><integer>3</integer>
// CHECK-NEXT: <key>file</key><integer>0</integer> // CHECK-NEXT: <key>file</key><integer>0</integer>
// CHECK-NEXT: </dict> // CHECK-NEXT: </dict>
// CHECK-NEXT: <dict> // CHECK-NEXT: <dict>
// CHECK-NEXT: <key>line</key><integer>8</integer> // CHECK-NEXT: <key>line</key><integer>9</integer>
// CHECK-NEXT: <key>col</key><integer>4</integer> // CHECK-NEXT: <key>col</key><integer>4</integer>
// CHECK-NEXT: <key>file</key><integer>0</integer> // CHECK-NEXT: <key>file</key><integer>0</integer>
// CHECK-NEXT: </dict> // CHECK-NEXT: </dict>
@ -150,12 +151,12 @@ void test(Odd *odd) {
// CHECK-NEXT: <key>end</key> // CHECK-NEXT: <key>end</key>
// CHECK-NEXT: <array> // CHECK-NEXT: <array>
// CHECK-NEXT: <dict> // CHECK-NEXT: <dict>
// CHECK-NEXT: <key>line</key><integer>10</integer> // CHECK-NEXT: <key>line</key><integer>11</integer>
// CHECK-NEXT: <key>col</key><integer>5</integer> // CHECK-NEXT: <key>col</key><integer>5</integer>
// CHECK-NEXT: <key>file</key><integer>0</integer> // CHECK-NEXT: <key>file</key><integer>0</integer>
// CHECK-NEXT: </dict> // CHECK-NEXT: </dict>
// CHECK-NEXT: <dict> // CHECK-NEXT: <dict>
// CHECK-NEXT: <key>line</key><integer>10</integer> // CHECK-NEXT: <key>line</key><integer>11</integer>
// CHECK-NEXT: <key>col</key><integer>10</integer> // CHECK-NEXT: <key>col</key><integer>10</integer>
// CHECK-NEXT: <key>file</key><integer>0</integer> // CHECK-NEXT: <key>file</key><integer>0</integer>
// CHECK-NEXT: </dict> // CHECK-NEXT: </dict>
@ -167,7 +168,7 @@ void test(Odd *odd) {
// CHECK-NEXT: <key>kind</key><string>event</string> // CHECK-NEXT: <key>kind</key><string>event</string>
// CHECK-NEXT: <key>location</key> // CHECK-NEXT: <key>location</key>
// CHECK-NEXT: <dict> // CHECK-NEXT: <dict>
// CHECK-NEXT: <key>line</key><integer>10</integer> // CHECK-NEXT: <key>line</key><integer>11</integer>
// CHECK-NEXT: <key>col</key><integer>5</integer> // CHECK-NEXT: <key>col</key><integer>5</integer>
// CHECK-NEXT: <key>file</key><integer>0</integer> // CHECK-NEXT: <key>file</key><integer>0</integer>
// CHECK-NEXT: </dict> // CHECK-NEXT: </dict>
@ -175,12 +176,12 @@ void test(Odd *odd) {
// CHECK-NEXT: <array> // CHECK-NEXT: <array>
// CHECK-NEXT: <array> // CHECK-NEXT: <array>
// CHECK-NEXT: <dict> // CHECK-NEXT: <dict>
// CHECK-NEXT: <key>line</key><integer>10</integer> // CHECK-NEXT: <key>line</key><integer>11</integer>
// CHECK-NEXT: <key>col</key><integer>5</integer> // CHECK-NEXT: <key>col</key><integer>5</integer>
// CHECK-NEXT: <key>file</key><integer>0</integer> // CHECK-NEXT: <key>file</key><integer>0</integer>
// CHECK-NEXT: </dict> // CHECK-NEXT: </dict>
// CHECK-NEXT: <dict> // CHECK-NEXT: <dict>
// CHECK-NEXT: <key>line</key><integer>10</integer> // CHECK-NEXT: <key>line</key><integer>11</integer>
// CHECK-NEXT: <key>col</key><integer>12</integer> // CHECK-NEXT: <key>col</key><integer>12</integer>
// CHECK-NEXT: <key>file</key><integer>0</integer> // CHECK-NEXT: <key>file</key><integer>0</integer>
// CHECK-NEXT: </dict> // CHECK-NEXT: </dict>
@ -200,12 +201,12 @@ void test(Odd *odd) {
// CHECK-NEXT: <key>start</key> // CHECK-NEXT: <key>start</key>
// CHECK-NEXT: <array> // CHECK-NEXT: <array>
// CHECK-NEXT: <dict> // CHECK-NEXT: <dict>
// CHECK-NEXT: <key>line</key><integer>10</integer> // CHECK-NEXT: <key>line</key><integer>11</integer>
// CHECK-NEXT: <key>col</key><integer>5</integer> // CHECK-NEXT: <key>col</key><integer>5</integer>
// CHECK-NEXT: <key>file</key><integer>0</integer> // CHECK-NEXT: <key>file</key><integer>0</integer>
// CHECK-NEXT: </dict> // CHECK-NEXT: </dict>
// CHECK-NEXT: <dict> // CHECK-NEXT: <dict>
// CHECK-NEXT: <key>line</key><integer>10</integer> // CHECK-NEXT: <key>line</key><integer>11</integer>
// CHECK-NEXT: <key>col</key><integer>10</integer> // CHECK-NEXT: <key>col</key><integer>10</integer>
// CHECK-NEXT: <key>file</key><integer>0</integer> // CHECK-NEXT: <key>file</key><integer>0</integer>
// CHECK-NEXT: </dict> // CHECK-NEXT: </dict>
@ -213,12 +214,12 @@ void test(Odd *odd) {
// CHECK-NEXT: <key>end</key> // CHECK-NEXT: <key>end</key>
// CHECK-NEXT: <array> // CHECK-NEXT: <array>
// CHECK-NEXT: <dict> // CHECK-NEXT: <dict>
// CHECK-NEXT: <key>line</key><integer>13</integer> // CHECK-NEXT: <key>line</key><integer>14</integer>
// CHECK-NEXT: <key>col</key><integer>3</integer> // CHECK-NEXT: <key>col</key><integer>3</integer>
// CHECK-NEXT: <key>file</key><integer>0</integer> // CHECK-NEXT: <key>file</key><integer>0</integer>
// CHECK-NEXT: </dict> // CHECK-NEXT: </dict>
// CHECK-NEXT: <dict> // CHECK-NEXT: <dict>
// CHECK-NEXT: <key>line</key><integer>13</integer> // CHECK-NEXT: <key>line</key><integer>14</integer>
// CHECK-NEXT: <key>col</key><integer>8</integer> // CHECK-NEXT: <key>col</key><integer>8</integer>
// CHECK-NEXT: <key>file</key><integer>0</integer> // CHECK-NEXT: <key>file</key><integer>0</integer>
// CHECK-NEXT: </dict> // CHECK-NEXT: </dict>
@ -230,7 +231,7 @@ void test(Odd *odd) {
// CHECK-NEXT: <key>kind</key><string>event</string> // CHECK-NEXT: <key>kind</key><string>event</string>
// CHECK-NEXT: <key>location</key> // CHECK-NEXT: <key>location</key>
// CHECK-NEXT: <dict> // CHECK-NEXT: <dict>
// CHECK-NEXT: <key>line</key><integer>13</integer> // CHECK-NEXT: <key>line</key><integer>14</integer>
// CHECK-NEXT: <key>col</key><integer>3</integer> // CHECK-NEXT: <key>col</key><integer>3</integer>
// CHECK-NEXT: <key>file</key><integer>0</integer> // CHECK-NEXT: <key>file</key><integer>0</integer>
// CHECK-NEXT: </dict> // CHECK-NEXT: </dict>
@ -238,12 +239,12 @@ void test(Odd *odd) {
// CHECK-NEXT: <array> // CHECK-NEXT: <array>
// CHECK-NEXT: <array> // CHECK-NEXT: <array>
// CHECK-NEXT: <dict> // CHECK-NEXT: <dict>
// CHECK-NEXT: <key>line</key><integer>13</integer> // CHECK-NEXT: <key>line</key><integer>14</integer>
// CHECK-NEXT: <key>col</key><integer>3</integer> // CHECK-NEXT: <key>col</key><integer>3</integer>
// CHECK-NEXT: <key>file</key><integer>0</integer> // CHECK-NEXT: <key>file</key><integer>0</integer>
// CHECK-NEXT: </dict> // CHECK-NEXT: </dict>
// CHECK-NEXT: <dict> // CHECK-NEXT: <dict>
// CHECK-NEXT: <key>line</key><integer>13</integer> // CHECK-NEXT: <key>line</key><integer>14</integer>
// CHECK-NEXT: <key>col</key><integer>10</integer> // CHECK-NEXT: <key>col</key><integer>10</integer>
// CHECK-NEXT: <key>file</key><integer>0</integer> // CHECK-NEXT: <key>file</key><integer>0</integer>
// CHECK-NEXT: </dict> // CHECK-NEXT: </dict>
@ -267,7 +268,7 @@ void test(Odd *odd) {
// CHECK-NEXT: <key>issue_hash_function_offset</key><string>8</string> // CHECK-NEXT: <key>issue_hash_function_offset</key><string>8</string>
// CHECK-NEXT: <key>location</key> // CHECK-NEXT: <key>location</key>
// CHECK-NEXT: <dict> // CHECK-NEXT: <dict>
// CHECK-NEXT: <key>line</key><integer>13</integer> // CHECK-NEXT: <key>line</key><integer>14</integer>
// CHECK-NEXT: <key>col</key><integer>3</integer> // CHECK-NEXT: <key>col</key><integer>3</integer>
// CHECK-NEXT: <key>file</key><integer>0</integer> // CHECK-NEXT: <key>file</key><integer>0</integer>
// CHECK-NEXT: </dict> // CHECK-NEXT: </dict>
@ -279,7 +280,7 @@ void test(Odd *odd) {
// CHECK-NEXT: <key>kind</key><string>event</string> // CHECK-NEXT: <key>kind</key><string>event</string>
// CHECK-NEXT: <key>location</key> // CHECK-NEXT: <key>location</key>
// CHECK-NEXT: <dict> // CHECK-NEXT: <dict>
// CHECK-NEXT: <key>line</key><integer>24</integer> // CHECK-NEXT: <key>line</key><integer>25</integer>
// CHECK-NEXT: <key>col</key><integer>2</integer> // CHECK-NEXT: <key>col</key><integer>2</integer>
// CHECK-NEXT: <key>file</key><integer>0</integer> // CHECK-NEXT: <key>file</key><integer>0</integer>
// CHECK-NEXT: </dict> // CHECK-NEXT: </dict>
@ -287,12 +288,12 @@ void test(Odd *odd) {
// CHECK-NEXT: <array> // CHECK-NEXT: <array>
// CHECK-NEXT: <array> // CHECK-NEXT: <array>
// CHECK-NEXT: <dict> // CHECK-NEXT: <dict>
// CHECK-NEXT: <key>line</key><integer>24</integer> // CHECK-NEXT: <key>line</key><integer>25</integer>
// CHECK-NEXT: <key>col</key><integer>2</integer> // CHECK-NEXT: <key>col</key><integer>2</integer>
// CHECK-NEXT: <key>file</key><integer>0</integer> // CHECK-NEXT: <key>file</key><integer>0</integer>
// CHECK-NEXT: </dict> // CHECK-NEXT: </dict>
// CHECK-NEXT: <dict> // CHECK-NEXT: <dict>
// CHECK-NEXT: <key>line</key><integer>24</integer> // CHECK-NEXT: <key>line</key><integer>25</integer>
// CHECK-NEXT: <key>col</key><integer>12</integer> // CHECK-NEXT: <key>col</key><integer>12</integer>
// CHECK-NEXT: <key>file</key><integer>0</integer> // CHECK-NEXT: <key>file</key><integer>0</integer>
// CHECK-NEXT: </dict> // CHECK-NEXT: </dict>
@ -308,7 +309,7 @@ void test(Odd *odd) {
// CHECK-NEXT: <key>kind</key><string>event</string> // CHECK-NEXT: <key>kind</key><string>event</string>
// CHECK-NEXT: <key>location</key> // CHECK-NEXT: <key>location</key>
// CHECK-NEXT: <dict> // CHECK-NEXT: <dict>
// CHECK-NEXT: <key>line</key><integer>18</integer> // CHECK-NEXT: <key>line</key><integer>19</integer>
// CHECK-NEXT: <key>col</key><integer>2</integer> // CHECK-NEXT: <key>col</key><integer>2</integer>
// CHECK-NEXT: <key>file</key><integer>0</integer> // CHECK-NEXT: <key>file</key><integer>0</integer>
// CHECK-NEXT: </dict> // CHECK-NEXT: </dict>
@ -326,12 +327,12 @@ void test(Odd *odd) {
// CHECK-NEXT: <key>start</key> // CHECK-NEXT: <key>start</key>
// CHECK-NEXT: <array> // CHECK-NEXT: <array>
// CHECK-NEXT: <dict> // CHECK-NEXT: <dict>
// CHECK-NEXT: <key>line</key><integer>18</integer> // CHECK-NEXT: <key>line</key><integer>19</integer>
// CHECK-NEXT: <key>col</key><integer>2</integer> // CHECK-NEXT: <key>col</key><integer>2</integer>
// CHECK-NEXT: <key>file</key><integer>0</integer> // CHECK-NEXT: <key>file</key><integer>0</integer>
// CHECK-NEXT: </dict> // CHECK-NEXT: </dict>
// CHECK-NEXT: <dict> // CHECK-NEXT: <dict>
// CHECK-NEXT: <key>line</key><integer>18</integer> // CHECK-NEXT: <key>line</key><integer>19</integer>
// CHECK-NEXT: <key>col</key><integer>5</integer> // CHECK-NEXT: <key>col</key><integer>5</integer>
// CHECK-NEXT: <key>file</key><integer>0</integer> // CHECK-NEXT: <key>file</key><integer>0</integer>
// CHECK-NEXT: </dict> // CHECK-NEXT: </dict>
@ -339,12 +340,12 @@ void test(Odd *odd) {
// CHECK-NEXT: <key>end</key> // CHECK-NEXT: <key>end</key>
// CHECK-NEXT: <array> // CHECK-NEXT: <array>
// CHECK-NEXT: <dict> // CHECK-NEXT: <dict>
// CHECK-NEXT: <key>line</key><integer>19</integer> // CHECK-NEXT: <key>line</key><integer>20</integer>
// CHECK-NEXT: <key>col</key><integer>3</integer> // CHECK-NEXT: <key>col</key><integer>3</integer>
// CHECK-NEXT: <key>file</key><integer>0</integer> // CHECK-NEXT: <key>file</key><integer>0</integer>
// CHECK-NEXT: </dict> // CHECK-NEXT: </dict>
// CHECK-NEXT: <dict> // CHECK-NEXT: <dict>
// CHECK-NEXT: <key>line</key><integer>19</integer> // CHECK-NEXT: <key>line</key><integer>20</integer>
// CHECK-NEXT: <key>col</key><integer>8</integer> // CHECK-NEXT: <key>col</key><integer>8</integer>
// CHECK-NEXT: <key>file</key><integer>0</integer> // CHECK-NEXT: <key>file</key><integer>0</integer>
// CHECK-NEXT: </dict> // CHECK-NEXT: </dict>
@ -356,7 +357,7 @@ void test(Odd *odd) {
// CHECK-NEXT: <key>kind</key><string>event</string> // CHECK-NEXT: <key>kind</key><string>event</string>
// CHECK-NEXT: <key>location</key> // CHECK-NEXT: <key>location</key>
// CHECK-NEXT: <dict> // CHECK-NEXT: <dict>
// CHECK-NEXT: <key>line</key><integer>19</integer> // CHECK-NEXT: <key>line</key><integer>20</integer>
// CHECK-NEXT: <key>col</key><integer>3</integer> // CHECK-NEXT: <key>col</key><integer>3</integer>
// CHECK-NEXT: <key>file</key><integer>0</integer> // CHECK-NEXT: <key>file</key><integer>0</integer>
// CHECK-NEXT: </dict> // CHECK-NEXT: </dict>
@ -364,12 +365,12 @@ void test(Odd *odd) {
// CHECK-NEXT: <array> // CHECK-NEXT: <array>
// CHECK-NEXT: <array> // CHECK-NEXT: <array>
// CHECK-NEXT: <dict> // CHECK-NEXT: <dict>
// CHECK-NEXT: <key>line</key><integer>19</integer> // CHECK-NEXT: <key>line</key><integer>20</integer>
// CHECK-NEXT: <key>col</key><integer>3</integer> // CHECK-NEXT: <key>col</key><integer>3</integer>
// CHECK-NEXT: <key>file</key><integer>0</integer> // CHECK-NEXT: <key>file</key><integer>0</integer>
// CHECK-NEXT: </dict> // CHECK-NEXT: </dict>
// CHECK-NEXT: <dict> // CHECK-NEXT: <dict>
// CHECK-NEXT: <key>line</key><integer>19</integer> // CHECK-NEXT: <key>line</key><integer>20</integer>
// CHECK-NEXT: <key>col</key><integer>13</integer> // CHECK-NEXT: <key>col</key><integer>13</integer>
// CHECK-NEXT: <key>file</key><integer>0</integer> // CHECK-NEXT: <key>file</key><integer>0</integer>
// CHECK-NEXT: </dict> // CHECK-NEXT: </dict>
@ -385,7 +386,7 @@ void test(Odd *odd) {
// CHECK-NEXT: <key>kind</key><string>event</string> // CHECK-NEXT: <key>kind</key><string>event</string>
// CHECK-NEXT: <key>location</key> // CHECK-NEXT: <key>location</key>
// CHECK-NEXT: <dict> // CHECK-NEXT: <dict>
// CHECK-NEXT: <key>line</key><integer>24</integer> // CHECK-NEXT: <key>line</key><integer>25</integer>
// CHECK-NEXT: <key>col</key><integer>2</integer> // CHECK-NEXT: <key>col</key><integer>2</integer>
// CHECK-NEXT: <key>file</key><integer>0</integer> // CHECK-NEXT: <key>file</key><integer>0</integer>
// CHECK-NEXT: </dict> // CHECK-NEXT: </dict>
@ -393,12 +394,12 @@ void test(Odd *odd) {
// CHECK-NEXT: <array> // CHECK-NEXT: <array>
// CHECK-NEXT: <array> // CHECK-NEXT: <array>
// CHECK-NEXT: <dict> // CHECK-NEXT: <dict>
// CHECK-NEXT: <key>line</key><integer>24</integer> // CHECK-NEXT: <key>line</key><integer>25</integer>
// CHECK-NEXT: <key>col</key><integer>2</integer> // CHECK-NEXT: <key>col</key><integer>2</integer>
// CHECK-NEXT: <key>file</key><integer>0</integer> // CHECK-NEXT: <key>file</key><integer>0</integer>
// CHECK-NEXT: </dict> // CHECK-NEXT: </dict>
// CHECK-NEXT: <dict> // CHECK-NEXT: <dict>
// CHECK-NEXT: <key>line</key><integer>24</integer> // CHECK-NEXT: <key>line</key><integer>25</integer>
// CHECK-NEXT: <key>col</key><integer>12</integer> // CHECK-NEXT: <key>col</key><integer>12</integer>
// CHECK-NEXT: <key>file</key><integer>0</integer> // CHECK-NEXT: <key>file</key><integer>0</integer>
// CHECK-NEXT: </dict> // CHECK-NEXT: </dict>
@ -418,12 +419,12 @@ void test(Odd *odd) {
// CHECK-NEXT: <key>start</key> // CHECK-NEXT: <key>start</key>
// CHECK-NEXT: <array> // CHECK-NEXT: <array>
// CHECK-NEXT: <dict> // CHECK-NEXT: <dict>
// CHECK-NEXT: <key>line</key><integer>24</integer> // CHECK-NEXT: <key>line</key><integer>25</integer>
// CHECK-NEXT: <key>col</key><integer>2</integer> // CHECK-NEXT: <key>col</key><integer>2</integer>
// CHECK-NEXT: <key>file</key><integer>0</integer> // CHECK-NEXT: <key>file</key><integer>0</integer>
// CHECK-NEXT: </dict> // CHECK-NEXT: </dict>
// CHECK-NEXT: <dict> // CHECK-NEXT: <dict>
// CHECK-NEXT: <key>line</key><integer>24</integer> // CHECK-NEXT: <key>line</key><integer>25</integer>
// CHECK-NEXT: <key>col</key><integer>4</integer> // CHECK-NEXT: <key>col</key><integer>4</integer>
// CHECK-NEXT: <key>file</key><integer>0</integer> // CHECK-NEXT: <key>file</key><integer>0</integer>
// CHECK-NEXT: </dict> // CHECK-NEXT: </dict>
@ -431,12 +432,12 @@ void test(Odd *odd) {
// CHECK-NEXT: <key>end</key> // CHECK-NEXT: <key>end</key>
// CHECK-NEXT: <array> // CHECK-NEXT: <array>
// CHECK-NEXT: <dict> // CHECK-NEXT: <dict>
// CHECK-NEXT: <key>line</key><integer>26</integer> // CHECK-NEXT: <key>line</key><integer>27</integer>
// CHECK-NEXT: <key>col</key><integer>2</integer> // CHECK-NEXT: <key>col</key><integer>2</integer>
// CHECK-NEXT: <key>file</key><integer>0</integer> // CHECK-NEXT: <key>file</key><integer>0</integer>
// CHECK-NEXT: </dict> // CHECK-NEXT: </dict>
// CHECK-NEXT: <dict> // CHECK-NEXT: <dict>
// CHECK-NEXT: <key>line</key><integer>26</integer> // CHECK-NEXT: <key>line</key><integer>27</integer>
// CHECK-NEXT: <key>col</key><integer>7</integer> // CHECK-NEXT: <key>col</key><integer>7</integer>
// CHECK-NEXT: <key>file</key><integer>0</integer> // CHECK-NEXT: <key>file</key><integer>0</integer>
// CHECK-NEXT: </dict> // CHECK-NEXT: </dict>
@ -448,7 +449,7 @@ void test(Odd *odd) {
// CHECK-NEXT: <key>kind</key><string>event</string> // CHECK-NEXT: <key>kind</key><string>event</string>
// CHECK-NEXT: <key>location</key> // CHECK-NEXT: <key>location</key>
// CHECK-NEXT: <dict> // CHECK-NEXT: <dict>
// CHECK-NEXT: <key>line</key><integer>26</integer> // CHECK-NEXT: <key>line</key><integer>27</integer>
// CHECK-NEXT: <key>col</key><integer>2</integer> // CHECK-NEXT: <key>col</key><integer>2</integer>
// CHECK-NEXT: <key>file</key><integer>0</integer> // CHECK-NEXT: <key>file</key><integer>0</integer>
// CHECK-NEXT: </dict> // CHECK-NEXT: </dict>
@ -456,12 +457,12 @@ void test(Odd *odd) {
// CHECK-NEXT: <array> // CHECK-NEXT: <array>
// CHECK-NEXT: <array> // CHECK-NEXT: <array>
// CHECK-NEXT: <dict> // CHECK-NEXT: <dict>
// CHECK-NEXT: <key>line</key><integer>26</integer> // CHECK-NEXT: <key>line</key><integer>27</integer>
// CHECK-NEXT: <key>col</key><integer>2</integer> // CHECK-NEXT: <key>col</key><integer>2</integer>
// CHECK-NEXT: <key>file</key><integer>0</integer> // CHECK-NEXT: <key>file</key><integer>0</integer>
// CHECK-NEXT: </dict> // CHECK-NEXT: </dict>
// CHECK-NEXT: <dict> // CHECK-NEXT: <dict>
// CHECK-NEXT: <key>line</key><integer>26</integer> // CHECK-NEXT: <key>line</key><integer>27</integer>
// CHECK-NEXT: <key>col</key><integer>11</integer> // CHECK-NEXT: <key>col</key><integer>11</integer>
// CHECK-NEXT: <key>file</key><integer>0</integer> // CHECK-NEXT: <key>file</key><integer>0</integer>
// CHECK-NEXT: </dict> // CHECK-NEXT: </dict>
@ -485,7 +486,7 @@ void test(Odd *odd) {
// CHECK-NEXT: <key>issue_hash_function_offset</key><string>3</string> // CHECK-NEXT: <key>issue_hash_function_offset</key><string>3</string>
// CHECK-NEXT: <key>location</key> // CHECK-NEXT: <key>location</key>
// CHECK-NEXT: <dict> // CHECK-NEXT: <dict>
// CHECK-NEXT: <key>line</key><integer>26</integer> // CHECK-NEXT: <key>line</key><integer>27</integer>
// CHECK-NEXT: <key>col</key><integer>2</integer> // CHECK-NEXT: <key>col</key><integer>2</integer>
// CHECK-NEXT: <key>file</key><integer>0</integer> // CHECK-NEXT: <key>file</key><integer>0</integer>
// CHECK-NEXT: </dict> // CHECK-NEXT: </dict>