diff --git a/lib/Interpreter/DefinitionShadower.cpp b/lib/Interpreter/DefinitionShadower.cpp index 04b9bb05..31331bcb 100644 --- a/lib/Interpreter/DefinitionShadower.cpp +++ b/lib/Interpreter/DefinitionShadower.cpp @@ -62,7 +62,11 @@ namespace cling { DefinitionShadower::DefinitionShadower(Sema& S, Interpreter& I) : ASTTransformer(&S), m_Context(S.getASTContext()), m_Interp(I), - m_TU(S.getASTContext().getTranslationUnitDecl()) + m_TU(S.getASTContext().getTranslationUnitDecl()), + m_ShadowsDeclInStdDiagID(S.getDiagnostics().getCustomDiagID( + DiagnosticsEngine::Warning, + "'%0' shadows a declaration with the same name in the 'std' " + "namespace; consider using '::%0' to reference this declaration")) {} bool DefinitionShadower::isClingShadowNamespace(const DeclContext *DC) { @@ -94,9 +98,12 @@ namespace cling { } void DefinitionShadower::invalidatePreviousDefinitions(NamedDecl *D) const { + // NotForRedeclaration: lookup anything visible; follows using directives LookupResult Previous(*m_Sema, D->getDeclName(), D->getLocation(), - Sema::LookupOrdinaryName, Sema::ForVisibleRedeclaration); + Sema::LookupOrdinaryName, Sema::NotForRedeclaration); + Previous.suppressDiagnostics(); m_Sema->LookupQualifiedName(Previous, m_TU); + bool shadowsDeclInStd{}; for (auto Prev : Previous) { if (Prev == D) @@ -116,6 +123,7 @@ namespace cling { /*IsForUsingDecl=*/false)) continue; + shadowsDeclInStd |= Prev->isInStdNamespace(); hideDecl(Prev); // For unscoped enumerations, also invalidate all enumerators. @@ -132,6 +140,18 @@ namespace cling { // : reference to 'xxx' is ambiguous" in `class C {}; class C; C foo;`. if (!Previous.empty() && !isDefinition(D)) D->setInvalidDecl(); + + // Diagnose shadowing of decls in the `std` namespace (see ROOT-5971). + // For unnamed macros, the input is ingested in a single `Interpreter::process()` + // call. Do not emit the warning in that case, as all references are local + // to the wrapper function and this diagnostic might be misleading. + if (shadowsDeclInStd + && ((m_Interp.getInputFlags() & (Interpreter::kInputFromFile + | Interpreter::kIFFLineByLine)) + != Interpreter::kInputFromFile)) { + m_Sema->Diag(D->getBeginLoc(), m_ShadowsDeclInStdDiagID) + << D->getQualifiedNameAsString(); + } } void DefinitionShadower::invalidatePreviousDefinitions(FunctionDecl *D) const { diff --git a/lib/Interpreter/DefinitionShadower.h b/lib/Interpreter/DefinitionShadower.h index affffff5..b8b11301 100644 --- a/lib/Interpreter/DefinitionShadower.h +++ b/lib/Interpreter/DefinitionShadower.h @@ -53,6 +53,7 @@ namespace cling { clang::ASTContext &m_Context; Interpreter &m_Interp; clang::TranslationUnitDecl *m_TU; + unsigned m_ShadowsDeclInStdDiagID; unsigned long long m_UniqueNameCounter = 0;