forked from OSchip/llvm-project
[analyzer][ctu] Only import const and trivial VarDecls
Do import the definition of objects from a foreign translation unit if that's type is const and trivial. Differential Revision: https://reviews.llvm.org/D122805
This commit is contained in:
parent
111cb395c9
commit
e63b81d10e
|
@ -109,8 +109,10 @@ llvm::Expected<InvocationListTy> parseInvocationList(
|
||||||
StringRef FileContent,
|
StringRef FileContent,
|
||||||
llvm::sys::path::Style PathStyle = llvm::sys::path::Style::posix);
|
llvm::sys::path::Style PathStyle = llvm::sys::path::Style::posix);
|
||||||
|
|
||||||
// Returns true if the variable or any field of a record variable is const.
|
/// Returns true if it makes sense to import a foreign variable definition.
|
||||||
bool containsConst(const VarDecl *VD, const ASTContext &ACtx);
|
/// For instance, we don't want to import variables that have non-trivial types
|
||||||
|
/// because the constructor might have side-effects.
|
||||||
|
bool shouldImport(const VarDecl *VD, const ASTContext &ACtx);
|
||||||
|
|
||||||
/// This class is used for tools that requires cross translation
|
/// This class is used for tools that requires cross translation
|
||||||
/// unit capability.
|
/// unit capability.
|
||||||
|
|
|
@ -220,14 +220,9 @@ createCrossTUIndexString(const llvm::StringMap<std::string> &Index) {
|
||||||
return Result.str();
|
return Result.str();
|
||||||
}
|
}
|
||||||
|
|
||||||
bool containsConst(const VarDecl *VD, const ASTContext &ACtx) {
|
bool shouldImport(const VarDecl *VD, const ASTContext &ACtx) {
|
||||||
CanQualType CT = ACtx.getCanonicalType(VD->getType());
|
CanQualType CT = ACtx.getCanonicalType(VD->getType());
|
||||||
if (!CT.isConstQualified()) {
|
return CT.isConstQualified() && VD->getType().isTrivialType(ACtx);
|
||||||
const RecordType *RTy = CT->getAs<RecordType>();
|
|
||||||
if (!RTy || !RTy->hasConstFields())
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
return true;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool hasBodyOrInit(const FunctionDecl *D, const FunctionDecl *&DefD) {
|
static bool hasBodyOrInit(const FunctionDecl *D, const FunctionDecl *&DefD) {
|
||||||
|
|
|
@ -289,7 +289,7 @@ public:
|
||||||
return true;
|
return true;
|
||||||
|
|
||||||
if (VD->hasExternalStorage() || VD->isStaticDataMember()) {
|
if (VD->hasExternalStorage() || VD->isStaticDataMember()) {
|
||||||
if (!cross_tu::containsConst(VD, *Ctx))
|
if (!cross_tu::shouldImport(VD, *Ctx))
|
||||||
return true;
|
return true;
|
||||||
} else {
|
} else {
|
||||||
// Cannot be initialized in another TU.
|
// Cannot be initialized in another TU.
|
||||||
|
|
|
@ -102,6 +102,12 @@ struct S {
|
||||||
int a;
|
int a;
|
||||||
};
|
};
|
||||||
extern const S extS = {.a = 4};
|
extern const S extS = {.a = 4};
|
||||||
|
extern S extNonConstS = {.a = 4};
|
||||||
|
struct NonTrivialS {
|
||||||
|
int a;
|
||||||
|
~NonTrivialS();
|
||||||
|
};
|
||||||
|
extern const NonTrivialS extNTS = {.a = 4};
|
||||||
struct A {
|
struct A {
|
||||||
static const int a;
|
static const int a;
|
||||||
};
|
};
|
||||||
|
@ -109,18 +115,18 @@ const int A::a = 3;
|
||||||
struct SC {
|
struct SC {
|
||||||
const int a;
|
const int a;
|
||||||
};
|
};
|
||||||
SC extSC = {.a = 8};
|
extern const SC extSC = {.a = 8};
|
||||||
struct ST {
|
struct ST {
|
||||||
static struct SC sc;
|
static const struct SC sc;
|
||||||
};
|
};
|
||||||
struct SC ST::sc = {.a = 2};
|
const struct SC ST::sc = {.a = 2};
|
||||||
struct SCNest {
|
struct SCNest {
|
||||||
struct SCN {
|
struct SCN {
|
||||||
const int a;
|
const int a;
|
||||||
} scn;
|
} scn;
|
||||||
};
|
};
|
||||||
SCNest extSCN = {.scn = {.a = 9}};
|
SCNest extSCN = {.scn = {.a = 9}};
|
||||||
SCNest::SCN extSubSCN = {.a = 1};
|
extern SCNest::SCN const extSubSCN = {.a = 1};
|
||||||
struct SCC {
|
struct SCC {
|
||||||
SCC(int c) : a(c) {}
|
SCC(int c) : a(c) {}
|
||||||
const int a;
|
const int a;
|
||||||
|
@ -130,7 +136,7 @@ union U {
|
||||||
const int a;
|
const int a;
|
||||||
const unsigned int b;
|
const unsigned int b;
|
||||||
};
|
};
|
||||||
U extU = {.a = 4};
|
extern const U extU = {.a = 4};
|
||||||
|
|
||||||
class TestAnonUnionUSR {
|
class TestAnonUnionUSR {
|
||||||
public:
|
public:
|
||||||
|
|
|
@ -18,6 +18,7 @@
|
||||||
9:c:@extInt ctu-other.cpp.ast
|
9:c:@extInt ctu-other.cpp.ast
|
||||||
17:c:@N@intns@extInt ctu-other.cpp.ast
|
17:c:@N@intns@extInt ctu-other.cpp.ast
|
||||||
7:c:@extS ctu-other.cpp.ast
|
7:c:@extS ctu-other.cpp.ast
|
||||||
|
9:c:@extNTS ctu-other.cpp.ast
|
||||||
8:c:@S@A@a ctu-other.cpp.ast
|
8:c:@S@A@a ctu-other.cpp.ast
|
||||||
8:c:@extSC ctu-other.cpp.ast
|
8:c:@extSC ctu-other.cpp.ast
|
||||||
10:c:@S@ST@sc ctu-other.cpp.ast
|
10:c:@S@ST@sc ctu-other.cpp.ast
|
||||||
|
|
|
@ -74,6 +74,13 @@ struct S {
|
||||||
int a;
|
int a;
|
||||||
};
|
};
|
||||||
extern const S extS;
|
extern const S extS;
|
||||||
|
extern S extNonConstS;
|
||||||
|
struct NonTrivialS {
|
||||||
|
int a;
|
||||||
|
// User declaring a dtor makes it non-trivial.
|
||||||
|
~NonTrivialS();
|
||||||
|
};
|
||||||
|
extern const NonTrivialS extNTS;
|
||||||
extern const int extHere;
|
extern const int extHere;
|
||||||
const int extHere = 6;
|
const int extHere = 6;
|
||||||
struct A {
|
struct A {
|
||||||
|
@ -82,9 +89,9 @@ struct A {
|
||||||
struct SC {
|
struct SC {
|
||||||
const int a;
|
const int a;
|
||||||
};
|
};
|
||||||
extern SC extSC;
|
extern const SC extSC;
|
||||||
struct ST {
|
struct ST {
|
||||||
static struct SC sc;
|
static const struct SC sc;
|
||||||
};
|
};
|
||||||
struct SCNest {
|
struct SCNest {
|
||||||
struct SCN {
|
struct SCN {
|
||||||
|
@ -92,7 +99,7 @@ struct SCNest {
|
||||||
} scn;
|
} scn;
|
||||||
};
|
};
|
||||||
extern SCNest extSCN;
|
extern SCNest extSCN;
|
||||||
extern SCNest::SCN extSubSCN;
|
extern const SCNest::SCN extSubSCN;
|
||||||
struct SCC {
|
struct SCC {
|
||||||
SCC(int c);
|
SCC(int c);
|
||||||
const int a;
|
const int a;
|
||||||
|
@ -102,7 +109,7 @@ union U {
|
||||||
const int a;
|
const int a;
|
||||||
const unsigned int b;
|
const unsigned int b;
|
||||||
};
|
};
|
||||||
extern U extU;
|
extern const U extU;
|
||||||
|
|
||||||
void test_virtual_functions(mycls* obj) {
|
void test_virtual_functions(mycls* obj) {
|
||||||
// The dynamic type is known.
|
// The dynamic type is known.
|
||||||
|
@ -153,6 +160,9 @@ int main() {
|
||||||
clang_analyzer_eval(extInt == 2); // expected-warning{{TRUE}}
|
clang_analyzer_eval(extInt == 2); // expected-warning{{TRUE}}
|
||||||
clang_analyzer_eval(intns::extInt == 3); // expected-warning{{TRUE}}
|
clang_analyzer_eval(intns::extInt == 3); // expected-warning{{TRUE}}
|
||||||
clang_analyzer_eval(extS.a == 4); // expected-warning{{TRUE}}
|
clang_analyzer_eval(extS.a == 4); // expected-warning{{TRUE}}
|
||||||
|
clang_analyzer_eval(extNonConstS.a == 4); // expected-warning{{TRUE}} expected-warning{{FALSE}}
|
||||||
|
// Do not import non-trivial classes' initializers.
|
||||||
|
clang_analyzer_eval(extNTS.a == 4); // expected-warning{{TRUE}} expected-warning{{FALSE}}
|
||||||
clang_analyzer_eval(extHere == 6); // expected-warning{{TRUE}}
|
clang_analyzer_eval(extHere == 6); // expected-warning{{TRUE}}
|
||||||
clang_analyzer_eval(A::a == 3); // expected-warning{{TRUE}}
|
clang_analyzer_eval(A::a == 3); // expected-warning{{TRUE}}
|
||||||
clang_analyzer_eval(extSC.a == 8); // expected-warning{{TRUE}}
|
clang_analyzer_eval(extSC.a == 8); // expected-warning{{TRUE}}
|
||||||
|
|
|
@ -23,7 +23,7 @@ extern S const s = {.a = 2};
|
||||||
struct SF {
|
struct SF {
|
||||||
const int a;
|
const int a;
|
||||||
};
|
};
|
||||||
SF sf = {.a = 2};
|
extern const SF sf = {.a = 2};
|
||||||
// CHECK-DAG: 5:c:@sf
|
// CHECK-DAG: 5:c:@sf
|
||||||
|
|
||||||
struct SStatic {
|
struct SStatic {
|
||||||
|
@ -39,7 +39,7 @@ union U {
|
||||||
const int a;
|
const int a;
|
||||||
const unsigned int b;
|
const unsigned int b;
|
||||||
};
|
};
|
||||||
U u = {.a = 6};
|
extern const U u = {.a = 6};
|
||||||
// CHECK-DAG: 4:c:@u
|
// CHECK-DAG: 4:c:@u
|
||||||
|
|
||||||
// No USR can be generated for this.
|
// No USR can be generated for this.
|
||||||
|
|
|
@ -64,7 +64,7 @@ void MapExtDefNamesConsumer::handleDecl(const Decl *D) {
|
||||||
if (const Stmt *Body = FD->getBody())
|
if (const Stmt *Body = FD->getBody())
|
||||||
addIfInMain(FD, Body->getBeginLoc());
|
addIfInMain(FD, Body->getBeginLoc());
|
||||||
} else if (const auto *VD = dyn_cast<VarDecl>(D)) {
|
} else if (const auto *VD = dyn_cast<VarDecl>(D)) {
|
||||||
if (cross_tu::containsConst(VD, Ctx) && VD->hasInit())
|
if (cross_tu::shouldImport(VD, Ctx) && VD->hasInit())
|
||||||
if (const Expr *Init = VD->getInit())
|
if (const Expr *Init = VD->getInit())
|
||||||
addIfInMain(VD, Init->getBeginLoc());
|
addIfInMain(VD, Init->getBeginLoc());
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue