aboutsummaryrefslogtreecommitdiff
path: root/include/clang
diff options
context:
space:
mode:
Diffstat (limited to 'include/clang')
-rw-r--r--include/clang/AST/ASTContext.h3
-rw-r--r--include/clang/AST/NestedNameSpecifier.h41
-rw-r--r--include/clang/AST/TemplateName.h9
-rw-r--r--include/clang/AST/Type.h36
-rw-r--r--include/clang/Basic/DiagnosticParseKinds.td6
-rw-r--r--include/clang/Basic/IdentifierTable.h27
-rw-r--r--include/clang/Parse/Action.h16
7 files changed, 111 insertions, 27 deletions
diff --git a/include/clang/AST/ASTContext.h b/include/clang/AST/ASTContext.h
index 6dd93fd9f2..503c4639cc 100644
--- a/include/clang/AST/ASTContext.h
+++ b/include/clang/AST/ASTContext.h
@@ -302,6 +302,9 @@ public:
QualType getTypenameType(NestedNameSpecifier *NNS,
const IdentifierInfo *Name,
QualType Canon = QualType());
+ QualType getTypenameType(NestedNameSpecifier *NNS,
+ const TemplateSpecializationType *TemplateId,
+ QualType Canon = QualType());
/// getObjCQualifiedInterfaceType - Return a
/// ObjCQualifiedInterfaceType type for the given interface decl and
diff --git a/include/clang/AST/NestedNameSpecifier.h b/include/clang/AST/NestedNameSpecifier.h
index 864459b8ce..96eebe8be6 100644
--- a/include/clang/AST/NestedNameSpecifier.h
+++ b/include/clang/AST/NestedNameSpecifier.h
@@ -40,7 +40,11 @@ class Type;
class NestedNameSpecifier : public llvm::FoldingSetNode {
/// \brief The nested name specifier that precedes this nested name
/// specifier.
- NestedNameSpecifier *Prefix;
+ ///
+ /// The pointer is the nested-name-specifier that precedes this
+ /// one. The integer stores one of the first four values of type
+ /// SpecifierKind.
+ llvm::PointerIntPair<NestedNameSpecifier *, 2> Prefix;
/// \brief The last component in the nested name specifier, which
/// can be an identifier, a declaration, or a type.
@@ -48,9 +52,8 @@ class NestedNameSpecifier : public llvm::FoldingSetNode {
/// 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;
+ /// specifier as encoded within the prefix.
+ void* Specifier;
public:
/// \brief The kind of specifier that completes this nested name
@@ -71,7 +74,7 @@ public:
private:
/// \brief Builds the global specifier.
- NestedNameSpecifier() : Prefix(0), Specifier(0, 0) { }
+ NestedNameSpecifier() : Prefix(0, 0), Specifier(0) { }
/// \brief Copy constructor used internally to clone nested name
/// specifiers.
@@ -84,7 +87,8 @@ private:
/// \brief Either find or insert the given nested name specifier
/// mockup in the given context.
- static NestedNameSpecifier *FindOrInsert(ASTContext &Context, const NestedNameSpecifier &Mockup);
+ static NestedNameSpecifier *FindOrInsert(ASTContext &Context,
+ const NestedNameSpecifier &Mockup);
public:
/// \brief Builds a specifier combining a prefix and an identifier.
@@ -117,20 +121,20 @@ public:
/// nested name specifier that represents "foo::bar::", the current
/// specifier will contain "bar::" and the prefix will contain
/// "foo::".
- NestedNameSpecifier *getPrefix() const { return Prefix; }
+ NestedNameSpecifier *getPrefix() const { return Prefix.getPointer(); }
/// \brief Determine what kind of nested name specifier is stored.
SpecifierKind getKind() const {
- if (Specifier.getPointer() == 0)
+ if (Specifier == 0)
return Global;
- return (SpecifierKind)Specifier.getInt();
+ return (SpecifierKind)Prefix.getInt();
}
/// \brief Retrieve the identifier stored in this nested name
/// specifier.
IdentifierInfo *getAsIdentifier() const {
- if (Specifier.getInt() == Identifier)
- return (IdentifierInfo *)Specifier.getPointer();
+ if (Prefix.getInt() == Identifier)
+ return (IdentifierInfo *)Specifier;
return 0;
}
@@ -138,17 +142,17 @@ public:
/// \brief Retrieve the namespace stored in this nested name
/// specifier.
NamespaceDecl *getAsNamespace() const {
- if (Specifier.getInt() == Namespace)
- return (NamespaceDecl *)Specifier.getPointer();
+ if (Prefix.getInt() == Namespace)
+ return (NamespaceDecl *)Specifier;
return 0;
}
/// \brief Retrieve the type stored in this nested name specifier.
Type *getAsType() const {
- if (Specifier.getInt() == TypeSpec ||
- Specifier.getInt() == TypeSpecWithTemplate)
- return (Type *)Specifier.getPointer();
+ if (Prefix.getInt() == TypeSpec ||
+ Prefix.getInt() == TypeSpecWithTemplate)
+ return (Type *)Specifier;
return 0;
}
@@ -162,9 +166,8 @@ public:
void print(llvm::raw_ostream &OS) const;
void Profile(llvm::FoldingSetNodeID &ID) const {
- ID.AddPointer(Prefix);
- ID.AddPointer(Specifier.getPointer());
- ID.AddInteger(Specifier.getInt());
+ ID.AddPointer(Prefix.getOpaqueValue());
+ ID.AddPointer(Specifier);
}
void Destroy(ASTContext &Context);
diff --git a/include/clang/AST/TemplateName.h b/include/clang/AST/TemplateName.h
index 86c443985d..8a83108f8c 100644
--- a/include/clang/AST/TemplateName.h
+++ b/include/clang/AST/TemplateName.h
@@ -97,7 +97,14 @@ public:
bool isDependent() const;
/// \brief Print the template name.
- void print(llvm::raw_ostream &OS) const;
+ ///
+ /// \param OS the output stream to which the template name will be
+ /// printed.
+ ///
+ /// \param SuppressNNS if true, don't print the
+ /// nested-name-specifier that precedes the template name (if it has
+ /// one).
+ void print(llvm::raw_ostream &OS, bool SuppressNNS = false) const;
/// \brief Debugging aid that dumps the template name to standard
/// error.
diff --git a/include/clang/AST/Type.h b/include/clang/AST/Type.h
index 4d92f45391..c3195eb668 100644
--- a/include/clang/AST/Type.h
+++ b/include/clang/AST/Type.h
@@ -15,12 +15,14 @@
#define LLVM_CLANG_AST_TYPE_H
#include "clang/Basic/Diagnostic.h"
+#include "clang/Basic/IdentifierTable.h"
#include "clang/AST/NestedNameSpecifier.h"
#include "clang/AST/TemplateName.h"
#include "llvm/Support/Casting.h"
#include "llvm/ADT/APSInt.h"
#include "llvm/ADT/FoldingSet.h"
#include "llvm/ADT/PointerIntPair.h"
+#include "llvm/ADT/PointerUnion.h"
#include "llvm/Bitcode/SerializationFwd.h"
using llvm::isa;
@@ -1649,9 +1651,11 @@ class TypenameType : public Type, public llvm::FoldingSetNode {
/// \brief The nested name specifier containing the qualifier.
NestedNameSpecifier *NNS;
+ typedef llvm::PointerUnion<const IdentifierInfo *,
+ const TemplateSpecializationType *> NameType;
+
/// \brief The type that this typename specifier refers to.
- /// FIXME: Also need to represent the "template simple-template-id" case.
- const IdentifierInfo *Name;
+ NameType Name;
TypenameType(NestedNameSpecifier *NNS, const IdentifierInfo *Name,
QualType CanonType)
@@ -1660,14 +1664,34 @@ class TypenameType : public Type, public llvm::FoldingSetNode {
"TypenameType requires a dependent nested-name-specifier");
}
+ TypenameType(NestedNameSpecifier *NNS, const TemplateSpecializationType *Ty,
+ QualType CanonType)
+ : Type(Typename, CanonType, true), NNS(NNS), Name(Ty) {
+ assert(NNS->isDependent() &&
+ "TypenameType requires a dependent nested-name-specifier");
+ }
+
friend class ASTContext; // ASTContext creates these
public:
/// \brief Retrieve the qualification on this type.
NestedNameSpecifier *getQualifier() const { return NNS; }
- /// \brief Retrieve the type named by the typename specifier.
- const IdentifierInfo *getName() const { return Name; }
+ /// \brief Retrieve the type named by the typename specifier as an
+ /// identifier.
+ ///
+ /// This routine will return a non-NULL identifier pointer when the
+ /// form of the original typename was terminated by an identifier,
+ /// e.g., "typename T::type".
+ const IdentifierInfo *getIdentifier() const {
+ return Name.dyn_cast<const IdentifierInfo *>();
+ }
+
+ /// \brief Retrieve the type named by the typename specifier as a
+ /// type specialization.
+ const TemplateSpecializationType *getTemplateId() const {
+ return Name.dyn_cast<const TemplateSpecializationType *>();
+ }
virtual void getAsStringInternal(std::string &InnerString) const;
@@ -1676,9 +1700,9 @@ public:
}
static void Profile(llvm::FoldingSetNodeID &ID, NestedNameSpecifier *NNS,
- const IdentifierInfo *Name) {
+ NameType Name) {
ID.AddPointer(NNS);
- ID.AddPointer(Name);
+ ID.AddPointer(Name.getOpaqueValue());
}
static bool classof(const Type *T) {
diff --git a/include/clang/Basic/DiagnosticParseKinds.td b/include/clang/Basic/DiagnosticParseKinds.td
index ad996b7eeb..a040d3532a 100644
--- a/include/clang/Basic/DiagnosticParseKinds.td
+++ b/include/clang/Basic/DiagnosticParseKinds.td
@@ -226,6 +226,8 @@ def err_template_spec_syntax_non_template : Error<
"template|<unused>|refers to a template template parameter}1">;
def err_id_after_template_in_nested_name_spec : Error<
"expected template name after 'template' keyword in nested name specifier">;
+def err_id_after_template_in_typename_spec : Error<
+ "expected template name after 'template' keyword in typename specifier">;
def err_less_after_template_name_in_nested_name_spec : Error<
"expected '<' after 'template %0' in nested name specifier">;
def err_two_right_angle_brackets_need_space : Error<
@@ -236,6 +238,10 @@ def warn_cxx0x_right_shift_in_template_arg : Warning<
def err_expected_qualified_after_typename : Error<
"expected a qualified name after 'typename'">;
+def err_typename_refers_to_non_type_template : Error<
+ "typename specifier refers to a non-template">;
+def err_expected_type_name_after_typename : Error<
+ "expected an identifier or template-id after '::'">;
// Language specific pragmas
// - Generic warnings
diff --git a/include/clang/Basic/IdentifierTable.h b/include/clang/Basic/IdentifierTable.h
index 02296c0e29..cb55d257a1 100644
--- a/include/clang/Basic/IdentifierTable.h
+++ b/include/clang/Basic/IdentifierTable.h
@@ -21,6 +21,7 @@
#include "llvm/ADT/SmallString.h"
#include "llvm/ADT/OwningPtr.h"
#include "llvm/Bitcode/SerializationFwd.h"
+#include "llvm/Support/PointerLikeTypeTraits.h"
#include <string>
#include <cassert>
@@ -512,5 +513,31 @@ struct DenseMapInfo<clang::Selector> {
static bool isPod() { return true; }
};
+// Provide PointerLikeTypeTraits for IdentifierInfo pointers, which
+// are not guaranteed to be 8-byte aligned.
+template<>
+class PointerLikeTypeTraits<clang::IdentifierInfo*> {
+public:
+ static inline void *getAsVoidPointer(clang::IdentifierInfo* P) {
+ return P;
+ }
+ static inline clang::IdentifierInfo *getFromVoidPointer(void *P) {
+ return static_cast<clang::IdentifierInfo*>(P);
+ }
+ enum { NumLowBitsAvailable = 1 };
+};
+
+template<>
+class PointerLikeTypeTraits<const clang::IdentifierInfo*> {
+public:
+ static inline const void *getAsVoidPointer(const clang::IdentifierInfo* P) {
+ return P;
+ }
+ static inline const clang::IdentifierInfo *getFromVoidPointer(const void *P) {
+ return static_cast<const clang::IdentifierInfo*>(P);
+ }
+ enum { NumLowBitsAvailable = 1 };
+};
+
} // end namespace llvm
#endif
diff --git a/include/clang/Parse/Action.h b/include/clang/Parse/Action.h
index 6186126e09..d53e1fb49c 100644
--- a/include/clang/Parse/Action.h
+++ b/include/clang/Parse/Action.h
@@ -1305,7 +1305,7 @@ public:
}
/// \brief Called when the parser has parsed a C++ typename
- /// specifier, e.g., "typename T::type".
+ /// specifier that ends in an identifier, e.g., "typename T::type".
///
/// \param TypenameLoc the location of the 'typename' keyword
/// \param SS the nested-name-specifier following the typename (e.g., 'T::').
@@ -1317,6 +1317,20 @@ public:
return TypeResult();
}
+ /// \brief Called when the parser has parsed a C++ typename
+ /// specifier that ends in a template-id, e.g.,
+ /// "typename MetaFun::template apply<T1, T2>".
+ ///
+ /// \param TypenameLoc the location of the 'typename' keyword
+ /// \param SS the nested-name-specifier following the typename (e.g., 'T::').
+ /// \param TemplateLoc the location of the 'template' keyword, if any.
+ /// \param Ty the type that the typename specifier refers to.
+ virtual TypeResult
+ ActOnTypenameType(SourceLocation TypenameLoc, const CXXScopeSpec &SS,
+ SourceLocation TemplateLoc, TypeTy *Ty) {
+ return TypeResult();
+ }
+
//===----------------------- Obj-C Declarations -------------------------===//
// ActOnStartClassInterface - this action is called immediately after parsing