forked from OSchip/llvm-project
Teach CXXScopeSpec to handle the extension of a nested-name-specifier
with another component in the nested-name-specifiers, updating its representation (a NestedNameSpecifier) and source-location information (currently a SourceRange) simultaneously. This is groundwork for adding source-location information to nested-name-specifiers. llvm-svn: 126346
This commit is contained in:
parent
60ed89dc54
commit
90c9972fb2
|
@ -29,9 +29,12 @@
|
|||
#include "llvm/Support/ErrorHandling.h"
|
||||
|
||||
namespace clang {
|
||||
class ASTContext;
|
||||
class TypeLoc;
|
||||
class LangOptions;
|
||||
class Diagnostic;
|
||||
class IdentifierInfo;
|
||||
class NamespaceDecl;
|
||||
class NestedNameSpecifier;
|
||||
class Preprocessor;
|
||||
class Declarator;
|
||||
|
@ -51,7 +54,7 @@ namespace clang {
|
|||
class CXXScopeSpec {
|
||||
SourceRange Range;
|
||||
NestedNameSpecifier *ScopeRep;
|
||||
|
||||
|
||||
public:
|
||||
CXXScopeSpec() : Range(), ScopeRep() { }
|
||||
|
||||
|
@ -65,6 +68,54 @@ public:
|
|||
NestedNameSpecifier *getScopeRep() const { return ScopeRep; }
|
||||
void setScopeRep(NestedNameSpecifier *S) { ScopeRep = S; }
|
||||
|
||||
/// \brief Extend the current nested-name-specifier by another
|
||||
/// nested-name-specifier component of the form 'type::'.
|
||||
///
|
||||
/// \param Context The AST context in which this nested-name-specifier
|
||||
/// resides.
|
||||
///
|
||||
/// \param TemplateKWLoc The location of the 'template' keyword, if present.
|
||||
///
|
||||
/// \param TL The TypeLoc that describes the type preceding the '::'.
|
||||
///
|
||||
/// \param ColonColonLoc The location of the trailing '::'.
|
||||
void Extend(ASTContext &Context, SourceLocation TemplateKWLoc, TypeLoc TL,
|
||||
SourceLocation ColonColonLoc);
|
||||
|
||||
/// \brief Extend the current nested-name-specifier by another
|
||||
/// nested-name-specifier component of the form 'identifier::'.
|
||||
///
|
||||
/// \param Context The AST context in which this nested-name-specifier
|
||||
/// resides.
|
||||
///
|
||||
/// \param Identifier The identifier.
|
||||
///
|
||||
/// \param IdentifierLoc The location of the identifier.
|
||||
///
|
||||
/// \param ColonColonLoc The location of the trailing '::'.
|
||||
void Extend(ASTContext &Context, IdentifierInfo *Identifier,
|
||||
SourceLocation IdentifierLoc, SourceLocation ColonColonLoc);
|
||||
|
||||
/// \brief Extend the current nested-name-specifier by another
|
||||
/// nested-name-specifier component of the form 'namespace-or-alias::'.
|
||||
///
|
||||
/// \param Context The AST context in which this nested-name-specifier
|
||||
/// resides.
|
||||
///
|
||||
/// \param Namespace The namespace.
|
||||
/// FIXME: This should also permit a namespace alias.
|
||||
///
|
||||
/// \param NamespaceLoc The location of the namespace or namespace alias
|
||||
/// name.
|
||||
///
|
||||
/// \param ColonColonLoc The location of the trailing '::'.
|
||||
void Extend(ASTContext &Context, NamespaceDecl *Namespace,
|
||||
SourceLocation NamespaceLoc, SourceLocation ColonColonLoc);
|
||||
|
||||
/// \brief Turn this (empty) nested-name-specifier into the global
|
||||
/// nested-name-specifier '::'.
|
||||
void MakeGlobal(ASTContext &Context, SourceLocation ColonColonLoc);
|
||||
|
||||
/// No scope specifier.
|
||||
bool isEmpty() const { return !Range.isValid(); }
|
||||
/// A scope specifier is present, but may be valid or invalid.
|
||||
|
@ -75,6 +126,15 @@ public:
|
|||
/// A scope specifier is present, and it refers to a real scope.
|
||||
bool isValid() const { return isNotEmpty() && ScopeRep != 0; }
|
||||
|
||||
/// \brief Indicate that this nested-name-specifier is invalid.
|
||||
void SetInvalid(SourceRange R) {
|
||||
assert(R.isValid() && "Must have a valid source range");
|
||||
if (Range.getBegin().isInvalid())
|
||||
Range.setBegin(R.getBegin());
|
||||
Range.setEnd(R.getEnd());
|
||||
ScopeRep = 0;
|
||||
}
|
||||
|
||||
/// Deprecated. Some call sites intend isNotEmpty() while others intend
|
||||
/// isValid().
|
||||
bool isSet() const { return ScopeRep != 0; }
|
||||
|
|
|
@ -2591,11 +2591,19 @@ public:
|
|||
CXXRecordDecl *getCurrentInstantiationOf(NestedNameSpecifier *NNS);
|
||||
bool isUnknownSpecialization(const CXXScopeSpec &SS);
|
||||
|
||||
/// ActOnCXXGlobalScopeSpecifier - Return the object that represents the
|
||||
/// global scope ('::').
|
||||
NestedNameSpecifier *
|
||||
ActOnCXXGlobalScopeSpecifier(Scope *S, SourceLocation CCLoc);
|
||||
|
||||
/// \brief The parser has parsed a global nested-name-specifier '::'.
|
||||
///
|
||||
/// \param S The scope in which this nested-name-specifier occurs.
|
||||
///
|
||||
/// \param CCLoc The location of the '::'.
|
||||
///
|
||||
/// \param SS The nested-name-specifier, which will be updated in-place
|
||||
/// to reflect the parsed nested-name-specifier.
|
||||
///
|
||||
/// \returns true if an error occurred, false otherwise.
|
||||
bool ActOnCXXGlobalScopeSpecifier(Scope *S, SourceLocation CCLoc,
|
||||
CXXScopeSpec &SS);
|
||||
|
||||
bool isAcceptableNestedNameSpecifier(NamedDecl *SD);
|
||||
NamedDecl *FindFirstQualifierInScope(Scope *S, NestedNameSpecifier *NNS);
|
||||
|
||||
|
@ -2604,42 +2612,72 @@ public:
|
|||
IdentifierInfo &II,
|
||||
ParsedType ObjectType);
|
||||
|
||||
NestedNameSpecifier *BuildCXXNestedNameSpecifier(Scope *S,
|
||||
CXXScopeSpec &SS,
|
||||
SourceLocation IdLoc,
|
||||
SourceLocation CCLoc,
|
||||
IdentifierInfo &II,
|
||||
QualType ObjectType,
|
||||
NamedDecl *ScopeLookupResult,
|
||||
bool EnteringContext,
|
||||
bool ErrorRecoveryLookup);
|
||||
bool BuildCXXNestedNameSpecifier(Scope *S,
|
||||
IdentifierInfo &Identifier,
|
||||
SourceLocation IdentifierLoc,
|
||||
SourceLocation CCLoc,
|
||||
QualType ObjectType,
|
||||
bool EnteringContext,
|
||||
CXXScopeSpec &SS,
|
||||
NamedDecl *ScopeLookupResult,
|
||||
bool ErrorRecoveryLookup);
|
||||
|
||||
NestedNameSpecifier *ActOnCXXNestedNameSpecifier(Scope *S,
|
||||
CXXScopeSpec &SS,
|
||||
SourceLocation IdLoc,
|
||||
SourceLocation CCLoc,
|
||||
IdentifierInfo &II,
|
||||
ParsedType ObjectType,
|
||||
bool EnteringContext);
|
||||
/// \brief The parser has parsed a nested-name-specifier 'identifier::'.
|
||||
///
|
||||
/// \param S The scope in which this nested-name-specifier occurs.
|
||||
///
|
||||
/// \param Identifier The identifier preceding the '::'.
|
||||
///
|
||||
/// \param IdentifierLoc The location of the identifier.
|
||||
///
|
||||
/// \param CCLoc The location of the '::'.
|
||||
///
|
||||
/// \param ObjectType The type of the object, if we're parsing
|
||||
/// nested-name-specifier in a member access expression.
|
||||
///
|
||||
/// \param EnteringContext Whether we're entering the context nominated by
|
||||
/// this nested-name-specifier.
|
||||
///
|
||||
/// \param SS The nested-name-specifier, which is both an input
|
||||
/// parameter (the nested-name-specifier before this type) and an
|
||||
/// output parameter (containing the full nested-name-specifier,
|
||||
/// including this new type).
|
||||
///
|
||||
/// \returns true if an error occurred, false otherwise.
|
||||
bool ActOnCXXNestedNameSpecifier(Scope *S,
|
||||
IdentifierInfo &Identifier,
|
||||
SourceLocation IdentifierLoc,
|
||||
SourceLocation CCLoc,
|
||||
ParsedType ObjectType,
|
||||
bool EnteringContext,
|
||||
CXXScopeSpec &SS);
|
||||
|
||||
bool IsInvalidUnlessNestedName(Scope *S, CXXScopeSpec &SS,
|
||||
IdentifierInfo &II,
|
||||
IdentifierInfo &Identifier,
|
||||
SourceLocation IdentifierLoc,
|
||||
SourceLocation ColonLoc,
|
||||
ParsedType ObjectType,
|
||||
bool EnteringContext);
|
||||
|
||||
/// ActOnCXXNestedNameSpecifier - Called during parsing of a
|
||||
/// nested-name-specifier that involves a template-id, e.g.,
|
||||
/// "foo::bar<int, float>::", and now we need to build a scope
|
||||
/// specifier. \p SS is empty or the previously parsed nested-name
|
||||
/// part ("foo::"), \p Type is the already-parsed class template
|
||||
/// specialization (or other template-id that names a type), \p
|
||||
/// TypeRange is the source range where the type is located, and \p
|
||||
/// CCLoc is the location of the trailing '::'.
|
||||
CXXScopeTy *ActOnCXXNestedNameSpecifier(Scope *S,
|
||||
const CXXScopeSpec &SS,
|
||||
ParsedType Type,
|
||||
SourceRange TypeRange,
|
||||
SourceLocation CCLoc);
|
||||
/// \brief The parser has parsed a nested-name-specifier 'type::'.
|
||||
///
|
||||
/// \param S The scope in which this nested-name-specifier occurs.
|
||||
///
|
||||
/// \param Type The type, which will be a template specialization
|
||||
/// type, preceding the '::'.
|
||||
///
|
||||
/// \param CCLoc The location of the '::'.
|
||||
///
|
||||
/// \param SS The nested-name-specifier, which is both an input
|
||||
/// parameter (the nested-name-specifier before this type) and an
|
||||
/// output parameter (containing the full nested-name-specifier,
|
||||
/// including this new type).
|
||||
///
|
||||
/// \returns true if an error occurred, false otherwise.
|
||||
bool ActOnCXXNestedNameSpecifier(Scope *S,
|
||||
ParsedType Type,
|
||||
SourceLocation CCLoc,
|
||||
CXXScopeSpec &SS);
|
||||
|
||||
bool ShouldEnterDeclaratorScope(Scope *S, const CXXScopeSpec &SS);
|
||||
|
||||
|
|
|
@ -80,10 +80,9 @@ bool Parser::ParseOptionalCXXScopeSpecifier(CXXScopeSpec &SS,
|
|||
return false;
|
||||
|
||||
// '::' - Global scope qualifier.
|
||||
SourceLocation CCLoc = ConsumeToken();
|
||||
SS.setBeginLoc(CCLoc);
|
||||
SS.setScopeRep(Actions.ActOnCXXGlobalScopeSpecifier(getCurScope(), CCLoc));
|
||||
SS.setEndLoc(CCLoc);
|
||||
if (Actions.ActOnCXXGlobalScopeSpecifier(getCurScope(), ConsumeToken(), SS))
|
||||
return true;
|
||||
|
||||
HasScopeSpecifier = true;
|
||||
}
|
||||
|
||||
|
@ -214,14 +213,14 @@ bool Parser::ParseOptionalCXXScopeSpecifier(CXXScopeSpec &SS,
|
|||
}
|
||||
|
||||
if (ParsedType T = getTypeAnnotation(TypeToken)) {
|
||||
CXXScopeTy *Scope =
|
||||
Actions.ActOnCXXNestedNameSpecifier(getCurScope(), SS, T,
|
||||
TypeToken.getAnnotationRange(),
|
||||
CCLoc);
|
||||
SS.setScopeRep(Scope);
|
||||
} else
|
||||
SS.setScopeRep(0);
|
||||
SS.setEndLoc(CCLoc);
|
||||
if (Actions.ActOnCXXNestedNameSpecifier(getCurScope(), T, CCLoc, SS))
|
||||
SS.SetInvalid(SourceRange(SS.getBeginLoc(), CCLoc));
|
||||
|
||||
continue;
|
||||
} else {
|
||||
SS.SetInvalid(SourceRange(SS.getBeginLoc(), CCLoc));
|
||||
}
|
||||
|
||||
continue;
|
||||
}
|
||||
|
||||
|
@ -245,7 +244,9 @@ bool Parser::ParseOptionalCXXScopeSpecifier(CXXScopeSpec &SS,
|
|||
// If we get foo:bar, this is almost certainly a typo for foo::bar. Recover
|
||||
// and emit a fixit hint for it.
|
||||
if (Next.is(tok::colon) && !ColonIsSacred) {
|
||||
if (Actions.IsInvalidUnlessNestedName(getCurScope(), SS, II, ObjectType,
|
||||
if (Actions.IsInvalidUnlessNestedName(getCurScope(), SS, II,
|
||||
Tok.getLocation(),
|
||||
Next.getLocation(), ObjectType,
|
||||
EnteringContext) &&
|
||||
// If the token after the colon isn't an identifier, it's still an
|
||||
// error, but they probably meant something else strange so don't
|
||||
|
@ -274,16 +275,11 @@ bool Parser::ParseOptionalCXXScopeSpecifier(CXXScopeSpec &SS,
|
|||
"NextToken() not working properly!");
|
||||
SourceLocation CCLoc = ConsumeToken();
|
||||
|
||||
if (!HasScopeSpecifier) {
|
||||
SS.setBeginLoc(IdLoc);
|
||||
HasScopeSpecifier = true;
|
||||
}
|
||||
|
||||
if (!SS.isInvalid())
|
||||
SS.setScopeRep(
|
||||
Actions.ActOnCXXNestedNameSpecifier(getCurScope(), SS, IdLoc, CCLoc, II,
|
||||
ObjectType, EnteringContext));
|
||||
SS.setEndLoc(CCLoc);
|
||||
HasScopeSpecifier = true;
|
||||
if (Actions.ActOnCXXNestedNameSpecifier(getCurScope(), II, IdLoc, CCLoc,
|
||||
ObjectType, EnteringContext, SS))
|
||||
SS.SetInvalid(SourceRange(IdLoc, CCLoc));
|
||||
|
||||
continue;
|
||||
}
|
||||
|
||||
|
|
|
@ -14,6 +14,8 @@
|
|||
#include "clang/Parse/ParseDiagnostic.h" // FIXME: remove this back-dependency!
|
||||
#include "clang/Sema/DeclSpec.h"
|
||||
#include "clang/Sema/ParsedTemplate.h"
|
||||
#include "clang/AST/NestedNameSpecifier.h"
|
||||
#include "clang/AST/TypeLoc.h"
|
||||
#include "clang/Lex/Preprocessor.h"
|
||||
#include "clang/Basic/LangOptions.h"
|
||||
#include "llvm/ADT/STLExtras.h"
|
||||
|
@ -44,6 +46,41 @@ void UnqualifiedId::setConstructorTemplateId(TemplateIdAnnotation *TemplateId) {
|
|||
EndLocation = TemplateId->RAngleLoc;
|
||||
}
|
||||
|
||||
void CXXScopeSpec::Extend(ASTContext &Context, SourceLocation TemplateKWLoc,
|
||||
TypeLoc TL, SourceLocation ColonColonLoc) {
|
||||
ScopeRep = NestedNameSpecifier::Create(Context, ScopeRep,
|
||||
TemplateKWLoc.isValid(),
|
||||
TL.getTypePtr());
|
||||
if (Range.getBegin().isInvalid())
|
||||
Range.setBegin(TL.getBeginLoc());
|
||||
Range.setEnd(ColonColonLoc);
|
||||
}
|
||||
|
||||
void CXXScopeSpec::Extend(ASTContext &Context, IdentifierInfo *Identifier,
|
||||
SourceLocation IdentifierLoc,
|
||||
SourceLocation ColonColonLoc) {
|
||||
ScopeRep = NestedNameSpecifier::Create(Context, ScopeRep, Identifier);
|
||||
if (Range.getBegin().isInvalid())
|
||||
Range.setBegin(IdentifierLoc);
|
||||
Range.setEnd(ColonColonLoc);
|
||||
}
|
||||
|
||||
void CXXScopeSpec::Extend(ASTContext &Context, NamespaceDecl *Namespace,
|
||||
SourceLocation NamespaceLoc,
|
||||
SourceLocation ColonColonLoc) {
|
||||
ScopeRep = NestedNameSpecifier::Create(Context, ScopeRep, Namespace);
|
||||
if (Range.getBegin().isInvalid())
|
||||
Range.setBegin(NamespaceLoc);
|
||||
Range.setEnd(ColonColonLoc);
|
||||
}
|
||||
|
||||
void CXXScopeSpec::MakeGlobal(ASTContext &Context,
|
||||
SourceLocation ColonColonLoc) {
|
||||
assert(!ScopeRep && "Already have a nested-name-specifier!?");
|
||||
ScopeRep = NestedNameSpecifier::GlobalSpecifier(Context);
|
||||
Range = SourceRange(ColonColonLoc);
|
||||
}
|
||||
|
||||
/// DeclaratorChunk::getFunction - Return a DeclaratorChunk for a function.
|
||||
/// "TheDeclarator" is the declarator that this will be added to.
|
||||
DeclaratorChunk DeclaratorChunk::getFunction(const ParsedAttributes &attrs,
|
||||
|
|
|
@ -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;
|
||||
|
@ -219,7 +220,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 +228,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 +352,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 +396,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 +441,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 +477,7 @@ Sema::CXXScopeTy *Sema::BuildCXXNestedNameSpecifier(Scope *S,
|
|||
<< ND->getDeclName();
|
||||
} else {
|
||||
Found.clear();
|
||||
Found.setLookupName(&II);
|
||||
Found.setLookupName(&Identifier);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -497,7 +494,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 +507,75 @@ 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);
|
||||
if (ErrorRecoveryLookup)
|
||||
return true;
|
||||
|
||||
// Fall through so that we'll pick the name we found in the object
|
||||
// type, since that's probably what the user wanted anyway.
|
||||
}
|
||||
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->getNamespace(), 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,36 @@ 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;
|
||||
}
|
||||
|
||||
bool Sema::ShouldEnterDeclaratorScope(Scope *S, const CXXScopeSpec &SS) {
|
||||
|
|
|
@ -7559,12 +7559,14 @@ TreeTransform<Derived>::RebuildNestedNameSpecifier(NestedNameSpecifier *Prefix,
|
|||
// FIXME: The source location information is all wrong.
|
||||
SS.setRange(Range);
|
||||
SS.setScopeRep(Prefix);
|
||||
return static_cast<NestedNameSpecifier *>(
|
||||
SemaRef.BuildCXXNestedNameSpecifier(0, SS, Range.getEnd(),
|
||||
Range.getEnd(), II,
|
||||
ObjectType,
|
||||
FirstQualifierInScope,
|
||||
false, false));
|
||||
if (SemaRef.BuildCXXNestedNameSpecifier(0, II, /*FIXME:*/Range.getBegin(),
|
||||
/*FIXME:*/Range.getEnd(),
|
||||
ObjectType, false,
|
||||
SS, FirstQualifierInScope,
|
||||
false))
|
||||
return 0;
|
||||
|
||||
return SS.getScopeRep();
|
||||
}
|
||||
|
||||
template<typename Derived>
|
||||
|
|
|
@ -107,6 +107,19 @@ class TypeLocBuilder {
|
|||
return DI;
|
||||
}
|
||||
|
||||
/// \brief Copies the type-location information to the given AST context and
|
||||
/// returns a \c TypeLoc referring into the AST context.
|
||||
TypeLoc getTypeLocInContext(ASTContext &Context, QualType T) {
|
||||
#ifndef NDEBUG
|
||||
assert(T == LastTy && "type doesn't match last type pushed!");
|
||||
#endif
|
||||
|
||||
size_t FullDataSize = Capacity - Index;
|
||||
void *Mem = Context.Allocate(FullDataSize);
|
||||
memcpy(Mem, &Buffer[Index], FullDataSize);
|
||||
return TypeLoc(T, Mem);
|
||||
}
|
||||
|
||||
private:
|
||||
TypeLoc pushImpl(QualType T, size_t LocalSize) {
|
||||
#ifndef NDEBUG
|
||||
|
|
Loading…
Reference in New Issue