/// ActOnCXXExitDeclaratorScope - Called when a declarator that previously /// invoked ActOnCXXEnterDeclaratorScope(), is finished. 'SS' is the same /// CXXScopeSpec that was passed to ActOnCXXEnterDeclaratorScope as well. /// Used to indicate that names should revert to being looked up in the /// defining scope. void Sema::ActOnCXXExitDeclaratorScope(Scope *S, const CXXScopeSpec &SS) { assert(SS.isSet() && "Parser passed invalid CXXScopeSpec."); if (SS.isInvalid()) return; assert(!SS.isInvalid() && computeDeclContext(SS, true) && "exiting declarator scope we never really entered"); ExitDeclaratorContext(S); }
/// \brief Require that the context specified by SS be complete. /// /// If SS refers to a type, this routine checks whether the type is /// complete enough (or can be made complete enough) for name lookup /// into the DeclContext. A type that is not yet completed can be /// considered "complete enough" if it is a class/struct/union/enum /// that is currently being defined. Or, if we have a type that names /// a class template specialization that is not a complete type, we /// will attempt to instantiate that class template. bool Sema::RequireCompleteDeclContext(const CXXScopeSpec &SS) { if (!SS.isSet() || SS.isInvalid()) return false; DeclContext *DC = computeDeclContext(SS, true); if (TagDecl *Tag = dyn_cast<TagDecl>(DC)) { // If this is a dependent type, then we consider it complete. if (Tag->isDependentContext()) return false; // If we're currently defining this type, then lookup into the // type is okay: don't complain that it isn't complete yet. const TagType *TagT = Context.getTypeDeclType(Tag)->getAs<TagType>(); if (TagT->isBeingDefined()) return false; // The type must be complete. return RequireCompleteType(SS.getRange().getBegin(), Context.getTypeDeclType(Tag), PDiag(diag::err_incomplete_nested_name_spec) << SS.getRange()); } return false; }
bool Sema::ActOnCXXNestedNameSpecifierDecltype(CXXScopeSpec &SS, const DeclSpec &DS, SourceLocation ColonColonLoc) { if (SS.isInvalid() || DS.getTypeSpecType() == DeclSpec::TST_error) return true; assert(DS.getTypeSpecType() == DeclSpec::TST_decltype); QualType T = BuildDecltypeType(DS.getRepAsExpr(), DS.getTypeSpecTypeLoc()); if (T.isNull()) return true; if (!T->isDependentType() && !T->getAs<TagType>()) { Diag(DS.getTypeSpecTypeLoc(), diag::err_expected_class_or_namespace) << T << getLangOpts().CPlusPlus; return true; } TypeLocBuilder TLB; DecltypeTypeLoc DecltypeTL = TLB.push<DecltypeTypeLoc>(T); DecltypeTL.setNameLoc(DS.getTypeSpecTypeLoc()); SS.Extend(Context, SourceLocation(), TLB.getTypeLocInContext(Context, T), ColonColonLoc); return false; }
bool Sema::isDependentScopeSpecifier(const CXXScopeSpec &SS) { if (!SS.isSet() || SS.isInvalid()) return false; NestedNameSpecifier *NNS = static_cast<NestedNameSpecifier *>(SS.getScopeRep()); return NNS->isDependent(); }
/// \brief Retrieve a version of the type 'T' that is qualified by the /// nested-name-specifier contained in SS. QualType Sema::getQualifiedNameType(const CXXScopeSpec &SS, QualType T) { if (!SS.isSet() || SS.isInvalid() || T.isNull()) return T; NestedNameSpecifier *NNS = static_cast<NestedNameSpecifier *>(SS.getScopeRep()); return Context.getQualifiedNameType(NNS, T); }
/// IsInvalidUnlessNestedName - This method is used for error recovery /// purposes to determine whether the specified identifier is only valid as /// a nested name specifier, for example a namespace name. It is /// conservatively correct to always return false from this method. /// /// The arguments are the same as those passed to ActOnCXXNestedNameSpecifier. bool Sema::IsInvalidUnlessNestedName(Scope *S, CXXScopeSpec &SS, NestedNameSpecInfo &IdInfo, bool EnteringContext) { if (SS.isInvalid()) return false; return !BuildCXXNestedNameSpecifier(S, IdInfo, EnteringContext, SS, /*ScopeLookupResult=*/nullptr, true); }
bool Sema::ActOnCXXNestedNameSpecifier(Scope *S, NestedNameSpecInfo &IdInfo, bool EnteringContext, CXXScopeSpec &SS, bool ErrorRecoveryLookup, bool *IsCorrectedToColon, bool OnlyNamespace) { if (SS.isInvalid()) return true; return BuildCXXNestedNameSpecifier(S, IdInfo, EnteringContext, SS, /*ScopeLookupResult=*/nullptr, false, IsCorrectedToColon, OnlyNamespace); }
/// IsInvalidUnlessNestedName - This method is used for error recovery /// purposes to determine whether the specified identifier is only valid as /// a nested name specifier, for example a namespace name. It is /// conservatively correct to always return false from this method. /// /// The arguments are the same as those passed to ActOnCXXNestedNameSpecifier. bool Sema::IsInvalidUnlessNestedName(Scope *S, CXXScopeSpec &SS, IdentifierInfo &Identifier, SourceLocation IdentifierLoc, SourceLocation ColonLoc, ParsedType ObjectType, bool EnteringContext) { if (SS.isInvalid()) return false; return !BuildCXXNestedNameSpecifier(S, Identifier, IdentifierLoc, ColonLoc, GetTypeFromParser(ObjectType), EnteringContext, SS, /*ScopeLookupResult=*/0, true); }
bool Sema::ActOnCXXNestedNameSpecifier(Scope *S, IdentifierInfo &Identifier, SourceLocation IdentifierLoc, SourceLocation CCLoc, ParsedType ObjectType, bool EnteringContext, CXXScopeSpec &SS) { if (SS.isInvalid()) return true; return BuildCXXNestedNameSpecifier(S, Identifier, IdentifierLoc, CCLoc, GetTypeFromParser(ObjectType), EnteringContext, SS, /*ScopeLookupResult=*/0, false); }
/// ActOnCXXEnterDeclaratorScope - Called when a C++ scope specifier (global /// scope or nested-name-specifier) is parsed, part of a declarator-id. /// After this method is called, according to [C++ 3.4.3p3], names should be /// looked up in the declarator-id's scope, until the declarator is parsed and /// ActOnCXXExitDeclaratorScope is called. /// The 'SS' should be a non-empty valid CXXScopeSpec. bool Sema::ActOnCXXEnterDeclaratorScope(Scope *S, const CXXScopeSpec &SS) { assert(SS.isSet() && "Parser passed invalid CXXScopeSpec."); if (SS.isInvalid()) return true; DeclContext *DC = computeDeclContext(SS, true); if (!DC) return true; // Before we enter a declarator's context, we need to make sure that // it is a complete declaration context. if (!DC->isDependentContext() && RequireCompleteDeclContext(SS)) return true; EnterDeclaratorContext(S, DC); return false; }
bool Sema::ActOnCXXNestedNameSpecifier(Scope *S, IdentifierInfo &Identifier, SourceLocation IdentifierLoc, SourceLocation CCLoc, ParsedType ObjectType, bool EnteringContext, CXXScopeSpec &SS, bool ErrorRecoveryLookup, bool *IsCorrectedToColon) { if (SS.isInvalid()) return true; return BuildCXXNestedNameSpecifier(S, Identifier, IdentifierLoc, CCLoc, GetTypeFromParser(ObjectType), EnteringContext, SS, /*ScopeLookupResult=*/nullptr, false, IsCorrectedToColon); }
/// ActOnCXXEnterDeclaratorScope - Called when a C++ scope specifier (global /// scope or nested-name-specifier) is parsed, part of a declarator-id. /// After this method is called, according to [C++ 3.4.3p3], names should be /// looked up in the declarator-id's scope, until the declarator is parsed and /// ActOnCXXExitDeclaratorScope is called. /// The 'SS' should be a non-empty valid CXXScopeSpec. bool Sema::ActOnCXXEnterDeclaratorScope(Scope *S, CXXScopeSpec &SS) { assert(SS.isSet() && "Parser passed invalid CXXScopeSpec."); if (SS.isInvalid()) return true; DeclContext *DC = computeDeclContext(SS, true); if (!DC) return true; // Before we enter a declarator's context, we need to make sure that // it is a complete declaration context. if (!DC->isDependentContext() && RequireCompleteDeclContext(SS, DC)) return true; EnterDeclaratorContext(S, DC); // Rebuild the nested name specifier for the new scope. if (DC->isDependentContext()) RebuildNestedNameSpecifierInCurrentInstantiation(SS); return false; }
bool Sema::ActOnCXXNestedNameSpecifier(Scope *S, SourceLocation TemplateLoc, CXXScopeSpec &SS, TemplateTy Template, SourceLocation TemplateNameLoc, SourceLocation LAngleLoc, ASTTemplateArgsPtr TemplateArgsIn, SourceLocation RAngleLoc, SourceLocation CCLoc, bool EnteringContext) { if (SS.isInvalid()) return true; // Translate the parser's template argument list in our AST format. TemplateArgumentListInfo TemplateArgs(LAngleLoc, RAngleLoc); translateTemplateArguments(TemplateArgsIn, TemplateArgs); if (DependentTemplateName *DTN = Template.get().getAsDependentTemplateName()){ // Handle a dependent template specialization for which we cannot resolve // the template name. assert(DTN->getQualifier() == static_cast<NestedNameSpecifier*>(SS.getScopeRep())); QualType T = Context.getDependentTemplateSpecializationType(ETK_None, DTN->getQualifier(), DTN->getIdentifier(), TemplateArgs); // Create source-location information for this type. TypeLocBuilder Builder; DependentTemplateSpecializationTypeLoc SpecTL = Builder.push<DependentTemplateSpecializationTypeLoc>(T); SpecTL.setLAngleLoc(LAngleLoc); SpecTL.setRAngleLoc(RAngleLoc); SpecTL.setKeywordLoc(SourceLocation()); SpecTL.setNameLoc(TemplateNameLoc); SpecTL.setQualifierLoc(SS.getWithLocInContext(Context)); for (unsigned I = 0, N = TemplateArgs.size(); I != N; ++I) SpecTL.setArgLocInfo(I, TemplateArgs[I].getLocInfo()); SS.Extend(Context, TemplateLoc, Builder.getTypeLocInContext(Context, T), CCLoc); return false; } if (Template.get().getAsOverloadedTemplate() || isa<FunctionTemplateDecl>(Template.get().getAsTemplateDecl())) { SourceRange R(TemplateNameLoc, RAngleLoc); if (SS.getRange().isValid()) R.setBegin(SS.getRange().getBegin()); Diag(CCLoc, diag::err_non_type_template_in_nested_name_specifier) << Template.get() << R; NoteAllFoundTemplates(Template.get()); return true; } // We were able to resolve the template name to an actual template. // Build an appropriate nested-name-specifier. QualType T = CheckTemplateIdType(Template.get(), TemplateNameLoc, TemplateArgs); if (T.isNull()) return true; // Alias template specializations can produce types which are not valid // nested name specifiers. if (!T->isDependentType() && !T->getAs<TagType>()) { Diag(TemplateNameLoc, diag::err_nested_name_spec_non_tag) << T; NoteAllFoundTemplates(Template.get()); return true; } // Provide source-location information for the template specialization // type. TypeLocBuilder Builder; TemplateSpecializationTypeLoc SpecTL = Builder.push<TemplateSpecializationTypeLoc>(T); SpecTL.setLAngleLoc(LAngleLoc); SpecTL.setRAngleLoc(RAngleLoc); SpecTL.setTemplateNameLoc(TemplateNameLoc); for (unsigned I = 0, N = TemplateArgs.size(); I != N; ++I) SpecTL.setArgLocInfo(I, TemplateArgs[I].getLocInfo()); SS.Extend(Context, TemplateLoc, Builder.getTypeLocInContext(Context, T), CCLoc); return false; }
bool Sema::isDependentScopeSpecifier(const CXXScopeSpec &SS) { if (!SS.isSet() || SS.isInvalid()) return false; return SS.getScopeRep()->isDependent(); }