diff options
author | dim <dim@FreeBSD.org> | 2011-02-26 22:09:03 +0000 |
---|---|---|
committer | dim <dim@FreeBSD.org> | 2011-02-26 22:09:03 +0000 |
commit | a0fb00f9837bd0d2e5948f16f6a6b82a7a628f51 (patch) | |
tree | abae0246ec9156cc1a7cbb947b2b0dfe95fa3189 /lib/Sema/SemaCXXScopeSpec.cpp | |
parent | 39fcc9a984e2820e4ea0fa2ac4abd17d9f3a31df (diff) | |
download | FreeBSD-src-a0fb00f9837bd0d2e5948f16f6a6b82a7a628f51.zip FreeBSD-src-a0fb00f9837bd0d2e5948f16f6a6b82a7a628f51.tar.gz |
Vendor import of clang trunk r126547:
http://llvm.org/svn/llvm-project/cfe/trunk@126547
Diffstat (limited to 'lib/Sema/SemaCXXScopeSpec.cpp')
-rw-r--r-- | lib/Sema/SemaCXXScopeSpec.cpp | 257 |
1 files changed, 169 insertions, 88 deletions
diff --git a/lib/Sema/SemaCXXScopeSpec.cpp b/lib/Sema/SemaCXXScopeSpec.cpp index aa0efcd..7ad4b45 100644 --- a/lib/Sema/SemaCXXScopeSpec.cpp +++ b/lib/Sema/SemaCXXScopeSpec.cpp @@ -19,6 +19,7 @@ #include "clang/AST/NestedNameSpecifier.h" #include "clang/Basic/PartialDiagnostic.h" #include "clang/Sema/DeclSpec.h" +#include "TypeLocBuilder.h" #include "llvm/ADT/STLExtras.h" #include "llvm/Support/raw_ostream.h" using namespace clang; @@ -138,6 +139,9 @@ DeclContext *Sema::computeDeclContext(const CXXScopeSpec &SS, 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>(); @@ -219,7 +223,7 @@ bool Sema::RequireCompleteDeclContext(CXXScopeSpec &SS, Context.getTypeDeclType(Tag), PDiag(diag::err_incomplete_nested_name_spec) << SS.getRange())) { - SS.setScopeRep(0); // Mark the ScopeSpec invalid. + SS.SetInvalid(SS.getRange()); return true; } } @@ -227,11 +231,10 @@ bool Sema::RequireCompleteDeclContext(CXXScopeSpec &SS, return false; } -/// ActOnCXXGlobalScopeSpecifier - Return the object that represents the -/// global scope ('::'). -Sema::CXXScopeTy *Sema::ActOnCXXGlobalScopeSpecifier(Scope *S, - SourceLocation CCLoc) { - return NestedNameSpecifier::GlobalSpecifier(Context); +bool Sema::ActOnCXXGlobalScopeSpecifier(Scope *S, SourceLocation CCLoc, + CXXScopeSpec &SS) { + SS.MakeGlobal(Context, CCLoc); + return false; } /// \brief Determines whether the given declaration is an valid acceptable @@ -352,22 +355,21 @@ bool Sema::isNonTypeNestedNameSpecifier(Scope *S, CXXScopeSpec &SS, /// /// If ErrorRecoveryLookup is true, then this call is used to improve error /// recovery. This means that it should not emit diagnostics, it should -/// just return null on failure. It also means it should only return a valid +/// just return true on failure. It also means it should only return a valid /// scope if it *knows* that the result is correct. It should not return in a -/// dependent context, for example. -Sema::CXXScopeTy *Sema::BuildCXXNestedNameSpecifier(Scope *S, - CXXScopeSpec &SS, - SourceLocation IdLoc, - SourceLocation CCLoc, - IdentifierInfo &II, - QualType ObjectType, - NamedDecl *ScopeLookupResult, - bool EnteringContext, - bool ErrorRecoveryLookup) { - NestedNameSpecifier *Prefix - = static_cast<NestedNameSpecifier *>(SS.getScopeRep()); - - LookupResult Found(*this, &II, IdLoc, LookupNestedNameSpecifierName); +/// dependent context, for example. Nor will it extend \p SS with the scope +/// specifier. +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); // Determine where to perform name lookup DeclContext *LookupCtx = 0; @@ -397,7 +399,7 @@ Sema::CXXScopeTy *Sema::BuildCXXNestedNameSpecifier(Scope *S, // The declaration context must be complete. if (!LookupCtx->isDependentContext() && RequireCompleteDeclContext(SS, LookupCtx)) - return 0; + return true; LookupQualifiedName(Found, LookupCtx); @@ -442,16 +444,14 @@ Sema::CXXScopeTy *Sema::BuildCXXNestedNameSpecifier(Scope *S, !cast<CXXRecordDecl>(LookupCtx)->hasAnyDependentBases()))) { // Don't speculate if we're just trying to improve error recovery. if (ErrorRecoveryLookup) - return 0; + return true; // We were not able to compute the declaration context for a dependent // base object type or prior nested-name-specifier, so this // nested-name-specifier refers to an unknown specialization. Just build // a dependent nested-name-specifier. - if (!Prefix) - return NestedNameSpecifier::Create(Context, &II); - - return NestedNameSpecifier::Create(Context, Prefix, &II); + SS.Extend(Context, &Identifier, IdentifierLoc, CCLoc); + return false; } // FIXME: Deal with ambiguities cleanly. @@ -480,7 +480,7 @@ Sema::CXXScopeTy *Sema::BuildCXXNestedNameSpecifier(Scope *S, << ND->getDeclName(); } else { Found.clear(); - Found.setLookupName(&II); + Found.setLookupName(&Identifier); } } @@ -497,7 +497,8 @@ Sema::CXXScopeTy *Sema::BuildCXXNestedNameSpecifier(Scope *S, // scope, reconstruct the result from the template instantiation itself. NamedDecl *OuterDecl; if (S) { - LookupResult FoundOuter(*this, &II, IdLoc, LookupNestedNameSpecifierName); + LookupResult FoundOuter(*this, &Identifier, IdentifierLoc, + LookupNestedNameSpecifierName); LookupName(FoundOuter, S); OuterDecl = FoundOuter.getAsSingle<NamedDecl>(); } else @@ -509,39 +510,72 @@ Sema::CXXScopeTy *Sema::BuildCXXNestedNameSpecifier(Scope *S, !Context.hasSameType( Context.getTypeDeclType(cast<TypeDecl>(OuterDecl)), Context.getTypeDeclType(cast<TypeDecl>(SD))))) { - if (ErrorRecoveryLookup) - return 0; - - Diag(IdLoc, diag::err_nested_name_member_ref_lookup_ambiguous) - << &II; - Diag(SD->getLocation(), diag::note_ambig_member_ref_object_type) - << ObjectType; - Diag(OuterDecl->getLocation(), diag::note_ambig_member_ref_scope); - - // Fall through so that we'll pick the name we found in the object - // type, since that's probably what the user wanted anyway. - } + 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); + + // Fall through so that we'll pick the name we found in the object + // type, since that's probably what the user wanted anyway. + } } - if (NamespaceDecl *Namespace = dyn_cast<NamespaceDecl>(SD)) - return NestedNameSpecifier::Create(Context, Prefix, Namespace); + // 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; + + if (NamespaceDecl *Namespace = dyn_cast<NamespaceDecl>(SD)) { + SS.Extend(Context, Namespace, IdentifierLoc, CCLoc); + return false; + } - // FIXME: It would be nice to maintain the namespace alias name, then - // see through that alias when resolving the nested-name-specifier down to - // a declaration context. - if (NamespaceAliasDecl *Alias = dyn_cast<NamespaceAliasDecl>(SD)) - return NestedNameSpecifier::Create(Context, Prefix, - Alias->getNamespace()); + if (NamespaceAliasDecl *Alias = dyn_cast<NamespaceAliasDecl>(SD)) { + SS.Extend(Context, Alias, IdentifierLoc, CCLoc); + return false; + } QualType T = Context.getTypeDeclType(cast<TypeDecl>(SD)); - return NestedNameSpecifier::Create(Context, Prefix, false, - T.getTypePtr()); + TypeLocBuilder TLB; + if (isa<InjectedClassNameType>(T)) { + InjectedClassNameTypeLoc InjectedTL + = TLB.push<InjectedClassNameTypeLoc>(T); + InjectedTL.setNameLoc(IdentifierLoc); + } else if (isa<RecordDecl>(SD)) { + RecordTypeLoc RecordTL = TLB.push<RecordTypeLoc>(T); + RecordTL.setNameLoc(IdentifierLoc); + } else if (isa<TypedefDecl>(SD)) { + TypedefTypeLoc TypedefTL = TLB.push<TypedefTypeLoc>(T); + TypedefTL.setNameLoc(IdentifierLoc); + } else if (isa<EnumDecl>(SD)) { + EnumTypeLoc EnumTL = TLB.push<EnumTypeLoc>(T); + EnumTL.setNameLoc(IdentifierLoc); + } else if (isa<TemplateTypeParmDecl>(SD)) { + TemplateTypeParmTypeLoc TemplateTypeTL + = TLB.push<TemplateTypeParmTypeLoc>(T); + TemplateTypeTL.setNameLoc(IdentifierLoc); + } else { + assert(isa<UnresolvedUsingTypenameDecl>(SD) && + "Unhandled TypeDecl node in nested-name-specifier"); + UnresolvedUsingTypeLoc UnresolvedTL + = TLB.push<UnresolvedUsingTypeLoc>(T); + UnresolvedTL.setNameLoc(IdentifierLoc); + } + + SS.Extend(Context, SourceLocation(), TLB.getTypeLocInContext(Context, T), + CCLoc); + return false; } // Otherwise, we have an error case. If we don't want diagnostics, just // return an error now. if (ErrorRecoveryLookup) - return 0; + return true; // If we didn't find anything during our lookup, try again with // ordinary name lookup, which can help us produce better error @@ -555,36 +589,34 @@ Sema::CXXScopeTy *Sema::BuildCXXNestedNameSpecifier(Scope *S, if (!Found.empty()) DiagID = diag::err_expected_class_or_namespace; else if (SS.isSet()) { - Diag(IdLoc, diag::err_no_member) << &II << LookupCtx << SS.getRange(); - return 0; + Diag(IdentifierLoc, diag::err_no_member) + << &Identifier << LookupCtx << SS.getRange(); + return true; } else DiagID = diag::err_undeclared_var_use; if (SS.isSet()) - Diag(IdLoc, DiagID) << &II << SS.getRange(); + Diag(IdentifierLoc, DiagID) << &Identifier << SS.getRange(); else - Diag(IdLoc, DiagID) << &II; + Diag(IdentifierLoc, DiagID) << &Identifier; - return 0; + return true; } -/// ActOnCXXNestedNameSpecifier - Called during parsing of a -/// nested-name-specifier. e.g. for "foo::bar::" we parsed "foo::" and now -/// we want to resolve "bar::". 'SS' is empty or the previously parsed -/// nested-name part ("foo::"), 'IdLoc' is the source location of 'bar', -/// 'CCLoc' is the location of '::' and 'II' is the identifier for 'bar'. -/// Returns a CXXScopeTy* object representing the C++ scope. -Sema::CXXScopeTy *Sema::ActOnCXXNestedNameSpecifier(Scope *S, - CXXScopeSpec &SS, - SourceLocation IdLoc, - SourceLocation CCLoc, - IdentifierInfo &II, - ParsedType ObjectTypePtr, - bool EnteringContext) { - return BuildCXXNestedNameSpecifier(S, SS, IdLoc, CCLoc, II, - GetTypeFromParser(ObjectTypePtr), - /*ScopeLookupResult=*/0, EnteringContext, - false); +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); } /// IsInvalidUnlessNestedName - This method is used for error recovery @@ -594,23 +626,71 @@ Sema::CXXScopeTy *Sema::ActOnCXXNestedNameSpecifier(Scope *S, /// /// The arguments are the same as those passed to ActOnCXXNestedNameSpecifier. bool Sema::IsInvalidUnlessNestedName(Scope *S, CXXScopeSpec &SS, - IdentifierInfo &II, ParsedType ObjectType, + IdentifierInfo &Identifier, + SourceLocation IdentifierLoc, + SourceLocation ColonLoc, + ParsedType ObjectType, bool EnteringContext) { - return BuildCXXNestedNameSpecifier(S, SS, SourceLocation(), SourceLocation(), - II, GetTypeFromParser(ObjectType), - /*ScopeLookupResult=*/0, EnteringContext, - true); + if (SS.isInvalid()) + return false; + + return !BuildCXXNestedNameSpecifier(S, Identifier, IdentifierLoc, ColonLoc, + GetTypeFromParser(ObjectType), + EnteringContext, SS, + /*ScopeLookupResult=*/0, true); } -Sema::CXXScopeTy *Sema::ActOnCXXNestedNameSpecifier(Scope *S, - const CXXScopeSpec &SS, - ParsedType Ty, - SourceRange TypeRange, - SourceLocation CCLoc) { - NestedNameSpecifier *Prefix = SS.getScopeRep(); - QualType T = GetTypeFromParser(Ty); - return NestedNameSpecifier::Create(Context, Prefix, /*FIXME:*/false, - T.getTypePtr()); +bool Sema::ActOnCXXNestedNameSpecifier(Scope *S, + ParsedType Type, + SourceLocation CCLoc, + CXXScopeSpec &SS) { + if (SS.isInvalid()) + return true; + + TypeSourceInfo *TSInfo; + QualType T = GetTypeFromParser(Type, &TSInfo); + if (T.isNull()) + return true; + + assert(TSInfo && "Not TypeSourceInfo in nested-name-specifier?"); + // FIXME: location of the 'template' keyword? + SS.Extend(Context, SourceLocation(), TSInfo->getTypeLoc(), CCLoc); + return false; +} + +namespace { + /// \brief A structure that stores a nested-name-specifier annotation, + /// including both the nested-name-specifier + 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) { @@ -636,6 +716,7 @@ bool Sema::ShouldEnterDeclaratorScope(Scope *S, const CXXScopeSpec &SS) { switch (Qualifier->getKind()) { case NestedNameSpecifier::Global: case NestedNameSpecifier::Namespace: + case NestedNameSpecifier::NamespaceAlias: // These are always namespace scopes. We never want to enter a // namespace scope from anything but a file context. return CurContext->getRedeclContext()->isFileContext(); |