diff options
Diffstat (limited to 'clang/lib')
-rw-r--r-- | clang/lib/AST/ASTContext.cpp | 3 | ||||
-rw-r--r-- | clang/lib/AST/ASTImporter.cpp | 7 | ||||
-rw-r--r-- | clang/lib/AST/ExprCXX.cpp | 3 | ||||
-rw-r--r-- | clang/lib/AST/ItaniumMangle.cpp | 6 | ||||
-rw-r--r-- | clang/lib/AST/NestedNameSpecifier.cpp | 71 | ||||
-rw-r--r-- | clang/lib/Parse/ParseDecl.cpp | 1 | ||||
-rw-r--r-- | clang/lib/Parse/ParseDeclCXX.cpp | 9 | ||||
-rw-r--r-- | clang/lib/Parse/ParseExpr.cpp | 3 | ||||
-rw-r--r-- | clang/lib/Parse/ParseExprCXX.cpp | 12 | ||||
-rw-r--r-- | clang/lib/Parse/ParseTentative.cpp | 1 | ||||
-rw-r--r-- | clang/lib/Parse/Parser.cpp | 12 | ||||
-rw-r--r-- | clang/lib/Sema/DeclSpec.cpp | 12 | ||||
-rw-r--r-- | clang/lib/Sema/SemaCXXScopeSpec.cpp | 37 | ||||
-rw-r--r-- | clang/lib/Sema/SemaDecl.cpp | 9 | ||||
-rw-r--r-- | clang/lib/Sema/SemaExprCXX.cpp | 2 | ||||
-rw-r--r-- | clang/lib/Sema/SemaLookup.cpp | 21 | ||||
-rw-r--r-- | clang/lib/Sema/SemaTemplate.cpp | 7 | ||||
-rw-r--r-- | clang/lib/Sema/SemaType.cpp | 2 | ||||
-rw-r--r-- | clang/lib/Sema/TreeTransform.h | 8 | ||||
-rw-r--r-- | clang/lib/Serialization/ASTReader.cpp | 15 | ||||
-rw-r--r-- | clang/lib/Serialization/ASTWriter.cpp | 9 |
21 files changed, 224 insertions, 26 deletions
diff --git a/clang/lib/AST/ASTContext.cpp b/clang/lib/AST/ASTContext.cpp index cafde32eb6f..7e5182e3397 100644 --- a/clang/lib/AST/ASTContext.cpp +++ b/clang/lib/AST/ASTContext.cpp @@ -4195,7 +4195,8 @@ ASTContext::getCanonicalNestedNameSpecifier(NestedNameSpecifier *NNS) const { } case NestedNameSpecifier::Global: - // The global specifier is canonical and unique. + case NestedNameSpecifier::Super: + // The global specifier and __super specifer are canonical and unique. return NNS; } diff --git a/clang/lib/AST/ASTImporter.cpp b/clang/lib/AST/ASTImporter.cpp index 05f39abaa37..ca7ab63c96f 100644 --- a/clang/lib/AST/ASTImporter.cpp +++ b/clang/lib/AST/ASTImporter.cpp @@ -4760,6 +4760,13 @@ NestedNameSpecifier *ASTImporter::Import(NestedNameSpecifier *FromNNS) { case NestedNameSpecifier::Global: return NestedNameSpecifier::GlobalSpecifier(ToContext); + case NestedNameSpecifier::Super: + if (CXXRecordDecl *RD = + cast<CXXRecordDecl>(Import(FromNNS->getAsRecordDecl()))) { + return NestedNameSpecifier::SuperSpecifier(ToContext, RD); + } + return nullptr; + case NestedNameSpecifier::TypeSpec: case NestedNameSpecifier::TypeSpecWithTemplate: { QualType T = Import(QualType(FromNNS->getAsType(), 0u)); diff --git a/clang/lib/AST/ExprCXX.cpp b/clang/lib/AST/ExprCXX.cpp index 08230bebed1..93361666183 100644 --- a/clang/lib/AST/ExprCXX.cpp +++ b/clang/lib/AST/ExprCXX.cpp @@ -1404,7 +1404,8 @@ CXXRecordDecl *UnresolvedMemberExpr::getNamingClass() const { // It can't be dependent: after all, we were actually able to do the // lookup. CXXRecordDecl *Record = nullptr; - if (getQualifier()) { + auto *NNS = getQualifier(); + if (NNS && NNS->getKind() != NestedNameSpecifier::Super) { const Type *T = getQualifier()->getAsType(); assert(T && "qualifier in member expression does not name type"); Record = T->getAsCXXRecordDecl(); diff --git a/clang/lib/AST/ItaniumMangle.cpp b/clang/lib/AST/ItaniumMangle.cpp index 4717174b4a4..d2d02fac03e 100644 --- a/clang/lib/AST/ItaniumMangle.cpp +++ b/clang/lib/AST/ItaniumMangle.cpp @@ -814,6 +814,9 @@ void CXXNameMangler::mangleUnresolvedPrefix(NestedNameSpecifier *qualifier, // We never want an 'E' here. return; + case NestedNameSpecifier::Super: + llvm_unreachable("Can't mangle __super specifier"); + case NestedNameSpecifier::Namespace: if (qualifier->getPrefix()) mangleUnresolvedPrefix(qualifier->getPrefix(), firstQualifierLookup, @@ -1462,6 +1465,9 @@ void CXXNameMangler::manglePrefix(NestedNameSpecifier *qualifier) { // nothing return; + case NestedNameSpecifier::Super: + llvm_unreachable("Can't mangle __super specifier"); + case NestedNameSpecifier::Namespace: mangleName(qualifier->getAsNamespace()); return; diff --git a/clang/lib/AST/NestedNameSpecifier.cpp b/clang/lib/AST/NestedNameSpecifier.cpp index 1f041aa4954..50a00502ca9 100644 --- a/clang/lib/AST/NestedNameSpecifier.cpp +++ b/clang/lib/AST/NestedNameSpecifier.cpp @@ -66,7 +66,7 @@ NestedNameSpecifier::Create(const ASTContext &Context, "Broken nested name specifier"); NestedNameSpecifier Mockup; Mockup.Prefix.setPointer(Prefix); - Mockup.Prefix.setInt(StoredNamespaceOrAlias); + Mockup.Prefix.setInt(StoredDecl); Mockup.Specifier = const_cast<NamespaceDecl *>(NS); return FindOrInsert(Context, Mockup); } @@ -82,7 +82,7 @@ NestedNameSpecifier::Create(const ASTContext &Context, "Broken nested name specifier"); NestedNameSpecifier Mockup; Mockup.Prefix.setPointer(Prefix); - Mockup.Prefix.setInt(StoredNamespaceOrAlias); + Mockup.Prefix.setInt(StoredDecl); Mockup.Specifier = Alias; return FindOrInsert(Context, Mockup); } @@ -118,6 +118,16 @@ NestedNameSpecifier::GlobalSpecifier(const ASTContext &Context) { return Context.GlobalNestedNameSpecifier; } +NestedNameSpecifier * +NestedNameSpecifier::SuperSpecifier(const ASTContext &Context, + CXXRecordDecl *RD) { + NestedNameSpecifier Mockup; + Mockup.Prefix.setPointer(nullptr); + Mockup.Prefix.setInt(StoredDecl); + Mockup.Specifier = RD; + return FindOrInsert(Context, Mockup); +} + NestedNameSpecifier::SpecifierKind NestedNameSpecifier::getKind() const { if (!Specifier) return Global; @@ -126,9 +136,12 @@ NestedNameSpecifier::SpecifierKind NestedNameSpecifier::getKind() const { case StoredIdentifier: return Identifier; - case StoredNamespaceOrAlias: - return isa<NamespaceDecl>(static_cast<NamedDecl *>(Specifier))? Namespace - : NamespaceAlias; + case StoredDecl: { + NamedDecl *ND = static_cast<NamedDecl *>(Specifier); + if (isa<CXXRecordDecl>(ND)) + return Super; + return isa<NamespaceDecl>(ND) ? Namespace : NamespaceAlias; + } case StoredTypeSpec: return TypeSpec; @@ -140,24 +153,29 @@ NestedNameSpecifier::SpecifierKind NestedNameSpecifier::getKind() const { llvm_unreachable("Invalid NNS Kind!"); } -/// \brief Retrieve the namespace stored in this nested name -/// specifier. +/// \brief Retrieve the namespace stored in this nested name specifier. NamespaceDecl *NestedNameSpecifier::getAsNamespace() const { - if (Prefix.getInt() == StoredNamespaceOrAlias) + if (Prefix.getInt() == StoredDecl) return dyn_cast<NamespaceDecl>(static_cast<NamedDecl *>(Specifier)); return nullptr; } -/// \brief Retrieve the namespace alias stored in this nested name -/// specifier. +/// \brief Retrieve the namespace alias stored in this nested name specifier. NamespaceAliasDecl *NestedNameSpecifier::getAsNamespaceAlias() const { - if (Prefix.getInt() == StoredNamespaceOrAlias) + if (Prefix.getInt() == StoredDecl) return dyn_cast<NamespaceAliasDecl>(static_cast<NamedDecl *>(Specifier)); return nullptr; } +/// \brief Retrieve the record declaration stored in this nested name specifier. +CXXRecordDecl *NestedNameSpecifier::getAsRecordDecl() const { + if (Prefix.getInt() == StoredDecl) + return dyn_cast<CXXRecordDecl>(static_cast<NamedDecl *>(Specifier)); + + return nullptr; +} /// \brief Whether this nested name specifier refers to a dependent /// type or not. @@ -172,6 +190,15 @@ bool NestedNameSpecifier::isDependent() const { case Global: return false; + case Super: { + CXXRecordDecl *RD = static_cast<CXXRecordDecl *>(Specifier); + for (const auto &Base : RD->bases()) + if (Base.getType()->isDependentType()) + return true; + + return false; + } + case TypeSpec: case TypeSpecWithTemplate: return getAsType()->isDependentType(); @@ -191,8 +218,9 @@ bool NestedNameSpecifier::isInstantiationDependent() const { case Namespace: case NamespaceAlias: case Global: + case Super: return false; - + case TypeSpec: case TypeSpecWithTemplate: return getAsType()->isInstantiationDependentType(); @@ -209,6 +237,7 @@ bool NestedNameSpecifier::containsUnexpandedParameterPack() const { case Namespace: case NamespaceAlias: case Global: + case Super: return false; case TypeSpec: @@ -246,6 +275,10 @@ NestedNameSpecifier::print(raw_ostream &OS, case Global: break; + case Super: + OS << "__super"; + break; + case TypeSpecWithTemplate: OS << "template "; // Fall through to print the type. @@ -304,6 +337,7 @@ NestedNameSpecifierLoc::getLocalDataLength(NestedNameSpecifier *Qualifier) { case NestedNameSpecifier::Identifier: case NestedNameSpecifier::Namespace: case NestedNameSpecifier::NamespaceAlias: + case NestedNameSpecifier::Super: // The location of the identifier or namespace name. Length += sizeof(unsigned); break; @@ -369,6 +403,7 @@ SourceRange NestedNameSpecifierLoc::getLocalSourceRange() const { case NestedNameSpecifier::Identifier: case NestedNameSpecifier::Namespace: case NestedNameSpecifier::NamespaceAlias: + case NestedNameSpecifier::Super: return SourceRange(LoadSourceLocation(Data, Offset), LoadSourceLocation(Data, Offset + sizeof(unsigned))); @@ -552,6 +587,17 @@ void NestedNameSpecifierLocBuilder::MakeGlobal(ASTContext &Context, SaveSourceLocation(ColonColonLoc, Buffer, BufferSize, BufferCapacity); } +void NestedNameSpecifierLocBuilder::MakeSuper(ASTContext &Context, + CXXRecordDecl *RD, + SourceLocation SuperLoc, + SourceLocation ColonColonLoc) { + Representation = NestedNameSpecifier::SuperSpecifier(Context, RD); + + // Push source-location info into the buffer. + SaveSourceLocation(SuperLoc, Buffer, BufferSize, BufferCapacity); + SaveSourceLocation(ColonColonLoc, Buffer, BufferSize, BufferCapacity); +} + void NestedNameSpecifierLocBuilder::MakeTrivial(ASTContext &Context, NestedNameSpecifier *Qualifier, SourceRange R) { @@ -583,6 +629,7 @@ void NestedNameSpecifierLocBuilder::MakeTrivial(ASTContext &Context, } case NestedNameSpecifier::Global: + case NestedNameSpecifier::Super: break; } diff --git a/clang/lib/Parse/ParseDecl.cpp b/clang/lib/Parse/ParseDecl.cpp index 53e3dbea81f..569234bf558 100644 --- a/clang/lib/Parse/ParseDecl.cpp +++ b/clang/lib/Parse/ParseDecl.cpp @@ -2731,6 +2731,7 @@ void Parser::ParseDeclarationSpecifiers(DeclSpec &DS, goto DoneWithDeclSpec; // typedef-name + case tok::kw___super: case tok::kw_decltype: case tok::identifier: { // This identifier can only be a typedef name if we haven't already seen diff --git a/clang/lib/Parse/ParseDeclCXX.cpp b/clang/lib/Parse/ParseDeclCXX.cpp index 362b2c04422..87b1dd89b7a 100644 --- a/clang/lib/Parse/ParseDeclCXX.cpp +++ b/clang/lib/Parse/ParseDeclCXX.cpp @@ -493,6 +493,12 @@ Decl *Parser::ParseUsingDeclaration(unsigned Context, if (TryConsumeToken(tok::kw_typename, TypenameLoc)) HasTypenameKeyword = true; + if (Tok.is(tok::kw___super)) { + Diag(Tok.getLocation(), diag::err_super_in_using_declaration); + SkipUntil(tok::semi); + return nullptr; + } + // Parse nested-name-specifier. IdentifierInfo *LastII = nullptr; ParseOptionalCXXScopeSpecifier(SS, ParsedType(), /*EnteringContext=*/false, @@ -2101,7 +2107,8 @@ void Parser::ParseCXXClassMemberDeclaration(AccessSpecifier AS, // Access declarations. bool MalformedTypeSpec = false; if (!TemplateInfo.Kind && - (Tok.is(tok::identifier) || Tok.is(tok::coloncolon))) { + (Tok.is(tok::identifier) || Tok.is(tok::coloncolon) || + Tok.is(tok::kw___super))) { if (TryAnnotateCXXScopeToken()) MalformedTypeSpec = true; diff --git a/clang/lib/Parse/ParseExpr.cpp b/clang/lib/Parse/ParseExpr.cpp index e121902bf0c..8f5a5cadf7d 100644 --- a/clang/lib/Parse/ParseExpr.cpp +++ b/clang/lib/Parse/ParseExpr.cpp @@ -688,11 +688,12 @@ ExprResult Parser::ParseCastExpression(bool isUnaryExpression, ConsumeToken(); break; + case tok::kw___super: case tok::kw_decltype: // Annotate the token and tail recurse. if (TryAnnotateTypeOrScopeToken()) return ExprError(); - assert(Tok.isNot(tok::kw_decltype)); + assert(Tok.isNot(tok::kw_decltype) && Tok.isNot(tok::kw___super)); return ParseCastExpression(isUnaryExpression, isAddressOfOperand); case tok::identifier: { // primary-expression: identifier diff --git a/clang/lib/Parse/ParseExprCXX.cpp b/clang/lib/Parse/ParseExprCXX.cpp index cf0e4ce5c0c..8f22f5609e6 100644 --- a/clang/lib/Parse/ParseExprCXX.cpp +++ b/clang/lib/Parse/ParseExprCXX.cpp @@ -218,7 +218,7 @@ bool Parser::ParseOptionalCXXScopeSpecifier(CXXScopeSpec &SS, return false; // '::' - Global scope qualifier. - if (Actions.ActOnCXXGlobalScopeSpecifier(getCurScope(), ConsumeToken(), SS)) + if (Actions.ActOnCXXGlobalScopeSpecifier(ConsumeToken(), SS)) return true; CheckForLParenAfterColonColon(); @@ -226,6 +226,16 @@ bool Parser::ParseOptionalCXXScopeSpecifier(CXXScopeSpec &SS, HasScopeSpecifier = true; } + if (Tok.is(tok::kw___super)) { + SourceLocation SuperLoc = ConsumeToken(); + if (!Tok.is(tok::coloncolon)) { + Diag(Tok.getLocation(), diag::err_expected_coloncolon_after_super); + return true; + } + + return Actions.ActOnSuperScopeSpecifier(SuperLoc, ConsumeToken(), SS); + } + bool CheckForDestructor = false; if (MayBePseudoDestructor && *MayBePseudoDestructor) { CheckForDestructor = true; diff --git a/clang/lib/Parse/ParseTentative.cpp b/clang/lib/Parse/ParseTentative.cpp index 8514af2a8c8..1020eefb0c4 100644 --- a/clang/lib/Parse/ParseTentative.cpp +++ b/clang/lib/Parse/ParseTentative.cpp @@ -1181,6 +1181,7 @@ Parser::isCXXDeclarationSpecifier(Parser::TPResult BracedCastResult, return TPResult::False; } // Fall through. + case tok::kw___super: case tok::kw_decltype: // Annotate typenames and C++ scope specifiers. If we get one, just // recurse to handle whatever we get. diff --git a/clang/lib/Parse/Parser.cpp b/clang/lib/Parse/Parser.cpp index 6dcbaf6bb29..5a0653026f2 100644 --- a/clang/lib/Parse/Parser.cpp +++ b/clang/lib/Parse/Parser.cpp @@ -1464,10 +1464,11 @@ bool Parser::TryKeywordIdentFallback(bool DisableKeyword) { /// Note that this routine emits an error if you call it with ::new or ::delete /// as the current tokens, so only call it in contexts where these are invalid. bool Parser::TryAnnotateTypeOrScopeToken(bool EnteringContext, bool NeedType) { - assert((Tok.is(tok::identifier) || Tok.is(tok::coloncolon) - || Tok.is(tok::kw_typename) || Tok.is(tok::annot_cxxscope) - || Tok.is(tok::kw_decltype) || Tok.is(tok::annot_template_id)) - && "Cannot be a type or scope token!"); + assert((Tok.is(tok::identifier) || Tok.is(tok::coloncolon) || + Tok.is(tok::kw_typename) || Tok.is(tok::annot_cxxscope) || + Tok.is(tok::kw_decltype) || Tok.is(tok::annot_template_id) || + Tok.is(tok::kw___super)) && + "Cannot be a type or scope token!"); if (Tok.is(tok::kw_typename)) { // MSVC lets you do stuff like: @@ -1676,7 +1677,8 @@ bool Parser::TryAnnotateCXXScopeToken(bool EnteringContext) { "Call sites of this function should be guarded by checking for C++"); assert((Tok.is(tok::identifier) || Tok.is(tok::coloncolon) || (Tok.is(tok::annot_template_id) && NextToken().is(tok::coloncolon)) || - Tok.is(tok::kw_decltype)) && "Cannot be a type or scope token!"); + Tok.is(tok::kw_decltype) || Tok.is(tok::kw___super)) && + "Cannot be a type or scope token!"); CXXScopeSpec SS; if (ParseOptionalCXXScopeSpecifier(SS, ParsedType(), EnteringContext)) diff --git a/clang/lib/Sema/DeclSpec.cpp b/clang/lib/Sema/DeclSpec.cpp index 17dccc8d22e..50ed49a3b90 100644 --- a/clang/lib/Sema/DeclSpec.cpp +++ b/clang/lib/Sema/DeclSpec.cpp @@ -113,6 +113,18 @@ void CXXScopeSpec::MakeGlobal(ASTContext &Context, "NestedNameSpecifierLoc range computation incorrect"); } +void CXXScopeSpec::MakeSuper(ASTContext &Context, CXXRecordDecl *RD, + SourceLocation SuperLoc, + SourceLocation ColonColonLoc) { + Builder.MakeSuper(Context, RD, SuperLoc, ColonColonLoc); + + Range.setBegin(SuperLoc); + Range.setEnd(ColonColonLoc); + + assert(Range == Builder.getSourceRange() && + "NestedNameSpecifierLoc range computation incorrect"); +} + void CXXScopeSpec::MakeTrivial(ASTContext &Context, NestedNameSpecifier *Qualifier, SourceRange R) { Builder.MakeTrivial(Context, Qualifier, R); diff --git a/clang/lib/Sema/SemaCXXScopeSpec.cpp b/clang/lib/Sema/SemaCXXScopeSpec.cpp index d3f0fad3151..739cba72339 100644 --- a/clang/lib/Sema/SemaCXXScopeSpec.cpp +++ b/clang/lib/Sema/SemaCXXScopeSpec.cpp @@ -148,6 +148,9 @@ DeclContext *Sema::computeDeclContext(const CXXScopeSpec &SS, case NestedNameSpecifier::Global: return Context.getTranslationUnitDecl(); + + case NestedNameSpecifier::Super: + return NNS->getAsRecordDecl(); } llvm_unreachable("Invalid NestedNameSpecifier::Kind!"); @@ -240,12 +243,43 @@ bool Sema::RequireCompleteDeclContext(CXXScopeSpec &SS, return true; } -bool Sema::ActOnCXXGlobalScopeSpecifier(Scope *S, SourceLocation CCLoc, +bool Sema::ActOnCXXGlobalScopeSpecifier(SourceLocation CCLoc, CXXScopeSpec &SS) { SS.MakeGlobal(Context, CCLoc); return false; } +bool Sema::ActOnSuperScopeSpecifier(SourceLocation SuperLoc, + SourceLocation ColonColonLoc, + CXXScopeSpec &SS) { + CXXRecordDecl *RD = nullptr; + for (Scope *S = getCurScope(); S; S = S->getParent()) { + if (S->isFunctionScope()) { + if (CXXMethodDecl *MD = dyn_cast<CXXMethodDecl>(S->getEntity())) + RD = MD->getParent(); + break; + } + if (S->isClassScope()) { + RD = cast<CXXRecordDecl>(S->getEntity()); + break; + } + } + + if (!RD) { + Diag(SuperLoc, diag::err_invalid_super_scope); + return true; + } else if (RD->isLambda()) { + Diag(SuperLoc, diag::err_super_in_lambda_unsupported); + return true; + } else if (RD->getNumBases() == 0) { + Diag(SuperLoc, diag::err_no_base_classes) << RD->getName(); + return true; + } + + SS.MakeSuper(Context, RD, SuperLoc, ColonColonLoc); + return false; +} + /// \brief Determines whether the given declaration is an valid acceptable /// result for name lookup of a nested-name-specifier. bool Sema::isAcceptableNestedNameSpecifier(const NamedDecl *SD) { @@ -953,6 +987,7 @@ bool Sema::ShouldEnterDeclaratorScope(Scope *S, const CXXScopeSpec &SS) { case NestedNameSpecifier::Identifier: case NestedNameSpecifier::TypeSpec: case NestedNameSpecifier::TypeSpecWithTemplate: + case NestedNameSpecifier::Super: // These are never namespace scopes. return true; } diff --git a/clang/lib/Sema/SemaDecl.cpp b/clang/lib/Sema/SemaDecl.cpp index 1bac28753fe..abbf4b2bb24 100644 --- a/clang/lib/Sema/SemaDecl.cpp +++ b/clang/lib/Sema/SemaDecl.cpp @@ -498,6 +498,9 @@ DeclSpec::TST Sema::isTagName(IdentifierInfo &II, Scope *S) { /// @endcode bool Sema::isMicrosoftMissingTypename(const CXXScopeSpec *SS, Scope *S) { if (CurContext->isRecord()) { + if (SS->getScopeRep()->getKind() == NestedNameSpecifier::Super) + return true; + const Type *Ty = SS->getScopeRep()->getAsType(); CXXRecordDecl *RD = cast<CXXRecordDecl>(CurContext); @@ -699,7 +702,11 @@ Sema::NameClassification Sema::ClassifyName(Scope *S, } LookupResult Result(*this, Name, NameLoc, LookupOrdinaryName); - LookupParsedName(Result, S, &SS, !CurMethod); + NestedNameSpecifier *NNS = SS.getScopeRep(); + if (NNS && NNS->getKind() == NestedNameSpecifier::Super) + LookupInSuper(Result, NNS->getAsRecordDecl()); + else + LookupParsedName(Result, S, &SS, !CurMethod); // For unqualified lookup in a class template in MSVC mode, look into // dependent base classes where the primary class template is known. diff --git a/clang/lib/Sema/SemaExprCXX.cpp b/clang/lib/Sema/SemaExprCXX.cpp index f938fd38cdc..d79dcca1e97 100644 --- a/clang/lib/Sema/SemaExprCXX.cpp +++ b/clang/lib/Sema/SemaExprCXX.cpp @@ -67,6 +67,7 @@ ParsedType Sema::getInheritingConstructorName(CXXScopeSpec &SS, break; case NestedNameSpecifier::Global: + case NestedNameSpecifier::Super: case NestedNameSpecifier::Namespace: case NestedNameSpecifier::NamespaceAlias: llvm_unreachable("Nested name specifier is not a type for inheriting ctor"); @@ -354,6 +355,7 @@ bool Sema::checkLiteralOperatorId(const CXXScopeSpec &SS, return true; case NestedNameSpecifier::Global: + case NestedNameSpecifier::Super: case NestedNameSpecifier::Namespace: case NestedNameSpecifier::NamespaceAlias: return false; diff --git a/clang/lib/Sema/SemaLookup.cpp b/clang/lib/Sema/SemaLookup.cpp index 54f9673e9fa..76e0ba1bcda 100644 --- a/clang/lib/Sema/SemaLookup.cpp +++ b/clang/lib/Sema/SemaLookup.cpp @@ -1824,6 +1824,26 @@ bool Sema::LookupParsedName(LookupResult &R, Scope *S, CXXScopeSpec *SS, return LookupName(R, S, AllowBuiltinCreation); } +/// \brief Perform qualified name lookup into all base classes of the given +/// class. +/// +/// \param R captures both the lookup criteria and any lookup results found. +/// +/// \param Class The context in which qualified name lookup will +/// search. Name lookup will search in all base classes merging the results. +void Sema::LookupInSuper(LookupResult &R, CXXRecordDecl *Class) { + for (const auto &BaseSpec : Class->bases()) { + CXXRecordDecl *RD = cast<CXXRecordDecl>( + BaseSpec.getType()->castAs<RecordType>()->getDecl()); + LookupResult Result(*this, R.getLookupNameInfo(), R.getLookupKind()); + Result.setBaseObjectType(Context.getRecordType(Class)); + LookupQualifiedName(Result, RD); + for (auto *Decl : Result) + R.addDecl(Decl); + } + + R.resolveKind(); +} /// \brief Produce a diagnostic describing the ambiguity that resulted /// from name lookup. @@ -3296,6 +3316,7 @@ static void getNestedNameSpecifierIdentifiers( break; case NestedNameSpecifier::Global: + case NestedNameSpecifier::Super: return; } diff --git a/clang/lib/Sema/SemaTemplate.cpp b/clang/lib/Sema/SemaTemplate.cpp index 3c37a3e2d06..b47ce684446 100644 --- a/clang/lib/Sema/SemaTemplate.cpp +++ b/clang/lib/Sema/SemaTemplate.cpp @@ -4127,6 +4127,7 @@ bool UnnamedLocalNoLinkageFinder::VisitNestedNameSpecifier( case NestedNameSpecifier::Namespace: case NestedNameSpecifier::NamespaceAlias: case NestedNameSpecifier::Global: + case NestedNameSpecifier::Super: return false; case NestedNameSpecifier::TypeSpec: @@ -7900,7 +7901,11 @@ Sema::CheckTypenameType(ElaboratedTypeKeyword Keyword, DeclarationName Name(&II); LookupResult Result(*this, Name, IILoc, LookupOrdinaryName); - LookupQualifiedName(Result, Ctx); + NestedNameSpecifier *NNS = SS.getScopeRep(); + if (NNS->getKind() == NestedNameSpecifier::Super) + LookupInSuper(Result, NNS->getAsRecordDecl()); + else + LookupQualifiedName(Result, Ctx); unsigned DiagID = 0; Decl *Referenced = nullptr; switch (Result.getResultKind()) { diff --git a/clang/lib/Sema/SemaType.cpp b/clang/lib/Sema/SemaType.cpp index 51f36feaa46..31d7f73e097 100644 --- a/clang/lib/Sema/SemaType.cpp +++ b/clang/lib/Sema/SemaType.cpp @@ -3021,6 +3021,7 @@ static TypeSourceInfo *GetFullTypeForDeclarator(TypeProcessingState &state, case NestedNameSpecifier::Namespace: case NestedNameSpecifier::NamespaceAlias: case NestedNameSpecifier::Global: + case NestedNameSpecifier::Super: llvm_unreachable("Nested-name-specifier must name a type"); case NestedNameSpecifier::TypeSpec: @@ -3717,6 +3718,7 @@ namespace { case NestedNameSpecifier::Namespace: case NestedNameSpecifier::NamespaceAlias: case NestedNameSpecifier::Global: + case NestedNameSpecifier::Super: llvm_unreachable("Nested-name-specifier must name a type"); } diff --git a/clang/lib/Sema/TreeTransform.h b/clang/lib/Sema/TreeTransform.h index af91ea9a00a..687f16473df 100644 --- a/clang/lib/Sema/TreeTransform.h +++ b/clang/lib/Sema/TreeTransform.h @@ -3100,6 +3100,14 @@ TreeTransform<Derived>::TransformNestedNameSpecifierLoc( SS.MakeGlobal(SemaRef.Context, Q.getBeginLoc()); break; + case NestedNameSpecifier::Super: { + CXXRecordDecl *RD = + cast_or_null<CXXRecordDecl>(getDerived().TransformDecl( + SourceLocation(), QNNS->getAsRecordDecl())); + SS.MakeSuper(SemaRef.Context, RD, Q.getBeginLoc(), Q.getEndLoc()); + break; + } + case NestedNameSpecifier::TypeSpecWithTemplate: case NestedNameSpecifier::TypeSpec: { TypeLoc TL = TransformTypeInObjectScope(Q.getTypeLoc(), ObjectType, diff --git a/clang/lib/Serialization/ASTReader.cpp b/clang/lib/Serialization/ASTReader.cpp index 93c01cb1e12..96639f37f0b 100644 --- a/clang/lib/Serialization/ASTReader.cpp +++ b/clang/lib/Serialization/ASTReader.cpp @@ -7927,6 +7927,12 @@ ASTReader::ReadNestedNameSpecifier(ModuleFile &F, // No associated value, and there can't be a prefix. break; } + + case NestedNameSpecifier::Super: { + CXXRecordDecl *RD = ReadDeclAs<CXXRecordDecl>(F, Record, Idx); + NNS = NestedNameSpecifier::SuperSpecifier(Context, RD); + break; + } } Prev = NNS; } @@ -7983,9 +7989,16 @@ ASTReader::ReadNestedNameSpecifierLoc(ModuleFile &F, const RecordData &Record, Builder.MakeGlobal(Context, ColonColonLoc); break; } + + case NestedNameSpecifier::Super: { + CXXRecordDecl *RD = ReadDeclAs<CXXRecordDecl>(F, Record, Idx); + SourceRange Range = ReadSourceRange(F, Record, Idx); + Builder.MakeSuper(Context, RD, Range.getBegin(), Range.getEnd()); + break; + } } } - + return Builder.getWithLocInContext(Context); } diff --git a/clang/lib/Serialization/ASTWriter.cpp b/clang/lib/Serialization/ASTWriter.cpp index 0b65d0a571d..04a39c07aaf 100644 --- a/clang/lib/Serialization/ASTWriter.cpp +++ b/clang/lib/Serialization/ASTWriter.cpp @@ -5245,6 +5245,10 @@ void ASTWriter::AddNestedNameSpecifier(NestedNameSpecifier *NNS, case NestedNameSpecifier::Global: // Don't need to write an associated value. break; + + case NestedNameSpecifier::Super: + AddDeclRef(NNS->getAsRecordDecl(), Record); + break; } } } @@ -5294,6 +5298,11 @@ void ASTWriter::AddNestedNameSpecifierLoc(NestedNameSpecifierLoc NNS, case NestedNameSpecifier::Global: AddSourceLocation(NNS.getLocalSourceRange().getEnd(), Record); break; + + case NestedNameSpecifier::Super: + AddDeclRef(NNS.getNestedNameSpecifier()->getAsRecordDecl(), Record); + AddSourceRange(NNS.getLocalSourceRange(), Record); + break; } } } |