SemaCXXScopeSpec.cpp [plain text]
#include "clang/Sema/SemaInternal.h"
#include "TypeLocBuilder.h"
#include "clang/AST/ASTContext.h"
#include "clang/AST/DeclTemplate.h"
#include "clang/AST/ExprCXX.h"
#include "clang/AST/NestedNameSpecifier.h"
#include "clang/Basic/PartialDiagnostic.h"
#include "clang/Sema/DeclSpec.h"
#include "clang/Sema/Lookup.h"
#include "clang/Sema/Template.h"
#include "llvm/ADT/STLExtras.h"
#include "llvm/Support/raw_ostream.h"
using namespace clang;
static CXXRecordDecl *getCurrentInstantiationOf(QualType T,
DeclContext *CurContext) {
if (T.isNull())
return 0;
const Type *Ty = T->getCanonicalTypeInternal().getTypePtr();
if (const RecordType *RecordTy = dyn_cast<RecordType>(Ty)) {
CXXRecordDecl *Record = cast<CXXRecordDecl>(RecordTy->getDecl());
if (!Record->isDependentContext() ||
Record->isCurrentInstantiation(CurContext))
return Record;
return 0;
} else if (isa<InjectedClassNameType>(Ty))
return cast<InjectedClassNameType>(Ty)->getDecl();
else
return 0;
}
DeclContext *Sema::computeDeclContext(QualType T) {
if (!T->isDependentType())
if (const TagType *Tag = T->getAs<TagType>())
return Tag->getDecl();
return ::getCurrentInstantiationOf(T, CurContext);
}
DeclContext *Sema::computeDeclContext(const CXXScopeSpec &SS,
bool EnteringContext) {
if (!SS.isSet() || SS.isInvalid())
return 0;
NestedNameSpecifier *NNS = SS.getScopeRep();
if (NNS->isDependent()) {
if (CXXRecordDecl *Record = getCurrentInstantiationOf(NNS))
return Record;
if (EnteringContext) {
const Type *NNSType = NNS->getAsType();
if (!NNSType) {
return 0;
}
NNSType = Context.getCanonicalType(NNSType);
if (const TemplateSpecializationType *SpecType
= NNSType->getAs<TemplateSpecializationType>()) {
if (ClassTemplateDecl *ClassTemplate
= dyn_cast_or_null<ClassTemplateDecl>(
SpecType->getTemplateName().getAsTemplateDecl())) {
QualType ContextType
= Context.getCanonicalType(QualType(SpecType, 0));
QualType Injected
= ClassTemplate->getInjectedClassNameSpecialization();
if (Context.hasSameType(Injected, ContextType))
return ClassTemplate->getTemplatedDecl();
if (ClassTemplatePartialSpecializationDecl *PartialSpec
= ClassTemplate->findPartialSpecialization(ContextType))
return PartialSpec;
}
} else if (const RecordType *RecordT = NNSType->getAs<RecordType>()) {
return RecordT->getDecl();
}
}
return 0;
}
switch (NNS->getKind()) {
case NestedNameSpecifier::Identifier:
llvm_unreachable("Dependent nested-name-specifier has no DeclContext");
case NestedNameSpecifier::Namespace:
return NNS->getAsNamespace();
case NestedNameSpecifier::NamespaceAlias:
return NNS->getAsNamespaceAlias()->getNamespace();
case NestedNameSpecifier::TypeSpec:
case NestedNameSpecifier::TypeSpecWithTemplate: {
const TagType *Tag = NNS->getAsType()->getAs<TagType>();
assert(Tag && "Non-tag type in nested-name-specifier");
return Tag->getDecl();
}
case NestedNameSpecifier::Global:
return Context.getTranslationUnitDecl();
}
llvm_unreachable("Invalid NestedNameSpecifier::Kind!");
}
bool Sema::isDependentScopeSpecifier(const CXXScopeSpec &SS) {
if (!SS.isSet() || SS.isInvalid())
return false;
return SS.getScopeRep()->isDependent();
}
CXXRecordDecl *Sema::getCurrentInstantiationOf(NestedNameSpecifier *NNS) {
assert(getLangOpts().CPlusPlus && "Only callable in C++");
assert(NNS->isDependent() && "Only dependent nested-name-specifier allowed");
if (!NNS->getAsType())
return 0;
QualType T = QualType(NNS->getAsType(), 0);
return ::getCurrentInstantiationOf(T, CurContext);
}
bool Sema::RequireCompleteDeclContext(CXXScopeSpec &SS,
DeclContext *DC) {
assert(DC != 0 && "given null context");
TagDecl *tag = dyn_cast<TagDecl>(DC);
if (!tag || tag->isDependentContext())
return false;
QualType type = Context.getTypeDeclType(tag);
const TagType *tagType = type->getAs<TagType>();
if (tagType && tagType->isBeingDefined())
return false;
SourceLocation loc = SS.getLastQualifierNameLoc();
if (loc.isInvalid()) loc = SS.getRange().getBegin();
if (RequireCompleteType(loc, type, diag::err_incomplete_nested_name_spec,
SS.getRange())) {
SS.SetInvalid(SS.getRange());
return true;
}
const EnumType *enumType = dyn_cast_or_null<EnumType>(tagType);
if (!enumType || enumType->getDecl()->isCompleteDefinition())
return false;
EnumDecl *ED = enumType->getDecl();
if (EnumDecl *Pattern = ED->getInstantiatedFromMemberEnum()) {
MemberSpecializationInfo *MSI = ED->getMemberSpecializationInfo();
if (MSI->getTemplateSpecializationKind() != TSK_ExplicitSpecialization) {
if (InstantiateEnum(loc, ED, Pattern, getTemplateInstantiationArgs(ED),
TSK_ImplicitInstantiation)) {
SS.SetInvalid(SS.getRange());
return true;
}
return false;
}
}
Diag(loc, diag::err_incomplete_nested_name_spec)
<< type << SS.getRange();
SS.SetInvalid(SS.getRange());
return true;
}
bool Sema::ActOnCXXGlobalScopeSpecifier(Scope *S, SourceLocation CCLoc,
CXXScopeSpec &SS) {
SS.MakeGlobal(Context, CCLoc);
return false;
}
bool Sema::isAcceptableNestedNameSpecifier(const NamedDecl *SD) {
if (!SD)
return false;
if (isa<NamespaceDecl>(SD) || isa<NamespaceAliasDecl>(SD))
return true;
if (!isa<TypeDecl>(SD))
return false;
QualType T = Context.getTypeDeclType(cast<TypeDecl>(SD));
if (T->isDependentType())
return true;
else if (const TypedefNameDecl *TD = dyn_cast<TypedefNameDecl>(SD)) {
if (TD->getUnderlyingType()->isRecordType() ||
(Context.getLangOpts().CPlusPlus11 &&
TD->getUnderlyingType()->isEnumeralType()))
return true;
} else if (isa<RecordDecl>(SD) ||
(Context.getLangOpts().CPlusPlus11 && isa<EnumDecl>(SD)))
return true;
return false;
}
NamedDecl *Sema::FindFirstQualifierInScope(Scope *S, NestedNameSpecifier *NNS) {
if (!S || !NNS)
return 0;
while (NNS->getPrefix())
NNS = NNS->getPrefix();
if (NNS->getKind() != NestedNameSpecifier::Identifier)
return 0;
LookupResult Found(*this, NNS->getAsIdentifier(), SourceLocation(),
LookupNestedNameSpecifierName);
LookupName(Found, S);
assert(!Found.isAmbiguous() && "Cannot handle ambiguities here yet");
if (!Found.isSingleResult())
return 0;
NamedDecl *Result = Found.getFoundDecl();
if (isAcceptableNestedNameSpecifier(Result))
return Result;
return 0;
}
bool Sema::isNonTypeNestedNameSpecifier(Scope *S, CXXScopeSpec &SS,
SourceLocation IdLoc,
IdentifierInfo &II,
ParsedType ObjectTypePtr) {
QualType ObjectType = GetTypeFromParser(ObjectTypePtr);
LookupResult Found(*this, &II, IdLoc, LookupNestedNameSpecifierName);
DeclContext *LookupCtx = 0;
bool isDependent = false;
if (!ObjectType.isNull()) {
assert(!SS.isSet() && "ObjectType and scope specifier cannot coexist");
LookupCtx = computeDeclContext(ObjectType);
isDependent = ObjectType->isDependentType();
} else if (SS.isSet()) {
LookupCtx = computeDeclContext(SS, false);
isDependent = isDependentScopeSpecifier(SS);
Found.setContextRange(SS.getRange());
}
if (LookupCtx) {
if (!LookupCtx->isDependentContext() &&
RequireCompleteDeclContext(SS, LookupCtx))
return false;
LookupQualifiedName(Found, LookupCtx);
} else if (isDependent) {
return false;
} else {
LookupName(Found, S);
}
Found.suppressDiagnostics();
if (NamedDecl *ND = Found.getAsSingle<NamedDecl>())
return isa<NamespaceDecl>(ND) || isa<NamespaceAliasDecl>(ND);
return false;
}
namespace {
class NestedNameSpecifierValidatorCCC : public CorrectionCandidateCallback {
public:
explicit NestedNameSpecifierValidatorCCC(Sema &SRef)
: SRef(SRef) {}
virtual bool ValidateCandidate(const TypoCorrection &candidate) {
return SRef.isAcceptableNestedNameSpecifier(candidate.getCorrectionDecl());
}
private:
Sema &SRef;
};
}
bool Sema::BuildCXXNestedNameSpecifier(Scope *S,
IdentifierInfo &Identifier,
SourceLocation IdentifierLoc,
SourceLocation CCLoc,
QualType ObjectType,
bool EnteringContext,
CXXScopeSpec &SS,
NamedDecl *ScopeLookupResult,
bool ErrorRecoveryLookup) {
LookupResult Found(*this, &Identifier, IdentifierLoc,
LookupNestedNameSpecifierName);
DeclContext *LookupCtx = 0;
bool isDependent = false;
if (!ObjectType.isNull()) {
assert(!SS.isSet() && "ObjectType and scope specifier cannot coexist");
LookupCtx = computeDeclContext(ObjectType);
isDependent = ObjectType->isDependentType();
} else if (SS.isSet()) {
LookupCtx = computeDeclContext(SS, EnteringContext);
isDependent = isDependentScopeSpecifier(SS);
Found.setContextRange(SS.getRange());
}
bool ObjectTypeSearchedInScope = false;
if (LookupCtx) {
if (!LookupCtx->isDependentContext() &&
RequireCompleteDeclContext(SS, LookupCtx))
return true;
LookupQualifiedName(Found, LookupCtx);
if (!ObjectType.isNull() && Found.empty()) {
if (S)
LookupName(Found, S);
else if (ScopeLookupResult)
Found.addDecl(ScopeLookupResult);
ObjectTypeSearchedInScope = true;
}
} else if (!isDependent) {
LookupName(Found, S);
}
if (Found.empty() && isDependent &&
!(LookupCtx && LookupCtx->isRecord() &&
(!cast<CXXRecordDecl>(LookupCtx)->hasDefinition() ||
!cast<CXXRecordDecl>(LookupCtx)->hasAnyDependentBases()))) {
if (ErrorRecoveryLookup)
return true;
SS.Extend(Context, &Identifier, IdentifierLoc, CCLoc);
return false;
}
if (Found.empty() && !ErrorRecoveryLookup && !getLangOpts().MSVCCompat) {
DeclarationName Name = Found.getLookupName();
NestedNameSpecifierValidatorCCC Validator(*this);
Found.clear();
if (TypoCorrection Corrected =
CorrectTypo(Found.getLookupNameInfo(), Found.getLookupKind(), S,
&SS, Validator, LookupCtx, EnteringContext)) {
if (LookupCtx) {
bool DroppedSpecifier =
Corrected.WillReplaceSpecifier() &&
Name.getAsString() == Corrected.getAsString(getLangOpts());
if (DroppedSpecifier)
SS.clear();
diagnoseTypo(Corrected, PDiag(diag::err_no_member_suggest)
<< Name << LookupCtx << DroppedSpecifier
<< SS.getRange());
} else
diagnoseTypo(Corrected, PDiag(diag::err_undeclared_var_use_suggest)
<< Name);
if (NamedDecl *ND = Corrected.getCorrectionDecl())
Found.addDecl(ND);
Found.setLookupName(Corrected.getCorrection());
} else {
Found.setLookupName(&Identifier);
}
}
NamedDecl *SD = Found.getAsSingle<NamedDecl>();
if (isAcceptableNestedNameSpecifier(SD)) {
if (!ObjectType.isNull() && !ObjectTypeSearchedInScope &&
!getLangOpts().CPlusPlus11) {
NamedDecl *OuterDecl;
if (S) {
LookupResult FoundOuter(*this, &Identifier, IdentifierLoc,
LookupNestedNameSpecifierName);
LookupName(FoundOuter, S);
OuterDecl = FoundOuter.getAsSingle<NamedDecl>();
} else
OuterDecl = ScopeLookupResult;
if (isAcceptableNestedNameSpecifier(OuterDecl) &&
OuterDecl->getCanonicalDecl() != SD->getCanonicalDecl() &&
(!isa<TypeDecl>(OuterDecl) || !isa<TypeDecl>(SD) ||
!Context.hasSameType(
Context.getTypeDeclType(cast<TypeDecl>(OuterDecl)),
Context.getTypeDeclType(cast<TypeDecl>(SD))))) {
if (ErrorRecoveryLookup)
return true;
Diag(IdentifierLoc,
diag::err_nested_name_member_ref_lookup_ambiguous)
<< &Identifier;
Diag(SD->getLocation(), diag::note_ambig_member_ref_object_type)
<< ObjectType;
Diag(OuterDecl->getLocation(), diag::note_ambig_member_ref_scope);
}
}
if (ErrorRecoveryLookup)
return false;
if (NamespaceDecl *Namespace = dyn_cast<NamespaceDecl>(SD)) {
SS.Extend(Context, Namespace, IdentifierLoc, CCLoc);
return false;
}
if (NamespaceAliasDecl *Alias = dyn_cast<NamespaceAliasDecl>(SD)) {
SS.Extend(Context, Alias, IdentifierLoc, CCLoc);
return false;
}
QualType T = Context.getTypeDeclType(cast<TypeDecl>(SD));
TypeLocBuilder TLB;
if (isa<InjectedClassNameType>(T)) {
InjectedClassNameTypeLoc InjectedTL
= TLB.push<InjectedClassNameTypeLoc>(T);
InjectedTL.setNameLoc(IdentifierLoc);
} else if (isa<RecordType>(T)) {
RecordTypeLoc RecordTL = TLB.push<RecordTypeLoc>(T);
RecordTL.setNameLoc(IdentifierLoc);
} else if (isa<TypedefType>(T)) {
TypedefTypeLoc TypedefTL = TLB.push<TypedefTypeLoc>(T);
TypedefTL.setNameLoc(IdentifierLoc);
} else if (isa<EnumType>(T)) {
EnumTypeLoc EnumTL = TLB.push<EnumTypeLoc>(T);
EnumTL.setNameLoc(IdentifierLoc);
} else if (isa<TemplateTypeParmType>(T)) {
TemplateTypeParmTypeLoc TemplateTypeTL
= TLB.push<TemplateTypeParmTypeLoc>(T);
TemplateTypeTL.setNameLoc(IdentifierLoc);
} else if (isa<UnresolvedUsingType>(T)) {
UnresolvedUsingTypeLoc UnresolvedTL
= TLB.push<UnresolvedUsingTypeLoc>(T);
UnresolvedTL.setNameLoc(IdentifierLoc);
} else if (isa<SubstTemplateTypeParmType>(T)) {
SubstTemplateTypeParmTypeLoc TL
= TLB.push<SubstTemplateTypeParmTypeLoc>(T);
TL.setNameLoc(IdentifierLoc);
} else if (isa<SubstTemplateTypeParmPackType>(T)) {
SubstTemplateTypeParmPackTypeLoc TL
= TLB.push<SubstTemplateTypeParmPackTypeLoc>(T);
TL.setNameLoc(IdentifierLoc);
} else {
llvm_unreachable("Unhandled TypeDecl node in nested-name-specifier");
}
if (T->isEnumeralType())
Diag(IdentifierLoc, diag::warn_cxx98_compat_enum_nested_name_spec);
SS.Extend(Context, SourceLocation(), TLB.getTypeLocInContext(Context, T),
CCLoc);
return false;
}
if (ErrorRecoveryLookup)
return true;
if (Found.empty()) {
Found.clear(LookupOrdinaryName);
LookupName(Found, S);
}
if (getLangOpts().MSVCCompat) {
DeclContext *DC = LookupCtx ? LookupCtx : CurContext;
if (DC->isDependentContext() && DC->isFunctionOrMethod()) {
SS.Extend(Context, &Identifier, IdentifierLoc, CCLoc);
return false;
}
}
unsigned DiagID;
if (!Found.empty())
DiagID = diag::err_expected_class_or_namespace;
else if (SS.isSet()) {
Diag(IdentifierLoc, diag::err_no_member)
<< &Identifier << LookupCtx << SS.getRange();
return true;
} else
DiagID = diag::err_undeclared_var_use;
if (SS.isSet())
Diag(IdentifierLoc, DiagID) << &Identifier << SS.getRange();
else
Diag(IdentifierLoc, DiagID) << &Identifier;
return 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,
0, 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->isDependentType() && !T->getAs<TagType>()) {
Diag(DS.getTypeSpecTypeLoc(), diag::err_expected_class)
<< 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::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,
0, true);
}
bool Sema::ActOnCXXNestedNameSpecifier(Scope *S,
CXXScopeSpec &SS,
SourceLocation TemplateKWLoc,
TemplateTy Template,
SourceLocation TemplateNameLoc,
SourceLocation LAngleLoc,
ASTTemplateArgsPtr TemplateArgsIn,
SourceLocation RAngleLoc,
SourceLocation CCLoc,
bool EnteringContext) {
if (SS.isInvalid())
return true;
TemplateArgumentListInfo TemplateArgs(LAngleLoc, RAngleLoc);
translateTemplateArguments(TemplateArgsIn, TemplateArgs);
DependentTemplateName *DTN = Template.get().getAsDependentTemplateName();
if (DTN && DTN->isIdentifier()) {
assert(DTN->getQualifier() == SS.getScopeRep());
QualType T = Context.getDependentTemplateSpecializationType(ETK_None,
DTN->getQualifier(),
DTN->getIdentifier(),
TemplateArgs);
TypeLocBuilder Builder;
DependentTemplateSpecializationTypeLoc SpecTL
= Builder.push<DependentTemplateSpecializationTypeLoc>(T);
SpecTL.setElaboratedKeywordLoc(SourceLocation());
SpecTL.setQualifierLoc(SS.getWithLocInContext(Context));
SpecTL.setTemplateKeywordLoc(TemplateKWLoc);
SpecTL.setTemplateNameLoc(TemplateNameLoc);
SpecTL.setLAngleLoc(LAngleLoc);
SpecTL.setRAngleLoc(RAngleLoc);
for (unsigned I = 0, N = TemplateArgs.size(); I != N; ++I)
SpecTL.setArgLocInfo(I, TemplateArgs[I].getLocInfo());
SS.Extend(Context, TemplateKWLoc, Builder.getTypeLocInContext(Context, T),
CCLoc);
return false;
}
TemplateDecl *TD = Template.get().getAsTemplateDecl();
if (Template.get().getAsOverloadedTemplate() || DTN ||
isa<FunctionTemplateDecl>(TD) || isa<VarTemplateDecl>(TD)) {
SourceRange R(TemplateNameLoc, RAngleLoc);
if (SS.getRange().isValid())
R.setBegin(SS.getRange().getBegin());
Diag(CCLoc, diag::err_non_type_template_in_nested_name_specifier)
<< (TD && isa<VarTemplateDecl>(TD)) << Template.get() << R;
NoteAllFoundTemplates(Template.get());
return true;
}
QualType T = CheckTemplateIdType(Template.get(), TemplateNameLoc,
TemplateArgs);
if (T.isNull())
return true;
if (!T->isDependentType() && !T->getAs<TagType>()) {
Diag(TemplateNameLoc, diag::err_nested_name_spec_non_tag) << T;
NoteAllFoundTemplates(Template.get());
return true;
}
TypeLocBuilder Builder;
TemplateSpecializationTypeLoc SpecTL
= Builder.push<TemplateSpecializationTypeLoc>(T);
SpecTL.setTemplateKeywordLoc(TemplateKWLoc);
SpecTL.setTemplateNameLoc(TemplateNameLoc);
SpecTL.setLAngleLoc(LAngleLoc);
SpecTL.setRAngleLoc(RAngleLoc);
for (unsigned I = 0, N = TemplateArgs.size(); I != N; ++I)
SpecTL.setArgLocInfo(I, TemplateArgs[I].getLocInfo());
SS.Extend(Context, TemplateKWLoc, Builder.getTypeLocInContext(Context, T),
CCLoc);
return false;
}
namespace {
struct NestedNameSpecifierAnnotation {
NestedNameSpecifier *NNS;
};
}
void *Sema::SaveNestedNameSpecifierAnnotation(CXXScopeSpec &SS) {
if (SS.isEmpty() || SS.isInvalid())
return 0;
void *Mem = Context.Allocate((sizeof(NestedNameSpecifierAnnotation) +
SS.location_size()),
llvm::alignOf<NestedNameSpecifierAnnotation>());
NestedNameSpecifierAnnotation *Annotation
= new (Mem) NestedNameSpecifierAnnotation;
Annotation->NNS = SS.getScopeRep();
memcpy(Annotation + 1, SS.location_data(), SS.location_size());
return Annotation;
}
void Sema::RestoreNestedNameSpecifierAnnotation(void *AnnotationPtr,
SourceRange AnnotationRange,
CXXScopeSpec &SS) {
if (!AnnotationPtr) {
SS.SetInvalid(AnnotationRange);
return;
}
NestedNameSpecifierAnnotation *Annotation
= static_cast<NestedNameSpecifierAnnotation *>(AnnotationPtr);
SS.Adopt(NestedNameSpecifierLoc(Annotation->NNS, Annotation + 1));
}
bool Sema::ShouldEnterDeclaratorScope(Scope *S, const CXXScopeSpec &SS) {
assert(SS.isSet() && "Parser passed invalid CXXScopeSpec.");
NestedNameSpecifier *Qualifier = SS.getScopeRep();
switch (Qualifier->getKind()) {
case NestedNameSpecifier::Global:
case NestedNameSpecifier::Namespace:
case NestedNameSpecifier::NamespaceAlias:
return CurContext->getRedeclContext()->isFileContext();
case NestedNameSpecifier::Identifier:
case NestedNameSpecifier::TypeSpec:
case NestedNameSpecifier::TypeSpecWithTemplate:
return true;
}
llvm_unreachable("Invalid NestedNameSpecifier::Kind!");
}
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;
if (!DC->isDependentContext() && RequireCompleteDeclContext(SS, DC))
return true;
EnterDeclaratorContext(S, DC);
if (DC->isDependentContext())
RebuildNestedNameSpecifierInCurrentInstantiation(SS);
return false;
}
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);
}