diff options
Diffstat (limited to 'lib/Sema/SemaCXXScopeSpec.cpp')
-rw-r--r-- | lib/Sema/SemaCXXScopeSpec.cpp | 65 |
1 files changed, 54 insertions, 11 deletions
diff --git a/lib/Sema/SemaCXXScopeSpec.cpp b/lib/Sema/SemaCXXScopeSpec.cpp index a70aca2..3e56e67 100644 --- a/lib/Sema/SemaCXXScopeSpec.cpp +++ b/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) { @@ -376,9 +410,6 @@ class NestedNameSpecifierValidatorCCC : public CorrectionCandidateCallback { /// \brief Build a new nested-name-specifier for "identifier::", as described /// by ActOnCXXNestedNameSpecifier. /// -/// This routine differs only slightly from ActOnCXXNestedNameSpecifier, in -/// that it contains an extra parameter \p ScopeLookupResult. -/// /// \param S Scope in which the nested-name-specifier occurs. /// \param Identifier Identifier in the sequence "identifier" "::". /// \param IdentifierLoc Location of the \p Identifier. @@ -541,12 +572,11 @@ bool Sema::BuildCXXNestedNameSpecifier(Scope *S, // We haven't found anything, and we're not recovering from a // different kind of error, so look for typos. DeclarationName Name = Found.getLookupName(); - NestedNameSpecifierValidatorCCC Validator(*this); Found.clear(); - if (TypoCorrection Corrected = - CorrectTypo(Found.getLookupNameInfo(), Found.getLookupKind(), S, - &SS, Validator, CTK_ErrorRecovery, LookupCtx, - EnteringContext)) { + if (TypoCorrection Corrected = CorrectTypo( + Found.getLookupNameInfo(), Found.getLookupKind(), S, &SS, + llvm::make_unique<NestedNameSpecifierValidatorCCC>(*this), + CTK_ErrorRecovery, LookupCtx, EnteringContext)) { if (LookupCtx) { bool DroppedSpecifier = Corrected.WillReplaceSpecifier() && @@ -612,10 +642,17 @@ bool Sema::BuildCXXNestedNameSpecifier(Scope *S, } } + if (auto *TD = dyn_cast_or_null<TypedefNameDecl>(SD)) + MarkAnyDeclReferenced(TD->getLocation(), TD, /*OdrUse=*/false); + // If we're just performing this lookup for error-recovery purposes, // don't extend the nested-name-specifier. Just return now. if (ErrorRecoveryLookup) return false; + + // The use of a nested name specifier may trigger deprecation warnings. + DiagnoseUseOfDecl(SD, CCLoc); + if (NamespaceDecl *Namespace = dyn_cast<NamespaceDecl>(SD)) { SS.Extend(Context, Namespace, IdentifierLoc, CCLoc); @@ -703,8 +740,13 @@ bool Sema::BuildCXXNestedNameSpecifier(Scope *S, if (getLangOpts().MSVCCompat) { DeclContext *DC = LookupCtx ? LookupCtx : CurContext; if (DC->isDependentContext() && DC->isFunctionOrMethod()) { - SS.Extend(Context, &Identifier, IdentifierLoc, CCLoc); - return false; + CXXRecordDecl *ContainingClass = dyn_cast<CXXRecordDecl>(DC->getParent()); + if (ContainingClass && ContainingClass->hasAnyDependentBases()) { + Diag(IdentifierLoc, diag::ext_undeclared_unqual_id_with_dependent_base) + << &Identifier << ContainingClass; + SS.Extend(Context, &Identifier, IdentifierLoc, CCLoc); + return false; + } } } @@ -945,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; } |