Diagnose shadowing of decls in the std namespace

Related to the discussion in ROOT-5971 (see https://sft.its.cern.ch/jira/browse/ROOT-5971),
this commit improves the situation by diagnosing the shadowing of declarations
in the `std` namespace.

In summary, given that ROOT issues an implicit `using namespace std;` and due to
the way `SemaLookup` works, decls that shadow something in the `std` namespace
cannot be referenced without using their fully-qualified name, i.e. `::xxx`.
Thus, we need to emit a warning for that case.
This commit is contained in:
Javier Lopez-Gomez 2022-02-02 12:00:38 +01:00 committed by jenkins
parent 2e500a3fb8
commit 0d71789370
2 changed files with 23 additions and 2 deletions

View File

@ -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 {

View File

@ -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;