This is an archive of the discontinued LLVM Phabricator instance.

[clang][parser] Fix namespace dropping after malformed declarations
ClosedPublic

Authored by alejandro-alvarez-sonarsource on May 10 2023, 2:22 AM.

Details

Summary
  • After a malformed top-level declaration
  • After a malformed templated class method declaration

In both cases, when there is a malformed declaration, any following namespace is dropped from the AST.
This can trigger a cascade of confusing diagnostics that may hide the original error. An example:

// Start #include "SomeFile.h"
template <class T>
void Foo<T>::Bar(void* aRawPtr) {
    (void)(aRawPtr);
}
// End #include "SomeFile.h"

#include <iostream>

int main() {}

We get the original error, plus 19 others from the standard library.
With this patch, we only get the original error.

clangd can also benefit from this patch, as namespaces following the malformed declaration is now preserved. i.e.

#pragma once

MACRO_FROM_MISSING_INCLUDE("X")

namespace my_namespace {
    //...
}

Before this patch, my_namespace is not visible for auto-completion.

Diff Detail

Event Timeline

Herald added a project: Restricted Project. · View Herald TranscriptMay 10 2023, 2:22 AM
Herald added a subscriber: kadircet. · View Herald Transcript
alejandro-alvarez-sonarsource requested review of this revision.May 10 2023, 2:22 AM

Thank you for working on this! FWIW, I verified that the precommit CI failures are unrelated to this patch.

Can you add a release note to clang/docs/ReleaseNotes.rst about the fix?

clang/lib/Parse/ParseDecl.cpp
2178–2179

It'd help to update the comment below since it doesn't mention why namespaces are handled specially.

2308–2311

Changes for our coding style.

There seems to be some unfortunate interplay here though. Consider:

void bar() namespace foo { int i; }

int main() {
  foo::i = 12;
}

Calling SkipMalformedDecl() changes the behavior for this test case because we don't recover as well. With your patch applied, this gives us two diagnostics:

C:\Users\aballman\OneDrive - Intel Corporation\Desktop\test.cpp:1:11: error: expected ';' after top level declarator
void bar() namespace foo { int i; }
          ^
          ;
C:\Users\aballman\OneDrive - Intel Corporation\Desktop\test.cpp:4:3: error: use of undeclared identifier 'foo'
  foo::i = 12;
  ^
2 errors generated.

If the namespace keyword is on its own line, then we recover gracefully and don't emit the "use of undeclared identifier" warning.

While this is technically a regression in behavior for this test case, I think the overall changes are still an improvement. I suspect not a whole lot of code puts namespace somewhere other than the start of a line (same for inline namespace which has the same behavior with your patch).

clang/lib/Parse/ParseTemplate.cpp
278

We'll have the same sort of recovery issues here unless the namespace is on its own line, but that also seems like a highly unlikely scenario.

clang/test/Parser/cxx-namespace-after-missing-semicolon.cpp
2
clang/test/Parser/cxx-template-recovery.cpp
2

Applied suggested changes.

clang/lib/Parse/ParseDecl.cpp
2308–2311

Calling SkipMalformedDecl() changes the behavior for this test case because we don't recover as well. With your patch applied, this gives us two diagnostics:

True. This can also be recovered by removing Tok.isAtStartOfLine() in line 2050. However, this has been around for a long time and would change the behavior of
two tests inside test/Parser/recovery.cpp, although only because the broken comments contain the namespace keyword.

Either case seems unlikely to me, so I think I'd lean toward not modifying SkipMalformedDecl. What do you think?

aaron.ballman accepted this revision.May 12 2023, 8:10 AM

LGTM! Do you need me to commit on your behalf? If so, what name and email address would you like used for patch attribution?

clang/lib/Parse/ParseDecl.cpp
2308–2311

I also lean towards not modifying SkipMalformedDecl(); I think it's recovery strategy is sensible.

This revision is now accepted and ready to land.May 12 2023, 8:10 AM
nridge added a subscriber: nridge.May 13 2023, 2:49 PM

LGTM! Do you need me to commit on your behalf? If so, what name and email address would you like used for patch attribution?

Thanks a lot! And yes, I would need you to commit. You can use

Name: Alejandro Álvarez Ayllón
Email: alejandro.alvarez@sonarsource.com