Skip to content

Commit f3dcec0

Browse files
authored
[clang] fix error recovery for invalid nested name specifiers (llvm#156772)
This fixes a regression which was introduced in llvm#147835. Since this regression was never released, there are no release notes. Fixes llvm#156458
1 parent c8d034a commit f3dcec0

File tree

5 files changed

+80
-55
lines changed

5 files changed

+80
-55
lines changed

clang/include/clang/Sema/Sema.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5363,7 +5363,7 @@ class Sema final : public SemaBase {
53635363
SourceLocation UsingLoc,
53645364
SourceLocation EnumLoc, SourceRange TyLoc,
53655365
const IdentifierInfo &II, ParsedType Ty,
5366-
CXXScopeSpec *SS = nullptr);
5366+
const CXXScopeSpec &SS);
53675367
Decl *ActOnAliasDeclaration(Scope *CurScope, AccessSpecifier AS,
53685368
MultiTemplateParamsArg TemplateParams,
53695369
SourceLocation UsingLoc, UnqualifiedId &Name,

clang/lib/Parse/ParseDeclCXX.cpp

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -672,7 +672,7 @@ Parser::DeclGroupPtrTy Parser::ParseUsingDeclaration(
672672
/*WantNontrivialTypeSourceInfo=*/true);
673673

674674
UED = Actions.ActOnUsingEnumDeclaration(
675-
getCurScope(), AS, UsingLoc, UELoc, IdentLoc, *IdentInfo, Type, &SS);
675+
getCurScope(), AS, UsingLoc, UELoc, IdentLoc, *IdentInfo, Type, SS);
676676
} else if (Tok.is(tok::annot_template_id)) {
677677
TemplateIdAnnotation *TemplateId = takeTemplateIdAnnotation(Tok);
678678

@@ -687,7 +687,7 @@ Parser::DeclGroupPtrTy Parser::ParseUsingDeclaration(
687687

688688
UED = Actions.ActOnUsingEnumDeclaration(getCurScope(), AS, UsingLoc,
689689
UELoc, Loc, *TemplateId->Name,
690-
Type.get(), &SS);
690+
Type.get(), SS);
691691
} else {
692692
Diag(Tok.getLocation(), diag::err_using_enum_not_enum)
693693
<< TemplateId->Name->getName()

clang/lib/Sema/SemaCXXScopeSpec.cpp

Lines changed: 60 additions & 48 deletions
Original file line numberDiff line numberDiff line change
@@ -398,6 +398,54 @@ class NestedNameSpecifierValidatorCCC final
398398

399399
}
400400

401+
[[nodiscard]] static bool ExtendNestedNameSpecifier(Sema &S, CXXScopeSpec &SS,
402+
const NamedDecl *ND,
403+
SourceLocation NameLoc,
404+
SourceLocation CCLoc) {
405+
TypeLocBuilder TLB;
406+
QualType T;
407+
if (const auto *USD = dyn_cast<UsingShadowDecl>(ND)) {
408+
T = S.Context.getUsingType(ElaboratedTypeKeyword::None, SS.getScopeRep(),
409+
USD);
410+
TLB.push<UsingTypeLoc>(T).set(/*ElaboratedKeywordLoc=*/SourceLocation(),
411+
SS.getWithLocInContext(S.Context), NameLoc);
412+
} else if (const auto *TD = dyn_cast<TypeDecl>(ND)) {
413+
T = S.Context.getTypeDeclType(ElaboratedTypeKeyword::None, SS.getScopeRep(),
414+
TD);
415+
switch (T->getTypeClass()) {
416+
case Type::Record:
417+
case Type::InjectedClassName:
418+
case Type::Enum: {
419+
auto TTL = TLB.push<TagTypeLoc>(T);
420+
TTL.setElaboratedKeywordLoc(SourceLocation());
421+
TTL.setQualifierLoc(SS.getWithLocInContext(S.Context));
422+
TTL.setNameLoc(NameLoc);
423+
break;
424+
}
425+
case Type::Typedef:
426+
TLB.push<TypedefTypeLoc>(T).set(/*ElaboratedKeywordLoc=*/SourceLocation(),
427+
SS.getWithLocInContext(S.Context),
428+
NameLoc);
429+
break;
430+
case Type::UnresolvedUsing:
431+
TLB.push<UnresolvedUsingTypeLoc>(T).set(
432+
/*ElaboratedKeywordLoc=*/SourceLocation(),
433+
SS.getWithLocInContext(S.Context), NameLoc);
434+
break;
435+
default:
436+
assert(SS.isEmpty());
437+
T = S.Context.getTypeDeclType(TD);
438+
TLB.pushTypeSpec(T).setNameLoc(NameLoc);
439+
break;
440+
}
441+
} else {
442+
return false;
443+
}
444+
SS.clear();
445+
SS.Make(S.Context, TLB.getTypeLocInContext(S.Context, T), CCLoc);
446+
return true;
447+
}
448+
401449
bool Sema::BuildCXXNestedNameSpecifier(Scope *S, NestedNameSpecInfo &IdInfo,
402450
bool EnteringContext, CXXScopeSpec &SS,
403451
NamedDecl *ScopeLookupResult,
@@ -653,40 +701,9 @@ bool Sema::BuildCXXNestedNameSpecifier(Scope *S, NestedNameSpecInfo &IdInfo,
653701
if (isa<EnumDecl>(TD))
654702
Diag(IdInfo.IdentifierLoc, diag::warn_cxx98_compat_enum_nested_name_spec);
655703

656-
QualType T;
657-
TypeLocBuilder TLB;
658-
if (const auto *USD = dyn_cast<UsingShadowDecl>(SD)) {
659-
T = Context.getUsingType(ElaboratedTypeKeyword::None, SS.getScopeRep(),
660-
USD);
661-
TLB.push<UsingTypeLoc>(T).set(/*ElaboratedKeywordLoc=*/SourceLocation(),
662-
SS.getWithLocInContext(Context),
663-
IdInfo.IdentifierLoc);
664-
} else if (const auto *Tag = dyn_cast<TagDecl>(TD)) {
665-
T = Context.getTagType(ElaboratedTypeKeyword::None, SS.getScopeRep(), Tag,
666-
/*OwnsTag=*/false);
667-
auto TTL = TLB.push<TagTypeLoc>(T);
668-
TTL.setElaboratedKeywordLoc(SourceLocation());
669-
TTL.setQualifierLoc(SS.getWithLocInContext(SemaRef.Context));
670-
TTL.setNameLoc(IdInfo.IdentifierLoc);
671-
} else if (auto *TN = dyn_cast<TypedefNameDecl>(TD)) {
672-
T = Context.getTypedefType(ElaboratedTypeKeyword::None, SS.getScopeRep(),
673-
TN);
674-
TLB.push<TypedefTypeLoc>(T).set(/*ElaboratedKeywordLoc=*/SourceLocation(),
675-
SS.getWithLocInContext(SemaRef.Context),
676-
IdInfo.IdentifierLoc);
677-
} else if (auto *UD = dyn_cast<UnresolvedUsingTypenameDecl>(TD)) {
678-
T = Context.getUnresolvedUsingType(ElaboratedTypeKeyword::None,
679-
SS.getScopeRep(), UD);
680-
TLB.push<UnresolvedUsingTypeLoc>(T).set(
681-
/*ElaboratedKeywordLoc=*/SourceLocation(),
682-
SS.getWithLocInContext(SemaRef.Context), IdInfo.IdentifierLoc);
683-
} else {
684-
assert(SS.isEmpty());
685-
T = Context.getTypeDeclType(TD);
686-
TLB.pushTypeSpec(T).setNameLoc(IdInfo.IdentifierLoc);
687-
}
688-
SS.clear();
689-
SS.Make(Context, TLB.getTypeLocInContext(Context, T), IdInfo.CCLoc);
704+
[[maybe_unused]] bool IsType = ::ExtendNestedNameSpecifier(
705+
*this, SS, SD, IdInfo.IdentifierLoc, IdInfo.CCLoc);
706+
assert(IsType && "unhandled declaration kind");
690707
return false;
691708
}
692709

@@ -762,21 +779,16 @@ bool Sema::BuildCXXNestedNameSpecifier(Scope *S, NestedNameSpecInfo &IdInfo,
762779
}
763780

764781
if (!Found.empty()) {
765-
if (TypeDecl *TD = Found.getAsSingle<TypeDecl>()) {
766-
QualType T;
767-
if (auto *TN = dyn_cast<TypedefNameDecl>(TD)) {
768-
T = Context.getTypedefType(ElaboratedTypeKeyword::None,
769-
SS.getScopeRep(), TN);
770-
} else {
771-
// FIXME: Enumerate the possibilities here.
772-
assert(!isa<TagDecl>(TD));
773-
assert(SS.isEmpty());
774-
T = Context.getTypeDeclType(TD);
775-
}
776-
782+
const auto *ND = Found.getAsSingle<NamedDecl>();
783+
if (::ExtendNestedNameSpecifier(*this, SS, ND, IdInfo.IdentifierLoc,
784+
IdInfo.CCLoc)) {
785+
const Type *T = SS.getScopeRep().getAsType();
777786
Diag(IdInfo.IdentifierLoc, diag::err_expected_class_or_namespace)
778-
<< T << getLangOpts().CPlusPlus;
779-
} else if (Found.getAsSingle<TemplateDecl>()) {
787+
<< QualType(T, 0) << getLangOpts().CPlusPlus;
788+
// Recover with this type if it would be a valid nested name specifier.
789+
return !T->getAsCanonical<TagType>();
790+
}
791+
if (isa<TemplateDecl>(ND)) {
780792
ParsedType SuggestedType;
781793
DiagnoseUnknownTypeName(IdInfo.Identifier, IdInfo.IdentifierLoc, S, &SS,
782794
SuggestedType);

clang/lib/Sema/SemaDeclCXX.cpp

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -12628,16 +12628,17 @@ Decl *Sema::ActOnUsingEnumDeclaration(Scope *S, AccessSpecifier AS,
1262812628
SourceLocation UsingLoc,
1262912629
SourceLocation EnumLoc, SourceRange TyLoc,
1263012630
const IdentifierInfo &II, ParsedType Ty,
12631-
CXXScopeSpec *SS) {
12632-
assert(SS && !SS->isInvalid() && "ScopeSpec is invalid");
12631+
const CXXScopeSpec &SS) {
1263312632
TypeSourceInfo *TSI = nullptr;
1263412633
SourceLocation IdentLoc = TyLoc.getBegin();
1263512634
QualType EnumTy = GetTypeFromParser(Ty, &TSI);
1263612635
if (EnumTy.isNull()) {
12637-
Diag(IdentLoc, isDependentScopeSpecifier(*SS)
12636+
Diag(IdentLoc, isDependentScopeSpecifier(SS)
1263812637
? diag::err_using_enum_is_dependent
1263912638
: diag::err_unknown_typename)
12640-
<< II.getName() << SourceRange(SS->getBeginLoc(), TyLoc.getEnd());
12639+
<< II.getName()
12640+
<< SourceRange(SS.isValid() ? SS.getBeginLoc() : IdentLoc,
12641+
TyLoc.getEnd());
1264112642
return nullptr;
1264212643
}
1264312644

clang/test/SemaCXX/GH156458.cpp

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
//RUN: %clang_cc1 -std=c++20 -fsyntax-only -verify %s
2+
3+
// Force a fatal error
4+
#include <unknownheader> // expected-error {{file not found}}
5+
6+
namespace N {}
7+
8+
enum class E {};
9+
using enum N::E::V;
10+
11+
using T = int;
12+
using enum N::T::v;

0 commit comments

Comments
 (0)