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,
|
||||
llvm::sys::path::Style PathStyle = llvm::sys::path::Style::posix);
|
||||
|
||||
// Returns true if the variable or any field of a record variable is const.
|
||||
bool containsConst(const VarDecl *VD, const ASTContext &ACtx);
|
||||
/// Returns true if it makes sense to import a foreign variable definition.
|
||||
/// 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
|
||||
/// unit capability.
|
||||
|
|
|
@ -220,14 +220,9 @@ createCrossTUIndexString(const llvm::StringMap<std::string> &Index) {
|
|||
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());
|
||||
if (!CT.isConstQualified()) {
|
||||
const RecordType *RTy = CT->getAs<RecordType>();
|
||||
if (!RTy || !RTy->hasConstFields())
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
return CT.isConstQualified() && VD->getType().isTrivialType(ACtx);
|
||||
}
|
||||
|
||||
static bool hasBodyOrInit(const FunctionDecl *D, const FunctionDecl *&DefD) {
|
||||
|
|
|
@ -289,7 +289,7 @@ public:
|
|||
return true;
|
||||
|
||||
if (VD->hasExternalStorage() || VD->isStaticDataMember()) {
|
||||
if (!cross_tu::containsConst(VD, *Ctx))
|
||||
if (!cross_tu::shouldImport(VD, *Ctx))
|
||||
return true;
|
||||
} else {
|
||||
// Cannot be initialized in another TU.
|
||||
|
|
|
@ -102,6 +102,12 @@ struct S {
|
|||
int a;
|
||||
};
|
||||
extern const S extS = {.a = 4};
|
||||
extern S extNonConstS = {.a = 4};
|
||||
struct NonTrivialS {
|
||||
int a;
|
||||
~NonTrivialS();
|
||||
};
|
||||
extern const NonTrivialS extNTS = {.a = 4};
|
||||
struct A {
|
||||
static const int a;
|
||||
};
|
||||
|
@ -109,18 +115,18 @@ const int A::a = 3;
|
|||
struct SC {
|
||||
const int a;
|
||||
};
|
||||
SC extSC = {.a = 8};
|
||||
extern const SC extSC = {.a = 8};
|
||||
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 SCN {
|
||||
const int a;
|
||||
} scn;
|
||||
};
|
||||
SCNest extSCN = {.scn = {.a = 9}};
|
||||
SCNest::SCN extSubSCN = {.a = 1};
|
||||
extern SCNest::SCN const extSubSCN = {.a = 1};
|
||||
struct SCC {
|
||||
SCC(int c) : a(c) {}
|
||||
const int a;
|
||||
|
@ -130,7 +136,7 @@ union U {
|
|||
const int a;
|
||||
const unsigned int b;
|
||||
};
|
||||
U extU = {.a = 4};
|
||||
extern const U extU = {.a = 4};
|
||||
|
||||
class TestAnonUnionUSR {
|
||||
public:
|
||||
|
|
|
@ -18,6 +18,7 @@
|
|||
9:c:@extInt ctu-other.cpp.ast
|
||||
17:c:@N@intns@extInt 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:@extSC ctu-other.cpp.ast
|
||||
10:c:@S@ST@sc ctu-other.cpp.ast
|
||||
|
|
|
@ -74,6 +74,13 @@ struct S {
|
|||
int a;
|
||||
};
|
||||
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;
|
||||
const int extHere = 6;
|
||||
struct A {
|
||||
|
@ -82,9 +89,9 @@ struct A {
|
|||
struct SC {
|
||||
const int a;
|
||||
};
|
||||
extern SC extSC;
|
||||
extern const SC extSC;
|
||||
struct ST {
|
||||
static struct SC sc;
|
||||
static const struct SC sc;
|
||||
};
|
||||
struct SCNest {
|
||||
struct SCN {
|
||||
|
@ -92,7 +99,7 @@ struct SCNest {
|
|||
} scn;
|
||||
};
|
||||
extern SCNest extSCN;
|
||||
extern SCNest::SCN extSubSCN;
|
||||
extern const SCNest::SCN extSubSCN;
|
||||
struct SCC {
|
||||
SCC(int c);
|
||||
const int a;
|
||||
|
@ -102,7 +109,7 @@ union U {
|
|||
const int a;
|
||||
const unsigned int b;
|
||||
};
|
||||
extern U extU;
|
||||
extern const U extU;
|
||||
|
||||
void test_virtual_functions(mycls* obj) {
|
||||
// The dynamic type is known.
|
||||
|
@ -153,6 +160,9 @@ int main() {
|
|||
clang_analyzer_eval(extInt == 2); // expected-warning{{TRUE}}
|
||||
clang_analyzer_eval(intns::extInt == 3); // 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(A::a == 3); // expected-warning{{TRUE}}
|
||||
clang_analyzer_eval(extSC.a == 8); // expected-warning{{TRUE}}
|
||||
|
|
|
@ -23,7 +23,7 @@ extern S const s = {.a = 2};
|
|||
struct SF {
|
||||
const int a;
|
||||
};
|
||||
SF sf = {.a = 2};
|
||||
extern const SF sf = {.a = 2};
|
||||
// CHECK-DAG: 5:c:@sf
|
||||
|
||||
struct SStatic {
|
||||
|
@ -39,7 +39,7 @@ union U {
|
|||
const int a;
|
||||
const unsigned int b;
|
||||
};
|
||||
U u = {.a = 6};
|
||||
extern const U u = {.a = 6};
|
||||
// CHECK-DAG: 4:c:@u
|
||||
|
||||
// No USR can be generated for this.
|
||||
|
|
|
@ -64,7 +64,7 @@ void MapExtDefNamesConsumer::handleDecl(const Decl *D) {
|
|||
if (const Stmt *Body = FD->getBody())
|
||||
addIfInMain(FD, Body->getBeginLoc());
|
||||
} 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())
|
||||
addIfInMain(VD, Init->getBeginLoc());
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue