diff --git a/clang/lib/Sema/Sema.h b/clang/lib/Sema/Sema.h index a5b43e8a04c1..a79b0007f785 100644 --- a/clang/lib/Sema/Sema.h +++ b/clang/lib/Sema/Sema.h @@ -2365,7 +2365,7 @@ public: virtual OwningExprResult ActOnFinishFullExpr(ExprArg Expr); // Marks SS invalid if it represents an incomplete type. - bool RequireCompleteDeclContext(CXXScopeSpec &SS); + bool RequireCompleteDeclContext(CXXScopeSpec &SS, DeclContext *DC); DeclContext *computeDeclContext(QualType T); DeclContext *computeDeclContext(const CXXScopeSpec &SS, diff --git a/clang/lib/Sema/SemaCXXScopeSpec.cpp b/clang/lib/Sema/SemaCXXScopeSpec.cpp index 10adc6762f0b..c0ec9e997d13 100644 --- a/clang/lib/Sema/SemaCXXScopeSpec.cpp +++ b/clang/lib/Sema/SemaCXXScopeSpec.cpp @@ -186,21 +186,10 @@ CXXRecordDecl *Sema::getCurrentInstantiationOf(NestedNameSpecifier *NNS) { /// 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(CXXScopeSpec &SS) { - if (!SS.isSet() || SS.isInvalid()) - return false; +bool Sema::RequireCompleteDeclContext(CXXScopeSpec &SS, + DeclContext *DC) { + assert(DC != 0 && "given null context"); - DeclContext *DC = computeDeclContext(SS, true); - if (!DC) { - // It's dependent. - assert(isDependentScopeSpecifier(SS) && - "No context for non-dependent scope specifier?"); - Diag(SS.getRange().getBegin(), diag::err_dependent_nested_name_spec) - << SS.getRange(); - SS.setScopeRep(0); - return true; - } - if (TagDecl *Tag = dyn_cast(DC)) { // If this is a dependent type, then we consider it complete. if (Tag->isDependentContext()) @@ -216,7 +205,7 @@ bool Sema::RequireCompleteDeclContext(CXXScopeSpec &SS) { if (RequireCompleteType(SS.getRange().getBegin(), Context.getTypeDeclType(Tag), PDiag(diag::err_incomplete_nested_name_spec) - << SS.getRange())) { + << SS.getRange())) { SS.setScopeRep(0); // Mark the ScopeSpec invalid. return true; } @@ -322,7 +311,8 @@ bool Sema::isNonTypeNestedNameSpecifier(Scope *S, CXXScopeSpec &SS, // nested-name-specifier. // The declaration context must be complete. - if (!LookupCtx->isDependentContext() && RequireCompleteDeclContext(SS)) + if (!LookupCtx->isDependentContext() && + RequireCompleteDeclContext(SS, LookupCtx)) return false; LookupQualifiedName(Found, LookupCtx); @@ -392,7 +382,8 @@ Sema::CXXScopeTy *Sema::BuildCXXNestedNameSpecifier(Scope *S, // nested-name-specifier. // The declaration context must be complete. - if (!LookupCtx->isDependentContext() && RequireCompleteDeclContext(SS)) + if (!LookupCtx->isDependentContext() && + RequireCompleteDeclContext(SS, LookupCtx)) return 0; LookupQualifiedName(Found, LookupCtx); @@ -656,7 +647,7 @@ bool Sema::ActOnCXXEnterDeclaratorScope(Scope *S, CXXScopeSpec &SS) { // Before we enter a declarator's context, we need to make sure that // it is a complete declaration context. - if (!DC->isDependentContext() && RequireCompleteDeclContext(SS)) + if (!DC->isDependentContext() && RequireCompleteDeclContext(SS, DC)) return true; EnterDeclaratorContext(S, DC); diff --git a/clang/lib/Sema/SemaCodeComplete.cpp b/clang/lib/Sema/SemaCodeComplete.cpp index 35bb6977efd9..c075d161704e 100644 --- a/clang/lib/Sema/SemaCodeComplete.cpp +++ b/clang/lib/Sema/SemaCodeComplete.cpp @@ -2286,7 +2286,7 @@ void Sema::CodeCompleteQualifiedId(Scope *S, CXXScopeSpec &SS, // Try to instantiate any non-dependent declaration contexts before // we look in them. - if (!isDependentScopeSpecifier(SS) && RequireCompleteDeclContext(SS)) + if (!isDependentScopeSpecifier(SS) && RequireCompleteDeclContext(SS, Ctx)) return; ResultBuilder Results(*this); diff --git a/clang/lib/Sema/SemaDecl.cpp b/clang/lib/Sema/SemaDecl.cpp index 7a70c32877c2..3e4c923285c3 100644 --- a/clang/lib/Sema/SemaDecl.cpp +++ b/clang/lib/Sema/SemaDecl.cpp @@ -97,7 +97,8 @@ Sema::TypeTy *Sema::getTypeName(IdentifierInfo &II, SourceLocation NameLoc, return 0; } - if (!LookupCtx->isDependentContext() && RequireCompleteDeclContext(*SS)) + if (!LookupCtx->isDependentContext() && + RequireCompleteDeclContext(*SS, LookupCtx)) return 0; } @@ -2030,7 +2031,7 @@ Sema::HandleDeclarator(Scope *S, Declarator &D, bool IsDependentContext = DC->isDependentContext(); if (!IsDependentContext && - RequireCompleteDeclContext(D.getCXXScopeSpec())) + RequireCompleteDeclContext(D.getCXXScopeSpec(), DC)) return DeclPtrTy(); if (isa(DC) && !cast(DC)->hasDefinition()) { @@ -4940,12 +4941,18 @@ Sema::DeclPtrTy Sema::ActOnTag(Scope *S, unsigned TagSpec, TagUseKind TUK, IsDependent = true; return DeclPtrTy(); } + } else { + DC = computeDeclContext(SS, true); + if (!DC) { + Diag(SS.getRange().getBegin(), diag::err_dependent_nested_name_spec) + << SS.getRange(); + return DeclPtrTy(); + } } - if (RequireCompleteDeclContext(SS)) + if (RequireCompleteDeclContext(SS, DC)) return DeclPtrTy::make((Decl *)0); - DC = computeDeclContext(SS, true); SearchDC = DC; // Look-up name inside 'foo::'. LookupQualifiedName(Previous, DC); diff --git a/clang/lib/Sema/SemaDeclCXX.cpp b/clang/lib/Sema/SemaDeclCXX.cpp index 854f204ab06f..c73c6caf2973 100644 --- a/clang/lib/Sema/SemaDeclCXX.cpp +++ b/clang/lib/Sema/SemaDeclCXX.cpp @@ -3724,7 +3724,7 @@ NamedDecl *Sema::BuildUsingDeclaration(Scope *S, AccessSpecifier AS, if (!LookupContext) return D; UsingDecl *UD = cast(D); - if (RequireCompleteDeclContext(SS)) { + if (RequireCompleteDeclContext(SS, LookupContext)) { UD->setInvalidDecl(); return UD; } @@ -5251,11 +5251,11 @@ Sema::ActOnFriendFunctionDecl(Scope *S, LookupResult Previous(*this, Name, D.getIdentifierLoc(), LookupOrdinaryName, ForRedeclaration); if (!ScopeQual.isInvalid() && ScopeQual.isSet()) { - // FIXME: RequireCompleteDeclContext DC = computeDeclContext(ScopeQual); // FIXME: handle dependent contexts if (!DC) return DeclPtrTy(); + if (RequireCompleteDeclContext(ScopeQual, DC)) return DeclPtrTy(); LookupQualifiedName(Previous, DC); diff --git a/clang/lib/Sema/SemaExpr.cpp b/clang/lib/Sema/SemaExpr.cpp index d8d525e99209..a1b66cd94600 100644 --- a/clang/lib/Sema/SemaExpr.cpp +++ b/clang/lib/Sema/SemaExpr.cpp @@ -1238,7 +1238,7 @@ Sema::BuildQualifiedDeclarationNameExpr(CXXScopeSpec &SS, if (!(DC = computeDeclContext(SS, false)) || DC->isDependentContext()) return BuildDependentDeclRefExpr(SS, Name, NameLoc, 0); - if (RequireCompleteDeclContext(SS)) + if (RequireCompleteDeclContext(SS, DC)) return ExprError(); LookupResult R(*this, Name, NameLoc, LookupOrdinaryName); @@ -2582,7 +2582,7 @@ LookupMemberExprInRecord(Sema &SemaRef, LookupResult &R, // nested-name-specifier. DC = SemaRef.computeDeclContext(SS, false); - if (SemaRef.RequireCompleteDeclContext(SS)) { + if (SemaRef.RequireCompleteDeclContext(SS, DC)) { SemaRef.Diag(SS.getRange().getEnd(), diag::err_typecheck_incomplete_tag) << SS.getRange() << DC; return true; diff --git a/clang/lib/Sema/SemaLookup.cpp b/clang/lib/Sema/SemaLookup.cpp index bdbbc119c616..337a4a3ce3f7 100644 --- a/clang/lib/Sema/SemaLookup.cpp +++ b/clang/lib/Sema/SemaLookup.cpp @@ -1261,7 +1261,7 @@ bool Sema::LookupParsedName(LookupResult &R, Scope *S, CXXScopeSpec *SS, if (DeclContext *DC = computeDeclContext(*SS, EnteringContext)) { // We have resolved the scope specifier to a particular declaration // contex, and will perform name lookup in that context. - if (!DC->isDependentContext() && RequireCompleteDeclContext(*SS)) + if (!DC->isDependentContext() && RequireCompleteDeclContext(*SS, DC)) return false; R.setContextRange(SS->getRange()); diff --git a/clang/lib/Sema/SemaTemplate.cpp b/clang/lib/Sema/SemaTemplate.cpp index 56410a2cfa4f..694b21c8393f 100644 --- a/clang/lib/Sema/SemaTemplate.cpp +++ b/clang/lib/Sema/SemaTemplate.cpp @@ -210,7 +210,7 @@ void Sema::LookupTemplateName(LookupResult &Found, isDependent = isDependentScopeSpecifier(SS); // The declaration context must be complete. - if (LookupCtx && RequireCompleteDeclContext(SS)) + if (LookupCtx && RequireCompleteDeclContext(SS, LookupCtx)) return; } @@ -753,15 +753,15 @@ Sema::CheckClassTemplate(Scope *S, unsigned TagSpec, TagUseKind TUK, LookupResult Previous(*this, Name, NameLoc, LookupOrdinaryName, ForRedeclaration); if (SS.isNotEmpty() && !SS.isInvalid()) { - if (RequireCompleteDeclContext(SS)) - return true; - SemanticContext = computeDeclContext(SS, true); if (!SemanticContext) { // FIXME: Produce a reasonable diagnostic here return true; } + if (RequireCompleteDeclContext(SS, SemanticContext)) + return true; + LookupQualifiedName(Previous, SemanticContext); } else { SemanticContext = CurContext; @@ -1633,7 +1633,7 @@ Sema::BuildQualifiedTemplateIdExpr(CXXScopeSpec &SS, DeclContext *DC; if (!(DC = computeDeclContext(SS, false)) || DC->isDependentContext() || - RequireCompleteDeclContext(SS)) + RequireCompleteDeclContext(SS, DC)) return BuildDependentDeclRefExpr(SS, Name, NameLoc, &TemplateArgs); LookupResult R(*this, Name, NameLoc, LookupOrdinaryName); @@ -5260,36 +5260,26 @@ QualType Sema::CheckTypenameType(ElaboratedTypeKeyword Keyword, NestedNameSpecifier *NNS, const IdentifierInfo &II, SourceRange Range) { - CXXRecordDecl *CurrentInstantiation = 0; - if (NNS->isDependent()) { - CurrentInstantiation = getCurrentInstantiationOf(NNS); + CXXScopeSpec SS; + SS.setScopeRep(NNS); + SS.setRange(Range); - // If the nested-name-specifier does not refer to the current - // instantiation, then build a typename type. - if (!CurrentInstantiation) - return Context.getDependentNameType(Keyword, NNS, &II); - - // The nested-name-specifier refers to the current instantiation, so the - // "typename" keyword itself is superfluous. In C++03, the program is - // actually ill-formed. However, DR 382 (in C++0x CD1) allows such - // extraneous "typename" keywords, and we retroactively apply this DR to - // C++03 code. + DeclContext *Ctx = computeDeclContext(SS); + if (!Ctx) { + // If the nested-name-specifier is dependent and couldn't be + // resolved to a type, build a typename type. + assert(NNS->isDependent()); + return Context.getDependentNameType(Keyword, NNS, &II); } - DeclContext *Ctx = 0; + // If the nested-name-specifier refers to the current instantiation, + // the "typename" keyword itself is superfluous. In C++03, the + // program is actually ill-formed. However, DR 382 (in C++0x CD1) + // allows such extraneous "typename" keywords, and we retroactively + // apply this DR to C++03 code. In any case we continue. - if (CurrentInstantiation) - Ctx = CurrentInstantiation; - else { - CXXScopeSpec SS; - SS.setScopeRep(NNS); - SS.setRange(Range); - if (RequireCompleteDeclContext(SS)) - return QualType(); - - Ctx = computeDeclContext(SS); - } - assert(Ctx && "No declaration context?"); + if (RequireCompleteDeclContext(SS, Ctx)) + return QualType(); DeclarationName Name(&II); LookupResult Result(*this, Name, Range.getEnd(), LookupOrdinaryName);