forked from OSchip/llvm-project
Revamp our representation of C++ nested-name-specifiers. We now have a
uniqued representation that should both save some memory and make it far easier to properly build canonical types for types involving dependent nested-name-specifiers, e.g., "typename T::Nested::type". This approach will greatly simplify the representation of CXXScopeSpec. That'll be next. llvm-svn: 67799
This commit is contained in:
parent
fe7c0492a0
commit
f21eb49a04
|
@ -18,6 +18,7 @@
|
|||
#include "clang/Basic/LangOptions.h"
|
||||
#include "clang/AST/Builtins.h"
|
||||
#include "clang/AST/Decl.h"
|
||||
#include "clang/AST/NestedNameSpecifier.h"
|
||||
#include "clang/AST/Type.h"
|
||||
#include "clang/Basic/SourceLocation.h"
|
||||
#include "llvm/ADT/DenseMap.h"
|
||||
|
@ -74,6 +75,14 @@ class ASTContext {
|
|||
llvm::FoldingSet<QualifiedNameType> QualifiedNameTypes;
|
||||
llvm::FoldingSet<ObjCQualifiedInterfaceType> ObjCQualifiedInterfaceTypes;
|
||||
llvm::FoldingSet<ObjCQualifiedIdType> ObjCQualifiedIdTypes;
|
||||
|
||||
/// \brief The set of nested name specifiers.
|
||||
///
|
||||
/// This set is managed by the NestedNameSpecifier class.
|
||||
llvm::FoldingSet<NestedNameSpecifier> NestedNameSpecifiers;
|
||||
NestedNameSpecifier *GlobalNestedNameSpecifier;
|
||||
friend class NestedNameSpecifier;
|
||||
|
||||
/// ASTRecordLayouts - A cache mapping from RecordDecls to ASTRecordLayouts.
|
||||
/// This is lazily created. This is intentionally not serialized.
|
||||
llvm::DenseMap<const RecordDecl*, const ASTRecordLayout*> ASTRecordLayouts;
|
||||
|
@ -284,8 +293,7 @@ public:
|
|||
unsigned NumArgs,
|
||||
QualType Canon = QualType());
|
||||
|
||||
QualType getQualifiedNameType(const NestedNameSpecifier *Components,
|
||||
unsigned NumComponents,
|
||||
QualType getQualifiedNameType(NestedNameSpecifier *NNS,
|
||||
QualType NamedType);
|
||||
|
||||
/// getObjCQualifiedInterfaceType - Return a
|
||||
|
|
|
@ -856,34 +856,22 @@ class QualifiedDeclRefExpr : public DeclRefExpr {
|
|||
/// nested-name-specifier.
|
||||
SourceRange QualifierRange;
|
||||
|
||||
/// The number of components in the complete nested-name-specifier.
|
||||
unsigned NumComponents;
|
||||
|
||||
QualifiedDeclRefExpr(NamedDecl *d, QualType t, SourceLocation l, bool TD,
|
||||
bool VD, SourceRange R,
|
||||
const NestedNameSpecifier *Components,
|
||||
unsigned NumComponents);
|
||||
/// \brief The nested-name-specifier that qualifies this declaration
|
||||
/// name.
|
||||
NestedNameSpecifier *NNS;
|
||||
|
||||
public:
|
||||
static QualifiedDeclRefExpr *Create(ASTContext &Context, NamedDecl *d,
|
||||
QualType t, SourceLocation l, bool TD,
|
||||
bool VD, SourceRange R,
|
||||
const NestedNameSpecifier *Components,
|
||||
unsigned NumComponents);
|
||||
QualifiedDeclRefExpr(NamedDecl *d, QualType t, SourceLocation l, bool TD,
|
||||
bool VD, SourceRange R, NestedNameSpecifier *NNS)
|
||||
: DeclRefExpr(QualifiedDeclRefExprClass, d, t, l, TD, VD),
|
||||
QualifierRange(R), NNS(NNS) { }
|
||||
|
||||
/// \brief Retrieve the source range of the nested-name-specifier.
|
||||
SourceRange getQualifierRange() const { return QualifierRange; }
|
||||
|
||||
// Iteration over of the parts of the nested-name-specifier.
|
||||
typedef const NestedNameSpecifier * iterator;
|
||||
|
||||
iterator begin() const {
|
||||
return reinterpret_cast<const NestedNameSpecifier *>(this + 1);
|
||||
}
|
||||
|
||||
iterator end() const { return begin() + NumComponents; }
|
||||
|
||||
unsigned size() const { return NumComponents; }
|
||||
/// \brief Retrieve the nested-name-specifier that qualifies this
|
||||
/// declaration.
|
||||
NestedNameSpecifier *getQualifier() const { return NNS; }
|
||||
|
||||
virtual SourceRange getSourceRange() const {
|
||||
return SourceRange(QualifierRange.getBegin(), getLocation());
|
||||
|
@ -908,7 +896,10 @@ public:
|
|||
/// the qualification (e.g., X<T>::) refers to a dependent type. In
|
||||
/// this case, X<T>::value cannot resolve to a declaration because the
|
||||
/// declaration will differ from on instantiation of X<T> to the
|
||||
/// next. Therefore, UnresolvedDeclRefExpr keeps track of the qualifier (X<T>::) and the name of the entity being referenced ("value"). Such expressions will instantiate to QualifiedDeclRefExprs.
|
||||
/// next. Therefore, UnresolvedDeclRefExpr keeps track of the
|
||||
/// qualifier (X<T>::) and the name of the entity being referenced
|
||||
/// ("value"). Such expressions will instantiate to
|
||||
/// QualifiedDeclRefExprs.
|
||||
class UnresolvedDeclRefExpr : public Expr {
|
||||
/// The name of the entity we will be referencing.
|
||||
DeclarationName Name;
|
||||
|
@ -920,18 +911,15 @@ class UnresolvedDeclRefExpr : public Expr {
|
|||
/// nested-name-specifier.
|
||||
SourceRange QualifierRange;
|
||||
|
||||
/// The number of components in the complete nested-name-specifier.
|
||||
unsigned NumComponents;
|
||||
|
||||
UnresolvedDeclRefExpr(DeclarationName N, QualType T, SourceLocation L,
|
||||
SourceRange R, const NestedNameSpecifier *Components,
|
||||
unsigned NumComponents);
|
||||
/// \brief The nested-name-specifier that qualifies this unresolved
|
||||
/// declaration name.
|
||||
NestedNameSpecifier *NNS;
|
||||
|
||||
public:
|
||||
static UnresolvedDeclRefExpr *Create(ASTContext &Context, DeclarationName N,
|
||||
SourceLocation L, SourceRange R,
|
||||
const NestedNameSpecifier *Components,
|
||||
unsigned NumComponents);
|
||||
UnresolvedDeclRefExpr(DeclarationName N, QualType T, SourceLocation L,
|
||||
SourceRange R, NestedNameSpecifier *NNS)
|
||||
: Expr(UnresolvedDeclRefExprClass, T, true, true),
|
||||
Name(N), Loc(L), QualifierRange(R), NNS(NNS) { }
|
||||
|
||||
/// \brief Retrieve the name that this expression refers to.
|
||||
DeclarationName getDeclName() const { return Name; }
|
||||
|
@ -942,16 +930,9 @@ public:
|
|||
/// \brief Retrieve the source range of the nested-name-specifier.
|
||||
SourceRange getQualifierRange() const { return QualifierRange; }
|
||||
|
||||
// Iteration over of the parts of the nested-name-specifier.
|
||||
typedef const NestedNameSpecifier * iterator;
|
||||
|
||||
iterator begin() const {
|
||||
return reinterpret_cast<const NestedNameSpecifier *>(this + 1);
|
||||
}
|
||||
|
||||
iterator end() const { return begin() + NumComponents; }
|
||||
|
||||
unsigned size() const { return NumComponents; }
|
||||
/// \brief Retrieve the nested-name-specifier that qualifies this
|
||||
/// declaration.
|
||||
NestedNameSpecifier *getQualifier() const { return NNS; }
|
||||
|
||||
virtual SourceRange getSourceRange() const {
|
||||
return SourceRange(QualifierRange.getBegin(), getLocation());
|
||||
|
|
|
@ -14,8 +14,8 @@
|
|||
#ifndef LLVM_CLANG_AST_NESTEDNAMESPECIFIER_H
|
||||
#define LLVM_CLANG_AST_NESTEDNAMESPECIFIER_H
|
||||
|
||||
#include "llvm/Support/DataTypes.h"
|
||||
#include <cassert>
|
||||
#include "llvm/ADT/FoldingSet.h"
|
||||
#include "llvm/ADT/PointerIntPair.h"
|
||||
|
||||
namespace llvm {
|
||||
class raw_ostream;
|
||||
|
@ -24,93 +24,151 @@ namespace llvm {
|
|||
namespace clang {
|
||||
|
||||
class ASTContext;
|
||||
class DeclContext;
|
||||
class DeclContext; // FIXME: die die die
|
||||
class NamespaceDecl;
|
||||
class IdentifierInfo;
|
||||
class Type;
|
||||
|
||||
/// \brief Represents a single component in a C++ nested-name-specifier.
|
||||
/// \brief Represents a C++ nested name specifier, such as
|
||||
/// "::std::vector<int>::".
|
||||
///
|
||||
/// C++ nested-name-specifiers are the prefixes to qualified
|
||||
/// namespaces. For example, "foo::" in "foo::x" is a
|
||||
/// nested-name-specifier. Multiple nested-name-specifiers can be
|
||||
/// strung together to build qualified names, e.g., "foo::bar::" in
|
||||
/// "foo::bar::x". Each NestedNameSpecifier class contains one of the
|
||||
/// terms, e.g., "foo::" or "bar::", which may be represented either
|
||||
/// as a type or as a DeclContext.
|
||||
class NestedNameSpecifier {
|
||||
/// \brief A DeclContext or Type pointer, depending on whether the
|
||||
/// low bit is set.
|
||||
uintptr_t Data;
|
||||
/// C++ nested name specifiers are the prefixes to qualified
|
||||
/// namespaces. For example, "foo::" in "foo::x" is a nested name
|
||||
/// specifier. Nested name specifiers are made up of a sequence of
|
||||
/// specifiers, each of which can be a namespace, type, identifier
|
||||
/// (for dependent names), or the global specifier ('::', must be the
|
||||
/// first specifier).
|
||||
class NestedNameSpecifier : public llvm::FoldingSetNode {
|
||||
/// \brief The nested name specifier that precedes this nested name
|
||||
/// specifier.
|
||||
NestedNameSpecifier *Prefix;
|
||||
|
||||
/// \brief The last component in the nested name specifier, which
|
||||
/// can be an identifier, a declaration, or a type.
|
||||
///
|
||||
/// When the pointer is NULL, this specifier represents the global
|
||||
/// specifier '::'. Otherwise, the pointer is one of
|
||||
/// IdentifierInfo*, Namespace*, or Type*, depending on the kind of
|
||||
/// specifier. The integer stores one ofthe first four values of
|
||||
/// type SpecifierKind.
|
||||
llvm::PointerIntPair<void*, 2> Specifier;
|
||||
|
||||
public:
|
||||
NestedNameSpecifier() : Data(0) { }
|
||||
/// \brief The kind of specifier that completes this nested name
|
||||
/// specifier.
|
||||
enum SpecifierKind {
|
||||
/// \brief An identifier, stored as an IdentifierInfo*.
|
||||
Identifier = 0,
|
||||
/// \brief A namespace, stored as a Namespace*.
|
||||
Namespace = 1,
|
||||
/// \brief A type, stored as a Type*.
|
||||
TypeSpec = 2,
|
||||
/// \brief A type that was preceded by the 'template' keyword,
|
||||
/// stored as a Type*.
|
||||
TypeSpecWithTemplate = 3,
|
||||
/// \brief The global specifier '::'. There is no stored value.
|
||||
Global = 4
|
||||
};
|
||||
|
||||
/// \brief Construct a nested name specifier that refers to a type.
|
||||
NestedNameSpecifier(const Type *T) {
|
||||
Data = reinterpret_cast<uintptr_t>(T);
|
||||
assert((Data & 0x01) == 0 && "cv-qualified type in nested-name-specifier");
|
||||
Data |= 0x01;
|
||||
private:
|
||||
/// \brief Builds the global specifier.
|
||||
NestedNameSpecifier() : Prefix(0), Specifier(0, 0) { }
|
||||
|
||||
/// \brief Copy constructor used internally to clone nested name
|
||||
/// specifiers.
|
||||
NestedNameSpecifier(const NestedNameSpecifier &Other)
|
||||
: llvm::FoldingSetNode(Other), Prefix(Other.Prefix),
|
||||
Specifier(Other.Specifier) {
|
||||
}
|
||||
|
||||
/// \brief Construct nested name specifier that refers to a
|
||||
/// DeclContext.
|
||||
NestedNameSpecifier(const DeclContext *DC) {
|
||||
Data = reinterpret_cast<uintptr_t>(DC);
|
||||
assert((Data & 0x01) == 0 && "Badly aligned DeclContext pointer");
|
||||
NestedNameSpecifier &operator=(const NestedNameSpecifier &); // do not implement
|
||||
|
||||
/// \brief Either find or insert the given nested name specifier
|
||||
/// mockup in the given context.
|
||||
static NestedNameSpecifier *FindOrInsert(ASTContext &Context, const NestedNameSpecifier &Mockup);
|
||||
|
||||
public:
|
||||
/// \brief Builds a specifier combining a prefix and an identifier.
|
||||
///
|
||||
/// The prefix must be dependent, since nested name specifiers
|
||||
/// referencing an identifier are only permitted when the identifier
|
||||
/// cannot be resolved.
|
||||
static NestedNameSpecifier *Create(ASTContext &Context,
|
||||
NestedNameSpecifier *Prefix,
|
||||
IdentifierInfo *II);
|
||||
|
||||
/// \brief Builds a nested name specifier that names a namespace.
|
||||
static NestedNameSpecifier *Create(ASTContext &Context,
|
||||
NestedNameSpecifier *Prefix,
|
||||
NamespaceDecl *NS);
|
||||
|
||||
/// \brief Builds a nested name specifier that names a type.
|
||||
static NestedNameSpecifier *Create(ASTContext &Context,
|
||||
NestedNameSpecifier *Prefix,
|
||||
bool Template, Type *T);
|
||||
|
||||
/// \brief Returns the nested name specifier representing the global
|
||||
/// scope.
|
||||
static NestedNameSpecifier *GlobalSpecifier(ASTContext &Context);
|
||||
|
||||
/// \brief Return the prefix of this nested name specifier.
|
||||
///
|
||||
/// The prefix contains all of the parts of the nested name
|
||||
/// specifier that preced this current specifier. For example, for a
|
||||
/// nested name specifier that represents "foo::bar::", the current
|
||||
/// specifier will contain "bar::" and the prefix will contain
|
||||
/// "foo::".
|
||||
NestedNameSpecifier *getPrefix() const { return Prefix; }
|
||||
|
||||
/// \brief Determine what kind of nested name specifier is stored.
|
||||
SpecifierKind getKind() const {
|
||||
if (Specifier.getPointer() == 0)
|
||||
return Global;
|
||||
return (SpecifierKind)Specifier.getInt();
|
||||
}
|
||||
|
||||
/// \brief Determines whether this nested-name-specifier refers to a
|
||||
/// type. Otherwise, it refers to a DeclContext.
|
||||
bool isType() const { return Data & 0x01; }
|
||||
/// \brief Retrieve the identifier stored in this nested name
|
||||
/// specifier.
|
||||
IdentifierInfo *getAsIdentifier() const {
|
||||
if (Specifier.getInt() == Identifier)
|
||||
return (IdentifierInfo *)Specifier.getPointer();
|
||||
|
||||
/// \brief Compute the declaration context to which this
|
||||
/// nested-name-specifier refers.
|
||||
///
|
||||
/// This routine computes the declaration context referenced by this
|
||||
/// nested-name-specifier. The nested-name-specifier may store
|
||||
/// either a DeclContext (the trivial case) or a non-dependent type
|
||||
/// (which will have an associated DeclContext). It is an error to
|
||||
/// invoke this routine when the nested-name-specifier refers to a
|
||||
/// dependent type.
|
||||
///
|
||||
/// \returns The stored DeclContext, if the nested-name-specifier
|
||||
/// stores a DeclContext. If the nested-name-specifier stores a
|
||||
/// non-dependent type, returns the DeclContext associated with that
|
||||
/// type.
|
||||
DeclContext *computeDeclContext(ASTContext &Context) const;
|
||||
|
||||
/// \brief Retrieve the nested-name-specifier as a type.
|
||||
///
|
||||
/// \returns The stored type. If the nested-name-specifier does not
|
||||
/// store a type, returns NULL.
|
||||
Type *getAsType() const {
|
||||
if (Data & 0x01)
|
||||
return reinterpret_cast<Type *>(Data & ~0x01);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/// \brief Retrieve the namespace stored in this nested name
|
||||
/// specifier.
|
||||
NamespaceDecl *getAsNamespace() const {
|
||||
if (Specifier.getInt() == Namespace)
|
||||
return (NamespaceDecl *)Specifier.getPointer();
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/// \brief Retrieves the nested-name-specifier as a DeclContext.
|
||||
///
|
||||
/// \returns The stored DeclContext. If the nested-name-specifier
|
||||
/// does not store a DeclContext, returns NULL.
|
||||
DeclContext *getAsDeclContext() const {
|
||||
if (Data & 0x01)
|
||||
return 0;
|
||||
return reinterpret_cast<DeclContext *>(Data);
|
||||
/// \brief Retrieve the type stored in this nested name specifier.
|
||||
Type *getAsType() const {
|
||||
if (Specifier.getInt() == TypeSpec ||
|
||||
Specifier.getInt() == TypeSpecWithTemplate)
|
||||
return (Type *)Specifier.getPointer();
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/// \brief Retrieve nested name specifier as an opaque pointer.
|
||||
void *getAsOpaquePtr() const { return reinterpret_cast<void *>(Data); }
|
||||
/// \brief Whether this nested name specifier refers to a dependent
|
||||
/// type or not.
|
||||
bool isDependent() const;
|
||||
|
||||
/// \brief Reconstruct a nested name specifier from an opaque pointer.
|
||||
static NestedNameSpecifier getFromOpaquePtr(void *Ptr) {
|
||||
NestedNameSpecifier NS;
|
||||
NS.Data = reinterpret_cast<uintptr_t>(Ptr);
|
||||
return NS;
|
||||
/// \brief Print this nested name specifier to the given output
|
||||
/// stream.
|
||||
void Print(llvm::raw_ostream &OS) const;
|
||||
|
||||
void Profile(llvm::FoldingSetNodeID &ID) const {
|
||||
ID.AddPointer(Prefix);
|
||||
ID.AddPointer(Specifier.getPointer());
|
||||
ID.AddInteger(Specifier.getInt());
|
||||
}
|
||||
|
||||
static void Print(llvm::raw_ostream &OS, const NestedNameSpecifier *First,
|
||||
const NestedNameSpecifier *Last);
|
||||
void Destroy(ASTContext &Context);
|
||||
};
|
||||
|
||||
}
|
||||
|
|
|
@ -1564,32 +1564,22 @@ protected:
|
|||
/// This type is used to keep track of a type name as written in the
|
||||
/// source code, including any nested-name-specifiers.
|
||||
class QualifiedNameType : public Type, public llvm::FoldingSetNode {
|
||||
/// \brief The number of components in the qualified name, not
|
||||
/// counting the final type.
|
||||
unsigned NumComponents;
|
||||
/// \brief The nested name specifier containing the qualifier.
|
||||
NestedNameSpecifier *NNS;
|
||||
|
||||
/// \brief The type that this qualified name refers to.
|
||||
QualType NamedType;
|
||||
|
||||
QualifiedNameType(const NestedNameSpecifier *Components,
|
||||
unsigned NumComponents, QualType NamedType,
|
||||
QualType CanonType);
|
||||
QualifiedNameType(NestedNameSpecifier *NNS, QualType NamedType,
|
||||
QualType CanonType)
|
||||
: Type(QualifiedName, CanonType, NamedType->isDependentType()),
|
||||
NNS(NNS), NamedType(NamedType) { }
|
||||
|
||||
friend class ASTContext; // ASTContext creates these
|
||||
|
||||
public:
|
||||
typedef const NestedNameSpecifier * iterator;
|
||||
|
||||
iterator begin() const { return getComponents(); }
|
||||
iterator end() const { return getComponents() + getNumComponents(); }
|
||||
|
||||
/// \brief Retrieve the array of nested-name-specifier components.
|
||||
const NestedNameSpecifier *getComponents() const {
|
||||
return reinterpret_cast<const NestedNameSpecifier *>(this + 1);
|
||||
}
|
||||
|
||||
/// \brief Retrieve the number of nested-name-specifier components.
|
||||
unsigned getNumComponents() const { return NumComponents; }
|
||||
/// \brief Retrieve the qualification on this type.
|
||||
NestedNameSpecifier *getQualifier() const { return NNS; }
|
||||
|
||||
/// \brief Retrieve the type named by the qualified-id.
|
||||
QualType getNamedType() const { return NamedType; }
|
||||
|
@ -1597,13 +1587,14 @@ public:
|
|||
virtual void getAsStringInternal(std::string &InnerString) const;
|
||||
|
||||
void Profile(llvm::FoldingSetNodeID &ID) {
|
||||
Profile(ID, getComponents(), NumComponents, NamedType);
|
||||
Profile(ID, NNS, NamedType);
|
||||
}
|
||||
|
||||
static void Profile(llvm::FoldingSetNodeID &ID,
|
||||
const NestedNameSpecifier *Components,
|
||||
unsigned NumComponents,
|
||||
QualType NamedType);
|
||||
static void Profile(llvm::FoldingSetNodeID &ID, NestedNameSpecifier *NNS,
|
||||
QualType NamedType) {
|
||||
ID.AddPointer(NNS);
|
||||
NamedType.Profile(ID);
|
||||
}
|
||||
|
||||
static bool classof(const Type *T) {
|
||||
return T->getTypeClass() == QualifiedName;
|
||||
|
|
|
@ -33,9 +33,9 @@ ASTContext::ASTContext(const LangOptions& LOpts, SourceManager &SM,
|
|||
TargetInfo &t,
|
||||
IdentifierTable &idents, SelectorTable &sels,
|
||||
bool FreeMem, unsigned size_reserve) :
|
||||
CFConstantStringTypeDecl(0), ObjCFastEnumerationStateTypeDecl(0),
|
||||
SourceMgr(SM), LangOpts(LOpts), FreeMemory(FreeMem), Target(t),
|
||||
Idents(idents), Selectors(sels)
|
||||
GlobalNestedNameSpecifier(0), CFConstantStringTypeDecl(0),
|
||||
ObjCFastEnumerationStateTypeDecl(0), SourceMgr(SM), LangOpts(LOpts),
|
||||
FreeMemory(FreeMem), Target(t), Idents(idents), Selectors(sels)
|
||||
{
|
||||
if (size_reserve > 0) Types.reserve(size_reserve);
|
||||
InitBuiltinTypes();
|
||||
|
@ -77,7 +77,18 @@ ASTContext::~ASTContext() {
|
|||
}
|
||||
}
|
||||
|
||||
// Destroy nested-name-specifiers.
|
||||
for (llvm::FoldingSet<NestedNameSpecifier>::iterator
|
||||
NNS = NestedNameSpecifiers.begin(),
|
||||
NNSEnd = NestedNameSpecifiers.end();
|
||||
NNS != NNSEnd; ++NNS)
|
||||
NNS->Destroy(*this);
|
||||
|
||||
if (GlobalNestedNameSpecifier)
|
||||
GlobalNestedNameSpecifier->Destroy(*this);
|
||||
|
||||
TUDecl->Destroy(*this);
|
||||
|
||||
}
|
||||
|
||||
void ASTContext::PrintStats() const {
|
||||
|
@ -1376,11 +1387,10 @@ ASTContext::getClassTemplateSpecializationType(TemplateDecl *Template,
|
|||
}
|
||||
|
||||
QualType
|
||||
ASTContext::getQualifiedNameType(const NestedNameSpecifier *Components,
|
||||
unsigned NumComponents,
|
||||
ASTContext::getQualifiedNameType(NestedNameSpecifier *NNS,
|
||||
QualType NamedType) {
|
||||
llvm::FoldingSetNodeID ID;
|
||||
QualifiedNameType::Profile(ID, Components, NumComponents, NamedType);
|
||||
QualifiedNameType::Profile(ID, NNS, NamedType);
|
||||
|
||||
void *InsertPos = 0;
|
||||
QualifiedNameType *T
|
||||
|
@ -1388,11 +1398,8 @@ ASTContext::getQualifiedNameType(const NestedNameSpecifier *Components,
|
|||
if (T)
|
||||
return QualType(T, 0);
|
||||
|
||||
void *Mem = Allocate((sizeof(QualifiedNameType) +
|
||||
sizeof(NestedNameSpecifier) * NumComponents),
|
||||
8);
|
||||
T = new (Mem) QualifiedNameType(Components, NumComponents, NamedType,
|
||||
getCanonicalType(NamedType));
|
||||
T = new (*this) QualifiedNameType(NNS, NamedType,
|
||||
getCanonicalType(NamedType));
|
||||
Types.push_back(T);
|
||||
QualifiedNameTypes.InsertNode(T, InsertPos);
|
||||
return QualType(T, 0);
|
||||
|
|
|
@ -24,54 +24,6 @@ void CXXConditionDeclExpr::Destroy(ASTContext& C) {
|
|||
C.Deallocate(this);
|
||||
}
|
||||
|
||||
QualifiedDeclRefExpr::QualifiedDeclRefExpr(NamedDecl *d, QualType t,
|
||||
SourceLocation l, bool TD,
|
||||
bool VD, SourceRange R,
|
||||
const NestedNameSpecifier *Components,
|
||||
unsigned NumComponents)
|
||||
: DeclRefExpr(QualifiedDeclRefExprClass, d, t, l, TD, VD),
|
||||
QualifierRange(R), NumComponents(NumComponents) {
|
||||
NestedNameSpecifier *Data
|
||||
= reinterpret_cast<NestedNameSpecifier *>(this + 1);
|
||||
for (unsigned I = 0; I < NumComponents; ++I)
|
||||
Data[I] = Components[I];
|
||||
}
|
||||
|
||||
QualifiedDeclRefExpr *
|
||||
QualifiedDeclRefExpr::Create(ASTContext &Context, NamedDecl *d, QualType t,
|
||||
SourceLocation l, bool TD,
|
||||
bool VD, SourceRange R,
|
||||
const NestedNameSpecifier *Components,
|
||||
unsigned NumComponents) {
|
||||
void *Mem = Context.Allocate((sizeof(QualifiedDeclRefExpr) +
|
||||
sizeof(NestedNameSpecifier) * NumComponents));
|
||||
return new (Mem) QualifiedDeclRefExpr(d, t, l, TD, VD, R, Components,
|
||||
NumComponents);
|
||||
}
|
||||
|
||||
UnresolvedDeclRefExpr::UnresolvedDeclRefExpr(DeclarationName N, QualType T,
|
||||
SourceLocation L, SourceRange R,
|
||||
const NestedNameSpecifier *Components,
|
||||
unsigned NumComponents)
|
||||
: Expr(UnresolvedDeclRefExprClass, T, true, true),
|
||||
Name(N), Loc(L), QualifierRange(R), NumComponents(NumComponents) {
|
||||
NestedNameSpecifier *Data
|
||||
= reinterpret_cast<NestedNameSpecifier *>(this + 1);
|
||||
for (unsigned I = 0; I < NumComponents; ++I)
|
||||
Data[I] = Components[I];
|
||||
}
|
||||
|
||||
UnresolvedDeclRefExpr *
|
||||
UnresolvedDeclRefExpr::Create(ASTContext &Context, DeclarationName N,
|
||||
SourceLocation L, SourceRange R,
|
||||
const NestedNameSpecifier *Components,
|
||||
unsigned NumComponents) {
|
||||
void *Mem = Context.Allocate((sizeof(UnresolvedDeclRefExpr) +
|
||||
sizeof(NestedNameSpecifier) * NumComponents));
|
||||
return new (Mem) UnresolvedDeclRefExpr(N, Context.DependentTy, L, R,
|
||||
Components, NumComponents);
|
||||
}
|
||||
|
||||
//===----------------------------------------------------------------------===//
|
||||
// Child Iterators for iterating over subexpressions/substatements
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
|
|
@ -16,46 +16,137 @@
|
|||
#include "clang/AST/Decl.h"
|
||||
#include "clang/AST/Type.h"
|
||||
#include "llvm/Support/raw_ostream.h"
|
||||
#include <cassert>
|
||||
|
||||
using namespace clang;
|
||||
|
||||
DeclContext *
|
||||
NestedNameSpecifier::computeDeclContext(ASTContext &Context) const {
|
||||
// The simple case: we're storing a DeclContext
|
||||
if ((Data & 0x01) == 0)
|
||||
return reinterpret_cast<DeclContext *>(Data);
|
||||
NestedNameSpecifier *
|
||||
NestedNameSpecifier::FindOrInsert(ASTContext &Context,
|
||||
const NestedNameSpecifier &Mockup) {
|
||||
llvm::FoldingSetNodeID ID;
|
||||
Mockup.Profile(ID);
|
||||
|
||||
Type *T = getAsType();
|
||||
if (!T)
|
||||
return 0;
|
||||
|
||||
// Retrieve the DeclContext associated with this type.
|
||||
const TagType *TagT = T->getAsTagType();
|
||||
assert(TagT && "No DeclContext from a non-tag type");
|
||||
return TagT->getDecl();
|
||||
}
|
||||
|
||||
void NestedNameSpecifier::Print(llvm::raw_ostream &OS,
|
||||
const NestedNameSpecifier *First,
|
||||
const NestedNameSpecifier *Last) {
|
||||
for (; First != Last; ++First) {
|
||||
if (Type *T = First->getAsType()) {
|
||||
std::string TypeStr;
|
||||
|
||||
// If this is a qualified name type, suppress the qualification:
|
||||
// it's part of our nested-name-specifier sequence anyway.
|
||||
if (const QualifiedNameType *QualT = dyn_cast<QualifiedNameType>(T))
|
||||
T = QualT->getNamedType().getTypePtr();
|
||||
|
||||
if (const TagType *TagT = dyn_cast<TagType>(T))
|
||||
TagT->getAsStringInternal(TypeStr, true);
|
||||
else
|
||||
T->getAsStringInternal(TypeStr);
|
||||
OS << TypeStr;
|
||||
} else if (NamedDecl *NamedDC
|
||||
= dyn_cast_or_null<NamedDecl>(First->getAsDeclContext()))
|
||||
OS << NamedDC->getNameAsString();
|
||||
|
||||
OS << "::";
|
||||
void *InsertPos = 0;
|
||||
NestedNameSpecifier *NNS
|
||||
= Context.NestedNameSpecifiers.FindNodeOrInsertPos(ID, InsertPos);
|
||||
if (!NNS) {
|
||||
NNS = new (Context) NestedNameSpecifier(Mockup);
|
||||
Context.NestedNameSpecifiers.InsertNode(NNS, InsertPos);
|
||||
}
|
||||
|
||||
return NNS;
|
||||
}
|
||||
|
||||
NestedNameSpecifier *
|
||||
NestedNameSpecifier::Create(ASTContext &Context, NestedNameSpecifier *Prefix,
|
||||
IdentifierInfo *II) {
|
||||
assert(II && "Identifier cannot be NULL");
|
||||
assert(Prefix && Prefix->isDependent() && "Prefix must be dependent");
|
||||
|
||||
NestedNameSpecifier Mockup;
|
||||
Mockup.Prefix = Prefix;
|
||||
Mockup.Specifier.setPointer(II);
|
||||
Mockup.Specifier.setInt(Identifier);
|
||||
return FindOrInsert(Context, Mockup);
|
||||
}
|
||||
|
||||
NestedNameSpecifier *
|
||||
NestedNameSpecifier::Create(ASTContext &Context, NestedNameSpecifier *Prefix,
|
||||
NamespaceDecl *NS) {
|
||||
assert(NS && "Namespace cannot be NULL");
|
||||
assert((!Prefix ||
|
||||
(Prefix->getAsType() == 0 && Prefix->getAsIdentifier() == 0)) &&
|
||||
"Broken nested name specifier");
|
||||
NestedNameSpecifier Mockup;
|
||||
Mockup.Prefix = Prefix;
|
||||
Mockup.Specifier.setPointer(NS);
|
||||
Mockup.Specifier.setInt(Namespace);
|
||||
return FindOrInsert(Context, Mockup);
|
||||
}
|
||||
|
||||
NestedNameSpecifier *
|
||||
NestedNameSpecifier::Create(ASTContext &Context, NestedNameSpecifier *Prefix,
|
||||
bool Template, Type *T) {
|
||||
assert(T && "Type cannot be NULL");
|
||||
NestedNameSpecifier Mockup;
|
||||
Mockup.Prefix = Prefix;
|
||||
Mockup.Specifier.setPointer(T);
|
||||
Mockup.Specifier.setInt(Template? TypeSpecWithTemplate : TypeSpec);
|
||||
return FindOrInsert(Context, Mockup);
|
||||
}
|
||||
|
||||
NestedNameSpecifier *NestedNameSpecifier::GlobalSpecifier(ASTContext &Context) {
|
||||
if (!Context.GlobalNestedNameSpecifier)
|
||||
Context.GlobalNestedNameSpecifier = new (Context) NestedNameSpecifier();
|
||||
return Context.GlobalNestedNameSpecifier;
|
||||
}
|
||||
|
||||
/// \brief Whether this nested name specifier refers to a dependent
|
||||
/// type or not.
|
||||
bool NestedNameSpecifier::isDependent() const {
|
||||
switch (getKind()) {
|
||||
case Identifier:
|
||||
// Identifier specifiers always represent dependent types
|
||||
return true;
|
||||
|
||||
case Namespace:
|
||||
case Global:
|
||||
return false;
|
||||
|
||||
case TypeSpec:
|
||||
case TypeSpecWithTemplate:
|
||||
return getAsType()->isDependentType();
|
||||
}
|
||||
|
||||
// Necessary to suppress a GCC warning.
|
||||
return false;
|
||||
}
|
||||
|
||||
/// \brief Print this nested name specifier to the given output
|
||||
/// stream.
|
||||
void NestedNameSpecifier::Print(llvm::raw_ostream &OS) const {
|
||||
if (Prefix)
|
||||
Prefix->Print(OS);
|
||||
|
||||
switch (getKind()) {
|
||||
case Identifier:
|
||||
OS << getAsIdentifier()->getName();
|
||||
break;
|
||||
|
||||
case Namespace:
|
||||
OS << getAsNamespace()->getIdentifier()->getName();
|
||||
break;
|
||||
|
||||
case Global:
|
||||
break;
|
||||
|
||||
case TypeSpecWithTemplate:
|
||||
OS << "template ";
|
||||
// Fall through to print the type.
|
||||
|
||||
case TypeSpec: {
|
||||
std::string TypeStr;
|
||||
Type *T = getAsType();
|
||||
|
||||
// If this is a qualified name type, suppress the qualification:
|
||||
// it's part of our nested-name-specifier sequence anyway. FIXME:
|
||||
// We should be able to assert that this doesn't happen.
|
||||
if (const QualifiedNameType *QualT = dyn_cast<QualifiedNameType>(T))
|
||||
T = QualT->getNamedType().getTypePtr();
|
||||
|
||||
if (const TagType *TagT = dyn_cast<TagType>(T))
|
||||
TagT->getAsStringInternal(TypeStr, true);
|
||||
else
|
||||
T->getAsStringInternal(TypeStr);
|
||||
OS << TypeStr;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
OS << "::";
|
||||
}
|
||||
|
||||
void NestedNameSpecifier::Destroy(ASTContext &Context) {
|
||||
this->~NestedNameSpecifier();
|
||||
Context.Deallocate((void *)this);
|
||||
}
|
||||
|
|
|
@ -533,12 +533,12 @@ void StmtPrinter::VisitDeclRefExpr(DeclRefExpr *Node) {
|
|||
void StmtPrinter::VisitQualifiedDeclRefExpr(QualifiedDeclRefExpr *Node) {
|
||||
NamedDecl *D = Node->getDecl();
|
||||
|
||||
NestedNameSpecifier::Print(OS, Node->begin(), Node->end());
|
||||
Node->getQualifier()->Print(OS);
|
||||
OS << D->getNameAsString();
|
||||
}
|
||||
|
||||
void StmtPrinter::VisitUnresolvedDeclRefExpr(UnresolvedDeclRefExpr *Node) {
|
||||
NestedNameSpecifier::Print(OS, Node->begin(), Node->end());
|
||||
Node->getQualifier()->Print(OS);
|
||||
OS << Node->getDeclName().getAsString();
|
||||
}
|
||||
|
||||
|
|
|
@ -1047,28 +1047,6 @@ ClassTemplateSpecializationType::Profile(llvm::FoldingSetNodeID &ID,
|
|||
Args[Idx].Profile(ID);
|
||||
}
|
||||
|
||||
QualifiedNameType::QualifiedNameType(const NestedNameSpecifier *Components,
|
||||
unsigned NumComponents,
|
||||
QualType NamedType,
|
||||
QualType CanonType)
|
||||
: Type(QualifiedName, CanonType, NamedType->isDependentType()),
|
||||
NumComponents(NumComponents), NamedType(NamedType) {
|
||||
NestedNameSpecifier *InitComponents
|
||||
= reinterpret_cast<NestedNameSpecifier *>(this + 1);
|
||||
for (unsigned I = 0; I < NumComponents; ++I)
|
||||
new (InitComponents + I) NestedNameSpecifier(Components[I]);
|
||||
}
|
||||
|
||||
void QualifiedNameType::Profile(llvm::FoldingSetNodeID &ID,
|
||||
const NestedNameSpecifier *Components,
|
||||
unsigned NumComponents,
|
||||
QualType NamedType) {
|
||||
ID.AddInteger(NumComponents);
|
||||
for (unsigned I = 0; I < NumComponents; ++I)
|
||||
ID.AddPointer(Components[I].getAsOpaquePtr());
|
||||
NamedType.Profile(ID);
|
||||
}
|
||||
|
||||
//===----------------------------------------------------------------------===//
|
||||
// Type Printing
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
@ -1440,7 +1418,7 @@ void QualifiedNameType::getAsStringInternal(std::string &InnerString) const {
|
|||
|
||||
{
|
||||
llvm::raw_string_ostream OS(MyString);
|
||||
NestedNameSpecifier::Print(OS, begin(), end());
|
||||
NNS->Print(OS);
|
||||
}
|
||||
|
||||
std::string TypeStr;
|
||||
|
|
|
@ -421,9 +421,7 @@ CreateImpl(ASTContext& Context, Deserializer& D) {
|
|||
// QualifiedNameType
|
||||
//===----------------------------------------------------------------------===//
|
||||
void QualifiedNameType::EmitImpl(llvm::Serializer& S) const {
|
||||
S.EmitInt(NumComponents);
|
||||
// FIXME: Serialize the actual components
|
||||
S.Emit(NamedType);
|
||||
}
|
||||
|
||||
Type*
|
||||
|
|
|
@ -1940,11 +1940,11 @@ public:
|
|||
ClassTemplateSpecializationDecl *ClassTemplateSpec,
|
||||
bool ExplicitInstantiation);
|
||||
|
||||
CXXScopeSpec InstantiateScopeSpecifier(const NestedNameSpecifier *Components,
|
||||
unsigned NumComponents,
|
||||
SourceRange Range,
|
||||
const TemplateArgument *TemplateArgs,
|
||||
unsigned NumTemplateArgs);
|
||||
NestedNameSpecifier *
|
||||
InstantiateNestedNameSpecifier(NestedNameSpecifier *NNS,
|
||||
SourceRange Range,
|
||||
const TemplateArgument *TemplateArgs,
|
||||
unsigned NumTemplateArgs);
|
||||
|
||||
// Simple function for cloning expressions.
|
||||
template<typename T>
|
||||
|
|
|
@ -24,24 +24,41 @@ DeclContext *Sema::computeDeclContext(const CXXScopeSpec &SS) {
|
|||
if (!SS.isSet() || SS.isInvalid())
|
||||
return 0;
|
||||
|
||||
NestedNameSpecifier NNS
|
||||
= NestedNameSpecifier::getFromOpaquePtr(SS.getCurrentScopeRep());
|
||||
return NNS.computeDeclContext(Context);
|
||||
NestedNameSpecifier *NNS
|
||||
= static_cast<NestedNameSpecifier *>(SS.getCurrentScopeRep());
|
||||
if (NNS->isDependent())
|
||||
return 0;
|
||||
|
||||
switch (NNS->getKind()) {
|
||||
case NestedNameSpecifier::Identifier:
|
||||
assert(false && "Dependent nested-name-specifier has no DeclContext");
|
||||
break;
|
||||
|
||||
case NestedNameSpecifier::Namespace:
|
||||
return NNS->getAsNamespace();
|
||||
|
||||
case NestedNameSpecifier::TypeSpec:
|
||||
case NestedNameSpecifier::TypeSpecWithTemplate: {
|
||||
const TagType *Tag = NNS->getAsType()->getAsTagType();
|
||||
assert(Tag && "Non-tag type in nested-name-specifier");
|
||||
return Tag->getDecl();
|
||||
} break;
|
||||
|
||||
case NestedNameSpecifier::Global:
|
||||
return Context.getTranslationUnitDecl();
|
||||
}
|
||||
|
||||
// Required to silence a GCC warning.
|
||||
return 0;
|
||||
}
|
||||
|
||||
bool Sema::isDependentScopeSpecifier(const CXXScopeSpec &SS) {
|
||||
if (!SS.isSet() || SS.isInvalid())
|
||||
return false;
|
||||
|
||||
NestedNameSpecifier NNS
|
||||
= NestedNameSpecifier::getFromOpaquePtr(SS.getCurrentScopeRep());
|
||||
|
||||
if (Type *T = NNS.getAsType())
|
||||
return T->isDependentType();
|
||||
|
||||
// FIXME: What about the injected-class-name of a class template? It
|
||||
// is dependent, but we represent it as a declaration.
|
||||
return false;
|
||||
NestedNameSpecifier *NNS
|
||||
= static_cast<NestedNameSpecifier *>(SS.getCurrentScopeRep());
|
||||
return NNS->isDependent();
|
||||
}
|
||||
|
||||
/// \brief Require that the context specified by SS be complete.
|
||||
|
@ -79,7 +96,7 @@ bool Sema::RequireCompleteDeclContext(const CXXScopeSpec &SS) {
|
|||
/// global scope ('::').
|
||||
Sema::CXXScopeTy *Sema::ActOnCXXGlobalScopeSpecifier(Scope *S,
|
||||
SourceLocation CCLoc) {
|
||||
return NestedNameSpecifier(Context.getTranslationUnitDecl()).getAsOpaquePtr();
|
||||
return NestedNameSpecifier::GlobalSpecifier(Context);
|
||||
}
|
||||
|
||||
/// ActOnCXXNestedNameSpecifier - Called during parsing of a
|
||||
|
@ -93,19 +110,37 @@ Sema::CXXScopeTy *Sema::ActOnCXXNestedNameSpecifier(Scope *S,
|
|||
SourceLocation IdLoc,
|
||||
SourceLocation CCLoc,
|
||||
IdentifierInfo &II) {
|
||||
NestedNameSpecifier *Prefix
|
||||
= static_cast<NestedNameSpecifier *>(SS.getCurrentScopeRep());
|
||||
|
||||
// If the prefix is already dependent, there is no name lookup to
|
||||
// perform. Just build the resulting nested-name-specifier.
|
||||
if (Prefix && Prefix->isDependent())
|
||||
return NestedNameSpecifier::Create(Context, Prefix, &II);
|
||||
|
||||
NamedDecl *SD = LookupParsedName(S, &SS, &II, LookupNestedNameSpecifierName);
|
||||
|
||||
if (SD) {
|
||||
if (TypedefDecl *TD = dyn_cast<TypedefDecl>(SD)) {
|
||||
if (TD->getUnderlyingType()->isRecordType())
|
||||
return NestedNameSpecifier(Context.getTypeDeclType(TD).getTypePtr())
|
||||
.getAsOpaquePtr();
|
||||
} else if (isa<NamespaceDecl>(SD) || isa<RecordDecl>(SD)) {
|
||||
return NestedNameSpecifier(cast<DeclContext>(SD)).getAsOpaquePtr();
|
||||
}
|
||||
if (NamespaceDecl *Namespace = dyn_cast<NamespaceDecl>(SD))
|
||||
return NestedNameSpecifier::Create(Context, Prefix, Namespace);
|
||||
|
||||
// FIXME: Template parameters and dependent types.
|
||||
// FIXME: C++0x scoped enums
|
||||
if (TypeDecl *Type = dyn_cast<TypeDecl>(SD)) {
|
||||
// Determine whether we have a class (or, in C++0x, an enum) or
|
||||
// a typedef thereof. If so, build the nested-name-specifier.
|
||||
QualType T;
|
||||
if (TypedefDecl *TD = dyn_cast<TypedefDecl>(SD)) {
|
||||
if (TD->getUnderlyingType()->isRecordType() ||
|
||||
(getLangOptions().CPlusPlus0x &&
|
||||
TD->getUnderlyingType()->isEnumeralType()))
|
||||
T = Context.getTypeDeclType(TD);
|
||||
} else if (isa<RecordDecl>(Type) ||
|
||||
(getLangOptions().CPlusPlus0x && isa<EnumDecl>(Type)))
|
||||
T = Context.getTypeDeclType(Type);
|
||||
|
||||
if (!T.isNull())
|
||||
return NestedNameSpecifier::Create(Context, Prefix, false,
|
||||
T.getTypePtr());
|
||||
}
|
||||
|
||||
// Fall through to produce an error: we found something that isn't
|
||||
// a class or a namespace.
|
||||
|
@ -137,8 +172,10 @@ Sema::CXXScopeTy *Sema::ActOnCXXNestedNameSpecifier(Scope *S,
|
|||
TypeTy *Ty,
|
||||
SourceRange TypeRange,
|
||||
SourceLocation CCLoc) {
|
||||
return NestedNameSpecifier(QualType::getFromOpaquePtr(Ty).getTypePtr())
|
||||
.getAsOpaquePtr();
|
||||
NestedNameSpecifier *Prefix
|
||||
= static_cast<NestedNameSpecifier *>(SS.getCurrentScopeRep());
|
||||
return NestedNameSpecifier::Create(Context, Prefix, /*FIXME:*/false,
|
||||
QualType::getFromOpaquePtr(Ty).getTypePtr());
|
||||
}
|
||||
|
||||
/// ActOnCXXEnterDeclaratorScope - Called when a C++ scope specifier (global
|
||||
|
@ -152,6 +189,7 @@ void Sema::ActOnCXXEnterDeclaratorScope(Scope *S, const CXXScopeSpec &SS) {
|
|||
assert(PreDeclaratorDC == 0 && "Previous declarator context not popped?");
|
||||
PreDeclaratorDC = static_cast<DeclContext*>(S->getEntity());
|
||||
CurContext = computeDeclContext(SS);
|
||||
assert(CurContext && "No context?");
|
||||
S->setEntity(CurContext);
|
||||
}
|
||||
|
||||
|
@ -170,4 +208,5 @@ void Sema::ActOnCXXExitDeclaratorScope(Scope *S, const CXXScopeSpec &SS) {
|
|||
while (!S->getEntity() && S->getParent())
|
||||
S = S->getParent();
|
||||
CurContext = static_cast<DeclContext*>(S->getEntity());
|
||||
assert(CurContext && "No context?");
|
||||
}
|
||||
|
|
|
@ -1159,9 +1159,13 @@ void Sema::AddImplicitlyDeclaredMembersToClass(CXXRecordDecl *ClassDecl) {
|
|||
/// Method declaration as if we had just parsed the qualified method
|
||||
/// name. However, it should not bring the parameters into scope;
|
||||
/// that will be performed by ActOnDelayedCXXMethodParameter.
|
||||
void Sema::ActOnStartDelayedCXXMethodDeclaration(Scope *S, DeclTy *Method) {
|
||||
void Sema::ActOnStartDelayedCXXMethodDeclaration(Scope *S, DeclTy *MethodD) {
|
||||
CXXScopeSpec SS;
|
||||
SS.setScopeRep(((FunctionDecl*)Method)->getDeclContext());
|
||||
FunctionDecl *Method = (FunctionDecl*)MethodD;
|
||||
QualType ClassTy
|
||||
= Context.getTypeDeclType(cast<RecordDecl>(Method->getDeclContext()));
|
||||
SS.setScopeRep(
|
||||
NestedNameSpecifier::Create(Context, 0, false, ClassTy.getTypePtr()));
|
||||
ActOnCXXEnterDeclaratorScope(S, SS);
|
||||
}
|
||||
|
||||
|
@ -1192,7 +1196,10 @@ void Sema::ActOnDelayedCXXMethodParameter(Scope *S, DeclTy *ParamD) {
|
|||
void Sema::ActOnFinishDelayedCXXMethodDeclaration(Scope *S, DeclTy *MethodD) {
|
||||
FunctionDecl *Method = (FunctionDecl*)MethodD;
|
||||
CXXScopeSpec SS;
|
||||
SS.setScopeRep(Method->getDeclContext());
|
||||
QualType ClassTy
|
||||
= Context.getTypeDeclType(cast<RecordDecl>(Method->getDeclContext()));
|
||||
SS.setScopeRep(
|
||||
NestedNameSpecifier::Create(Context, 0, false, ClassTy.getTypePtr()));
|
||||
ActOnCXXExitDeclaratorScope(S, SS);
|
||||
|
||||
// Now that we have our default arguments, check the constructor
|
||||
|
|
|
@ -440,13 +440,9 @@ Sema::BuildDeclRefExpr(NamedDecl *D, QualType Ty, SourceLocation Loc,
|
|||
bool TypeDependent, bool ValueDependent,
|
||||
const CXXScopeSpec *SS) {
|
||||
if (SS && !SS->isEmpty()) {
|
||||
llvm::SmallVector<NestedNameSpecifier, 16> Specs;
|
||||
for (CXXScopeSpec::iterator Spec = SS->begin(), SpecEnd = SS->end();
|
||||
Spec != SpecEnd; ++Spec)
|
||||
Specs.push_back(NestedNameSpecifier::getFromOpaquePtr(*Spec));
|
||||
return QualifiedDeclRefExpr::Create(Context, D, Ty, Loc, TypeDependent,
|
||||
ValueDependent, SS->getRange(),
|
||||
&Specs[0], Specs.size());
|
||||
return new (Context) QualifiedDeclRefExpr(D, Ty, Loc, TypeDependent,
|
||||
ValueDependent, SS->getRange(),
|
||||
static_cast<NestedNameSpecifier *>(SS->getCurrentScopeRep()));
|
||||
} else
|
||||
return new (Context) DeclRefExpr(D, Ty, Loc, TypeDependent, ValueDependent);
|
||||
}
|
||||
|
@ -619,13 +615,9 @@ Sema::ActOnDeclarationNameExpr(Scope *S, SourceLocation Loc,
|
|||
// -- a nested-name-specifier that contains a class-name that
|
||||
// names a dependent type.
|
||||
if (SS && isDependentScopeSpecifier(*SS)) {
|
||||
llvm::SmallVector<NestedNameSpecifier, 16> Specs;
|
||||
for (CXXScopeSpec::iterator Spec = SS->begin(), SpecEnd = SS->end();
|
||||
Spec != SpecEnd; ++Spec)
|
||||
Specs.push_back(NestedNameSpecifier::getFromOpaquePtr(*Spec));
|
||||
return Owned(UnresolvedDeclRefExpr::Create(Context, Name, Loc,
|
||||
SS->getRange(), &Specs[0],
|
||||
Specs.size()));
|
||||
return Owned(new (Context) UnresolvedDeclRefExpr(Name, Context.DependentTy,
|
||||
Loc, SS->getRange(),
|
||||
static_cast<NestedNameSpecifier *>(SS->getCurrentScopeRep())));
|
||||
}
|
||||
|
||||
LookupResult Lookup = LookupParsedName(S, SS, Name, LookupOrdinaryName,
|
||||
|
@ -2302,12 +2294,11 @@ Sema::ActOnCallExpr(Scope *S, ExprArg fn, SourceLocation LParenLoc,
|
|||
Expr *NewFn = 0;
|
||||
if (QualifiedDeclRefExpr *QDRExpr
|
||||
= dyn_cast_or_null<QualifiedDeclRefExpr>(DRExpr))
|
||||
NewFn = QualifiedDeclRefExpr::Create(Context, FDecl, FDecl->getType(),
|
||||
QDRExpr->getLocation(),
|
||||
false, false,
|
||||
QDRExpr->getQualifierRange(),
|
||||
QDRExpr->begin(),
|
||||
QDRExpr->size());
|
||||
NewFn = new (Context) QualifiedDeclRefExpr(FDecl, FDecl->getType(),
|
||||
QDRExpr->getLocation(),
|
||||
false, false,
|
||||
QDRExpr->getQualifierRange(),
|
||||
QDRExpr->getQualifier());
|
||||
else
|
||||
NewFn = new (Context) DeclRefExpr(FDecl, FDecl->getType(),
|
||||
Fn->getSourceRange().getBegin());
|
||||
|
|
|
@ -768,33 +768,52 @@ Sema::InstantiateClassTemplateSpecialization(
|
|||
ClassTemplateSpec->getNumTemplateArgs());
|
||||
}
|
||||
|
||||
/// \brief Instantiate a sequence of nested-name-specifiers into a
|
||||
/// scope specifier.
|
||||
CXXScopeSpec
|
||||
Sema::InstantiateScopeSpecifier(const NestedNameSpecifier *Components,
|
||||
unsigned NumComponents,
|
||||
SourceRange Range,
|
||||
const TemplateArgument *TemplateArgs,
|
||||
unsigned NumTemplateArgs) {
|
||||
CXXScopeSpec SS;
|
||||
for (unsigned Comp = 0; Comp < NumComponents; ++Comp) {
|
||||
if (Type *T = Components[Comp].getAsType()) {
|
||||
QualType NewT = InstantiateType(QualType(T, 0), TemplateArgs,
|
||||
NumTemplateArgs, Range.getBegin(),
|
||||
DeclarationName());
|
||||
if (NewT.isNull())
|
||||
return SS;
|
||||
NestedNameSpecifier NNS(NewT.getTypePtr());
|
||||
SS.addScopeRep(NNS.getAsOpaquePtr());
|
||||
} else {
|
||||
DeclContext *DC = Components[Comp].getAsDeclContext();
|
||||
// FIXME: injected-class-name might be dependent, and therefore
|
||||
// would need instantiation.
|
||||
NestedNameSpecifier NNS(DC);
|
||||
SS.addScopeRep(NNS.getAsOpaquePtr());
|
||||
}
|
||||
/// \brief Instantiate a nested-name-specifier.
|
||||
NestedNameSpecifier *
|
||||
Sema::InstantiateNestedNameSpecifier(NestedNameSpecifier *NNS,
|
||||
SourceRange Range,
|
||||
const TemplateArgument *TemplateArgs,
|
||||
unsigned NumTemplateArgs) {
|
||||
// Instantiate the prefix of this nested name specifier.
|
||||
NestedNameSpecifier *Prefix = NNS->getPrefix();
|
||||
if (Prefix) {
|
||||
Prefix = InstantiateNestedNameSpecifier(Prefix, Range, TemplateArgs,
|
||||
NumTemplateArgs);
|
||||
if (!Prefix)
|
||||
return 0;
|
||||
}
|
||||
|
||||
SS.setRange(Range);
|
||||
return SS;
|
||||
switch (NNS->getKind()) {
|
||||
case NestedNameSpecifier::Identifier:
|
||||
// FIXME: Implement this lookup!
|
||||
assert(false && "Cannot instantiate this nested-name-specifier");
|
||||
break;
|
||||
|
||||
case NestedNameSpecifier::Namespace:
|
||||
case NestedNameSpecifier::Global:
|
||||
return NNS;
|
||||
|
||||
case NestedNameSpecifier::TypeSpecWithTemplate:
|
||||
case NestedNameSpecifier::TypeSpec: {
|
||||
QualType T = QualType(NNS->getAsType(), 0);
|
||||
if (!T->isDependentType())
|
||||
return NNS;
|
||||
|
||||
T = InstantiateType(T, TemplateArgs, NumTemplateArgs, Range.getBegin(),
|
||||
DeclarationName());
|
||||
if (T.isNull())
|
||||
return 0;
|
||||
|
||||
// Note that T.getTypePtr(), below, strips cv-qualifiers. This is
|
||||
// perfectly reasonable, since cv-qualified types in
|
||||
// nested-name-specifiers don't matter.
|
||||
// FIXME: we need to perform more checking on this type.
|
||||
return NestedNameSpecifier::Create(Context, Prefix,
|
||||
NNS->getKind() == NestedNameSpecifier::TypeSpecWithTemplate,
|
||||
T.getTypePtr());
|
||||
}
|
||||
}
|
||||
|
||||
// Required to silence GCC warning.
|
||||
return 0;
|
||||
}
|
||||
|
|
|
@ -321,13 +321,17 @@ TemplateExprInstantiator::VisitSizeOfAlignOfExpr(SizeOfAlignOfExpr *E) {
|
|||
|
||||
Sema::OwningExprResult
|
||||
TemplateExprInstantiator::VisitUnresolvedDeclRefExpr(UnresolvedDeclRefExpr *E) {
|
||||
CXXScopeSpec SS = SemaRef.InstantiateScopeSpecifier(E->begin(), E->size(),
|
||||
E->getQualifierRange(),
|
||||
TemplateArgs,
|
||||
NumTemplateArgs);
|
||||
if (SS.isInvalid() || SS.isEmpty())
|
||||
NestedNameSpecifier *NNS
|
||||
= SemaRef.InstantiateNestedNameSpecifier(E->getQualifier(),
|
||||
E->getQualifierRange(),
|
||||
TemplateArgs, NumTemplateArgs);
|
||||
if (!NNS)
|
||||
return SemaRef.ExprError();
|
||||
|
||||
CXXScopeSpec SS;
|
||||
SS.setRange(E->getQualifierRange());
|
||||
SS.setScopeRep(NNS);
|
||||
|
||||
// FIXME: We're passing in a NULL scope, because
|
||||
// ActOnDeclarationNameExpr doesn't actually use the scope when we
|
||||
// give it a non-empty scope specifier. Investigate whether it would
|
||||
|
|
|
@ -1101,9 +1101,7 @@ QualType Sema::getQualifiedNameType(const CXXScopeSpec &SS, QualType T) {
|
|||
if (!SS.isSet() || SS.isInvalid() || T.isNull())
|
||||
return T;
|
||||
|
||||
llvm::SmallVector<NestedNameSpecifier, 4> Specs;
|
||||
for (CXXScopeSpec::iterator Spec = SS.begin(), SpecEnd = SS.end();
|
||||
Spec != SpecEnd; ++Spec)
|
||||
Specs.push_back(NestedNameSpecifier::getFromOpaquePtr(*Spec));
|
||||
return Context.getQualifiedNameType(&Specs[0], Specs.size(), T);
|
||||
NestedNameSpecifier *NNS
|
||||
= static_cast<NestedNameSpecifier *>(SS.getCurrentScopeRep());
|
||||
return Context.getQualifiedNameType(NNS, T);
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue