summaryrefslogtreecommitdiffstats
path: root/clang/lib
diff options
context:
space:
mode:
authorGabor Marton <gabor.marton@ericsson.com>2019-08-27 11:36:10 +0000
committerGabor Marton <gabor.marton@ericsson.com>2019-08-27 11:36:10 +0000
commitf035b75d8f079a7b3c8d5c163e2ab0596ac59d17 (patch)
tree728488b68992c3688630151ee4ed9e29361066cb /clang/lib
parentc397a266f01d7907e45a1f5c54bd9be219e94ea3 (diff)
downloadbcm5719-llvm-f035b75d8f079a7b3c8d5c163e2ab0596ac59d17.tar.gz
bcm5719-llvm-f035b75d8f079a7b3c8d5c163e2ab0596ac59d17.zip
[ASTImporter] Fix name conflict handling with different strategies
There are numorous flaws about the name conflict handling, this patch attempts fixes them. Changes in details: * HandleNameConflict return with a false DeclarationName Hitherto we effectively never returned with a NameConflict error, even if the preceding StructuralMatch indicated a conflict. Because we just simply returned with the parameter `Name` in HandleNameConflict and that name is almost always `true` when converted to `bool`. * Add tests which indicate wrong NameConflict handling * Add to ConflictingDecls only if decl kind is different Note, we might not indicate an ODR error when there is an existing record decl and a enum is imported with same name. But there are other cases. E.g. think about the case when we import a FunctionTemplateDecl with name f and we found a simple FunctionDecl with name f. They overload. Or in case of a ClassTemplateDecl and CXXRecordDecl, the CXXRecordDecl could be the 'templated' class, so it would be false to report error. So I think we should report a name conflict error only when we are 100% sure of that. That is why I think it should be a general pattern to report the error only if the kind is the same. * Fix failing ctu test with EnumConstandDecl In ctu-main.c we have the enum class 'A' which brings in the enum constant 'x' with value 0 into the global namespace. In ctu-other.c we had the enum class 'B' which brought in the same name ('x') as an enum constant but with a different enum value (42). This is clearly an ODR violation in the global namespace. The solution was to rename the second enum constant. * Introduce ODR handling strategies Reviewers: a_sidorin, shafik Differential Revision: https://reviews.llvm.org/D59692 llvm-svn: 370045
Diffstat (limited to 'clang/lib')
-rw-r--r--clang/lib/AST/ASTImporter.cpp171
1 files changed, 90 insertions, 81 deletions
diff --git a/clang/lib/AST/ASTImporter.cpp b/clang/lib/AST/ASTImporter.cpp
index 8a442bbef66..19321fd0747 100644
--- a/clang/lib/AST/ASTImporter.cpp
+++ b/clang/lib/AST/ASTImporter.cpp
@@ -80,6 +80,7 @@ namespace clang {
using ExpectedExpr = llvm::Expected<Expr *>;
using ExpectedDecl = llvm::Expected<Decl *>;
using ExpectedSLoc = llvm::Expected<SourceLocation>;
+ using ExpectedName = llvm::Expected<DeclarationName>;
std::string ImportError::toString() const {
// FIXME: Improve error texts.
@@ -2247,11 +2248,13 @@ ExpectedDecl ASTNodeImporter::VisitNamespaceDecl(NamespaceDecl *D) {
}
if (!ConflictingDecls.empty()) {
- Name = Importer.HandleNameConflict(Name, DC, Decl::IDNS_Namespace,
- ConflictingDecls.data(),
- ConflictingDecls.size());
- if (!Name)
- return make_error<ImportError>(ImportError::NameConflict);
+ ExpectedName NameOrErr = Importer.HandleNameConflict(
+ Name, DC, Decl::IDNS_Namespace, ConflictingDecls.data(),
+ ConflictingDecls.size());
+ if (NameOrErr)
+ Name = NameOrErr.get();
+ else
+ return NameOrErr.takeError();
}
}
@@ -2355,21 +2358,21 @@ ASTNodeImporter::VisitTypedefNameDecl(TypedefNameDecl *D, bool IsAlias) {
// already have a complete underlying type then return with that.
if (!FromUT->isIncompleteType() && !FoundUT->isIncompleteType())
return Importer.MapImported(D, FoundTypedef);
+ // FIXME Handle redecl chain. When you do that make consistent changes
+ // in ASTImporterLookupTable too.
+ } else {
+ ConflictingDecls.push_back(FoundDecl);
}
- // FIXME Handle redecl chain. When you do that make consistent changes
- // in ASTImporterLookupTable too.
- break;
}
-
- ConflictingDecls.push_back(FoundDecl);
}
if (!ConflictingDecls.empty()) {
- Name = Importer.HandleNameConflict(Name, DC, IDNS,
- ConflictingDecls.data(),
- ConflictingDecls.size());
- if (!Name)
- return make_error<ImportError>(ImportError::NameConflict);
+ ExpectedName NameOrErr = Importer.HandleNameConflict(
+ Name, DC, IDNS, ConflictingDecls.data(), ConflictingDecls.size());
+ if (NameOrErr)
+ Name = NameOrErr.get();
+ else
+ return NameOrErr.takeError();
}
}
@@ -2442,11 +2445,12 @@ ASTNodeImporter::VisitTypeAliasTemplateDecl(TypeAliasTemplateDecl *D) {
}
if (!ConflictingDecls.empty()) {
- Name = Importer.HandleNameConflict(Name, DC, IDNS,
- ConflictingDecls.data(),
- ConflictingDecls.size());
- if (!Name)
- return make_error<ImportError>(ImportError::NameConflict);
+ ExpectedName NameOrErr = Importer.HandleNameConflict(
+ Name, DC, IDNS, ConflictingDecls.data(), ConflictingDecls.size());
+ if (NameOrErr)
+ Name = NameOrErr.get();
+ else
+ return NameOrErr.takeError();
}
}
@@ -2550,17 +2554,18 @@ ExpectedDecl ASTNodeImporter::VisitEnumDecl(EnumDecl *D) {
continue;
if (IsStructuralMatch(D, FoundEnum))
return Importer.MapImported(D, FoundEnum);
+ ConflictingDecls.push_back(FoundDecl);
}
-
- ConflictingDecls.push_back(FoundDecl);
}
if (!ConflictingDecls.empty()) {
- Name = Importer.HandleNameConflict(SearchName, DC, IDNS,
- ConflictingDecls.data(),
- ConflictingDecls.size());
- if (!Name)
- return make_error<ImportError>(ImportError::NameConflict);
+ ExpectedName NameOrErr = Importer.HandleNameConflict(
+ SearchName, DC, IDNS, ConflictingDecls.data(),
+ ConflictingDecls.size());
+ if (NameOrErr)
+ Name = NameOrErr.get();
+ else
+ return NameOrErr.takeError();
}
}
@@ -2685,17 +2690,18 @@ ExpectedDecl ASTNodeImporter::VisitRecordDecl(RecordDecl *D) {
PrevDecl = FoundRecord->getMostRecentDecl();
break;
}
- }
-
- ConflictingDecls.push_back(FoundDecl);
+ ConflictingDecls.push_back(FoundDecl);
+ } // kind is RecordDecl
} // for
if (!ConflictingDecls.empty() && SearchName) {
- Name = Importer.HandleNameConflict(SearchName, DC, IDNS,
- ConflictingDecls.data(),
- ConflictingDecls.size());
- if (!Name)
- return make_error<ImportError>(ImportError::NameConflict);
+ ExpectedName NameOrErr = Importer.HandleNameConflict(
+ SearchName, DC, IDNS, ConflictingDecls.data(),
+ ConflictingDecls.size());
+ if (NameOrErr)
+ Name = NameOrErr.get();
+ else
+ return NameOrErr.takeError();
}
}
@@ -2854,17 +2860,17 @@ ExpectedDecl ASTNodeImporter::VisitEnumConstantDecl(EnumConstantDecl *D) {
if (auto *FoundEnumConstant = dyn_cast<EnumConstantDecl>(FoundDecl)) {
if (IsStructuralMatch(D, FoundEnumConstant))
return Importer.MapImported(D, FoundEnumConstant);
+ ConflictingDecls.push_back(FoundDecl);
}
-
- ConflictingDecls.push_back(FoundDecl);
}
if (!ConflictingDecls.empty()) {
- Name = Importer.HandleNameConflict(Name, DC, IDNS,
- ConflictingDecls.data(),
- ConflictingDecls.size());
- if (!Name)
- return make_error<ImportError>(ImportError::NameConflict);
+ ExpectedName NameOrErr = Importer.HandleNameConflict(
+ Name, DC, IDNS, ConflictingDecls.data(), ConflictingDecls.size());
+ if (NameOrErr)
+ Name = NameOrErr.get();
+ else
+ return NameOrErr.takeError();
}
}
@@ -3102,17 +3108,17 @@ ExpectedDecl ASTNodeImporter::VisitFunctionDecl(FunctionDecl *D) {
<< Name << D->getType() << FoundFunction->getType();
Importer.ToDiag(FoundFunction->getLocation(), diag::note_odr_value_here)
<< FoundFunction->getType();
+ ConflictingDecls.push_back(FoundDecl);
}
-
- ConflictingDecls.push_back(FoundDecl);
}
if (!ConflictingDecls.empty()) {
- Name = Importer.HandleNameConflict(Name, DC, IDNS,
- ConflictingDecls.data(),
- ConflictingDecls.size());
- if (!Name)
- return make_error<ImportError>(ImportError::NameConflict);
+ ExpectedName NameOrErr = Importer.HandleNameConflict(
+ Name, DC, IDNS, ConflictingDecls.data(), ConflictingDecls.size());
+ if (NameOrErr)
+ Name = NameOrErr.get();
+ else
+ return NameOrErr.takeError();
}
}
@@ -3758,17 +3764,17 @@ ExpectedDecl ASTNodeImporter::VisitVarDecl(VarDecl *D) {
<< Name << D->getType() << FoundVar->getType();
Importer.ToDiag(FoundVar->getLocation(), diag::note_odr_value_here)
<< FoundVar->getType();
+ ConflictingDecls.push_back(FoundDecl);
}
-
- ConflictingDecls.push_back(FoundDecl);
}
if (!ConflictingDecls.empty()) {
- Name = Importer.HandleNameConflict(Name, DC, IDNS,
- ConflictingDecls.data(),
- ConflictingDecls.size());
- if (!Name)
- return make_error<ImportError>(ImportError::NameConflict);
+ ExpectedName NameOrErr = Importer.HandleNameConflict(
+ Name, DC, IDNS, ConflictingDecls.data(), ConflictingDecls.size());
+ if (NameOrErr)
+ Name = NameOrErr.get();
+ else
+ return NameOrErr.takeError();
}
}
@@ -5106,19 +5112,19 @@ ExpectedDecl ASTNodeImporter::VisitClassTemplateDecl(ClassTemplateDecl *D) {
// see ASTTests test ImportExistingFriendClassTemplateDef.
continue;
}
+ ConflictingDecls.push_back(FoundDecl);
}
-
- ConflictingDecls.push_back(FoundDecl);
}
if (!ConflictingDecls.empty()) {
- Name = Importer.HandleNameConflict(Name, DC, Decl::IDNS_Ordinary,
- ConflictingDecls.data(),
- ConflictingDecls.size());
+ ExpectedName NameOrErr = Importer.HandleNameConflict(
+ Name, DC, Decl::IDNS_Ordinary, ConflictingDecls.data(),
+ ConflictingDecls.size());
+ if (NameOrErr)
+ Name = NameOrErr.get();
+ else
+ return NameOrErr.takeError();
}
-
- if (!Name)
- return make_error<ImportError>(ImportError::NameConflict);
}
CXXRecordDecl *FromTemplated = D->getTemplatedDecl();
@@ -5391,22 +5397,20 @@ ExpectedDecl ASTNodeImporter::VisitVarTemplateDecl(VarTemplateDecl *D) {
FoundTemplate->getTemplatedDecl());
return Importer.MapImported(D, FoundTemplate);
}
+ ConflictingDecls.push_back(FoundDecl);
}
-
- ConflictingDecls.push_back(FoundDecl);
}
if (!ConflictingDecls.empty()) {
- Name = Importer.HandleNameConflict(Name, DC, Decl::IDNS_Ordinary,
- ConflictingDecls.data(),
- ConflictingDecls.size());
+ ExpectedName NameOrErr = Importer.HandleNameConflict(
+ Name, DC, Decl::IDNS_Ordinary, ConflictingDecls.data(),
+ ConflictingDecls.size());
+ if (NameOrErr)
+ Name = NameOrErr.get();
+ else
+ return NameOrErr.takeError();
}
- if (!Name)
- // FIXME: Is it possible to get other error than name conflict?
- // (Put this `if` into the previous `if`?)
- return make_error<ImportError>(ImportError::NameConflict);
-
VarDecl *DTemplated = D->getTemplatedDecl();
// Import the type.
@@ -7817,7 +7821,7 @@ ASTImporter::ASTImporter(ASTContext &ToContext, FileManager &ToFileManager,
std::shared_ptr<ASTImporterSharedState> SharedState)
: SharedState(SharedState), ToContext(ToContext), FromContext(FromContext),
ToFileManager(ToFileManager), FromFileManager(FromFileManager),
- Minimal(MinimalImport) {
+ Minimal(MinimalImport), ODRHandling(ODRHandlingType::Conservative) {
// Create a default state without the lookup table: LLDB case.
if (!SharedState) {
@@ -8744,12 +8748,17 @@ Expected<Selector> ASTImporter::Import(Selector FromSel) {
return ToContext.Selectors.getSelector(FromSel.getNumArgs(), Idents.data());
}
-DeclarationName ASTImporter::HandleNameConflict(DeclarationName Name,
- DeclContext *DC,
- unsigned IDNS,
- NamedDecl **Decls,
- unsigned NumDecls) {
- return Name;
+Expected<DeclarationName> ASTImporter::HandleNameConflict(DeclarationName Name,
+ DeclContext *DC,
+ unsigned IDNS,
+ NamedDecl **Decls,
+ unsigned NumDecls) {
+ if (ODRHandling == ODRHandlingType::Conservative)
+ // Report error at any name conflict.
+ return make_error<ImportError>(ImportError::NameConflict);
+ else
+ // Allow to create the new Decl with the same name.
+ return Name;
}
DiagnosticBuilder ASTImporter::ToDiag(SourceLocation Loc, unsigned DiagID) {
OpenPOWER on IntegriCloud