Coverage Report

Created: 2020-09-22 08:39

/Users/buildslave/jenkins/workspace/coverage/llvm-project/clang/tools/libclang/CXString.cpp
Line
Count
Source (jump to first uncovered line)
1
//===- CXString.cpp - Routines for manipulating CXStrings -----------------===//
2
//
3
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4
// See https://llvm.org/LICENSE.txt for license information.
5
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6
//
7
//===----------------------------------------------------------------------===//
8
//
9
// This file defines routines for manipulating CXStrings. It should be the
10
// only file that has internal knowledge of the encoding of the data in
11
// CXStrings.
12
//
13
//===----------------------------------------------------------------------===//
14
15
#include "CXString.h"
16
#include "CXTranslationUnit.h"
17
#include "clang-c/Index.h"
18
#include "clang/Frontend/ASTUnit.h"
19
#include "llvm/Support/ErrorHandling.h"
20
21
using namespace clang;
22
23
/// Describes the kind of underlying data in CXString.
24
enum CXStringFlag {
25
  /// CXString contains a 'const char *' that it doesn't own.
26
  CXS_Unmanaged,
27
28
  /// CXString contains a 'const char *' that it allocated with malloc().
29
  CXS_Malloc,
30
31
  /// CXString contains a CXStringBuf that needs to be returned to the
32
  /// CXStringPool.
33
  CXS_StringBuf
34
};
35
36
namespace clang {
37
namespace cxstring {
38
39
//===----------------------------------------------------------------------===//
40
// Basic generation of CXStrings.
41
//===----------------------------------------------------------------------===//
42
43
173k
CXString createEmpty() {
44
173k
  CXString Str;
45
173k
  Str.data = "";
46
173k
  Str.private_flags = CXS_Unmanaged;
47
173k
  return Str;
48
173k
}
49
50
121k
CXString createNull() {
51
121k
  CXString Str;
52
121k
  Str.data = nullptr;
53
121k
  Str.private_flags = CXS_Unmanaged;
54
121k
  return Str;
55
121k
}
56
57
512k
CXString createRef(const char *String) {
58
512k
  if (String && 
String[0] == '\0'400k
)
59
4
    return createEmpty();
60
61
512k
  CXString Str;
62
512k
  Str.data = String;
63
512k
  Str.private_flags = CXS_Unmanaged;
64
512k
  return Str;
65
512k
}
66
67
0
CXString createDup(const char *String) {
68
0
  if (!String)
69
0
    return createNull();
70
71
0
  if (String[0] == '\0')
72
0
    return createEmpty();
73
74
0
  CXString Str;
75
0
  Str.data = strdup(String);
76
0
  Str.private_flags = CXS_Malloc;
77
0
  return Str;
78
0
}
79
80
138k
CXString createRef(StringRef String) {
81
  // If the string is not nul-terminated, we have to make a copy.
82
83
  // FIXME: This is doing a one past end read, and should be removed! For memory
84
  // we don't manage, the API string can become unterminated at any time outside
85
  // our control.
86
87
138k
  if (!String.empty() && 
String.data()[String.size()] != 020.9k
)
88
3.31k
    return createDup(String);
89
90
135k
  CXString Result;
91
135k
  Result.data = String.data();
92
135k
  Result.private_flags = (unsigned) CXS_Unmanaged;
93
135k
  return Result;
94
135k
}
95
96
46.6k
CXString createDup(StringRef String) {
97
46.6k
  CXString Result;
98
46.6k
  char *Spelling = static_cast<char *>(llvm::safe_malloc(String.size() + 1));
99
46.6k
  memmove(Spelling, String.data(), String.size());
100
46.6k
  Spelling[String.size()] = 0;
101
46.6k
  Result.data = Spelling;
102
46.6k
  Result.private_flags = (unsigned) CXS_Malloc;
103
46.6k
  return Result;
104
46.6k
}
105
106
3.18k
CXString createCXString(CXStringBuf *buf) {
107
3.18k
  CXString Str;
108
3.18k
  Str.data = buf;
109
3.18k
  Str.private_flags = (unsigned) CXS_StringBuf;
110
3.18k
  return Str;
111
3.18k
}
112
113
64
CXStringSet *createSet(const std::vector<std::string> &Strings) {
114
64
  CXStringSet *Set = new CXStringSet;
115
64
  Set->Count = Strings.size();
116
64
  Set->Strings = new CXString[Set->Count];
117
131
  for (unsigned SI = 0, SE = Set->Count; SI < SE; 
++SI67
)
118
67
    Set->Strings[SI] = createDup(Strings[SI]);
119
64
  return Set;
120
64
}
121
122
123
//===----------------------------------------------------------------------===//
124
// String pools.
125
//===----------------------------------------------------------------------===//
126
127
1.04k
CXStringPool::~CXStringPool() {
128
1.04k
  for (std::vector<CXStringBuf *>::iterator I = Pool.begin(), E = Pool.end();
129
1.17k
       I != E; 
++I131
) {
130
131
    delete *I;
131
131
  }
132
1.04k
}
133
134
3.24k
CXStringBuf *CXStringPool::getCXStringBuf(CXTranslationUnit TU) {
135
3.24k
  if (Pool.empty())
136
131
    return new CXStringBuf(TU);
137
138
3.11k
  CXStringBuf *Buf = Pool.back();
139
3.11k
  Buf->Data.clear();
140
3.11k
  Pool.pop_back();
141
3.11k
  return Buf;
142
3.11k
}
143
144
3.24k
CXStringBuf *getCXStringBuf(CXTranslationUnit TU) {
145
3.24k
  return TU->StringPool->getCXStringBuf(TU);
146
3.24k
}
147
148
3.24k
void CXStringBuf::dispose() {
149
3.24k
  TU->StringPool->Pool.push_back(this);
150
3.24k
}
151
152
0
bool isManagedByPool(CXString str) {
153
0
  return ((CXStringFlag) str.private_flags) == CXS_StringBuf;
154
0
}
155
156
} // end namespace cxstring
157
} // end namespace clang
158
159
//===----------------------------------------------------------------------===//
160
// libClang public APIs.
161
//===----------------------------------------------------------------------===//
162
163
733k
const char *clang_getCString(CXString string) {
164
733k
  if (string.private_flags == (unsigned) CXS_StringBuf) {
165
3.18k
    return static_cast<const cxstring::CXStringBuf *>(string.data)->Data.data();
166
3.18k
  }
167
730k
  return static_cast<const char *>(string.data);
168
730k
}
169
170
993k
void clang_disposeString(CXString string) {
171
993k
  switch ((CXStringFlag) string.private_flags) {
172
943k
    case CXS_Unmanaged:
173
943k
      break;
174
46.6k
    case CXS_Malloc:
175
46.6k
      if (string.data)
176
46.6k
        free(const_cast<void *>(string.data));
177
46.6k
      break;
178
3.18k
    case CXS_StringBuf:
179
3.18k
      static_cast<cxstring::CXStringBuf *>(
180
3.18k
          const_cast<void *>(string.data))->dispose();
181
3.18k
      break;
182
993k
  }
183
993k
}
184
185
64
void clang_disposeStringSet(CXStringSet *set) {
186
131
  for (unsigned SI = 0, SE = set->Count; SI < SE; 
++SI67
)
187
67
    clang_disposeString(set->Strings[SI]);
188
64
  delete[] set->Strings;
189
64
  delete set;
190
64
}
191