danix800 updated this revision to Diff 553335.
danix800 edited the summary of this revision.
danix800 added a comment.
1. `getDynamicExtent()` can return both signed/unsigned results. They are
converted to signed version as `ArrayIndexType` to keep consistency. All other
APIs return this version
(even for static type size). Testcases are not affected. `ArrayBoundV2` doesn't
need explicit `unsigned`-to-`signed` casts to avoid `signed<->unsigned`
comparison;
2. `getElementExtent()` could be 0, add more defensive checking;
3. `MPIChecker` added more defensive checking, e.g: `ElementCount` doesn't have
to be `ConcreteInt` so avoid direct
`ElementCount.castAs<nonloc::ConcreteInt>()`.
Repository:
rG LLVM Github Monorepo
CHANGES SINCE LAST ACTION
https://reviews.llvm.org/D158707/new/
https://reviews.llvm.org/D158707
Files:
clang/include/clang/StaticAnalyzer/Core/PathSensitive/DynamicExtent.h
clang/lib/StaticAnalyzer/Checkers/ExprInspectionChecker.cpp
clang/lib/StaticAnalyzer/Checkers/MPI-Checker/MPIChecker.cpp
clang/lib/StaticAnalyzer/Core/DynamicExtent.cpp
clang/test/Analysis/array-bound-v2-constraint-check.c
clang/test/Analysis/flexible-array-members.c
clang/test/Analysis/memory-model.cpp
clang/test/Analysis/mpichecker.cpp
Index: clang/test/Analysis/mpichecker.cpp
===================================================================
--- clang/test/Analysis/mpichecker.cpp
+++ clang/test/Analysis/mpichecker.cpp
@@ -272,6 +272,49 @@
MPI_Wait(&rs.req2, MPI_STATUS_IGNORE);
} // no error
+void nestedRequestWithCount() {
+ typedef struct {
+ MPI_Request req[3];
+ MPI_Request req2;
+ } ReqStruct;
+
+ ReqStruct rs;
+ int rank = 0;
+ double buf = 0;
+ MPI_Comm_rank(MPI_COMM_WORLD, &rank);
+
+ for (int i = 0; i < 3; ++i)
+ MPI_Ireduce(MPI_IN_PLACE, &buf, 1, MPI_DOUBLE, MPI_SUM, 0, MPI_COMM_WORLD,
+ &rs.req[i]);
+ MPI_Ireduce(MPI_IN_PLACE, &buf, 1, MPI_DOUBLE, MPI_SUM, 0, MPI_COMM_WORLD,
+ &rs.req2);
+ MPI_Waitall(2, rs.req, MPI_STATUSES_IGNORE);
+ MPI_Waitall(1, rs.req + 2, MPI_STATUSES_IGNORE);
+ MPI_Wait(&rs.req2, MPI_STATUS_IGNORE);
+} // no error
+
+void nestedRequestWithCountMissingNonBlockingWait() {
+ typedef struct {
+ MPI_Request req[3];
+ MPI_Request req2;
+ } ReqStruct;
+
+ ReqStruct rs;
+ int rank = 0;
+ double buf = 0;
+ MPI_Comm_rank(MPI_COMM_WORLD, &rank);
+
+ for (int i = 0; i < 3; ++i)
+ MPI_Ireduce(MPI_IN_PLACE, &buf, 1, MPI_DOUBLE, MPI_SUM, 0, MPI_COMM_WORLD,
+ &rs.req[i]);
+ MPI_Ireduce(MPI_IN_PLACE, &buf, 1, MPI_DOUBLE, MPI_SUM, 0, MPI_COMM_WORLD,
+ &rs.req2);
+ MPI_Waitall(1, rs.req, MPI_STATUSES_IGNORE);
+ // MPI_Waitall(1, rs.req + 1, MPI_STATUSES_IGNORE);
+ MPI_Waitall(1, rs.req + 2, MPI_STATUSES_IGNORE);
+ MPI_Wait(&rs.req2, MPI_STATUS_IGNORE);
+} // expected-warning{{Request 'rs.req[1]' has no matching wait.}}
+
void singleRequestInWaitall() {
MPI_Request r;
int rank = 0;
Index: clang/test/Analysis/memory-model.cpp
===================================================================
--- clang/test/Analysis/memory-model.cpp
+++ clang/test/Analysis/memory-model.cpp
@@ -66,8 +66,8 @@
void field_ptr(S *a) {
clang_analyzer_dump(&a->f); // expected-warning {{Element{SymRegion{reg_$0<S * a>},0 S64b,struct S}.f}}
- clang_analyzer_dumpExtent(&a->f); // expected-warning {{4 S64b}}
- clang_analyzer_dumpElementCount(&a->f); // expected-warning {{1 S64b}}
+ clang_analyzer_dumpExtent(&a->f); // expected-warning {{extent_$1{SymRegion{reg_$0<S * a>}}}}
+ clang_analyzer_dumpElementCount(&a->f); // expected-warning {{(extent_$1{SymRegion{reg_$0<S * a>}}) / 4U}}
}
void symbolic_array() {
@@ -90,7 +90,7 @@
void symbolic_malloc() {
int *a = (int *)malloc(12);
clang_analyzer_dump(a); // expected-warning {{Element{HeapSymRegion{conj}}
- clang_analyzer_dumpExtent(a); // expected-warning {{12 U64b}}
+ clang_analyzer_dumpExtent(a); // expected-warning {{12 S64b}}
clang_analyzer_dumpElementCount(a); // expected-warning {{3 S64b}}
free(a);
}
@@ -98,22 +98,22 @@
void symbolic_alloca() {
int *a = (int *)alloca(12);
clang_analyzer_dump(a); // expected-warning {{Element{HeapSymRegion{conj}}
- clang_analyzer_dumpExtent(a); // expected-warning {{12 U64b}}
+ clang_analyzer_dumpExtent(a); // expected-warning {{12 S64b}}
clang_analyzer_dumpElementCount(a); // expected-warning {{3 S64b}}
}
void symbolic_complex() {
int *a = (int *)malloc(4);
- clang_analyzer_dumpExtent(a); // expected-warning {{4 U64b}}
+ clang_analyzer_dumpExtent(a); // expected-warning {{4 S64b}}
clang_analyzer_dumpElementCount(a); // expected-warning {{1 S64b}}
int *b = (int *)realloc(a, sizeof(int) * 2);
- clang_analyzer_dumpExtent(b); // expected-warning {{8 U64b}}
+ clang_analyzer_dumpExtent(b); // expected-warning {{8 S64b}}
clang_analyzer_dumpElementCount(b); // expected-warning {{2 S64b}}
free(b);
int *c = (int *)calloc(3, 4);
- clang_analyzer_dumpExtent(c); // expected-warning {{12 U64b}}
+ clang_analyzer_dumpExtent(c); // expected-warning {{12 S64b}}
clang_analyzer_dumpElementCount(c); // expected-warning {{3 S64b}}
free(c);
}
@@ -123,7 +123,7 @@
char *b = (char *)malloc(13);
clang_analyzer_dump(clang_analyzer_getExtent(a)); // expected-warning {{13 S64b}}
- clang_analyzer_dump(clang_analyzer_getExtent(b)); // expected-warning {{13 U64b}}
+ clang_analyzer_dump(clang_analyzer_getExtent(b)); // expected-warning {{13 S64b}}
clang_analyzer_eval(clang_analyzer_getExtent(a) ==
clang_analyzer_getExtent(b));
// expected-warning@-2 {{TRUE}}
@@ -155,3 +155,16 @@
operator delete[](a, std::align_val_t(32));
}
+
+int a[5][0];
+struct T {
+ int x[];
+};
+
+T t[5];
+void zero_sized_element() {
+ clang_analyzer_dumpExtent(a); // expected-warning {{0 S64b}}
+ clang_analyzer_dumpElementCount(a); // expected-warning {{5 S64b}}
+ clang_analyzer_dumpExtent(t); // expected-warning {{0 S64b}}
+ clang_analyzer_dumpElementCount(t); // expected-warning {{5 S64b}}
+}
Index: clang/test/Analysis/flexible-array-members.c
===================================================================
--- clang/test/Analysis/flexible-array-members.c
+++ clang/test/Analysis/flexible-array-members.c
@@ -44,20 +44,52 @@
clang_analyzer_dump(clang_analyzer_getExtent(&fam));
clang_analyzer_dump(clang_analyzer_getExtent(fam.data));
// expected-warning@-2 {{4 S64b}}
- // expected-warning@-2 {{Unknown}}
+ // expected-warning@-2 {{0 S64b}}
FAM *p = (FAM *)alloca(sizeof(FAM));
clang_analyzer_dump(clang_analyzer_getExtent(p));
clang_analyzer_dump(clang_analyzer_getExtent(p->data));
- // expected-warning@-2 {{4 U64b}}
- // expected-warning@-2 {{Unknown}}
+ // expected-warning@-2 {{4 S64b}}
+ // expected-warning@-2 {{0 S64b}}
FAM *q = (FAM *)malloc(sizeof(FAM));
clang_analyzer_dump(clang_analyzer_getExtent(q));
clang_analyzer_dump(clang_analyzer_getExtent(q->data));
- // expected-warning@-2 {{4 U64b}}
- // expected-warning@-2 {{Unknown}}
+ // expected-warning@-2 {{4 S64b}}
+ // expected-warning@-2 {{0 S64b}}
+ free(q);
+
+ q = (FAM *)malloc(sizeof(FAM) + sizeof(int) * 2);
+ clang_analyzer_dump(clang_analyzer_getExtent(q));
+ clang_analyzer_dump(clang_analyzer_getExtent(q->data));
+ // expected-warning@-2 {{12 S64b}}
+ // expected-warning@-2 {{8 S64b}}
free(q);
+
+ typedef struct __attribute__((packed)) {
+ char c;
+ int data[];
+ } PackedFAM;
+
+ PackedFAM *t = (PackedFAM *)malloc(sizeof(PackedFAM) + sizeof(int) * 2);
+ clang_analyzer_dump(clang_analyzer_getExtent(t));
+ clang_analyzer_dump(clang_analyzer_getExtent(t->data));
+ // expected-warning@-2 {{9 S64b}}
+ // expected-warning@-2 {{8 S64b}}
+ free(t);
+}
+
+void test_too_small_base(void) {
+ typedef struct FAM {
+ long c;
+ int data[];
+ } FAM;
+ short s = 0;
+ FAM *p = (FAM *) &s;
+ clang_analyzer_dump(clang_analyzer_getExtent(p));
+ clang_analyzer_dump(clang_analyzer_getExtent(p->data));
+ // expected-warning@-2 {{2 S64b}}
+ // expected-warning@-2 {{-6 S64b}}
}
void test_zero_length_array_fam(void) {
@@ -70,19 +102,19 @@
clang_analyzer_dump(clang_analyzer_getExtent(&fam));
clang_analyzer_dump(clang_analyzer_getExtent(fam.data));
// expected-warning@-2 {{4 S64b}}
- // expected-warning@-2 {{Unknown}}
+ // expected-warning@-2 {{0 S64b}}
FAM *p = (FAM *)alloca(sizeof(FAM));
clang_analyzer_dump(clang_analyzer_getExtent(p));
clang_analyzer_dump(clang_analyzer_getExtent(p->data));
- // expected-warning@-2 {{4 U64b}}
- // expected-warning@-2 {{Unknown}}
+ // expected-warning@-2 {{4 S64b}}
+ // expected-warning@-2 {{0 S64b}}
FAM *q = (FAM *)malloc(sizeof(FAM));
clang_analyzer_dump(clang_analyzer_getExtent(q));
clang_analyzer_dump(clang_analyzer_getExtent(q->data));
- // expected-warning@-2 {{4 U64b}}
- // expected-warning@-2 {{Unknown}}
+ // expected-warning@-2 {{4 S64b}}
+ // expected-warning@-2 {{0 S64b}}
free(q);
}
@@ -97,19 +129,19 @@
clang_analyzer_dump(clang_analyzer_getExtent(&likely_fam));
clang_analyzer_dump(clang_analyzer_getExtent(likely_fam.data));
// expected-warning@-2 {{8 S64b}}
- // expected-warning@-2 {{Unknown}}
+ // expected-warning@-2 {{4 S64b}}
FAM *p = (FAM *)alloca(sizeof(FAM));
clang_analyzer_dump(clang_analyzer_getExtent(p));
clang_analyzer_dump(clang_analyzer_getExtent(p->data));
- // expected-warning@-2 {{8 U64b}}
- // expected-warning@-2 {{Unknown}}
+ // expected-warning@-2 {{8 S64b}}
+ // expected-warning@-2 {{4 S64b}}
FAM *q = (FAM *)malloc(sizeof(FAM));
clang_analyzer_dump(clang_analyzer_getExtent(q));
clang_analyzer_dump(clang_analyzer_getExtent(q->data));
- // expected-warning@-2 {{8 U64b}}
- // expected-warning@-2 {{Unknown}}
+ // expected-warning@-2 {{8 S64b}}
+ // expected-warning@-2 {{4 S64b}}
free(q);
#else
FAM likely_fam;
@@ -121,13 +153,13 @@
FAM *p = (FAM *)alloca(sizeof(FAM));
clang_analyzer_dump(clang_analyzer_getExtent(p));
clang_analyzer_dump(clang_analyzer_getExtent(p->data));
- // expected-warning@-2 {{8 U64b}}
+ // expected-warning@-2 {{8 S64b}}
// expected-warning@-2 {{4 S64b}}
FAM *q = (FAM *)malloc(sizeof(FAM));
clang_analyzer_dump(clang_analyzer_getExtent(q));
clang_analyzer_dump(clang_analyzer_getExtent(q->data));
- // expected-warning@-2 {{8 U64b}}
+ // expected-warning@-2 {{8 S64b}}
// expected-warning@-2 {{4 S64b}}
free(q);
#endif
Index: clang/test/Analysis/array-bound-v2-constraint-check.c
===================================================================
--- clang/test/Analysis/array-bound-v2-constraint-check.c
+++ clang/test/Analysis/array-bound-v2-constraint-check.c
@@ -1,10 +1,10 @@
-// RUN: %clang_analyze_cc1 -analyzer-checker=core,alpha.security.ArrayBoundV2,debug.ExprInspection \
+// RUN: %clang_analyze_cc1 -analyzer-checker=core,unix.Malloc,alpha.security.ArrayBoundV2,debug.ExprInspection \
// RUN: -analyzer-config eagerly-assume=false -verify %s
void clang_analyzer_eval(int);
void clang_analyzer_printState(void);
-typedef unsigned long long size_t;
+typedef typeof(sizeof(int)) size_t;
const char a[] = "abcd"; // extent: 5 bytes
void symbolic_size_t_and_int0(size_t len) {
@@ -83,6 +83,18 @@
clang_analyzer_eval(len <= 2); // expected-warning {{UNKNOWN}}
}
+void *malloc(size_t);
+void free(void *);
+void symbolic_longlong_and_int0_dynamic_extent(long long len) {
+ char *b = malloc(5);
+ (void)b[len + 1]; // no-warning
+ // len: [-1,3]
+ clang_analyzer_eval(-1 <= len && len <= 3); // expected-warning {{TRUE}}
+ clang_analyzer_eval(0 <= len); // expected-warning {{UNKNOWN}}
+ clang_analyzer_eval(len <= 2); // expected-warning {{UNKNOWN}}
+ free(b);
+}
+
void symbolic_longlong_and_int1(long long len) {
(void)a[len]; // no-warning
// len: [0,4]
Index: clang/lib/StaticAnalyzer/Core/DynamicExtent.cpp
===================================================================
--- clang/lib/StaticAnalyzer/Core/DynamicExtent.cpp
+++ clang/lib/StaticAnalyzer/Core/DynamicExtent.cpp
@@ -30,7 +30,9 @@
MR = MR->StripCasts();
if (const DefinedOrUnknownSVal *Size = State->get<DynamicExtentMap>(MR))
- return *Size;
+ if (auto SSize =
+ SVB.convertToArrayIndex(*Size).getAs<DefinedOrUnknownSVal>())
+ return *SSize;
return MR->getMemRegionManager().getStaticSize(MR, SVB);
}
@@ -40,6 +42,39 @@
SVB.getArrayIndexType());
}
+static DefinedOrUnknownSVal getConstantArrayElementCount(SValBuilder &SVB,
+ const MemRegion *MR) {
+ if (!MR)
+ return UnknownVal();
+ MR = MR->StripCasts();
+
+ const auto *TVR = MR->getAs<TypedValueRegion>();
+ if (!TVR)
+ return UnknownVal();
+
+ QualType Ty = TVR->getValueType();
+ if (const auto *ConstArrayTy =
+ dyn_cast_or_null<ConstantArrayType>(Ty->getAsArrayTypeUnsafe()))
+ return SVB.makeIntVal(ConstArrayTy->getSize(), false);
+
+ return UnknownVal();
+}
+
+static DefinedOrUnknownSVal
+getDynamicElementCount(ProgramStateRef State, SVal Size,
+ DefinedOrUnknownSVal ElementSize) {
+ assert(!ElementSize.isZeroConstant() && "Non-zero element size expected");
+ if (Size.isUndef())
+ return UnknownVal();
+
+ SValBuilder &SVB = State->getStateManager().getSValBuilder();
+
+ auto ElementCount =
+ SVB.evalBinOp(State, BO_Div, Size, ElementSize, SVB.getArrayIndexType())
+ .getAs<DefinedOrUnknownSVal>();
+ return ElementCount ? *ElementCount : UnknownVal();
+}
+
DefinedOrUnknownSVal getDynamicElementCount(ProgramStateRef State,
const MemRegion *MR,
SValBuilder &SVB,
@@ -47,13 +82,12 @@
assert(MR != nullptr && "Not-null region expected");
MR = MR->StripCasts();
- DefinedOrUnknownSVal Size = getDynamicExtent(State, MR, SVB);
- SVal ElementSize = getElementExtent(ElementTy, SVB);
+ DefinedOrUnknownSVal ElementSize = getElementExtent(ElementTy, SVB);
+ if (ElementSize.isZeroConstant())
+ return getConstantArrayElementCount(SVB, MR);
- SVal ElementCount =
- SVB.evalBinOp(State, BO_Div, Size, ElementSize, SVB.getArrayIndexType());
-
- return ElementCount.castAs<DefinedOrUnknownSVal>();
+ return getDynamicElementCount(State, getDynamicExtent(State, MR, SVB),
+ ElementSize);
}
SVal getDynamicExtentWithOffset(ProgramStateRef State, SVal BufV) {
@@ -79,6 +113,18 @@
SvalBuilder.getArrayIndexType());
}
+DefinedOrUnknownSVal getDynamicElementCountWithOffset(ProgramStateRef State,
+ SVal BufV,
+ QualType ElementTy) {
+ SValBuilder &SVB = State->getStateManager().getSValBuilder();
+ DefinedOrUnknownSVal ElementSize = getElementExtent(ElementTy, SVB);
+ if (ElementSize.isZeroConstant())
+ return getConstantArrayElementCount(SVB, BufV.getAsRegion());
+
+ return getDynamicElementCount(State, getDynamicExtentWithOffset(State, BufV),
+ ElementSize);
+}
+
ProgramStateRef setDynamicExtent(ProgramStateRef State, const MemRegion *MR,
DefinedOrUnknownSVal Size, SValBuilder &SVB) {
MR = MR->StripCasts();
Index: clang/lib/StaticAnalyzer/Checkers/MPI-Checker/MPIChecker.cpp
===================================================================
--- clang/lib/StaticAnalyzer/Checkers/MPI-Checker/MPIChecker.cpp
+++ clang/lib/StaticAnalyzer/Checkers/MPI-Checker/MPIChecker.cpp
@@ -161,20 +161,41 @@
return;
}
- DefinedOrUnknownSVal ElementCount = getDynamicElementCount(
- Ctx.getState(), SuperRegion, Ctx.getSValBuilder(),
- CE.getArgExpr(1)->getType()->getPointeeType());
- const llvm::APSInt &ArrSize =
- ElementCount.castAs<nonloc::ConcreteInt>().getValue();
+ QualType ElemType = CE.getArgExpr(1)->getType()->getPointeeType();
+ ProgramStateRef State = Ctx.getState();
+ SValBuilder &SVB = Ctx.getSValBuilder();
+ ASTContext &ASTCtx = Ctx.getASTContext();
+
+ auto ElementCount =
+ getDynamicElementCountWithOffset(State, CE.getArgSVal(1), ElemType)
+ .getAs<nonloc::ConcreteInt>();
+ if (!ElementCount)
+ return;
+ const llvm::APSInt &ArrSize = ElementCount->getValue();
+
+ CharUnits ElemSizeInChars = ASTCtx.getTypeSizeInChars(ElemType);
+ int64_t ElemSizeInBits =
+ (ElemSizeInChars.isZero() ? 1 : ElemSizeInChars.getQuantity()) *
+ ASTCtx.getCharWidth();
+ const NonLoc MROffset =
+ SVB.makeArrayIndex(MR->getAsOffset().getOffset() / ElemSizeInBits);
+ SVal Count = CE.getArgSVal(0);
for (size_t i = 0; i < ArrSize; ++i) {
const NonLoc Idx = Ctx.getSValBuilder().makeArrayIndex(i);
-
- const ElementRegion *const ER = RegionManager.getElementRegion(
- CE.getArgExpr(1)->getType()->getPointeeType(), Idx, SuperRegion,
- Ctx.getASTContext());
-
- ReqRegions.push_back(ER->getAs<MemRegion>());
+ auto CountReached = SVB.evalBinOp(State, BO_GE, Idx, Count, ASTCtx.BoolTy)
+ .getAs<DefinedOrUnknownSVal>();
+ if (CountReached && State->assume(*CountReached, true))
+ break;
+
+ auto ElementRegionIndex =
+ SVB.evalBinOp(State, BO_Add, Idx, MROffset, SVB.getArrayIndexType())
+ .getAs<NonLoc>();
+ if (ElementRegionIndex) {
+ const ElementRegion *const ER = RegionManager.getElementRegion(
+ ElemType, *ElementRegionIndex, SuperRegion, Ctx.getASTContext());
+ ReqRegions.push_back(ER);
+ }
}
} else if (FuncClassifier->isMPI_Wait(CE.getCalleeIdentifier())) {
ReqRegions.push_back(MR);
Index: clang/lib/StaticAnalyzer/Checkers/ExprInspectionChecker.cpp
===================================================================
--- clang/lib/StaticAnalyzer/Checkers/ExprInspectionChecker.cpp
+++ clang/lib/StaticAnalyzer/Checkers/ExprInspectionChecker.cpp
@@ -325,12 +325,12 @@
void ExprInspectionChecker::analyzerGetExtent(const CallExpr *CE,
CheckerContext &C) const {
- const MemRegion *MR = getArgRegion(CE, C);
- if (!MR)
+ const Expr *Arg = getArgExpr(CE, C);
+ if (!Arg)
return;
ProgramStateRef State = C.getState();
- DefinedOrUnknownSVal Size = getDynamicExtent(State, MR, C.getSValBuilder());
+ SVal Size = getDynamicExtentWithOffset(State, C.getSVal(Arg));
State = State->BindExpr(CE, C.getLocationContext(), Size);
C.addTransition(State);
@@ -338,12 +338,12 @@
void ExprInspectionChecker::analyzerDumpExtent(const CallExpr *CE,
CheckerContext &C) const {
- const MemRegion *MR = getArgRegion(CE, C);
- if (!MR)
+ const Expr *Arg = getArgExpr(CE, C);
+ if (!Arg)
return;
- DefinedOrUnknownSVal Size =
- getDynamicExtent(C.getState(), MR, C.getSValBuilder());
+ ProgramStateRef State = C.getState();
+ SVal Size = getDynamicExtentWithOffset(State, C.getSVal(Arg));
printAndReport(C, Size);
}
@@ -362,8 +362,8 @@
assert(!ElementTy->isPointerType());
- DefinedOrUnknownSVal ElementCount =
- getDynamicElementCount(C.getState(), MR, C.getSValBuilder(), ElementTy);
+ DefinedOrUnknownSVal ElementCount = getDynamicElementCountWithOffset(
+ C.getState(), C.getSVal(getArgExpr(CE, C)), ElementTy);
printAndReport(C, ElementCount);
}
Index: clang/include/clang/StaticAnalyzer/Core/PathSensitive/DynamicExtent.h
===================================================================
--- clang/include/clang/StaticAnalyzer/Core/PathSensitive/DynamicExtent.h
+++ clang/include/clang/StaticAnalyzer/Core/PathSensitive/DynamicExtent.h
@@ -53,6 +53,11 @@
/// (bufptr) // extent is unknown
SVal getDynamicExtentWithOffset(ProgramStateRef State, SVal BufV);
+/// \returns The stored element count of the region represented by a symbolic
+/// value \p BufV.
+DefinedOrUnknownSVal getDynamicElementCountWithOffset(ProgramStateRef State,
+ SVal BufV, QualType Ty);
+
} // namespace ento
} // namespace clang
_______________________________________________
cfe-commits mailing list
[email protected]
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits