[CrossTU] Handle case when no USR could be generated during Decl search.

Summary:
When searching for a declaration to be loaded the "lookup name" for every
other Decl is computed. If the USR can not be determined here should be
not an assert, instead skip this Decl.

Reviewers: martong

Reviewed By: martong

Subscribers: rnkovacs, dkrupp, Szelethus, gamesh411, cfe-commits

Tags: #clang

Differential Revision: https://reviews.llvm.org/D65445

llvm-svn: 368020
This commit is contained in:
Balazs Keri 2019-08-06 12:10:16 +00:00
parent 56bdb0c508
commit 4e79097dc7
7 changed files with 56 additions and 12 deletions

View File

@ -17,6 +17,7 @@
#include "clang/AST/ASTImporterSharedState.h" #include "clang/AST/ASTImporterSharedState.h"
#include "clang/Basic/LLVM.h" #include "clang/Basic/LLVM.h"
#include "llvm/ADT/DenseMap.h" #include "llvm/ADT/DenseMap.h"
#include "llvm/ADT/Optional.h"
#include "llvm/ADT/SmallPtrSet.h" #include "llvm/ADT/SmallPtrSet.h"
#include "llvm/ADT/StringMap.h" #include "llvm/ADT/StringMap.h"
#include "llvm/Support/Error.h" #include "llvm/Support/Error.h"
@ -159,7 +160,7 @@ public:
ASTUnit *Unit); ASTUnit *Unit);
/// Get a name to identify a named decl. /// Get a name to identify a named decl.
static std::string getLookupName(const NamedDecl *ND); static llvm::Optional<std::string> getLookupName(const NamedDecl *ND);
/// Emit diagnostics for the user for potential configuration errors. /// Emit diagnostics for the user for potential configuration errors.
void emitCrossTUDiagnostics(const IndexError &IE); void emitCrossTUDiagnostics(const IndexError &IE);

View File

@ -193,12 +193,13 @@ CrossTranslationUnitContext::CrossTranslationUnitContext(CompilerInstance &CI)
CrossTranslationUnitContext::~CrossTranslationUnitContext() {} CrossTranslationUnitContext::~CrossTranslationUnitContext() {}
std::string CrossTranslationUnitContext::getLookupName(const NamedDecl *ND) { llvm::Optional<std::string>
CrossTranslationUnitContext::getLookupName(const NamedDecl *ND) {
SmallString<128> DeclUSR; SmallString<128> DeclUSR;
bool Ret = index::generateUSRForDecl(ND, DeclUSR); bool Ret = index::generateUSRForDecl(ND, DeclUSR);
(void)Ret; if (Ret)
assert(!Ret && "Unable to generate USR"); return {};
return DeclUSR.str(); return std::string(DeclUSR.str());
} }
/// Recursively visits the decls of a DeclContext, and returns one with the /// Recursively visits the decls of a DeclContext, and returns one with the
@ -218,7 +219,8 @@ CrossTranslationUnitContext::findDefInDeclContext(const DeclContext *DC,
const T *ResultDecl; const T *ResultDecl;
if (!ND || !hasBodyOrInit(ND, ResultDecl)) if (!ND || !hasBodyOrInit(ND, ResultDecl))
continue; continue;
if (getLookupName(ResultDecl) != LookupName) llvm::Optional<std::string> ResultLookupName = getLookupName(ResultDecl);
if (!ResultLookupName || *ResultLookupName != LookupName)
continue; continue;
return ResultDecl; return ResultDecl;
} }
@ -233,12 +235,12 @@ llvm::Expected<const T *> CrossTranslationUnitContext::getCrossTUDefinitionImpl(
assert(!hasBodyOrInit(D) && assert(!hasBodyOrInit(D) &&
"D has a body or init in current translation unit!"); "D has a body or init in current translation unit!");
++NumGetCTUCalled; ++NumGetCTUCalled;
const std::string LookupName = getLookupName(D); const llvm::Optional<std::string> LookupName = getLookupName(D);
if (LookupName.empty()) if (!LookupName)
return llvm::make_error<IndexError>( return llvm::make_error<IndexError>(
index_error_code::failed_to_generate_usr); index_error_code::failed_to_generate_usr);
llvm::Expected<ASTUnit *> ASTUnitOrError = llvm::Expected<ASTUnit *> ASTUnitOrError =
loadExternalAST(LookupName, CrossTUDir, IndexName, DisplayCTUProgress); loadExternalAST(*LookupName, CrossTUDir, IndexName, DisplayCTUProgress);
if (!ASTUnitOrError) if (!ASTUnitOrError)
return ASTUnitOrError.takeError(); return ASTUnitOrError.takeError();
ASTUnit *Unit = *ASTUnitOrError; ASTUnit *Unit = *ASTUnitOrError;
@ -294,7 +296,7 @@ llvm::Expected<const T *> CrossTranslationUnitContext::getCrossTUDefinitionImpl(
} }
TranslationUnitDecl *TU = Unit->getASTContext().getTranslationUnitDecl(); TranslationUnitDecl *TU = Unit->getASTContext().getTranslationUnitDecl();
if (const T *ResultDecl = findDefInDeclContext<T>(TU, LookupName)) if (const T *ResultDecl = findDefInDeclContext<T>(TU, *LookupName))
return importDefinition(ResultDecl, Unit); return importDefinition(ResultDecl, Unit);
return llvm::make_error<IndexError>(index_error_code::failed_import); return llvm::make_error<IndexError>(index_error_code::failed_import);
} }

View File

@ -131,3 +131,17 @@ union U {
const unsigned int b; const unsigned int b;
}; };
U extU = {.a = 4}; U extU = {.a = 4};
class TestAnonUnionUSR {
public:
inline float f(int value) {
union {
float f;
int i;
};
i = value;
return f;
}
static const int Test;
};
const int TestAnonUnionUSR::Test = 5;

View File

@ -25,3 +25,4 @@ c:@extSCN ctu-other.cpp.ast
c:@extSubSCN ctu-other.cpp.ast c:@extSubSCN ctu-other.cpp.ast
c:@extSCC ctu-other.cpp.ast c:@extSCC ctu-other.cpp.ast
c:@extU ctu-other.cpp.ast c:@extU ctu-other.cpp.ast
c:@S@TestAnonUnionUSR@Test ctu-other.cpp.ast

View File

@ -112,6 +112,19 @@ void test_virtual_functions(mycls* obj) {
clang_analyzer_eval(obj->fvcl(1) == 8); // expected-warning{{FALSE}} expected-warning{{TRUE}} clang_analyzer_eval(obj->fvcl(1) == 8); // expected-warning{{FALSE}} expected-warning{{TRUE}}
} }
class TestAnonUnionUSR {
public:
inline float f(int value) {
union {
float f;
int i;
};
i = value;
return f;
}
static const int Test;
};
int main() { int main() {
clang_analyzer_eval(f(3) == 2); // expected-warning{{TRUE}} clang_analyzer_eval(f(3) == 2); // expected-warning{{TRUE}}
clang_analyzer_eval(f(4) == 3); // expected-warning{{TRUE}} clang_analyzer_eval(f(4) == 3); // expected-warning{{TRUE}}
@ -144,4 +157,5 @@ int main() {
clang_analyzer_eval(extSubSCN.a == 1); // expected-warning{{TRUE}} clang_analyzer_eval(extSubSCN.a == 1); // expected-warning{{TRUE}}
// clang_analyzer_eval(extSCC.a == 7); // TODO // clang_analyzer_eval(extSCC.a == 7); // TODO
clang_analyzer_eval(extU.a == 4); // expected-warning{{TRUE}} clang_analyzer_eval(extU.a == 4); // expected-warning{{TRUE}}
clang_analyzer_eval(TestAnonUnionUSR::Test == 5); // expected-warning{{TRUE}}
} }

View File

@ -41,3 +41,10 @@ union U {
}; };
U u = {.a = 6}; U u = {.a = 6};
// CHECK-DAG: c:@u // CHECK-DAG: c:@u
// No USR can be generated for this.
// Check for no crash in this case.
static union {
float uf;
const int ui;
};

View File

@ -76,7 +76,12 @@ void MapExtDefNamesConsumer::handleDecl(const Decl *D) {
void MapExtDefNamesConsumer::addIfInMain(const DeclaratorDecl *DD, void MapExtDefNamesConsumer::addIfInMain(const DeclaratorDecl *DD,
SourceLocation defStart) { SourceLocation defStart) {
std::string LookupName = CrossTranslationUnitContext::getLookupName(DD); llvm::Optional<std::string> LookupName =
CrossTranslationUnitContext::getLookupName(DD);
if (!LookupName)
return;
assert(!LookupName->empty() && "Lookup name should be non-empty.");
if (CurrentFileName.empty()) { if (CurrentFileName.empty()) {
CurrentFileName = CurrentFileName =
SM.getFileEntryForID(SM.getMainFileID())->tryGetRealPathName(); SM.getFileEntryForID(SM.getMainFileID())->tryGetRealPathName();
@ -89,7 +94,7 @@ void MapExtDefNamesConsumer::addIfInMain(const DeclaratorDecl *DD,
case VisibleNoLinkage: case VisibleNoLinkage:
case UniqueExternalLinkage: case UniqueExternalLinkage:
if (SM.isInMainFile(defStart)) if (SM.isInMainFile(defStart))
Index[LookupName] = CurrentFileName; Index[*LookupName] = CurrentFileName;
break; break;
default: default:
break; break;