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:
Douglas Gregor 2011-02-24 00:17:56 +00:00
parent 60ed89dc54
commit 90c9972fb2
7 changed files with 340 additions and 149 deletions

View File

@ -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; }

View File

@ -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);

View File

@ -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;
}

View File

@ -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,

View File

@ -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) {

View File

@ -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>

View File

@ -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